|
@@ -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)))))
|
|
|
+
|