rewrite project status checking logic

This commit is contained in:
petrucci4prez 2018-04-27 09:58:08 -04:00
parent 316844f512
commit 0ef5fe8dd1
2 changed files with 116 additions and 57 deletions

83
conf.el
View File

@ -437,11 +437,8 @@ that in turn are children of todoitems (discontinous project)"
:active
:done-incomplete
:undone-complete
:undone-closed
:done-unclosed
:invalid-todostate
:scheduled-project
:discontinous)
:scheduled-project)
"list of statuscodes to be used in assessing projects
Note they are listed in order of priority (eg items further
down the list override higher items")
@ -512,33 +509,65 @@ down the list override higher items")
(org-forward-heading-same-level 1 t)))
project-state))
(defmacro nd/is-project-keyword-status-p (top-keyword operator statuscode)
"tests if a project has toplevel heading of top-keyword and
child status equal to status code and returns keyword if
both are true"
`(if (and (equal ,keyword ,top-keyword)
(nd/compare-statuscodes ,operator (nd/descend-into-project) statuscode))
,keyword))
(defun nd/is-project-status-p (statuscode)
(let ((keyword (nd/is-project-p)))
(if keyword
(cond ((member keyword nd/project-invalid-todostates)
(if (nd/status= statuscode :invalid-todostate) keyword))
((equal keyword "HOLD") (if (nd/status= statuscode :held) keyword))
((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p)
(if (nd/status= statuscode :archivable) keyword)
(if (nd/status= statuscode :complete) keyword)))
(t (let ((child-statuscode (nd/descend-into-project)))
(cond ((equal keyword "DONE")
(case statuscode
;; projects closed more than 30 days ago
;; note CANCELLED overrides all subtasks/projects
(:archivable
(if (nd/is-archivable-heading-p)
;; TODO make my statuscode condition checker handle multiples
(if (and (nd/status= statuscode :archivable)
(nd/status= child-statuscode :archivable))
keyword)
(if (and (nd/status= statuscode :complete)
(nd/status= child-statuscode :complete))
keyword
(if (and (nd/status> child-statuscode :complete)
(nd/status= statuscode :done-incomplete))
keyword))))
((equal keyword "TODO")
(if (nd/status> child-statuscode :complete)
(if (nd/status= statuscode child-statuscode) keyword)
(if (nd/status= statuscode :undone-complete) keyword)))
(t (if (nd/status= statuscode child-statuscode) keyword)))))))))
(cond ((equal keyword "CANCELLED") keyword)
(t (nd/is-project-keyword-status-p "DONE" = :archivable)))))
;; projects closed less than 30 days ago
;; note CANCELLED overrides all subtasks/projects
(:complete
(if (not (nd/is-archivable-heading-p))
(cond ((equal keyword "CANCELLED") keyword)
(t (nd/is-project-keyword-status-p "DONE" = :complete)))))
;; projects with no waiting, held, or active components
(:stuck
(nd/is-project-keyword-status-p "TODO" = :stuck))
;; held projects
;; note toplevel HOLD overrides all subtasks/projects
(:held
(cond ((equal keyword "HOLD") keyword)
(t (nd/is-project-keyword-status-p "TODO" = :stuck))))
;; projects with at least one waiting component
(:waiting
(nd/is-project-keyword-status-p "TODO" = :waiting))
;; projects with at least one active component
(:active
(nd/is-project-keyword-status-p "TODO" = :active))
;; projects marked DONE but still have undone subtasks
(:done-incomplete
(nd/is-project-keyword-status-p "DONE" > :complete))
;; projects not marked DONE but all subtasks are done
(:undone-complete
(nd/is-project-keyword-status-p "TODO" < :stuck))
;; projects with invalid todo keywords
(:invalid-todostate
(if (member keyword nd/project-invalid-todostates) keyword))
;; projects with scheduled heading (only subtasks should be scheduled)
(:scheduled-project
(if (nd/is-scheduled-heading-p) keyword))))))
;; TODO we could clean this up with macros
(defun nd/skip-non-atomic-tasks ()

View File

@ -605,11 +605,8 @@ These are the building blocks for skip functions.
:active
:done-incomplete
:undone-complete
:undone-closed
:done-unclosed
:invalid-todostate
:scheduled-project
:discontinous)
:scheduled-project)
"list of statuscodes to be used in assessing projects
Note they are listed in order of priority (eg items further
down the list override higher items")
@ -680,33 +677,66 @@ These are the building blocks for skip functions.
(org-forward-heading-same-level 1 t)))
project-state))
(defmacro nd/is-project-keyword-status-p (top-keyword operator statuscode)
"tests if a project has toplevel heading of top-keyword and
child status equal to status code and returns keyword if
both are true"
`(if (and (equal ,keyword ,top-keyword)
(nd/compare-statuscodes ,operator (nd/descend-into-project) statuscode))
,keyword))
(defun nd/is-project-status-p (statuscode)
(let ((keyword (nd/is-project-p)))
(if keyword
(cond ((member keyword nd/project-invalid-todostates)
(if (nd/status= statuscode :invalid-todostate) keyword))
((equal keyword "HOLD") (if (nd/status= statuscode :held) keyword))
((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p)
(if (nd/status= statuscode :archivable) keyword)
(if (nd/status= statuscode :complete) keyword)))
(t (let ((child-statuscode (nd/descend-into-project)))
(cond ((equal keyword "DONE")
(case statuscode
;; projects closed more than 30 days ago
;; note CANCELLED overrides all subtasks/projects
(:archivable
(if (nd/is-archivable-heading-p)
;; TODO make my statuscode condition checker handle multiples
(if (and (nd/status= statuscode :archivable)
(nd/status= child-statuscode :archivable))
keyword)
(if (and (nd/status= statuscode :complete)
(nd/status= child-statuscode :complete))
keyword
(if (and (nd/status> child-statuscode :complete)
(nd/status= statuscode :done-incomplete))
keyword))))
((equal keyword "TODO")
(if (nd/status> child-statuscode :complete)
(if (nd/status= statuscode child-statuscode) keyword)
(if (nd/status= statuscode :undone-complete) keyword)))
(t (if (nd/status= statuscode child-statuscode) keyword)))))))))
(cond ((equal keyword "CANCELLED") keyword)
(t (nd/is-project-keyword-status-p "DONE" = :archivable)))))
;; projects closed less than 30 days ago
;; note CANCELLED overrides all subtasks/projects
(:complete
(if (not (nd/is-archivable-heading-p))
(cond ((equal keyword "CANCELLED") keyword)
(t (nd/is-project-keyword-status-p "DONE" = :complete)))))
;; projects with no waiting, held, or active components
(:stuck
(nd/is-project-keyword-status-p "TODO" = :stuck))
;; held projects
;; note toplevel HOLD overrides all subtasks/projects
(:held
(cond ((equal keyword "HOLD") keyword)
(t (nd/is-project-keyword-status-p "TODO" = :stuck))))
;; projects with at least one waiting component
(:waiting
(nd/is-project-keyword-status-p "TODO" = :waiting))
;; projects with at least one active component
(:active
(nd/is-project-keyword-status-p "TODO" = :active))
;; projects marked DONE but still have undone subtasks
(:done-incomplete
(nd/is-project-keyword-status-p "DONE" > :complete))
;; projects not marked DONE but all subtasks are done
(:undone-complete
(nd/is-project-keyword-status-p "TODO" < :stuck))
;; projects with invalid todo keywords
(:invalid-todostate
(if (member keyword nd/project-invalid-todostates) keyword))
;; projects with scheduled heading (only subtasks should be scheduled)
(:scheduled-project
(if (nd/is-scheduled-heading-p) keyword))))))
#+END_SRC
*** skip functions
These are the primary means we use to sort through tasks. Note that we could do this with