Cleaned up entrant macros to only return clauses
This commit is contained in:
parent
5418e77c63
commit
15b1d36fa2
1 changed files with 66 additions and 42 deletions
|
|
@ -79,12 +79,10 @@ COUNT 0) means EVERY day-of-week (eg. every Saturday)"
|
||||||
((> count 0) ;; Positive count
|
((> count 0) ;; Positive count
|
||||||
(let ((decoded (gensym)))
|
(let ((decoded (gensym)))
|
||||||
`(let ((,decoded (decode-time date)))
|
`(let ((,decoded (decode-time date)))
|
||||||
(if (and (eq (nth 6 ,decoded) ,day-of-week)
|
(and (eq (nth 6 ,decoded) ,day-of-week)
|
||||||
(between (nth 3 ,decoded)
|
(between (nth 3 ,decoded)
|
||||||
,(* (1- count) 7)
|
,(* (1- count) 7)
|
||||||
,(* count 7)))
|
,(* count 7))))))
|
||||||
t
|
|
||||||
nil))))
|
|
||||||
((< count 0)
|
((< count 0)
|
||||||
(let ((days-in-month (gensym))
|
(let ((days-in-month (gensym))
|
||||||
(decoded (gensym)))
|
(decoded (gensym)))
|
||||||
|
|
@ -92,12 +90,10 @@ COUNT 0) means EVERY day-of-week (eg. every Saturday)"
|
||||||
(,days-in-month (ledger-schedule-days-in-month
|
(,days-in-month (ledger-schedule-days-in-month
|
||||||
(nth 4 ,decoded)
|
(nth 4 ,decoded)
|
||||||
(nth 5 ,decoded))))
|
(nth 5 ,decoded))))
|
||||||
(if (and (eq (nth 6 ,decoded) ,day-of-week)
|
(and (eq (nth 6 ,decoded) ,day-of-week)
|
||||||
(between (nth 3 ,decoded)
|
(between (nth 3 ,decoded)
|
||||||
(+ ,days-in-month ,(* count 7))
|
(+ ,days-in-month ,(* count 7))
|
||||||
(+ ,days-in-month ,(* (1+ count) 7))))
|
(+ ,days-in-month ,(* (1+ count) 7)))))))
|
||||||
t
|
|
||||||
nil))))
|
|
||||||
(t
|
(t
|
||||||
(error "COUNT out of range, COUNT=%S" count)))
|
(error "COUNT out of range, COUNT=%S" count)))
|
||||||
(error "Invalid argument to ledger-schedule-day-in-month-macro %S %S"
|
(error "Invalid argument to ledger-schedule-day-in-month-macro %S %S"
|
||||||
|
|
@ -117,13 +113,13 @@ of date."
|
||||||
(between (eval day) 1 (ledger-schedule-days-in-month (eval month) (eval year))))
|
(between (eval day) 1 (ledger-schedule-days-in-month (eval month) (eval year))))
|
||||||
(between (eval day) 1 31)) ;; no month specified, assume 31 days.
|
(between (eval day) 1 31)) ;; no month specified, assume 31 days.
|
||||||
`'(and ,(if (eval year)
|
`'(and ,(if (eval year)
|
||||||
`(if (eq (nth 5 (decode-time date)) ,(eval year)) t)
|
`(eq (nth 5 (decode-time date)) ,(eval year))
|
||||||
`t)
|
`t)
|
||||||
,(if (eval month)
|
,(if (eval month)
|
||||||
`(if (eq (nth 4 (decode-time date)) ,(eval month)) t)
|
`(eq (nth 4 (decode-time date)) ,(eval month))
|
||||||
`t)
|
`t)
|
||||||
,(if (eval day)
|
,(if (eval day)
|
||||||
`(if (eq (nth 3 (decode-time date)) ,(eval day)) t)))
|
`(eq (nth 3 (decode-time date)) ,(eval day))))
|
||||||
(error "ledger-schedule-constraint-numerical-date-macro: date out of range %S %S %S" (eval year) (eval month) (eval day))))
|
(error "ledger-schedule-constraint-numerical-date-macro: date out of range %S %S %S" (eval year) (eval month) (eval day))))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -133,10 +129,8 @@ of date."
|
||||||
For example every second Friday, regardless of month."
|
For example every second Friday, regardless of month."
|
||||||
(let ((start-day (nth 6 (decode-time (eval start-date)))))
|
(let ((start-day (nth 6 (decode-time (eval start-date)))))
|
||||||
(if (eq start-day day-of-week) ;; good, can proceed
|
(if (eq start-day day-of-week) ;; good, can proceed
|
||||||
`(if (zerop (mod (- (time-to-days date) ,(time-to-days (eval start-date))) ,(* skip 7)))
|
`(zerop (mod (- (time-to-days date) ,(time-to-days (eval start-date))) ,(* skip 7)))
|
||||||
t
|
(error "START-DATE day of week doesn't match DAY-OF-WEEK"))))
|
||||||
nil)
|
|
||||||
(error "START-DATE day of week doesn't match DAY-OF-WEEK"))))
|
|
||||||
|
|
||||||
(defmacro ledger-schedule-constrain-date-range-macro (month1 day1 month2 day2)
|
(defmacro ledger-schedule-constrain-date-range-macro (month1 day1 month2 day2)
|
||||||
"Return a form of DATE that is true if DATE falls between MONTH1 DAY1 and MONTH2 DAY2."
|
"Return a form of DATE that is true if DATE falls between MONTH1 DAY1 and MONTH2 DAY2."
|
||||||
|
|
@ -191,7 +185,7 @@ the transaction should be logged for that day."
|
||||||
(replace-match "(" nil t)))
|
(replace-match "(" nil t)))
|
||||||
|
|
||||||
(defun ledger-schedule-read-descriptor-tree (descriptor-string)
|
(defun ledger-schedule-read-descriptor-tree (descriptor-string)
|
||||||
"Take a date descriptor string and return a function that
|
"Take a date DESCRIPTOR-STRING and return a function of date that
|
||||||
returns true if the date meets the requirements"
|
returns true if the date meets the requirements"
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
;; copy the descriptor string into a temp buffer for manipulation
|
;; copy the descriptor string into a temp buffer for manipulation
|
||||||
|
|
@ -222,51 +216,76 @@ returns true if the date meets the requirements"
|
||||||
|
|
||||||
;; read the descriptor string into a lisp object the transform the
|
;; read the descriptor string into a lisp object the transform the
|
||||||
;; string descriptor into useable things
|
;; string descriptor into useable things
|
||||||
(ledger-transform-auto-tree
|
(ledger-schedule-transform-auto-tree
|
||||||
(read (buffer-substring-no-properties (point-min) (point-max))))))
|
(read (buffer-substring-no-properties (point-min) (point-max))))))
|
||||||
|
|
||||||
(defun ledger-transform-auto-tree (tree)
|
(defun ledger-schedule-transform-auto-tree (descriptor-string-list)
|
||||||
"Takes a lisp list of date descriptor strings, TREE, and returns a string with a lambda function of date."
|
"Takes a lisp list of date descriptor strings, TREE, and returns a string with a lambda function of date."
|
||||||
;; use funcall to use the lambda function spit out here
|
;; use funcall to use the lambda function spit out here
|
||||||
(if (consp tree)
|
(if (consp descriptor-string-list)
|
||||||
(let (result)
|
(let (result)
|
||||||
(while (consp tree)
|
(while (consp descriptor-string-list)
|
||||||
(let ((newcar (car tree)))
|
(let ((newcar (car descriptor-string-list)))
|
||||||
(if (consp newcar)
|
(if (consp newcar)
|
||||||
(setq newcar (ledger-transform-auto-tree (car tree))))
|
(setq newcar (ledger-schedule-transform-auto-tree (car descriptor-string-list))))
|
||||||
|
;; newcar may be a cons now, after ledger-schedule-transfrom-auto-tree
|
||||||
(if (consp newcar)
|
(if (consp newcar)
|
||||||
(push newcar result)
|
(push newcar result)
|
||||||
|
;; this is where we actually turn the string descriptor into useful lisp
|
||||||
(push (ledger-schedule-parse-date-descriptor newcar) result)) )
|
(push (ledger-schedule-parse-date-descriptor newcar) result)) )
|
||||||
(setq tree (cdr tree)))
|
(setq descriptor-string-list (cdr descriptor-string-list)))
|
||||||
|
|
||||||
;; tie up all the clauses in a big or and lambda
|
;; tie up all the clauses in a big or and lambda, and return
|
||||||
|
;; the lambda function as list to be executed by funcall
|
||||||
`(lambda (date)
|
`(lambda (date)
|
||||||
,(nconc (list 'or) (nreverse result) tree)))))
|
,(nconc (list 'or) (nreverse result) descriptor-string-list)))))
|
||||||
|
|
||||||
(defun ledger-schedule-split-constraints (descriptor-string)
|
(defun ledger-schedule-split-constraints (descriptor-string)
|
||||||
"Return a list with the year, month and day fields split"
|
"Return a list with the year, month and day fields split"
|
||||||
(let ((fields (split-string descriptor-string "[/\\-]" t))
|
(let ((fields (split-string descriptor-string "[/\\-]" t))
|
||||||
constrain-year constrain-month constrain-day)
|
constrain-year constrain-month constrain-day)
|
||||||
(if (string= (car fields) "*")
|
(if (string= (nth 0 fields) "*")
|
||||||
(setq constrain-year nil)
|
(setq constrain-year nil)
|
||||||
(setq constrain-year (car fields)))
|
(setq constrain-year (nth 0 fields)))
|
||||||
(if (string= (cadr fields) "*")
|
|
||||||
|
;;(setq constrain-month (ledger-schedule-classify-month-constraint (nth 1 fields)))
|
||||||
|
|
||||||
|
(if (string= (nth 1 fields) "*")
|
||||||
(setq constrain-month nil)
|
(setq constrain-month nil)
|
||||||
(setq constrain-month (cadr fields)))
|
(setq constrain-month (nth 1 fields)))
|
||||||
|
|
||||||
(if (string= (nth 2 fields) "*")
|
(if (string= (nth 2 fields) "*")
|
||||||
(setq constrain-day nil)
|
(setq constrain-day nil)
|
||||||
(setq constrain-day (nth 2 fields)))
|
(setq constrain-day (nth 2 fields)))
|
||||||
(list constrain-year constrain-month constrain-day)))
|
(list constrain-year constrain-month constrain-day)))
|
||||||
|
|
||||||
(defun ledger-string-to-number-or-nil (str)
|
(defun ledger-schedule-string-to-number-or-nil (str)
|
||||||
(if str
|
(if str
|
||||||
(string-to-number str)
|
(string-to-number str)
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
|
(defun ledger-schedule-classify-month-constraint (str)
|
||||||
|
(cond ((string= str "*")
|
||||||
|
t)
|
||||||
|
((/= 0 (string-to-number str))
|
||||||
|
(ledger-schedule-constrain-month-numerical (string-to-number str)))
|
||||||
|
(t
|
||||||
|
(error "Improperly specified month constraint: " str))))
|
||||||
|
|
||||||
|
(defun ledger-schedule-constrain-numerical-month (month)
|
||||||
|
"Return an exprssion of date that is only true if all constraints are met.
|
||||||
|
A nil constraint matches any input, a numerical entry must match that field
|
||||||
|
of date."
|
||||||
|
;; Do bounds checking to make sure the incoming date constraint is sane
|
||||||
|
|
||||||
|
(if (between (eval month) 1 12) ;; no month specified, assume 31 days.
|
||||||
|
`(eq (nth 4 (decode-time date)) ,(eval month))
|
||||||
|
(error "ledger-schedule-constrain-numerical-month: month out of range %S" (eval month))))
|
||||||
|
|
||||||
(defun ledger-schedule-compile-constraints (constraint-list)
|
(defun ledger-schedule-compile-constraints (constraint-list)
|
||||||
(let ((year-constraint (ledger-string-to-number-or-nil (nth 0 constraint-list)))
|
(let ((year-constraint (ledger-schedule-string-to-number-or-nil (nth 0 constraint-list)))
|
||||||
(month-constraint (ledger-string-to-number-or-nil (nth 1 constraint-list)))
|
(month-constraint (ledger-schedule-string-to-number-or-nil (nth 1 constraint-list)))
|
||||||
(day-constraint (ledger-string-to-number-or-nil (nth 2 constraint-list))))
|
(day-constraint (ledger-schedule-string-to-number-or-nil (nth 2 constraint-list))))
|
||||||
(ledger-schedule-constrain-numerical-date-macro
|
(ledger-schedule-constrain-numerical-date-macro
|
||||||
year-constraint
|
year-constraint
|
||||||
month-constraint
|
month-constraint
|
||||||
|
|
@ -303,7 +322,9 @@ returns true if the date meets the requirements"
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
(dolist (candidate candidates)
|
(dolist (candidate candidates)
|
||||||
(if (not (ledger-schedule-already-entered candidate ledger-buf))
|
(if (not (ledger-schedule-already-entered candidate ledger-buf))
|
||||||
(insert (format-time-string date-format (car candidate) ) " " (cadr candidate) "\n"))))))
|
(insert (format-time-string date-format (car candidate) ) " " (cadr candidate) "\n")))
|
||||||
|
(ledger-mode))
|
||||||
|
(length candidates)))
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
@ -311,9 +332,12 @@ returns true if the date meets the requirements"
|
||||||
;;
|
;;
|
||||||
(defvar auto-items)
|
(defvar auto-items)
|
||||||
|
|
||||||
(defun ledger-schedule-test-setup ()
|
(defun ledger-schedule-test ( early horizon)
|
||||||
(setq auto-items
|
(ledger-schedule-create-auto-buffer
|
||||||
(ledger-schedule-scan-transactions ledger-schedule-file)))
|
(ledger-schedule-scan-transactions ledger-schedule-file)
|
||||||
|
early
|
||||||
|
horizon
|
||||||
|
(get-buffer "2013.ledger")))
|
||||||
|
|
||||||
|
|
||||||
(defun ledger-schedule-test-predict ()
|
(defun ledger-schedule-test-predict ()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue