Take notes on the command line

From Rosetta Code
Task
Take notes on the command line
You are encouraged to solve this task according to the task description, using any language you may know.
Take notes on the command line is part of Short Circuit's Console Program Basics selection.

Take notes on command line

NOTES.CMD is a commandline tool written as a Batch file. The task is to implement the same in your language.

Invoking NOTES without commandline arguments displays the current contents of the local NOTES.TXT if it exists. If NOTES has arguments, the current date and time are appended to the local NOTES.TXT followed by a newline. Then all the arguments, joined with spaces, prepended with a tab, and appended with a trailing newline, are written to NOTES.TXT.

AutoHotkey

<lang autohotkey>Notes := "Notes.txt"

If 0 = 0 ; no arguments {

   If FileExist(Notes) {
       FileRead, Content, %Notes%
       MsgBox, %Content%
   } Else
       MsgBox, %Notes% does not exist
   Goto, EOF

}

date and time, colon, newline (CRLF), tab

Date := A_DD "/" A_MM "/" A_YYYY Time := A_Hour ":" A_Min ":" A_Sec "." A_MSec FileAppend, %Date% %Time%:`r`n%A_Tab%, %Notes%

command line parameters, trailing newline (CRLF)

Loop, %0%

   FileAppend, % %A_Index% " ", %Notes%

FileAppend, `r`n, %Notes%

EOF:</lang>

Batch File

Works with: Windows NT version 4

<lang dos>@echo off if %1@==@ (

   if exist notes.txt more notes.txt
   goto :eof

) echo %date% %time%:>>notes.txt echo %*>>notes.txt</lang>

C

<lang c>#include <stdio.h>

  1. include <time.h>
  1. define note_file "NOTES.TXT"

int main(int argc, char**argv) { FILE *note; time_t timer; int i; char ch;

if(argc==1) { //Read NOTES.TXT and print it note = fopen(note_file, "r"); if(note!=NULL) { while((ch=getc(note))!=EOF) putchar(ch); } } else { //Write date & time to NOTES.TXT, and then arguments note = fopen(note_file, "a"); if(note!=NULL) { timer = time(NULL); fprintf(note,"%s",asctime(localtime(&timer))); putc('\t', note); for(i=1;i<argc;i++) fprintf(note, "%s ", argv[i]); putc('\n', note); } }

if(note!=NULL) fclose(note); return 0; } </lang>

C++

<lang cpp>#include <fstream>

  1. include <iostream>
  2. include <ctime>

using namespace std;

  1. define note_file "NOTES.TXT"

int main(int argc, char **argv) { if(argc>1) { ofstream Notes(note_file, ios::app); time_t timer = time(NULL); if(Notes.is_open()) { Notes << asctime(localtime(&timer)) << '\t'; for(int i=1;i<argc;i++) Notes << argv[i] << ' '; Notes << endl; Notes.close(); } } else { ifstream Notes(note_file, ios::in); string line; if(Notes.is_open()) { while(!Notes.eof()) { getline(Notes, line); cout << line << endl; } Notes.close(); } } }</lang>

Factor

<lang factor>#! /usr/bin/env factor USING: kernel calendar calendar.format io io.encodings.utf8 io.files sequences command-line namespaces ;

command-line get [

   "notes.txt" utf8 file-contents print

] [

   " " join "\t" prepend
   "notes.txt" utf8 [
       now timestamp>ymdhms print
       print flush
   ] with-file-appender

] if-empty</lang>

Haskell

<lang haskell>import System.Environment (getArgs) import System.Time (getClockTime)

main :: IO () main = do

 args <- getArgs
 if null args
   then catch (readFile "notes.txt" >>= putStr)
              (\_ -> return ())
   else
     do ct <- getClockTime
        appendFile "notes.txt" $ show ct ++ "\n\t" ++ unwords args ++ "\n"</lang>

Sample output after a few runs:

Thu Apr 22 19:01:41 PDT 2010
	Test line 1.
Thu Apr 22 19:01:45 PDT 2010
	Test line 2.

JavaScript

Works with: JScript

<lang javascript>var notes = 'NOTES.TXT';

var args = WScript.Arguments; var fso = new ActiveXObject("Scripting.FileSystemObject"); var ForReading = 1, ForWriting = 2, ForAppending = 8;

if (args.length == 0) {

   if (fso.FileExists(notes)) {
       var f = fso.OpenTextFile(notes, ForReading);
       WScript.Echo(f.ReadAll());
       f.Close();
   }

} else {

   var f = fso.OpenTextFile(notes, ForAppending, true);
   var d = new Date();
   f.WriteLine(d.toLocaleString());
   f.Write("\t");
   // note that WScript.Arguments is not an array, it is a "collection"
   // it does not have a join() method.
   for (var i = 0; i < args.length; i++) {
       f.Write(args(i) + " ");
   }
   f.WriteLine();
   f.Close();

}</lang>

> del NOTES.TXT
> cscript /nologo notes.js
> cscript /nologo notes.js this   is   the   first note
> cscript /nologo notes.js
April 1, 2010 5:18:38 PM
        this is the first note


OCaml

<lang ocaml>#! /usr/bin/env ocaml

  1. load "unix.cma"

let notes_file = "notes.txt"

let take_notes() =

 let gmt = Unix.gmtime (Unix.time()) in
 let date =
   Printf.sprintf "%d-%02d-%02d %02d:%02d:%02d"
     (1900 + gmt.Unix.tm_year) (1 + gmt.Unix.tm_mon) gmt.Unix.tm_mday
     gmt.Unix.tm_hour gmt.Unix.tm_min gmt.Unix.tm_sec
 in
 let oc = open_out_gen [Open_append; Open_creat; Open_text] 0o644 notes_file in
 output_string oc (date ^ "\t");
 output_string oc (String.concat " " (List.tl(Array.to_list Sys.argv)));
 output_string oc "\n";

let dump_notes() =

 if not(Sys.file_exists notes_file)
 then (prerr_endline "no local notes found"; exit 1);
 let ic = open_in notes_file in
 try while true do
   print_endline (input_line ic)
 done with End_of_file -> ()

let () =

 if Array.length Sys.argv = 1
 then dump_notes()
 else take_notes()</lang>


Oz

<lang oz>functor import

  Application
  Open
  OS
  System

define

  fun {TimeStamp}
     N = {OS.localTime}
  in
     (1900+N.year)#"-"#(1+N.mon)#"-"#N.mDay#", "#N.hour#":"#N.min#":"#N.sec
  end
  fun {Join X|Xr Sep}
     {FoldL Xr fun {$ Z X} Z#Sep#X end X}
  end
  
  case {Application.getArgs plain}
  of nil then
     try
        F = {New Open.file init(name:"notes.txt")}
     in
        {System.printInfo {F read(list:$ size:all)}}
        {F close}
     catch _ then skip end      
  [] Args then
     F = {New Open.file init(name:"notes.txt" flags:[write text create append])}
  in
     {F write(vs:{TimeStamp}#"\n")}
     {F write(vs:"\t"#{Join Args " "}#"\n")}
     {F close}
  end
  {Application.exit 0}

end</lang>

Perl

<lang Perl>my $file = 'notes.txt'; if ( @ARGV ) {

 open NOTES, '>>', $file or die "Can't append to file $file: $!";
 print NOTES scalar localtime, "\n\t@ARGV\n";

} else {

 open NOTES, '<', $file or die "Can't read file $file: $!";
 print <NOTES>;

} close NOTES;</lang>

Sample output after a few runs:

Thu Apr 22 19:01:41 2010
	Test line 1.
Thu Apr 22 19:01:45 2010
	Test line 2.

PicoLisp

<lang PicoLisp>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l

(load "@lib/misc.l") (if (argv)

  (out "+notes.txt" (prinl (stamp) "^J^I" (glue " " @)))
  (and (info "notes.txt") (in "notes.txt" (echo))) )

(bye)</lang>

PowerShell

<lang powershell>$notes = "notes.txt" if (($args).length -eq 0) {

   if(Test-Path $notes) {
       Get-Content $notes
   }

} else {

   Get-Date | Add-Content $notes
   "`t" + $args -join " " | Add-Content $notes

}</lang>

PureBasic

<lang PureBasic>#FileName="notes.txt" Define argc=CountProgramParameters() If OpenConsole()

 If argc=0
   If ReadFile(0,#FileName)
     While Eof(0)=0
       PrintN(ReadString(0))                    ; No new notes, so present the old
     Wend
     CloseFile(0)
   EndIf
 Else ; e.g. we have some arguments
   Define d$=FormatDate("%yyyy-%mm-%dd %hh:%ii:%ss",date())
   If OpenFile(0,#FileName)
     Define args$=""
     While argc
       args$+" "+ProgramParameter()             ; Read all arguments
       argc-1
     Wend
     FileSeek(0,Lof(0))                         ; Go to the end of this file
     WriteStringN(0,d$+#CRLF$+#TAB$+args$)      ; Append date & note
     CloseFile(0)
   EndIf
 EndIf

EndIf</lang>

Python

<lang python>import sys, datetime

  1. sys.argv[1:] = 'go for it'.split()

if len(sys.argv) == 1:

   try:
       f = open('notes.txt', 'r')
       sys.stdout.write(f.read())
       f.close()
   except IOError:
       pass

else:

   f = open('notes.txt', 'a')
   f.write(datetime.datetime.now().isoformat() + '\n')
   f.write("\t%s\n" % ' '.join(sys.argv[1:]))
   f.close()</lang>

Sample notes.txt file

After assorted runs:

2010-04-01T17:06:20.312000
	go for it
2010-04-01T17:08:20.718000
	go for it

Ruby

<lang ruby>notes = 'NOTES.TXT' if ARGV.empty?

 File.copy_stream(notes, $stdout) rescue nil

else

 File.open(notes, 'a') {|file| file.puts "%s\n\t%s" % [Time.now, ARGV.join(' ')]}

end</lang>

SNOBOL4

Works with: Macro SNOBOL4 in C

<lang snobol>#! /usr/local/bin/snobol4 -b a = 2 ;* skip '-b' parameter notefile = "notes.txt" while args = args host(2,a = a + 1) " " :s(while) ident(args) :f(append) noparms input(.notes,io_findunit(),,notefile) :s(display)f(end) display output = notes :s(display) endfile(notes) :(end) append output(.notes,io_findunit(),"A",notefile) :f(end) notes = date() notes = char(9) args end</lang>

Tcl

<lang tcl># Make it easier to change the name of the notes file set notefile notes.txt

if {$argc} {

   # Write a message to the file
   set msg [clock format [clock seconds]]\n\t[join $argv " "]
   set f [open $notefile a]
   puts $f $msg
   close $f

} else {

   # Print the contents of the file
   catch {

set f [open $notefile] fcopy $f stdout close $f

   }

}</lang> Sample output after a few runs:

Thu Apr 01 19:28:07 BST 2010
	test 1 two three
Thu Apr 01 19:28:49 BST 2010
	TODO: Submit notes.tcl to Rosetta Code

UNIX Shell

Bash version <lang bash># NOTES=$HOME/notes.txt if $# -eq 0  ; then

 -r  $NOTES  && more $NOTES

else

 date >> $NOTES
 echo "  $*" >> $NOTES

fi</lang>

"Spoiled Bash kid" version <lang bash>N=~/notes.txt;$# -gt 0 && { date ; echo " $*"; exit 0; } >> $N || -r $N && cat $N</lang>


Portable version <lang shell>NOTES=$HOME/notes.txt if test "x$*" = "x" then

       if test -r  $NOTES
       then
               more $NOTES
       fi

else

       date >> $NOTES
       echo "  $*" >> $NOTES

fi</lang>