|
@@ -6,12 +6,15 @@
|
|
|
|
|
|
;;; Features
|
|
|
;;; - Import records from old .txt format
|
|
|
+;;; - Removed as I'll never use it again
|
|
|
;;; - 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
|
|
|
+;;; - Should support encryption/decryption of records - DONE
|
|
|
+;;; - Interface is not good, and doesn't protect the user from
|
|
|
+;;; data entry mistakes
|
|
|
|
|
|
;;;; Reimplementation of my bills tracker in Lisp
|
|
|
|
|
@@ -148,38 +151,11 @@
|
|
|
:if-exists :overwrite
|
|
|
:if-does-not-exist :create)
|
|
|
(yason:encode *records* stream))
|
|
|
- (encrypt-records key filename))
|
|
|
+ (encrypt-records key filename)
|
|
|
+ (delete-file filename))
|
|
|
|
|
|
(defun deserialize-records (key filename)
|
|
|
-
|
|
|
-
|
|
|
-;; Import records from old perl version (plaintext file)
|
|
|
-(defun import-records (filename)
|
|
|
- (let ((old-file-lines
|
|
|
- (with-open-file (stream filename)
|
|
|
- (loop for line = (read-line stream nil)
|
|
|
- while line
|
|
|
- collect line)))
|
|
|
- (mre (ppcre:create-scanner "^(.*)[0-9]{4}$"))
|
|
|
- (ere (ppcre:create-scanner "^([A-Z].*)\ -\ \\\$([0-9]{1,4}) - PAID"))
|
|
|
- (cur-mon)
|
|
|
- (cur-exp))
|
|
|
- (loop for line in old-file-lines
|
|
|
- do (progn
|
|
|
- (if (ppcre:scan mre line) (setf cur-mon line))
|
|
|
- (if (ppcre:scan ere line)
|
|
|
- (progn
|
|
|
- (setf cur-exp (ppcre:register-groups-bind (first second) (ere line) :sharedp t (list first second)))
|
|
|
- (print cur-exp)
|
|
|
- (if (gethash cur-mon *records*)
|
|
|
- (let ((innerhash (gethash cur-mon *records*)))
|
|
|
- (setf (gethash (first cur-exp) innerhash) (second cur-exp))))
|
|
|
- (if (not (gethash cur-mon *records*))
|
|
|
- (progn
|
|
|
- (add-month cur-mon)
|
|
|
- (let ((innerhash (gethash cur-mon *records*)))
|
|
|
- (setf (gethash (first cur-exp) innerhash) (second cur-exp)))))))))))
|
|
|
-
|
|
|
+ (setf *records* (yason:parse (decrypt-records key filename))))
|
|
|
|
|
|
(defmacro generic-handler (form error-string)
|
|
|
`(handler-case ,form
|
|
@@ -199,7 +175,6 @@
|
|
|
(format t "3. Write records~%")
|
|
|
(format t "4. Read records~%")
|
|
|
(format t "5. Quit~%")
|
|
|
- (format t "6. Import Records~%")
|
|
|
(let
|
|
|
((answer (prompt-read "Select an option")))
|
|
|
(if (string= answer "1")
|
|
@@ -217,14 +192,11 @@
|
|
|
"Serialization error or invalid filename"))
|
|
|
(if (string= answer "4")
|
|
|
(generic-handler
|
|
|
- (deserialize-records (prompt-read "Enter filename"))
|
|
|
+ (deserialize-records (prompt-read "Enter decryption key")
|
|
|
+ (prompt-read "Enter filename"))
|
|
|
"Deserialization error or invalid filename"))
|
|
|
(if (string= answer "5")
|
|
|
- (quit))
|
|
|
- (if (string= answer "6")
|
|
|
- (generic-handler
|
|
|
- (import-records (prompt-read "Enter filename"))
|
|
|
- "Parsing error or invalid filename")))
|
|
|
+ (quit)))
|
|
|
(interactive-mode))
|
|
|
|
|
|
(defun display-help ()
|