| 
					
				 | 
			
			
				@@ -1,8 +1,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (ql:quickload "cl-store") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(ql:quickload "cl-ppcre") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;;; Reimplementation of my bills tracker in Lisp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun reload () 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (load "/Users/swatson/Repos/lisp-files/fin-lisp/fin-lisp.lisp")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (load "~/Repos/fin-lisp/fin-lisp.lisp")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;; All records exist in this data structure 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;; nil on start and loaded in from file 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -11,6 +12,21 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;;; and the value is the monthly expenses hash 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defvar *records* (make-hash-table :test 'equalp)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;; Lookup table for matching a "pretty" month name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;; with a date eg. December2021 -> 202112 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+(defparameter *month-table* (list (cons 'January 01) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'February 02) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'March 03) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'April 04) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'May 05) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'June 06) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'July 07) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'August 08) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'September 09) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'October 10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'November 11) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				  (cons 'December 12))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun reset-records () 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (setf *records* (make-hash-table :test 'equalp))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -63,6 +79,42 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   ;(setf *records* (cl-store:restore (pathname filename)))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (setf *records* (cl-store:restore 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-Za-z].*).*$([0-9]{1,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) (progn 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;;					   (let ((result) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;;						 (month-num)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;;					     (setf result (ppcre:register-groups-bind (first second) (mre line) :sharedp t (list first second))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;;					     (setf month-num (cdr (assoc '(first result) *month-table*))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+;;;					     (setf cur-mon (concatenate (second result) month-num))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	       (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))))))))))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ;; Entry point 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 (defun main () 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (format t "Available options:~C" #\linefeed) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -71,6 +123,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (format t "3. Write records~C" #\linefeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (format t "4. Read records~C" #\linefeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (format t "5. Quit~C" #\linefeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  (format t "6. Import Records~C" #\linefeed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (let 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       ((answer (prompt-read "Select an option"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (if (string= answer "1") 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -79,12 +132,13 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	  (prompt-read "Enter month")))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (if (string= answer "2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(dump-month 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	 (read-from-string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	  (prompt-read "Enter month")))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	  (prompt-read "Enter month"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (if (string= answer "3") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(serialize-records (prompt-read "Enter filename"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (if (string= answer "4") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	(deserialize-records (prompt-read "Enter filename"))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     (if (string= answer "5") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	(quit))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(quit)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (if (string= answer "6") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(import-records (prompt-read "Enter filename")))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   (main)) 
			 |