Browse Source

Adding basics of CLI

Simon Watson 2 years ago
parent
commit
cf3fdd18b3
1 changed files with 73 additions and 6 deletions
  1. 73 6
      fin-lisp.lisp

+ 73 - 6
fin-lisp.lisp

@@ -1,9 +1,17 @@
 (ql:quickload "cl-store")
 (ql:quickload "cl-ppcre")
+(ql:quickload "unix-opts")
+
+;;; Features
+;;; - Import records from old .txt format
+;;; - Interactive prompt to manage expenses
+;;; - Generic expense handling
+;;; TODO
+;;; - Non interactive CLI Interface
+;;; - Upload/download support like perl version
+;;;   - Should support encryption/decryption of records
 
 ;;;; Reimplementation of my bills tracker in Lisp
-(defun reload ()
-  (load "~/Repos/fin-lisp/fin-lisp.lisp"))
 
 ;;; All records exist in this data structure
 ;;; nil on start and loaded in from file
@@ -12,6 +20,43 @@
 ;;; and the value is the monthly expenses hash
 (defvar *records* (make-hash-table :test 'equalp))
 
+(defun file-test (filename)
+  (if (probe-file filename) filename (print "Couldn't find filename")))
+
+;;; Used by "print-month" arg to validate
+;;; the user provided a valid key
+(defun check-month (month-key)
+  (if (stringp month-key) month-key))
+
+(opts:define-opts
+  (:name :help
+   :description "Print help text"
+   :short #\h
+   :long "help")
+  (:name :read
+   :description "Read serialized records file"
+   :short #\r
+   :long "read"
+   :arg-parser #'file-test)
+  (:name :print-month
+   :description "Print records for given month"
+   :short #\p
+   :long "print-month"
+   :arg-parser #'check-month)
+  (:name :interactive-mode
+   :description "Run in interactive mode"
+   :short #\i
+   :long "interactive"))
+
+;; See: https://github.com/libre-man/unix-opts/blob/master/example/example.lisp
+(defmacro when-option ((options opt) &body body)
+  `(let ((it (getf ,options ,opt)))
+     (when it
+       ,@body)))
+
+(defun reload ()
+  (load "~/Repos/fin-lisp/fin-lisp.lisp"))
+
 (defun reset-records ()
   (setf *records* (make-hash-table :test 'equalp)))
   
@@ -102,8 +147,7 @@
 (defun cls()
   (format t "~A[H~@*~A[J" #\escape))
 
-;; Entry point
-(defun main ()
+(defun interactive-mode ()
   (format t "~%")
   (format t "Available options:~%")
   (format t "1. Enter expense~%")
@@ -135,5 +179,28 @@
     (if (string= answer "6")
 	(generic-handler
 	 (import-records (prompt-read "Enter filename"))
-	 "Parsing error or invalid filename"))
-  (main)))
+	 "Parsing error or invalid filename")))
+  (interactive-mode))
+
+(defun display-help ()
+  (format t "foo ~%")
+  (opts:describe
+   :prefix "fin-lisp.lisp - Basic expense tracker in lisp"
+   :usage-of "fin-lisp.lisp"
+   :args "[FREE-ARGS]")
+  (quit))
+
+;; Entry point
+(defun main ()
+  (if (= 1 (length sb-ext:*posix-argv*)) (interactive-mode))
+  (let ((matches (opts:get-opts)))
+    (format t "~a ~%" matches)
+    (when-option (matches :help)
+      (display-help))
+    (when-option (matches :print-month)
+      
+    (when-option (matches :interactive-mode)
+      (progn
+	(interactive-mode)
+	(quit)))))
+