use keywords for statuscodes

This commit is contained in:
petrucci4prez 2018-04-27 07:52:05 -04:00
parent 3852c00842
commit 316844f512
2 changed files with 202 additions and 178 deletions

186
conf.el
View File

@ -267,6 +267,8 @@
(:endgroup) (:endgroup)
("#laptop" . ?L) ("#laptop" . ?L)
("#hood" . ?H) ("#hood" . ?H)
("WORK" . ?W)
("PERSONAL" . ?P)
("NOTE" . ?N) ("NOTE" . ?N)
("FLAGGED" . ??))) ("FLAGGED" . ??)))
@ -426,70 +428,85 @@ that in turn are children of todoitems (discontinous project)"
"projects cannot have these todostates") "projects cannot have these todostates")
;; project level testing ;; project level testing
(defconst nd/project-statuscodes
'(:archivable
:complete
:stuck
:held
:waiting
:active
:done-incomplete
:undone-complete
:undone-closed
:done-unclosed
:invalid-todostate
:scheduled-project
:discontinous)
"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")
(defmacro nd/compare-statuscodes (operator statuscode-1 statuscode-2)
"syntactic suger to compare statuscodes by position"
`(,operator (position ,statuscode-1 nd/project-statuscodes)
(position ,statuscode-2 nd/project-statuscodes)))
(defun nd/status< (statuscode-1 statuscode-2)
"returns t is statuscode-1 is lesser priority than statuscode-2"
(nd/compare-statuscodes < statuscode-1 statuscode-2))
(defun nd/status> (statuscode-1 statuscode-2)
"returns t is statuscode-1 is greater priority than statuscode-2"
(nd/compare-statuscodes > statuscode-1 statuscode-2))
(defun nd/status= (statuscode-1 statuscode-2)
"returns t is statuscode-1 is equal priority than statuscode-2"
(nd/compare-statuscodes = statuscode-1 statuscode-2))
(defun nd/descend-into-project () (defun nd/descend-into-project ()
"returns statuscode according to state of project: "returns statuscode of project and recursively descends into subprojects"
0: archivable (let ((project-state :archivable)
5: complete
10: stuck
20: held
30: waiting
40: active
50: invalid
This function works on an assumed order of precendence:
- we start by assuming all projects as complete (eg only DONE and CANCELLED)
- if project has any TODO (regardless of DONE or CANCELLED) it is stuck
- if project has any HOLD (regardless of DONE, CANCELLED, or TODO) it is held
- in the same manner WAITING means waiting project
- in the same manner, NEXT or scheduled means active.
- can also detect errors which override all
- anything higher than active breaks the recursion/tree walk
Using this scheme, we simply compare the magnitude of the statuscodes"
(let ((project-state 0)
(previous-point)) (previous-point))
(save-excursion (save-excursion
(setq previous-point (point)) (setq previous-point (point))
(outline-next-heading) (outline-next-heading)
(while (and (< project-state 40) ;; loop breaks if active or higher priority
;; note that all invalid statuscodes are higher
;; thus this function will only return the first
;; encountered error
(while (and (nd/status< project-state :active)
(> (point) previous-point)) (> (point) previous-point))
(let ((keyword (nd/is-todoitem-p))) (let ((keyword (nd/is-todoitem-p)))
(if keyword (if keyword
(let ((cur-state (let ((cur-state
(if (nd/heading-has-children) (if (nd/heading-has-children)
;; invalid todo states or scheduled project headers auto invalidate (cond ((member keyword nd/project-invalid-todostates) :invalid-todostate)
(cond ((member keyword nd/project-invalid-todostates) 50) ((nd/is-scheduled-heading-p) :scheduled-project)
((nd/is-scheduled-heading-p) 50) ((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p)
;; cancelled and hold work independent of everything underneath :archivable
((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p) 0 5)) :complete))
((equal keyword "HOLD") 20) ((equal keyword "HOLD") :held)
;; all other tests require a descent into the child project
(t (let ((child-statuscode (nd/descend-into-project))) (t (let ((child-statuscode (nd/descend-into-project)))
;; projects marked TODO should not be complete (cond ((equal keyword "TODO")
(cond ((equal keyword "TODO") (if (> child-statuscode 5) (if (nd/status> child-statuscode :complete)
child-statuscode 50)) child-statuscode
;; assume that all projects here are DONE :undone-complete))
;; first test if all children are archivable
(t (case child-statuscode (t (case child-statuscode
(5 5) (:complete :complete)
;; if this heading is archivable (:archivable (if (nd/is-archivable-heading-p)
;; then the entire project is archivable :archivable
;; else merely completed :complete))
(0 (if (nd/is-archivable-heading-p) 0 5)) (t (if (= child-statuscode :complete)
;; if children are completed but not archivable :complete
;; then the project is completed, otherwise :done-imcomplete))))))))
;; the project is marked DONE with incomplete (cond ((equal keyword "HOLD") :held)
;; subtasks and therefore invalid ((equal keyword "WAITING") :waiting)
(t (if (= child-statuscode 5) 5 50)))))))) ((equal keyword "NEXT") :active)
(cond ((equal keyword "HOLD") 20) ((and (equal keyword "TODO") (nd/is-scheduled-heading-p)) :active)
((equal keyword "WAITING") 30) ((equal keyword "TODO") :stuck)
((equal keyword "NEXT") 40) ((nd/is-archivable-heading-p) :archivable)
((and (equal keyword "TODO") (nd/is-scheduled-heading-p)) 40) (t :complete)))))
((equal keyword "TODO") 10) (if (nd/status> cur-state project-state)
((nd/is-archivable-heading-p) 0)
;; catchall means CANCELLED or DONE (complete)
(t 5)))))
(if (> cur-state project-state)
(setq project-state cur-state))))) (setq project-state cur-state)))))
(setq previous-point (point)) (setq previous-point (point))
(org-forward-heading-same-level 1 t))) (org-forward-heading-same-level 1 t)))
@ -498,35 +515,30 @@ Using this scheme, we simply compare the magnitude of the statuscodes"
(defun nd/is-project-status-p (statuscode) (defun nd/is-project-status-p (statuscode)
(let ((keyword (nd/is-project-p))) (let ((keyword (nd/is-project-p)))
(if keyword (if keyword
;; these first cases are determined entirely by the toplevel heading (cond ((member keyword nd/project-invalid-todostates)
;; if invalid keyword, t if we ask about 50 (if (nd/status= statuscode :invalid-todostate) keyword))
(cond ((member keyword nd/project-invalid-todostates) (if (= statuscode 50) keyword)) ((equal keyword "HOLD") (if (nd/status= statuscode :held) keyword))
;; if hold, t if we ask about 20
((equal keyword "HOLD") (if (= statuscode 20) keyword))
;; if cancelled, figure out if archivable
;; t if archivable and we ask 0 and t if not archivable and we ask 5
((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p) ((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p)
(if (= statuscode 0) keyword) (if (nd/status= statuscode :archivable) keyword)
(if (= statuscode 5) keyword))) (if (nd/status= statuscode :complete) keyword)))
;; all other cases need the statuscode from the subtasks below the heading
(t (let ((child-statuscode (nd/descend-into-project))) (t (let ((child-statuscode (nd/descend-into-project)))
;; if done, t if project is done and we ask about 0 (cond ((equal keyword "DONE")
;; or t if project is not done (>0) and we ask about 50
(if (equal keyword "DONE")
(if (nd/is-archivable-heading-p) (if (nd/is-archivable-heading-p)
(if (= statuscode child-statuscode 0) keyword) ;; TODO make my statuscode condition checker handle multiples
(if (= statuscode child-statuscode 5) (if (and (nd/status= statuscode :archivable)
(nd/status= child-statuscode :archivable))
keyword)
(if (and (nd/status= statuscode :complete)
(nd/status= child-statuscode :complete))
keyword keyword
(if (and (> child-statuscode 5) (= statuscode 50)) keyword))) (if (and (nd/status> child-statuscode :complete)
(nd/status= statuscode :done-incomplete))
;; if TODO then the subtasks must not be done (completed or archivable) keyword))))
(if (equal keyword "TODO") ((equal keyword "TODO")
(if (> child-statuscode 5) (if (nd/status> child-statuscode :complete)
(if (= statuscode child-statuscode) keyword) (if (nd/status= statuscode child-statuscode) keyword)
(if (= statuscode 50) keyword)) (if (nd/status= statuscode :undone-complete) keyword)))
;; all other queries are independent of heading (t (if (nd/status= statuscode child-statuscode) keyword)))))))))
;; t if children match the statuscode we ask
(if (= statuscode child-statuscode) keyword)))))))))
;; TODO we could clean this up with macros ;; TODO we could clean this up with macros
(defun nd/skip-non-atomic-tasks () (defun nd/skip-non-atomic-tasks ()
@ -655,33 +667,33 @@ Using this scheme, we simply compare the magnitude of the statuscodes"
,(nd/agenda-base-task-command "Held Project" ''nd/skip-non-held-project-tasks))) ,(nd/agenda-base-task-command "Held Project" ''nd/skip-non-held-project-tasks)))
("o" ("o"
"Project Overview" "Project Overview"
(,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Stuck" 10) (,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Stuck" :stuck)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Waiting" 30) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Waiting" :waiting)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Active" 40) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Active" :active)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Held" 20))) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Held" :held)))
("r" ("r"
"Refile and errors" "Refile and errors"
((tags "REFILE" ((tags "REFILE"
((org-agenda-overriding-header "Tasks to Refile")) ((org-agenda-overriding-header "Tasks to Refile"))
(org-tags-match-list-sublevels nil)) (org-tags-match-list-sublevels nil))
,(nd/agenda-base-task-command "Discontinous Project" ''nd/skip-non-discontinuous-project-tasks) ,(nd/agenda-base-task-command "Discontinous Project" ''nd/skip-non-discontinuous-project-tasks)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Unmarked Completed" 5) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Unmarked Completed" :complete)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/" "Invalid" 50) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/" "Invalid" :invalid-todostate)
;; ,(nd/agenda-base-task-command "Done But Not Closed" ''nd/skip-non-done-open-todoitems) ;; ,(nd/agenda-base-task-command "Done But Not Closed" ''nd/skip-non-done-open-todoitems)
;; ,(nd/agenda-base-task-command "Closed But Not Done" ''nd/skip-non-open-closed-todoitems) ;; ,(nd/agenda-base-task-command "Closed But Not Done" ''nd/skip-non-open-closed-todoitems)
)) ))
("s" ("s"
"Series projects" "Series projects"
(,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Active Series" 40) (,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Active Series" :active)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Empty Series" 5))) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Empty Series" :complete)))
("A" ("A"
"Archivable Tasks and Projects" "Archivable Tasks and Projects"
((tags "-NA-REFILE/" ((tags "-NA-REFILE/"
((org-agenda-overriding-header "Atomic Tasks to Archive") ((org-agenda-overriding-header "Atomic Tasks to Archive")
(org-agenda-skip-function 'nd/skip-non-archivable-atomic-tasks) (org-agenda-skip-function 'nd/skip-non-archivable-atomic-tasks)
(org-tags-match-list-sublevels nil))) (org-tags-match-list-sublevels nil)))
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Archivable Series" 0) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Archivable Series" :archivable)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC/" "Archivable" 0))))) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC/" "Archivable" :archivable)))))
(evil-define-key 'motion org-agenda-mode-map "T" 'nd/toggle-project-toplevel-display) (evil-define-key 'motion org-agenda-mode-map "T" 'nd/toggle-project-toplevel-display)

186
conf.org
View File

@ -414,6 +414,8 @@ I use tags for contexts (mostly). The "@" represents location contexts and a mut
(:endgroup) (:endgroup)
("#laptop" . ?L) ("#laptop" . ?L)
("#hood" . ?H) ("#hood" . ?H)
("WORK" . ?W)
("PERSONAL" . ?P)
("NOTE" . ?N) ("NOTE" . ?N)
("FLAGGED" . ??))) ("FLAGGED" . ??)))
@ -594,70 +596,85 @@ These are the building blocks for skip functions.
"projects cannot have these todostates") "projects cannot have these todostates")
;; project level testing ;; project level testing
(defconst nd/project-statuscodes
'(:archivable
:complete
:stuck
:held
:waiting
:active
:done-incomplete
:undone-complete
:undone-closed
:done-unclosed
:invalid-todostate
:scheduled-project
:discontinous)
"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")
(defmacro nd/compare-statuscodes (operator statuscode-1 statuscode-2)
"syntactic suger to compare statuscodes by position"
`(,operator (position ,statuscode-1 nd/project-statuscodes)
(position ,statuscode-2 nd/project-statuscodes)))
(defun nd/status< (statuscode-1 statuscode-2)
"returns t is statuscode-1 is lesser priority than statuscode-2"
(nd/compare-statuscodes < statuscode-1 statuscode-2))
(defun nd/status> (statuscode-1 statuscode-2)
"returns t is statuscode-1 is greater priority than statuscode-2"
(nd/compare-statuscodes > statuscode-1 statuscode-2))
(defun nd/status= (statuscode-1 statuscode-2)
"returns t is statuscode-1 is equal priority than statuscode-2"
(nd/compare-statuscodes = statuscode-1 statuscode-2))
(defun nd/descend-into-project () (defun nd/descend-into-project ()
"returns statuscode according to state of project: "returns statuscode of project and recursively descends into subprojects"
0: archivable (let ((project-state :archivable)
5: complete
10: stuck
20: held
30: waiting
40: active
50: invalid
This function works on an assumed order of precendence:
- we start by assuming all projects as complete (eg only DONE and CANCELLED)
- if project has any TODO (regardless of DONE or CANCELLED) it is stuck
- if project has any HOLD (regardless of DONE, CANCELLED, or TODO) it is held
- in the same manner WAITING means waiting project
- in the same manner, NEXT or scheduled means active.
- can also detect errors which override all
- anything higher than active breaks the recursion/tree walk
Using this scheme, we simply compare the magnitude of the statuscodes"
(let ((project-state 0)
(previous-point)) (previous-point))
(save-excursion (save-excursion
(setq previous-point (point)) (setq previous-point (point))
(outline-next-heading) (outline-next-heading)
(while (and (< project-state 40) ;; loop breaks if active or higher priority
;; note that all invalid statuscodes are higher
;; thus this function will only return the first
;; encountered error
(while (and (nd/status< project-state :active)
(> (point) previous-point)) (> (point) previous-point))
(let ((keyword (nd/is-todoitem-p))) (let ((keyword (nd/is-todoitem-p)))
(if keyword (if keyword
(let ((cur-state (let ((cur-state
(if (nd/heading-has-children) (if (nd/heading-has-children)
;; invalid todo states or scheduled project headers auto invalidate (cond ((member keyword nd/project-invalid-todostates) :invalid-todostate)
(cond ((member keyword nd/project-invalid-todostates) 50) ((nd/is-scheduled-heading-p) :scheduled-project)
((nd/is-scheduled-heading-p) 50) ((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p)
;; cancelled and hold work independent of everything underneath :archivable
((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p) 0 5)) :complete))
((equal keyword "HOLD") 20) ((equal keyword "HOLD") :held)
;; all other tests require a descent into the child project
(t (let ((child-statuscode (nd/descend-into-project))) (t (let ((child-statuscode (nd/descend-into-project)))
;; projects marked TODO should not be complete (cond ((equal keyword "TODO")
(cond ((equal keyword "TODO") (if (> child-statuscode 5) (if (nd/status> child-statuscode :complete)
child-statuscode 50)) child-statuscode
;; assume that all projects here are DONE :undone-complete))
;; first test if all children are archivable
(t (case child-statuscode (t (case child-statuscode
(5 5) (:complete :complete)
;; if this heading is archivable (:archivable (if (nd/is-archivable-heading-p)
;; then the entire project is archivable :archivable
;; else merely completed :complete))
(0 (if (nd/is-archivable-heading-p) 0 5)) (t (if (= child-statuscode :complete)
;; if children are completed but not archivable :complete
;; then the project is completed, otherwise :done-imcomplete))))))))
;; the project is marked DONE with incomplete (cond ((equal keyword "HOLD") :held)
;; subtasks and therefore invalid ((equal keyword "WAITING") :waiting)
(t (if (= child-statuscode 5) 5 50)))))))) ((equal keyword "NEXT") :active)
(cond ((equal keyword "HOLD") 20) ((and (equal keyword "TODO") (nd/is-scheduled-heading-p)) :active)
((equal keyword "WAITING") 30) ((equal keyword "TODO") :stuck)
((equal keyword "NEXT") 40) ((nd/is-archivable-heading-p) :archivable)
((and (equal keyword "TODO") (nd/is-scheduled-heading-p)) 40) (t :complete)))))
((equal keyword "TODO") 10) (if (nd/status> cur-state project-state)
((nd/is-archivable-heading-p) 0)
;; catchall means CANCELLED or DONE (complete)
(t 5)))))
(if (> cur-state project-state)
(setq project-state cur-state))))) (setq project-state cur-state)))))
(setq previous-point (point)) (setq previous-point (point))
(org-forward-heading-same-level 1 t))) (org-forward-heading-same-level 1 t)))
@ -666,35 +683,30 @@ These are the building blocks for skip functions.
(defun nd/is-project-status-p (statuscode) (defun nd/is-project-status-p (statuscode)
(let ((keyword (nd/is-project-p))) (let ((keyword (nd/is-project-p)))
(if keyword (if keyword
;; these first cases are determined entirely by the toplevel heading (cond ((member keyword nd/project-invalid-todostates)
;; if invalid keyword, t if we ask about 50 (if (nd/status= statuscode :invalid-todostate) keyword))
(cond ((member keyword nd/project-invalid-todostates) (if (= statuscode 50) keyword)) ((equal keyword "HOLD") (if (nd/status= statuscode :held) keyword))
;; if hold, t if we ask about 20
((equal keyword "HOLD") (if (= statuscode 20) keyword))
;; if cancelled, figure out if archivable
;; t if archivable and we ask 0 and t if not archivable and we ask 5
((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p) ((equal keyword "CANCELLED") (if (nd/is-archivable-heading-p)
(if (= statuscode 0) keyword) (if (nd/status= statuscode :archivable) keyword)
(if (= statuscode 5) keyword))) (if (nd/status= statuscode :complete) keyword)))
;; all other cases need the statuscode from the subtasks below the heading
(t (let ((child-statuscode (nd/descend-into-project))) (t (let ((child-statuscode (nd/descend-into-project)))
;; if done, t if project is done and we ask about 0 (cond ((equal keyword "DONE")
;; or t if project is not done (>0) and we ask about 50
(if (equal keyword "DONE")
(if (nd/is-archivable-heading-p) (if (nd/is-archivable-heading-p)
(if (= statuscode child-statuscode 0) keyword) ;; TODO make my statuscode condition checker handle multiples
(if (= statuscode child-statuscode 5) (if (and (nd/status= statuscode :archivable)
(nd/status= child-statuscode :archivable))
keyword)
(if (and (nd/status= statuscode :complete)
(nd/status= child-statuscode :complete))
keyword keyword
(if (and (> child-statuscode 5) (= statuscode 50)) keyword))) (if (and (nd/status> child-statuscode :complete)
(nd/status= statuscode :done-incomplete))
;; if TODO then the subtasks must not be done (completed or archivable) keyword))))
(if (equal keyword "TODO") ((equal keyword "TODO")
(if (> child-statuscode 5) (if (nd/status> child-statuscode :complete)
(if (= statuscode child-statuscode) keyword) (if (nd/status= statuscode child-statuscode) keyword)
(if (= statuscode 50) keyword)) (if (nd/status= statuscode :undone-complete) keyword)))
;; all other queries are independent of heading (t (if (nd/status= statuscode child-statuscode) keyword)))))))))
;; t if children match the statuscode we ask
(if (= statuscode child-statuscode) keyword)))))))))
#+END_SRC #+END_SRC
*** skip functions *** skip functions
These are the primary means we use to sort through tasks. Note that we could do this with These are the primary means we use to sort through tasks. Note that we could do this with
@ -832,33 +844,33 @@ tags in the custom commands section but I find this easier to maintain and possi
,(nd/agenda-base-task-command "Held Project" ''nd/skip-non-held-project-tasks))) ,(nd/agenda-base-task-command "Held Project" ''nd/skip-non-held-project-tasks)))
("o" ("o"
"Project Overview" "Project Overview"
(,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Stuck" 10) (,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Stuck" :stuck)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Waiting" 30) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Waiting" :waiting)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Active" 40) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Active" :active)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Held" 20))) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Held" :held)))
("r" ("r"
"Refile and errors" "Refile and errors"
((tags "REFILE" ((tags "REFILE"
((org-agenda-overriding-header "Tasks to Refile")) ((org-agenda-overriding-header "Tasks to Refile"))
(org-tags-match-list-sublevels nil)) (org-tags-match-list-sublevels nil))
,(nd/agenda-base-task-command "Discontinous Project" ''nd/skip-non-discontinuous-project-tasks) ,(nd/agenda-base-task-command "Discontinous Project" ''nd/skip-non-discontinuous-project-tasks)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Unmarked Completed" 5) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/!" "Unmarked Completed" :complete)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/" "Invalid" 50) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC-Project_Type=\"series\"/" "Invalid" :invalid-todostate)
;; ,(nd/agenda-base-task-command "Done But Not Closed" ''nd/skip-non-done-open-todoitems) ;; ,(nd/agenda-base-task-command "Done But Not Closed" ''nd/skip-non-done-open-todoitems)
;; ,(nd/agenda-base-task-command "Closed But Not Done" ''nd/skip-non-open-closed-todoitems) ;; ,(nd/agenda-base-task-command "Closed But Not Done" ''nd/skip-non-open-closed-todoitems)
)) ))
("s" ("s"
"Series projects" "Series projects"
(,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Active Series" 40) (,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Active Series" :active)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Empty Series" 5))) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Empty Series" :complete)))
("A" ("A"
"Archivable Tasks and Projects" "Archivable Tasks and Projects"
((tags "-NA-REFILE/" ((tags "-NA-REFILE/"
((org-agenda-overriding-header "Atomic Tasks to Archive") ((org-agenda-overriding-header "Atomic Tasks to Archive")
(org-agenda-skip-function 'nd/skip-non-archivable-atomic-tasks) (org-agenda-skip-function 'nd/skip-non-archivable-atomic-tasks)
(org-tags-match-list-sublevels nil))) (org-tags-match-list-sublevels nil)))
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Archivable Series" 0) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC+Project_Type=\"series\"/!" "Archivable Series" :archivable)
,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC/" "Archivable" 0))))) ,(nd/agenda-base-project-command "-NA-REFILE-ATOMIC/" "Archivable" :archivable)))))
#+END_SRC #+END_SRC
*** keymap *** keymap