From ce338e1fbe8d83a7206a0bb3f7b88b50c97a5b3e Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Thu, 22 Mar 2018 00:32:17 -0400 Subject: [PATCH 01/17] added atomic skip function --- conf.el | 116 +++++++++++++------------------------------------------ conf.org | 116 +++++++++++++------------------------------------------ 2 files changed, 54 insertions(+), 178 deletions(-) diff --git a/conf.el b/conf.el index 06b29b9..062dd40 100644 --- a/conf.el +++ b/conf.el @@ -365,7 +365,7 @@ (if nd/hide-scheduled-and-waiting-next-tasks "" " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-project-tasks) + (org-agenda-skip-function 'nd/skip-non-atomic-tasks) (org-agenda-todo-ignore-with-date 'all) (org-agenda-sorting-strategy '(category-keep)))) @@ -413,23 +413,9 @@ (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) -(defun nd/find-project-task () - "Move point to the parent (project) task if any" - (save-restriction - (widen) - (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) - ;; go up to parent heading (no error) - (while (org-up-heading-safe) - ;; in case the parent has no todo keyword, keep going - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - ;; when parent found, go there and return its position - (goto-char parent-task) - parent-task))) - -;; keep +;; functions to define headlings relative to project structure (or lack thereof) (defun nd/is-project-p () - "Any task with a todo keyword subtask" + "todo heading with a todo subheadings" (save-restriction (widen) (let ((has-subtask) @@ -444,63 +430,18 @@ (setq has-subtask t)))) (and is-a-task has-subtask)))) -;; old version -;; (defun nd/is-subtask-p () -;; "Any task with a todo keyword that is in a project subtree. -;; Callers of this function already widen the buffer view." -;; ;; go back up to heading -;; (let ((task (save-excursion (org-back-to-heading 'invisible-ok) -;; (point)))) - -;; (save-excursion -;; (nd/find-project-task) -;; ;; go up to parent heading -;; (if (equal (point) task) -;; nil -;; t)))) - - -;; (defun nd/is-subproject-p () -;; "Any task which is a subtask of another project" -;; (let ((is-subproject) -;; ;; is-a-task is true if it has a valid TODO keyword -;; (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) -;; (save-excursion -;; ;; loop up through headings until we encounter a task or the top level -;; (while (and (not is-subproject) (org-up-heading-safe)) -;; (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) -;; (setq is-subproject t)))) -;; (and is-a-task is-subproject))) - (defun nd/is-subtask-p () - "Any task with a todo keyword that is in a project subtree. -Callers of this function already widen the buffer view." - ;; go back up to heading - (let ((task (save-excursion (org-back-to-heading 'invisible-ok) - (point)))) + "todo heading that is part of a project" + (if (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (let ((is-subproject)) + (save-excursion + (while (and (not is-subproject) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq is-subproject t)))) + is-subproject))) - (save-excursion - (nd/find-project-task) - ;; go up to parent heading - (if (equal (point) task) - nil - t)))) -;; (defun nd/find-project-task () -;; "Move point to the parent (project) task if any" -;; (save-restriction -;; (widen) -;; (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) -;; ;; go up to parent heading (no error) -;; (while (org-up-heading-safe) -;; ;; in case the parent has no todo keyword, keep going -;; (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) -;; (setq parent-task (point)))) -;; ;; when parent found, go there and return its position -;; (goto-char parent-task) -;; parent-task))) - -(defun nd/is-atomic-task-p () - "Any task with a todo keyword and no subtask" +(defun nd/is-atomic-p () + "todo heading with no todo subheadings" (save-restriction (widen) (let ((has-subtask) @@ -514,21 +455,18 @@ Callers of this function already widen the buffer view." (when (member (org-get-todo-state) org-todo-keywords-1) (setq has-subtask t)))) (and is-a-task (not has-subtask))))) -;; (defun nd/list-sublevels-for-projects-indented () -;; "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. -;; This is normally used by skipping functions where this variable is already local to the agenda." -;; (if (marker-buffer org-agenda-restrict-begin) -;; (setq org-tags-match-list-sublevels 'indented) -;; (setq org-tags-match-list-sublevels nil)) -;; nil) -;; (defun nd/list-sublevels-for-projects () -;; "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. -;; This is normally used by skipping functions where this variable is already local to the agenda." -;; (if (marker-buffer org-agenda-restrict-begin) -;; (setq org-tags-match-list-sublevels t) -;; (setq org-tags-match-list-sublevels nil)) -;; nil) +;; functions to test tasks (which are "atomic") +;; (defun nd/is-scheduled-p () +;; "task with scheduled property" +;; ((org-entry-get nil "SCHEDULED"))) + +;; task skip functions +(defun nd/skip-non-atomic-tasks () + (save-restriction + (widen) + (if (not (nd/is-atomic-p)) + (save-excursion (or (outline-next-heading) (point-max)))))) (defvar nd/hide-scheduled-and-waiting-next-tasks t) @@ -643,7 +581,7 @@ Callers of this function already widen the buffer view." (cond ((nd/is-project-p) nil) - ((and (nd/is-subtask-p) (not (nd/is-atomic-task-p))) + ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) nil) (t subtree-end)))) @@ -656,7 +594,7 @@ Skip project and sub-project tasks, habits, and project related tasks." (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond - ((nd/is-atomic-task-p) + ((nd/is-atomic-p) nil) (t next-headline))))) @@ -687,7 +625,7 @@ Skip project and sub-project tasks, habits, and project related tasks." next-headline) ((nd/is-project-p) next-headline) - ((and (nd/is-atomic-task-p) (not (nd/is-subtask-p))) + ((and (nd/is-atomic-p) (not (nd/is-subtask-p))) next-headline) (t nil))))) diff --git a/conf.org b/conf.org index fd0cac7..3e859a1 100644 --- a/conf.org +++ b/conf.org @@ -542,7 +542,7 @@ TODO: add meeting template as scheduled+action item thing (if nd/hide-scheduled-and-waiting-next-tasks "" " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-project-tasks) + (org-agenda-skip-function 'nd/skip-non-atomic-tasks) (org-agenda-todo-ignore-with-date 'all) (org-agenda-sorting-strategy '(category-keep)))) @@ -595,23 +595,9 @@ TODO: add meeting template as scheduled+action item thing #+END_SRC *** filtering functions #+BEGIN_SRC emacs-lisp - (defun nd/find-project-task () - "Move point to the parent (project) task if any" - (save-restriction - (widen) - (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) - ;; go up to parent heading (no error) - (while (org-up-heading-safe) - ;; in case the parent has no todo keyword, keep going - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - ;; when parent found, go there and return its position - (goto-char parent-task) - parent-task))) - - ;; keep + ;; functions to define headlings relative to project structure (or lack thereof) (defun nd/is-project-p () - "Any task with a todo keyword subtask" + "todo heading with a todo subheadings" (save-restriction (widen) (let ((has-subtask) @@ -626,63 +612,18 @@ TODO: add meeting template as scheduled+action item thing (setq has-subtask t)))) (and is-a-task has-subtask)))) - ;; old version - ;; (defun nd/is-subtask-p () - ;; "Any task with a todo keyword that is in a project subtree. - ;; Callers of this function already widen the buffer view." - ;; ;; go back up to heading - ;; (let ((task (save-excursion (org-back-to-heading 'invisible-ok) - ;; (point)))) - - ;; (save-excursion - ;; (nd/find-project-task) - ;; ;; go up to parent heading - ;; (if (equal (point) task) - ;; nil - ;; t)))) - - - ;; (defun nd/is-subproject-p () - ;; "Any task which is a subtask of another project" - ;; (let ((is-subproject) - ;; ;; is-a-task is true if it has a valid TODO keyword - ;; (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - ;; (save-excursion - ;; ;; loop up through headings until we encounter a task or the top level - ;; (while (and (not is-subproject) (org-up-heading-safe)) - ;; (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - ;; (setq is-subproject t)))) - ;; (and is-a-task is-subproject))) - (defun nd/is-subtask-p () - "Any task with a todo keyword that is in a project subtree. - Callers of this function already widen the buffer view." - ;; go back up to heading - (let ((task (save-excursion (org-back-to-heading 'invisible-ok) - (point)))) + "todo heading that is part of a project" + (if (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (let ((is-subproject)) + (save-excursion + (while (and (not is-subproject) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq is-subproject t)))) + is-subproject))) - (save-excursion - (nd/find-project-task) - ;; go up to parent heading - (if (equal (point) task) - nil - t)))) - ;; (defun nd/find-project-task () - ;; "Move point to the parent (project) task if any" - ;; (save-restriction - ;; (widen) - ;; (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) - ;; ;; go up to parent heading (no error) - ;; (while (org-up-heading-safe) - ;; ;; in case the parent has no todo keyword, keep going - ;; (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - ;; (setq parent-task (point)))) - ;; ;; when parent found, go there and return its position - ;; (goto-char parent-task) - ;; parent-task))) - - (defun nd/is-atomic-task-p () - "Any task with a todo keyword and no subtask" + (defun nd/is-atomic-p () + "todo heading with no todo subheadings" (save-restriction (widen) (let ((has-subtask) @@ -696,21 +637,18 @@ TODO: add meeting template as scheduled+action item thing (when (member (org-get-todo-state) org-todo-keywords-1) (setq has-subtask t)))) (and is-a-task (not has-subtask))))) - ;; (defun nd/list-sublevels-for-projects-indented () - ;; "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - ;; This is normally used by skipping functions where this variable is already local to the agenda." - ;; (if (marker-buffer org-agenda-restrict-begin) - ;; (setq org-tags-match-list-sublevels 'indented) - ;; (setq org-tags-match-list-sublevels nil)) - ;; nil) - ;; (defun nd/list-sublevels-for-projects () - ;; "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - ;; This is normally used by skipping functions where this variable is already local to the agenda." - ;; (if (marker-buffer org-agenda-restrict-begin) - ;; (setq org-tags-match-list-sublevels t) - ;; (setq org-tags-match-list-sublevels nil)) - ;; nil) + ;; functions to test tasks (which are "atomic") + ;; (defun nd/is-scheduled-p () + ;; "task with scheduled property" + ;; ((org-entry-get nil "SCHEDULED"))) + + ;; task skip functions + (defun nd/skip-non-atomic-tasks () + (save-restriction + (widen) + (if (not (and ((nd/is-atomic-p) (not (nd/is-subtask-p))))) + (save-excursion (or (outline-next-heading) (point-max)))))) (defvar nd/hide-scheduled-and-waiting-next-tasks t) @@ -825,7 +763,7 @@ TODO: add meeting template as scheduled+action item thing (cond ((nd/is-project-p) nil) - ((and (nd/is-subtask-p) (not (nd/is-atomic-task-p))) + ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) nil) (t subtree-end)))) @@ -838,7 +776,7 @@ TODO: add meeting template as scheduled+action item thing (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond - ((nd/is-atomic-task-p) + ((nd/is-atomic-p) nil) (t next-headline))))) @@ -869,7 +807,7 @@ TODO: add meeting template as scheduled+action item thing next-headline) ((nd/is-project-p) next-headline) - ((and (nd/is-atomic-task-p) (not (nd/is-subtask-p))) + ((and (nd/is-atomic-p) (not (nd/is-subtask-p))) next-headline) (t nil))))) From c466eb11deb62dc02991ba72cb0196621f63a56d Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Thu, 22 Mar 2018 23:32:11 -0400 Subject: [PATCH 02/17] add some psuedocode --- conf.el | 4 +-- conf.org | 106 +++++++++++++++++-------------------------------------- 2 files changed, 35 insertions(+), 75 deletions(-) diff --git a/conf.el b/conf.el index 062dd40..6a9ddf1 100644 --- a/conf.el +++ b/conf.el @@ -226,7 +226,7 @@ (load "ess-site") (setq ess-history-file "session.Rhistory") (setq ess-history-directory - (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) + (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) (setq org-log-done t) (setq org-src-window-setup 'current-window) @@ -465,7 +465,7 @@ (defun nd/skip-non-atomic-tasks () (save-restriction (widen) - (if (not (nd/is-atomic-p)) + (if (not (and ((nd/is-atomic-p) (not (nd/is-subtask-p))))) (save-excursion (or (outline-next-heading) (point-max)))))) (defvar nd/hide-scheduled-and-waiting-next-tasks t) diff --git a/conf.org b/conf.org index 3e859a1..c93002b 100644 --- a/conf.org +++ b/conf.org @@ -566,7 +566,6 @@ TODO: add meeting template as scheduled+action item thing (tags-todo "-NA-CANCELLED/!" ((org-agenda-overriding-header "Stuck Projects") (org-agenda-skip-function 'nd/skip-non-stuck-projects) - (org-agenda-skip-function 'nd/skip-non-blocked-projects) (org-agenda-sorting-strategy '(category-keep)))) (tags-todo "-NA-HOLD-CANCELLED/!" @@ -594,6 +593,16 @@ TODO: add meeting template as scheduled+action item thing (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) #+END_SRC *** filtering functions +some definitions: +- task: todo heading with no todo headings beneath it +- project: todo heading with tasks or other project in subtree +- subtask: task that is part of a project +- subproject: project that is part of another project +- atomic task: task that is not part of a project +- project order: quantifies the degree of project nesting. + - First order projects have only subtasks + - Second order projects have subtasks or first order subprojects + - etc #+BEGIN_SRC emacs-lisp ;; functions to define headlings relative to project structure (or lack thereof) (defun nd/is-project-p () @@ -643,6 +652,8 @@ TODO: add meeting template as scheduled+action item thing ;; "task with scheduled property" ;; ((org-entry-get nil "SCHEDULED"))) + ;; org-forward-heading-same-level + ;; task skip functions (defun nd/skip-non-atomic-tasks () (save-restriction @@ -659,60 +670,8 @@ TODO: add meeting template as scheduled+action item thing (org-agenda-redo)) (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) - ;; this skip function seems inefficient, it looks like we are skipping one headline at a time - ;; but searching for NEXT in the entire subtree - ;; can I do better? - (defun nd/skip-stuck-projects () - "Skip trees that are not stuck projects" - ;; save narrow buffer state - (save-restriction - ;; widen to see the entire buffer - (widen) - ;; define next-headline as either the next headline or the end of the buffer - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - ;; if headline has subtasks - (if (nd/is-project-p) - ;; define subtree-end as the end of the subtree - ;; initialize has-next with nil - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - ;; save where we are pointing - (save-excursion - ;; go forward one line - (forward-line 1) - ;; while loop which continues if - ;; - has-next is nil - ;; - we are not at the end of the subtree - ;; - there is no NEXT between here and the subtree end - - ;; this is a loop because there could be multiple NEXT tasks (obviously) - ;; the regex search moves the point to the end of the first found NEXT - ;; relative to the start point position - ;; once it gets to the end of the subtree it returns nil and the loop breaks - (while (and (not has-next) - (< (point) subtree-end) - (re-search-forward "^\\*+ NEXT " subtree-end t)) - ;; if WAITING is not in tag list - ;; i guess this is here because if the loop finds next - ;; and the NEXT task also has WAITING (which it would need to inherit - ;; because WAITING and NEXT are mutully exclusive) then we keep looping - - ;; so the Bernt defined stuck projects as those which have WAITING tasks - ;; that override a NEXT subtask - (unless (member "WAITING" (org-get-tags-at)) - ;; set has-next to true - (setq has-next t)))) - ;; if we have a next task, set to nil (eg don't skip) - (if has-next - nil - ;; if no next task, skip to next headline - next-headline)) ; a stuck project, has subtasks but no next task - ;; don't skip if not a project - nil)))) - (defun nd/skip-non-stuck-projects () "Skip trees that are not stuck projects" - ;; (nd/list-sublevels-for-projects-indented) (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) @@ -731,27 +690,28 @@ TODO: add meeting template as scheduled+action item thing nil)) ; a stuck project, has subtasks but no next task next-headline)))) - (defun nd/skip-non-blocked-projects () - "Skip trees that are not stuck projects" - ;; (nd/list-sublevels-for-projects-indented) - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (nd/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) - (< (point) subtree-end) - (re-search-forward "^\\*+ WAITING " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) + ;; project test functions + ;; is state + ;; if project + ;; if order = 1 + ;; return (state is true) + ;; else order > 1 + ;; call is state (recursive) + ;; else if task + ;; return (state is true) + ;; note: this needs to iterate through lines + ;; (defun nd/skip-non-stuck-projects () + ;; goto next headline + ;; if project + ;; if project order 1 + ;; if it has NEXT, WAITING, HOLD, or a scheduled task + ;; then skip (return end of subtree) + ;; else stuck project, return nil + ;; else (order > 1) + ;; descend into project (recursion) + ;; skip (either an atomic task or non-todo, return next heading) + ;; ) (defun nd/skip-non-projects () "Skip trees that are not projects" From a9956a4e850246d01ceec85849ee54865f834445 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sat, 24 Mar 2018 00:50:01 -0400 Subject: [PATCH 03/17] added some small helper functions --- conf.el | 182 +++++++++++++++++++++---------------------------------- conf.org | 85 ++++++++++++++------------ 2 files changed, 117 insertions(+), 150 deletions(-) diff --git a/conf.el b/conf.el index 6a9ddf1..1355777 100644 --- a/conf.el +++ b/conf.el @@ -226,7 +226,7 @@ (load "ess-site") (setq ess-history-file "session.Rhistory") (setq ess-history-directory - (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) + (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) (setq org-log-done t) (setq org-src-window-setup 'current-window) @@ -389,7 +389,6 @@ (tags-todo "-NA-CANCELLED/!" ((org-agenda-overriding-header "Stuck Projects") (org-agenda-skip-function 'nd/skip-non-stuck-projects) - (org-agenda-skip-function 'nd/skip-non-blocked-projects) (org-agenda-sorting-strategy '(category-keep)))) (tags-todo "-NA-HOLD-CANCELLED/!" @@ -414,53 +413,50 @@ (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) ;; functions to define headlings relative to project structure (or lack thereof) -(defun nd/is-project-p () - "todo heading with a todo subheadings" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task has-subtask)))) +(defun nd/is-todoitem-p () + "return t if headline has valid todo keyword" + (member (nth 2 (org-heading-components)) org-todo-keywords-1)) -(defun nd/is-subtask-p () - "todo heading that is part of a project" - (if (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (let ((is-subproject)) +(defun nd/todoitem-has-children () + "returns t if heading is a todoitem and has todoitems in its subtree" + (if (nd/is-todoitem-p) + (let ((has-children) + (subtree-end (save-excursion (org-end-of-subtree t)))) (save-excursion - (while (and (not is-subproject) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq is-subproject t)))) - is-subproject))) + (outline-next-heading) + (while (and (not has-children) + (< (point) subtree-end)) + (when (nd/is-todoitem-p) + (setq has-children t) + (outline-next-heading)))) + has-children))) -(defun nd/is-atomic-p () - "todo heading with no todo subheadings" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task (not has-subtask))))) +(defun nd/todoitem-has-parent () + "returns t if heading is a todoitem that is in the subtree of another todoitem" + (if (nd/is-todoitem-p) + (let ((has-parent)) + (save-excursion + (while (and (not has-parent) (org-up-heading-safe)) + (when (nd/is-todoitem-p) + (setq has-parent t)))) + has-parent))) +(defun nd/is-project-p () + (nd/todoitem-has-children)) + +(defun nd/is-task-p () + (and (nd/is-todoitem-p) (not nd/todoitem-has-children))) + +(defun nd/is-atomic-task-p () + (and (nd/is-task-p) (not (nd/todoitem-has-parent)))) + ;; functions to test tasks (which are "atomic") ;; (defun nd/is-scheduled-p () ;; "task with scheduled property" ;; ((org-entry-get nil "SCHEDULED"))) +;; org-forward-heading-same-level + ;; task skip functions (defun nd/skip-non-atomic-tasks () (save-restriction @@ -477,60 +473,8 @@ (org-agenda-redo)) (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) -;; this skip function seems inefficient, it looks like we are skipping one headline at a time -;; but searching for NEXT in the entire subtree -;; can I do better? -(defun nd/skip-stuck-projects () - "Skip trees that are not stuck projects" - ;; save narrow buffer state - (save-restriction - ;; widen to see the entire buffer - (widen) - ;; define next-headline as either the next headline or the end of the buffer - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - ;; if headline has subtasks - (if (nd/is-project-p) - ;; define subtree-end as the end of the subtree - ;; initialize has-next with nil - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - ;; save where we are pointing - (save-excursion - ;; go forward one line - (forward-line 1) - ;; while loop which continues if - ;; - has-next is nil - ;; - we are not at the end of the subtree - ;; - there is no NEXT between here and the subtree end - - ;; this is a loop because there could be multiple NEXT tasks (obviously) - ;; the regex search moves the point to the end of the first found NEXT - ;; relative to the start point position - ;; once it gets to the end of the subtree it returns nil and the loop breaks - (while (and (not has-next) - (< (point) subtree-end) - (re-search-forward "^\\*+ NEXT " subtree-end t)) - ;; if WAITING is not in tag list - ;; i guess this is here because if the loop finds next - ;; and the NEXT task also has WAITING (which it would need to inherit - ;; because WAITING and NEXT are mutully exclusive) then we keep looping - - ;; so the Bernt defined stuck projects as those which have WAITING tasks - ;; that override a NEXT subtask - (unless (member "WAITING" (org-get-tags-at)) - ;; set has-next to true - (setq has-next t)))) - ;; if we have a next task, set to nil (eg don't skip) - (if has-next - nil - ;; if no next task, skip to next headline - next-headline)) ; a stuck project, has subtasks but no next task - ;; don't skip if not a project - nil)))) - (defun nd/skip-non-stuck-projects () "Skip trees that are not stuck projects" - ;; (nd/list-sublevels-for-projects-indented) (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) @@ -549,27 +493,41 @@ nil)) ; a stuck project, has subtasks but no next task next-headline)))) -(defun nd/skip-non-blocked-projects () - "Skip trees that are not stuck projects" - ;; (nd/list-sublevels-for-projects-indented) - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (nd/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) - (< (point) subtree-end) - (re-search-forward "^\\*+ WAITING " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) +;; project test functions +;; is state +;; if project +;; if order = 1 +;; return (state is true) +;; else order > 1 +;; call is state (recursive) +;; else if task +;; return (state is true) +;; note: this needs to iterate through lines +(defun nd/is-active-project-p () + "return true if project has at least one +NEXT/scheduled task or active subproject" + ;; if not a project then don't bother + (if (nd/is-project-p) + (let (((subtree-end (save-excursion (org-end-of-subtree t)))) + (is-active)) + (save-excursion + (while (and (not is-active) + (< (point) subtree-end)) + (outline-heading-next) + (cond ((nd/is-active-task-p) (setq is-active t)) + ((nd/is-active-project-p) (setq is-active)))))))) +;; (defun nd/skip-non-stuck-projects () + ;; goto next headline + ;; if project + ;; if project order 1 + ;; if it has NEXT, WAITING, HOLD, or a scheduled task + ;; then skip (return end of subtree) + ;; else stuck project, return nil + ;; else (order > 1) + ;; descend into project (recursion) + ;; skip (either an atomic task or non-todo, return next heading) +;; ) (defun nd/skip-non-projects () "Skip trees that are not projects" diff --git a/conf.org b/conf.org index c93002b..509d415 100644 --- a/conf.org +++ b/conf.org @@ -594,6 +594,7 @@ TODO: add meeting template as scheduled+action item thing #+END_SRC *** filtering functions some definitions: +- todoitem: heading with todo state - task: todo heading with no todo headings beneath it - project: todo heading with tasks or other project in subtree - subtask: task that is part of a project @@ -605,48 +606,43 @@ some definitions: - etc #+BEGIN_SRC emacs-lisp ;; functions to define headlings relative to project structure (or lack thereof) - (defun nd/is-project-p () - "todo heading with a todo subheadings" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task has-subtask)))) + (defun nd/is-todoitem-p () + "return t if headline has valid todo keyword" + (member (nth 2 (org-heading-components)) org-todo-keywords-1)) - (defun nd/is-subtask-p () - "todo heading that is part of a project" - (if (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (let ((is-subproject)) + (defun nd/todoitem-has-children () + "returns t if heading is a todoitem and has todoitems in its subtree" + (if (nd/is-todoitem-p) + (let ((has-children) + (subtree-end (save-excursion (org-end-of-subtree t)))) (save-excursion - (while (and (not is-subproject) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq is-subproject t)))) - is-subproject))) + (outline-next-heading) + (while (and (not has-children) + (< (point) subtree-end)) + (when (nd/is-todoitem-p) + (setq has-children t) + (outline-next-heading)))) + has-children))) - (defun nd/is-atomic-p () - "todo heading with no todo subheadings" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (forward-line 1) - (while (and (not has-subtask) - (< (point) subtree-end) - (re-search-forward "^\*+ " subtree-end t)) - (when (member (org-get-todo-state) org-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task (not has-subtask))))) + (defun nd/todoitem-has-parent () + "returns t if heading is a todoitem that is in the subtree of another todoitem" + (if (nd/is-todoitem-p) + (let ((has-parent)) + (save-excursion + (while (and (not has-parent) (org-up-heading-safe)) + (when (nd/is-todoitem-p) + (setq has-parent t)))) + has-parent))) + (defun nd/is-project-p () + (nd/todoitem-has-children)) + + (defun nd/is-task-p () + (and (nd/is-todoitem-p) (not nd/todoitem-has-children))) + + (defun nd/is-atomic-task-p () + (and (nd/is-task-p) (not (nd/todoitem-has-parent)))) + ;; functions to test tasks (which are "atomic") ;; (defun nd/is-scheduled-p () ;; "task with scheduled property" @@ -700,6 +696,19 @@ some definitions: ;; else if task ;; return (state is true) ;; note: this needs to iterate through lines + (defun nd/is-active-project-p () + "return true if project has at least one + NEXT/scheduled task or active subproject" + ;; if not a project then don't bother + (if (nd/is-project-p) + (let (((subtree-end (save-excursion (org-end-of-subtree t)))) + (is-active)) + (save-excursion + (while (and (not is-active) + (< (point) subtree-end)) + (outline-heading-next) + (cond ((nd/is-active-task-p) (setq is-active t)) + ((nd/is-active-project-p) (setq is-active)))))))) ;; (defun nd/skip-non-stuck-projects () ;; goto next headline From 231042d8e4311c1daf6286fdffeb4bd5f92a0ecf Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sat, 24 Mar 2018 18:13:54 -0400 Subject: [PATCH 04/17] added recursive active project function --- conf.el | 128 +++++++++++++++++++++++++++++++++++------------------- conf.org | 130 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 167 insertions(+), 91 deletions(-) diff --git a/conf.el b/conf.el index 1355777..edee8df 100644 --- a/conf.el +++ b/conf.el @@ -412,51 +412,89 @@ (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) -;; functions to define headlings relative to project structure (or lack thereof) (defun nd/is-todoitem-p () - "return t if headline has valid todo keyword" - (member (nth 2 (org-heading-components)) org-todo-keywords-1)) + "return todo keyword if present in headline +(which defines the heading as a todoitem) +this is used to both test if a heading is a todoitem +and retrieve the keyword" + (let ((keyword (nth 2 (org-heading-components)))) + (if (member keyword org-todo-keywords-1) + keyword))) -(defun nd/todoitem-has-children () - "returns t if heading is a todoitem and has todoitems in its subtree" - (if (nd/is-todoitem-p) - (let ((has-children) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (save-excursion - (outline-next-heading) - (while (and (not has-children) - (< (point) subtree-end)) - (when (nd/is-todoitem-p) - (setq has-children t) - (outline-next-heading)))) - has-children))) +(defun nd/heading-has-children () + "returns t if heading has todoitems in its subtree" + (let ((has-children) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (save-excursion + (outline-next-heading) + (while (and (not has-children) + (< (point) subtree-end)) + (when (nd/is-todoitem-p) + (setq has-children t) + (outline-next-heading)))) + has-children)) -(defun nd/todoitem-has-parent () - "returns t if heading is a todoitem that is in the subtree of another todoitem" - (if (nd/is-todoitem-p) - (let ((has-parent)) - (save-excursion - (while (and (not has-parent) (org-up-heading-safe)) - (when (nd/is-todoitem-p) - (setq has-parent t)))) - has-parent))) +(defun nd/heading-has-parent () + "returns t if heading is in the subtree of a todoitem" + (let ((has-parent)) + (save-excursion + (while (and (not has-parent) (org-up-heading-safe)) + (when (nd/is-todoitem-p) + (setq has-parent t)))) + has-parent)) (defun nd/is-project-p () - (nd/todoitem-has-children)) + "return todo keyword if heading is todoitem and has children" + (and (nd/heading-has-children) + (nd/is-todoitem-p))) (defun nd/is-task-p () - (and (nd/is-todoitem-p) (not nd/todoitem-has-children))) + "return todo keyword if heading is todoitem with no children" + (and (not (nd/heading-has-children)) + (nd/is-todoitem-p))) (defun nd/is-atomic-task-p () - (and (nd/is-task-p) (not (nd/todoitem-has-parent)))) + "return todo keyword if heading is task with no parents" + (and (not (nd/heading-has-parent)) + (nd/is-task-p))) -;; functions to test tasks (which are "atomic") -;; (defun nd/is-scheduled-p () -;; "task with scheduled property" -;; ((org-entry-get nil "SCHEDULED"))) +(defun nd/is-scheduled-heading-p () + "return timestamp if headline is scheduled" + (org-entry-get nil "SCHEDULED")) + +(defun nd/is-active-task-p () + "return keyword if task is either NEXT or scheduled" + (let ((keyword (nd/is-task-p))) + (if (or (equal keyword "NEXT") (nd/is-scheduled-heading-p)) + keyword))) + +(defun nd/is-blocked-task-p () + "return keyword if task is WAITING" + (equal (nd/is-task-p) "WAITING")) ;; org-forward-heading-same-level +;; project level testing +(defun nd/is-active-project-p () + "return keyword if project has at least one +active task or project" + (let ((keyword (nd/is-project-p))) + (if keyword + (let ((found-active) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (save-excursion + (outline-next-heading) + (while (and (not found-active) + (< (point) subtree-end)) + (when (or (nd/is-active-project-p) (nd/is-active-task-p)) + (setq found-active t)) + ;; TODO; this is not very efficient as we test for project twice + (if (nd/is-project-p) + (org-forward-heading-same-level 1 t) + (outline-next-heading)))) + (and found-active + keyword))))) + ;; task skip functions (defun nd/skip-non-atomic-tasks () (save-restriction @@ -503,19 +541,19 @@ ;; else if task ;; return (state is true) ;; note: this needs to iterate through lines -(defun nd/is-active-project-p () - "return true if project has at least one -NEXT/scheduled task or active subproject" - ;; if not a project then don't bother - (if (nd/is-project-p) - (let (((subtree-end (save-excursion (org-end-of-subtree t)))) - (is-active)) - (save-excursion - (while (and (not is-active) - (< (point) subtree-end)) - (outline-heading-next) - (cond ((nd/is-active-task-p) (setq is-active t)) - ((nd/is-active-project-p) (setq is-active)))))))) +;; (defun nd/is-active-project-p () +;; "return true if project has at least one +;; NEXT/scheduled task or active subproject" +;; ;; if not a project then don't bother +;; (if (nd/is-project-p) +;; (let (((subtree-end (save-excursion (org-end-of-subtree t)))) +;; (is-active)) +;; (save-excursion +;; (while (and (not is-active) +;; (< (point) subtree-end)) +;; (outline-heading-next) +;; (cond ((nd/is-active-task-p) (setq is-active t)) +;; ((nd/is-active-project-p) (setq is-active)))))))) ;; (defun nd/skip-non-stuck-projects () ;; goto next headline diff --git a/conf.org b/conf.org index 509d415..03fc3af 100644 --- a/conf.org +++ b/conf.org @@ -592,7 +592,7 @@ TODO: add meeting template as scheduled+action item thing (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) #+END_SRC -*** filtering functions +*** COMMENT filtering functions some definitions: - todoitem: heading with todo state - task: todo heading with no todo headings beneath it @@ -605,51 +605,89 @@ some definitions: - Second order projects have subtasks or first order subprojects - etc #+BEGIN_SRC emacs-lisp - ;; functions to define headlings relative to project structure (or lack thereof) (defun nd/is-todoitem-p () - "return t if headline has valid todo keyword" - (member (nth 2 (org-heading-components)) org-todo-keywords-1)) + "return todo keyword if present in headline + (which defines the heading as a todoitem) + this is used to both test if a heading is a todoitem + and retrieve the keyword" + (let ((keyword (nth 2 (org-heading-components)))) + (if (member keyword org-todo-keywords-1) + keyword))) - (defun nd/todoitem-has-children () - "returns t if heading is a todoitem and has todoitems in its subtree" - (if (nd/is-todoitem-p) - (let ((has-children) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (save-excursion - (outline-next-heading) - (while (and (not has-children) - (< (point) subtree-end)) - (when (nd/is-todoitem-p) - (setq has-children t) - (outline-next-heading)))) - has-children))) + (defun nd/heading-has-children () + "returns t if heading has todoitems in its subtree" + (let ((has-children) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (save-excursion + (outline-next-heading) + (while (and (not has-children) + (< (point) subtree-end)) + (when (nd/is-todoitem-p) + (setq has-children t) + (outline-next-heading)))) + has-children)) - (defun nd/todoitem-has-parent () - "returns t if heading is a todoitem that is in the subtree of another todoitem" - (if (nd/is-todoitem-p) - (let ((has-parent)) - (save-excursion - (while (and (not has-parent) (org-up-heading-safe)) - (when (nd/is-todoitem-p) - (setq has-parent t)))) - has-parent))) + (defun nd/heading-has-parent () + "returns t if heading is in the subtree of a todoitem" + (let ((has-parent)) + (save-excursion + (while (and (not has-parent) (org-up-heading-safe)) + (when (nd/is-todoitem-p) + (setq has-parent t)))) + has-parent)) (defun nd/is-project-p () - (nd/todoitem-has-children)) + "return todo keyword if heading is todoitem and has children" + (and (nd/heading-has-children) + (nd/is-todoitem-p))) (defun nd/is-task-p () - (and (nd/is-todoitem-p) (not nd/todoitem-has-children))) + "return todo keyword if heading is todoitem with no children" + (and (not (nd/heading-has-children)) + (nd/is-todoitem-p))) (defun nd/is-atomic-task-p () - (and (nd/is-task-p) (not (nd/todoitem-has-parent)))) + "return todo keyword if heading is task with no parents" + (and (not (nd/heading-has-parent)) + (nd/is-task-p))) - ;; functions to test tasks (which are "atomic") - ;; (defun nd/is-scheduled-p () - ;; "task with scheduled property" - ;; ((org-entry-get nil "SCHEDULED"))) + (defun nd/is-scheduled-heading-p () + "return timestamp if headline is scheduled" + (org-entry-get nil "SCHEDULED")) + + (defun nd/is-active-task-p () + "return keyword if task is either NEXT or scheduled" + (let ((keyword (nd/is-task-p))) + (if (or (equal keyword "NEXT") (nd/is-scheduled-heading-p)) + keyword))) + + (defun nd/is-blocked-task-p () + "return keyword if task is WAITING" + (equal (nd/is-task-p) "WAITING")) ;; org-forward-heading-same-level + ;; project level testing + (defun nd/is-active-project-p () + "return keyword if project has at least one + active task or project" + (let ((keyword (nd/is-project-p))) + (if keyword + (let ((found-active) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (save-excursion + (outline-next-heading) + (while (and (not found-active) + (< (point) subtree-end)) + (when (or (nd/is-active-project-p) (nd/is-active-task-p)) + (setq found-active t)) + ;; TODO; this is not very efficient as we test for project twice + (if (nd/is-project-p) + (org-forward-heading-same-level 1 t) + (outline-next-heading)))) + (and found-active + keyword))))) + ;; task skip functions (defun nd/skip-non-atomic-tasks () (save-restriction @@ -696,19 +734,19 @@ some definitions: ;; else if task ;; return (state is true) ;; note: this needs to iterate through lines - (defun nd/is-active-project-p () - "return true if project has at least one - NEXT/scheduled task or active subproject" - ;; if not a project then don't bother - (if (nd/is-project-p) - (let (((subtree-end (save-excursion (org-end-of-subtree t)))) - (is-active)) - (save-excursion - (while (and (not is-active) - (< (point) subtree-end)) - (outline-heading-next) - (cond ((nd/is-active-task-p) (setq is-active t)) - ((nd/is-active-project-p) (setq is-active)))))))) + ;; (defun nd/is-active-project-p () + ;; "return true if project has at least one + ;; NEXT/scheduled task or active subproject" + ;; ;; if not a project then don't bother + ;; (if (nd/is-project-p) + ;; (let (((subtree-end (save-excursion (org-end-of-subtree t)))) + ;; (is-active)) + ;; (save-excursion + ;; (while (and (not is-active) + ;; (< (point) subtree-end)) + ;; (outline-heading-next) + ;; (cond ((nd/is-active-task-p) (setq is-active t)) + ;; ((nd/is-active-project-p) (setq is-active)))))))) ;; (defun nd/skip-non-stuck-projects () ;; goto next headline From 1699aec7030e521c4098688e976a4e5e762a0ef9 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sun, 25 Mar 2018 01:18:48 -0400 Subject: [PATCH 05/17] added inner recursion to project testing --- conf.el | 35 +++++++++++++++++++++-------------- conf.org | 37 ++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/conf.el b/conf.el index edee8df..c42fce5 100644 --- a/conf.el +++ b/conf.el @@ -475,25 +475,32 @@ and retrieve the keyword" ;; org-forward-heading-same-level ;; project level testing +(defun nd/test-first-order-project () + "tests the state of a project assuming first order. +if not first order, this function will iterate to the next project +and descend into it by calling itelf recursively. +function is not meant to be called independently." + (let ((found-active) + (previous-point)) + (save-excursion + (setq previous-point (point)) + (outline-next-heading) + (while (and (not found-active) + (> (point) previous-point)) + (when (or (and (nd/is-project-p) + (nd/test-first-order-project)) + (nd/is-active-task-p)) + (setq found-active t)) + (setq previous-point (point)) + (org-forward-heading-same-level 1 t))) + found-active)) + (defun nd/is-active-project-p () "return keyword if project has at least one active task or project" (let ((keyword (nd/is-project-p))) (if keyword - (let ((found-active) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (save-excursion - (outline-next-heading) - (while (and (not found-active) - (< (point) subtree-end)) - (when (or (nd/is-active-project-p) (nd/is-active-task-p)) - (setq found-active t)) - ;; TODO; this is not very efficient as we test for project twice - (if (nd/is-project-p) - (org-forward-heading-same-level 1 t) - (outline-next-heading)))) - (and found-active - keyword))))) + (nd/test-first-order-project)))) ;; task skip functions (defun nd/skip-non-atomic-tasks () diff --git a/conf.org b/conf.org index 03fc3af..a205172 100644 --- a/conf.org +++ b/conf.org @@ -592,7 +592,7 @@ TODO: add meeting template as scheduled+action item thing (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) #+END_SRC -*** COMMENT filtering functions +*** filtering functions some definitions: - todoitem: heading with todo state - task: todo heading with no todo headings beneath it @@ -668,25 +668,32 @@ some definitions: ;; org-forward-heading-same-level ;; project level testing + (defun nd/test-first-order-project () + "tests the state of a project assuming first order. + if not first order, this function will iterate to the next project + and descend into it by calling itelf recursively. + function is not meant to be called independently." + (let ((found-active) + (previous-point)) + (save-excursion + (setq previous-point (point)) + (outline-next-heading) + (while (and (not found-active) + (> (point) previous-point)) + (when (or (and (nd/is-project-p) + (nd/test-first-order-project)) + (nd/is-active-task-p)) + (setq found-active t)) + (setq previous-point (point)) + (org-forward-heading-same-level 1 t))) + found-active)) + (defun nd/is-active-project-p () "return keyword if project has at least one active task or project" (let ((keyword (nd/is-project-p))) (if keyword - (let ((found-active) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (save-excursion - (outline-next-heading) - (while (and (not found-active) - (< (point) subtree-end)) - (when (or (nd/is-active-project-p) (nd/is-active-task-p)) - (setq found-active t)) - ;; TODO; this is not very efficient as we test for project twice - (if (nd/is-project-p) - (org-forward-heading-same-level 1 t) - (outline-next-heading)))) - (and found-active - keyword))))) + (nd/test-first-order-project)))) ;; task skip functions (defun nd/skip-non-atomic-tasks () From e7bbc5547821249f75b7b8fdea125538e308ca86 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Wed, 28 Mar 2018 00:41:11 -0400 Subject: [PATCH 06/17] generalized project descention function...not tested --- conf.el | 23 ++++++++++++++++++++++- conf.org | 32 +++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/conf.el b/conf.el index c42fce5..14d906e 100644 --- a/conf.el +++ b/conf.el @@ -226,7 +226,7 @@ (load "ess-site") (setq ess-history-file "session.Rhistory") (setq ess-history-directory - (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) + (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) (setq org-log-done t) (setq org-src-window-setup 'current-window) @@ -495,6 +495,27 @@ function is not meant to be called independently." (org-forward-heading-same-level 1 t))) found-active)) +;; project level testing +(defun nd/test-blocked-project () + (let ((found-active) + (found-blocked) + (found-held) + (previous-point)) + (save-excursion + (setq previous-point (point)) + (outline-next-heading) + ;; note, only active tasks can break the loop because we don't know if the final + ;; heading in the project will be active (and could override the project status) + (while (and (not found-active) + (> (point) previous-point)) + (when (or (and (nd/is-project-p) + (nd/test-blocked-project)) + (nd/is-active-task-p)) + (setq found-active t)) + (setq previous-point (point)) + (org-forward-heading-same-level 1 t))) + found-active)) + (defun nd/is-active-project-p () "return keyword if project has at least one active task or project" diff --git a/conf.org b/conf.org index a205172..f0adf20 100644 --- a/conf.org +++ b/conf.org @@ -666,7 +666,6 @@ some definitions: (equal (nd/is-task-p) "WAITING")) ;; org-forward-heading-same-level - ;; project level testing (defun nd/test-first-order-project () "tests the state of a project assuming first order. @@ -688,6 +687,37 @@ some definitions: (org-forward-heading-same-level 1 t))) found-active)) + ;; project level testing + (defun nd/descend-into-project () + "returns numeric value according to state of project: + 0: stuck + 1: held + 2: waiting + 3: active + + Larger values have precedence over smaller (eg a NEXT + keyword will override any other WAITING or HELD task present" + (let ((project-state 0) + (previous-point)) + (save-excursion + (setq previous-point (point)) + (outline-next-heading) + (while (and (< project-state 3) + (> (point) previous-point)) + (let ((keyword (nd/is-todoitem)) + (if keyword + (let ((cur-state (cond ((nd/heading-has-children) (nd/descend-into-project)) + ((equal keyword "HOLD") 1) + ((equal keyword "WAITING") 2) + ((equal keyword "NEXT") 3) + ((nd/is-scheduled-heading) 3) + (t 0)))) + (if (> cur-state project-state) + (setq project-state cur-state)))) + (setq previous-point (point)) + (org-forward-heading-same-level 1 t))) + project-state)) + (defun nd/is-active-project-p () "return keyword if project has at least one active task or project" From c619aae18f5f50d8391435e960e0aa64cb88763a Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Fri, 30 Mar 2018 20:54:25 -0400 Subject: [PATCH 07/17] fixed and tested descend-into-project --- conf.el | 40 ++++++++++++++++++++++++---------------- conf.org | 11 ++++++----- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/conf.el b/conf.el index 14d906e..3452e58 100644 --- a/conf.el +++ b/conf.el @@ -226,7 +226,7 @@ (load "ess-site") (setq ess-history-file "session.Rhistory") (setq ess-history-directory - (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) + (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) (setq org-log-done t) (setq org-src-window-setup 'current-window) @@ -473,7 +473,6 @@ and retrieve the keyword" (equal (nd/is-task-p) "WAITING")) ;; org-forward-heading-same-level - ;; project level testing (defun nd/test-first-order-project () "tests the state of a project assuming first order. @@ -496,32 +495,41 @@ function is not meant to be called independently." found-active)) ;; project level testing -(defun nd/test-blocked-project () - (let ((found-active) - (found-blocked) - (found-held) +(defun nd/descend-into-project () + "returns numeric value according to state of project: +0: stuck +1: held +2: waiting +3: active + +Larger values have precedence over smaller (eg a NEXT +keyword will override any other WAITING or HELD task present" + (let ((project-state 0) (previous-point)) (save-excursion (setq previous-point (point)) (outline-next-heading) - ;; note, only active tasks can break the loop because we don't know if the final - ;; heading in the project will be active (and could override the project status) - (while (and (not found-active) + (while (and (< project-state 3) (> (point) previous-point)) - (when (or (and (nd/is-project-p) - (nd/test-blocked-project)) - (nd/is-active-task-p)) - (setq found-active t)) + (let ((keyword (nd/is-todoitem-p))) + (if keyword + (let ((cur-state (cond ((nd/heading-has-children) (nd/descend-into-project)) + ((equal keyword "HOLD") 1) + ((equal keyword "WAITING") 2) + ((equal keyword "NEXT") 3) + ((nd/is-scheduled-heading-p) 3) + (t 0)))) + (if (> cur-state project-state) + (setq project-state cur-state))))) (setq previous-point (point)) (org-forward-heading-same-level 1 t))) - found-active)) + project-state)) (defun nd/is-active-project-p () "return keyword if project has at least one active task or project" (let ((keyword (nd/is-project-p))) - (if keyword - (nd/test-first-order-project)))) + (and keyword (equal 3 (nd/descend-into-project))))) ;; task skip functions (defun nd/skip-non-atomic-tasks () diff --git a/conf.org b/conf.org index f0adf20..c38795d 100644 --- a/conf.org +++ b/conf.org @@ -704,16 +704,17 @@ some definitions: (outline-next-heading) (while (and (< project-state 3) (> (point) previous-point)) - (let ((keyword (nd/is-todoitem)) + (let ((keyword (nd/is-todoitem-p))) (if keyword + ;; TODO: filter out project headings like HOLD and DONE (let ((cur-state (cond ((nd/heading-has-children) (nd/descend-into-project)) ((equal keyword "HOLD") 1) ((equal keyword "WAITING") 2) ((equal keyword "NEXT") 3) - ((nd/is-scheduled-heading) 3) + ((nd/is-scheduled-heading-p) 3) (t 0)))) (if (> cur-state project-state) - (setq project-state cur-state)))) + (setq project-state cur-state))))) (setq previous-point (point)) (org-forward-heading-same-level 1 t))) project-state)) @@ -721,9 +722,9 @@ some definitions: (defun nd/is-active-project-p () "return keyword if project has at least one active task or project" + ;; TODO: skip over projects based on heading alone (eg HOLD and DONE) (let ((keyword (nd/is-project-p))) - (if keyword - (nd/test-first-order-project)))) + (and keyword (equal 3 (nd/descend-into-project))))) ;; task skip functions (defun nd/skip-non-atomic-tasks () From 834e1270caffedfcad0862793e96c693eb956668 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sat, 31 Mar 2018 01:43:17 -0400 Subject: [PATCH 08/17] began testing skip functions --- conf.el | 233 +++++++++++++++++++++++++++--------------------------- conf.org | 235 ++++++++++++++++++++++++++++--------------------------- 2 files changed, 236 insertions(+), 232 deletions(-) diff --git a/conf.el b/conf.el index 3452e58..2832110 100644 --- a/conf.el +++ b/conf.el @@ -350,57 +350,54 @@ (tags "REFILE" ((org-agenda-overriding-header "Tasks to Refile") (org-tags-match-list-sublevels nil))) - (tags-todo "-NA-CANCELLED/!NEXT" - ((org-agenda-overriding-header (concat "Project Next Tasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-projects-and-habits-and-single-tasks) - (org-tags-match-list-sublevels t) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "Atomic Tasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "Project Subtasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-non-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-CANCELLED+WAITING|HOLD/!" - ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-non-tasks) - (org-tags-match-list-sublevels nil) - (org-agenda-todo-ignore-with-date 'all))) - (tags-todo "-NA-CANCELLED/!" + ;; (tags-todo "-NA-CANCELLED/!NEXT" + ;; ((org-agenda-overriding-header (concat "Project Next Tasks" + ;; (if nd/hide-scheduled-and-waiting-next-tasks + ;; "" + ;; " (including WAITING and SCHEDULED tasks)"))) + ;; (org-agenda-skip-function 'nd/skip-projects-and-habits-and-single-tasks) + ;; (org-tags-match-list-sublevels t) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(todo-state-down effort-up category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header (concat "Atomic Tasks")) + ;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) + ;; ;;(org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" + ;; ((org-agenda-overriding-header (concat "Project Subtasks" + ;; (if nd/hide-scheduled-and-waiting-next-tasks + ;; "" + ;; " (including WAITING and SCHEDULED tasks)"))) + ;; (org-agenda-skip-function 'nd/skip-non-project-tasks) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-CANCELLED+WAITING|HOLD/!" + ;; ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" + ;; (if nd/hide-scheduled-and-waiting-next-tasks + ;; "" + ;; " (including WAITING and SCHEDULED tasks)"))) + ;; (org-agenda-skip-function 'nd/skip-non-tasks) + ;; (org-tags-match-list-sublevels nil) + ;; (org-agenda-todo-ignore-with-date 'all))) + (tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header "Stuck Projects") (org-agenda-skip-function 'nd/skip-non-stuck-projects) (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "Projects") - (org-agenda-skip-function 'nd/skip-non-projects) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags "-NA-REFILE/" - ((org-agenda-overriding-header "Tasks to Archive") - (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - (org-tags-match-list-sublevels nil)))) + '(category-keep))))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Projects") + ;; (org-agenda-skip-function 'nd/skip-non-projects) + ;; (org-tags-match-list-sublevels 'indented) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags "-NA-REFILE/" + ;; ((org-agenda-overriding-header "Tasks to Archive") + ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) + ;; (org-tags-match-list-sublevels nil)))) nil)))) (defun nd/org-auto-exclude-function (tag) @@ -422,7 +419,7 @@ and retrieve the keyword" keyword))) (defun nd/heading-has-children () - "returns t if heading has todoitems in its subtree" + "returns t if heading has todoitems in its immediate subtree" (let ((has-children) (subtree-end (save-excursion (org-end-of-subtree t)))) (save-excursion @@ -430,33 +427,26 @@ and retrieve the keyword" (while (and (not has-children) (< (point) subtree-end)) (when (nd/is-todoitem-p) - (setq has-children t) - (outline-next-heading)))) + (setq has-children t)) +;; (org-forward-heading-same-level 1 t))) + (outline-next-heading))) has-children)) (defun nd/heading-has-parent () - "returns t if heading is in the subtree of a todoitem" - (let ((has-parent)) - (save-excursion - (while (and (not has-parent) (org-up-heading-safe)) - (when (nd/is-todoitem-p) - (setq has-parent t)))) - has-parent)) + "returns parent keyword if heading is in the immediate subtree of a todoitem" + (save-excursion (and (org-up-heading-safe) (nd/is-todoitem-p)))) (defun nd/is-project-p () "return todo keyword if heading is todoitem and has children" - (and (nd/heading-has-children) - (nd/is-todoitem-p))) + (and (nd/heading-has-children) (nd/is-todoitem-p))) (defun nd/is-task-p () "return todo keyword if heading is todoitem with no children" - (and (not (nd/heading-has-children)) - (nd/is-todoitem-p))) + (and (not (nd/heading-has-children)) (nd/is-todoitem-p))) (defun nd/is-atomic-task-p () "return todo keyword if heading is task with no parents" - (and (not (nd/heading-has-parent)) - (nd/is-task-p))) + (and (not (nd/heading-has-parent)) (nd/is-task-p))) (defun nd/is-scheduled-heading-p () "return timestamp if headline is scheduled" @@ -494,6 +484,9 @@ function is not meant to be called independently." (org-forward-heading-same-level 1 t))) found-active)) +;; projects that have these keywords are not considered in determining status +(defvar nd/project-skip-keywords '("HOLD" "DONE" "CANCELLED")) + ;; project level testing (defun nd/descend-into-project () "returns numeric value according to state of project: @@ -513,7 +506,9 @@ keyword will override any other WAITING or HELD task present" (> (point) previous-point)) (let ((keyword (nd/is-todoitem-p))) (if keyword - (let ((cur-state (cond ((nd/heading-has-children) (nd/descend-into-project)) + (let ((cur-state (cond ((and (not (member keyword nd/project-skip-keywords)) + (nd/heading-has-children)) + (nd/descend-into-project)) ((equal keyword "HOLD") 1) ((equal keyword "WAITING") 2) ((equal keyword "NEXT") 3) @@ -525,47 +520,55 @@ keyword will override any other WAITING or HELD task present" (org-forward-heading-same-level 1 t))) project-state)) -(defun nd/is-active-project-p () - "return keyword if project has at least one -active task or project" +(defun nd/is-project-status-p (statuscode) + ;;TODO maybe return keyword here to consistant? (let ((keyword (nd/is-project-p))) - (and keyword (equal 3 (nd/descend-into-project))))) + (and keyword + (not (member keyword nd/project-skip-keywords)) + (equal statuscode (nd/descend-into-project))))) ;; task skip functions +;; NOTE: use save-restriction and widen if we ever actually use narrowing (defun nd/skip-non-atomic-tasks () - (save-restriction - (widen) - (if (not (and ((nd/is-atomic-p) (not (nd/is-subtask-p))))) - (save-excursion (or (outline-next-heading) (point-max)))))) - -(defvar nd/hide-scheduled-and-waiting-next-tasks t) - -(defun nd/toggle-next-task-display () - (interactive) - (setq nd/hide-scheduled-and-waiting-next-tasks (not nd/hide-scheduled-and-waiting-next-tasks)) - (when (equal major-mode 'org-agenda-mode) - (org-agenda-redo)) - (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + (if (not (nd/is-atomic-task-p)) + (save-excursion (or (outline-next-heading) (point-max))))) +(defun nd/skip-non-projects () + (if (not (nd/is-project-p)) + (save-excursion (or (outline-next-heading) (point-max))))) + (defun nd/skip-non-stuck-projects () - "Skip trees that are not stuck projects" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (nd/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) - (< (point) subtree-end) - (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) + (if (not (nd/is-project-status-p 0)) + (save-excursion (or (outline-next-heading) (point-max))))) + +;; (defvar nd/hide-scheduled-and-waiting-next-tasks t) + +;; (defun nd/toggle-next-task-display () +;; (interactive) +;; (setq nd/hide-scheduled-and-waiting-next-tasks (not nd/hide-scheduled-and-waiting-next-tasks)) +;; (when (equal major-mode 'org-agenda-mode) +;; (org-agenda-redo)) +;; (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + +;; (defun nd/skip-non-stuck-projects () +;; "Skip trees that are not stuck projects" +;; (save-restriction +;; (widen) +;; (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) +;; (if (nd/is-project-p) +;; (let* ((subtree-end (save-excursion (org-end-of-subtree t))) +;; (has-next )) +;; (save-excursion +;; (forward-line 1) +;; (while (and (not has-next) +;; (< (point) subtree-end) +;; (re-search-forward "^\\*+ NEXT " subtree-end t)) +;; (unless (member "WAITING" (org-get-tags-at)) +;; (setq has-next t)))) +;; (if has-next +;; next-headline +;; nil)) ; a stuck project, has subtasks but no next task +;; next-headline)))) ;; project test functions ;; is state @@ -603,21 +606,21 @@ active task or project" ;; skip (either an atomic task or non-todo, return next heading) ;; ) -(defun nd/skip-non-projects () - "Skip trees that are not projects" - ;; (nd/list-sublevels-for-projects-indented) - (if (save-excursion (nd/skip-non-stuck-projects)) - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - nil) - ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) - nil) - (t - subtree-end)))) - (save-excursion (org-end-of-subtree t)))) +;; (defun nd/skip-non-projects () +;; "Skip trees that are not projects" +;; ;; (nd/list-sublevels-for-projects-indented) +;; (if (save-excursion (nd/skip-non-stuck-projects)) +;; (save-restriction +;; (widen) +;; (let ((subtree-end (save-excursion (org-end-of-subtree t)))) +;; (cond +;; ((nd/is-project-p) +;; nil) +;; ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) +;; nil) +;; (t +;; subtree-end)))) +;; (save-excursion (org-end-of-subtree t)))) (defun nd/skip-non-tasks () "Show non-project tasks. diff --git a/conf.org b/conf.org index c38795d..c828058 100644 --- a/conf.org +++ b/conf.org @@ -527,57 +527,54 @@ TODO: add meeting template as scheduled+action item thing (tags "REFILE" ((org-agenda-overriding-header "Tasks to Refile") (org-tags-match-list-sublevels nil))) - (tags-todo "-NA-CANCELLED/!NEXT" - ((org-agenda-overriding-header (concat "Project Next Tasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-projects-and-habits-and-single-tasks) - (org-tags-match-list-sublevels t) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "Atomic Tasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header (concat "Project Subtasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-non-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-CANCELLED+WAITING|HOLD/!" - ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" - (if nd/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'nd/skip-non-tasks) - (org-tags-match-list-sublevels nil) - (org-agenda-todo-ignore-with-date 'all))) - (tags-todo "-NA-CANCELLED/!" + ;; (tags-todo "-NA-CANCELLED/!NEXT" + ;; ((org-agenda-overriding-header (concat "Project Next Tasks" + ;; (if nd/hide-scheduled-and-waiting-next-tasks + ;; "" + ;; " (including WAITING and SCHEDULED tasks)"))) + ;; (org-agenda-skip-function 'nd/skip-projects-and-habits-and-single-tasks) + ;; (org-tags-match-list-sublevels t) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(todo-state-down effort-up category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header (concat "Atomic Tasks")) + ;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) + ;; ;;(org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" + ;; ((org-agenda-overriding-header (concat "Project Subtasks" + ;; (if nd/hide-scheduled-and-waiting-next-tasks + ;; "" + ;; " (including WAITING and SCHEDULED tasks)"))) + ;; (org-agenda-skip-function 'nd/skip-non-project-tasks) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-CANCELLED+WAITING|HOLD/!" + ;; ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" + ;; (if nd/hide-scheduled-and-waiting-next-tasks + ;; "" + ;; " (including WAITING and SCHEDULED tasks)"))) + ;; (org-agenda-skip-function 'nd/skip-non-tasks) + ;; (org-tags-match-list-sublevels nil) + ;; (org-agenda-todo-ignore-with-date 'all))) + (tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header "Stuck Projects") (org-agenda-skip-function 'nd/skip-non-stuck-projects) (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "Projects") - (org-agenda-skip-function 'nd/skip-non-projects) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags "-NA-REFILE/" - ((org-agenda-overriding-header "Tasks to Archive") - (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - (org-tags-match-list-sublevels nil)))) + '(category-keep))))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Projects") + ;; (org-agenda-skip-function 'nd/skip-non-projects) + ;; (org-tags-match-list-sublevels 'indented) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags "-NA-REFILE/" + ;; ((org-agenda-overriding-header "Tasks to Archive") + ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) + ;; (org-tags-match-list-sublevels nil)))) nil)))) #+END_SRC @@ -615,7 +612,7 @@ some definitions: keyword))) (defun nd/heading-has-children () - "returns t if heading has todoitems in its subtree" + "returns t if heading has todoitems in its immediate subtree" (let ((has-children) (subtree-end (save-excursion (org-end-of-subtree t)))) (save-excursion @@ -623,33 +620,26 @@ some definitions: (while (and (not has-children) (< (point) subtree-end)) (when (nd/is-todoitem-p) - (setq has-children t) - (outline-next-heading)))) + (setq has-children t)) + ;; (org-forward-heading-same-level 1 t))) + (outline-next-heading))) has-children)) (defun nd/heading-has-parent () - "returns t if heading is in the subtree of a todoitem" - (let ((has-parent)) - (save-excursion - (while (and (not has-parent) (org-up-heading-safe)) - (when (nd/is-todoitem-p) - (setq has-parent t)))) - has-parent)) + "returns parent keyword if heading is in the immediate subtree of a todoitem" + (save-excursion (and (org-up-heading-safe) (nd/is-todoitem-p)))) (defun nd/is-project-p () "return todo keyword if heading is todoitem and has children" - (and (nd/heading-has-children) - (nd/is-todoitem-p))) + (and (nd/heading-has-children) (nd/is-todoitem-p))) (defun nd/is-task-p () "return todo keyword if heading is todoitem with no children" - (and (not (nd/heading-has-children)) - (nd/is-todoitem-p))) + (and (not (nd/heading-has-children)) (nd/is-todoitem-p))) (defun nd/is-atomic-task-p () "return todo keyword if heading is task with no parents" - (and (not (nd/heading-has-parent)) - (nd/is-task-p))) + (and (not (nd/heading-has-parent)) (nd/is-task-p))) (defun nd/is-scheduled-heading-p () "return timestamp if headline is scheduled" @@ -687,6 +677,9 @@ some definitions: (org-forward-heading-same-level 1 t))) found-active)) + ;; projects that have these keywords are not considered in determining status + (defvar nd/project-skip-keywords '("HOLD" "DONE" "CANCELLED")) + ;; project level testing (defun nd/descend-into-project () "returns numeric value according to state of project: @@ -706,8 +699,9 @@ some definitions: (> (point) previous-point)) (let ((keyword (nd/is-todoitem-p))) (if keyword - ;; TODO: filter out project headings like HOLD and DONE - (let ((cur-state (cond ((nd/heading-has-children) (nd/descend-into-project)) + (let ((cur-state (cond ((and (not (member keyword nd/project-skip-keywords)) + (nd/heading-has-children)) + (nd/descend-into-project)) ((equal keyword "HOLD") 1) ((equal keyword "WAITING") 2) ((equal keyword "NEXT") 3) @@ -719,48 +713,55 @@ some definitions: (org-forward-heading-same-level 1 t))) project-state)) - (defun nd/is-active-project-p () - "return keyword if project has at least one - active task or project" - ;; TODO: skip over projects based on heading alone (eg HOLD and DONE) + (defun nd/is-project-status-p (statuscode) + ;;TODO maybe return keyword here to consistant? (let ((keyword (nd/is-project-p))) - (and keyword (equal 3 (nd/descend-into-project))))) + (and keyword + (not (member keyword nd/project-skip-keywords)) + (equal statuscode (nd/descend-into-project))))) ;; task skip functions + ;; NOTE: use save-restriction and widen if we ever actually use narrowing (defun nd/skip-non-atomic-tasks () - (save-restriction - (widen) - (if (not (and ((nd/is-atomic-p) (not (nd/is-subtask-p))))) - (save-excursion (or (outline-next-heading) (point-max)))))) - - (defvar nd/hide-scheduled-and-waiting-next-tasks t) - - (defun nd/toggle-next-task-display () - (interactive) - (setq nd/hide-scheduled-and-waiting-next-tasks (not nd/hide-scheduled-and-waiting-next-tasks)) - (when (equal major-mode 'org-agenda-mode) - (org-agenda-redo)) - (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + (if (not (nd/is-atomic-task-p)) + (save-excursion (or (outline-next-heading) (point-max))))) + (defun nd/skip-non-projects () + (if (not (nd/is-project-p)) + (save-excursion (or (outline-next-heading) (point-max))))) + (defun nd/skip-non-stuck-projects () - "Skip trees that are not stuck projects" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (nd/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) - (< (point) subtree-end) - (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) + (if (not (nd/is-project-status-p 0)) + (save-excursion (or (outline-next-heading) (point-max))))) + + ;; (defvar nd/hide-scheduled-and-waiting-next-tasks t) + + ;; (defun nd/toggle-next-task-display () + ;; (interactive) + ;; (setq nd/hide-scheduled-and-waiting-next-tasks (not nd/hide-scheduled-and-waiting-next-tasks)) + ;; (when (equal major-mode 'org-agenda-mode) + ;; (org-agenda-redo)) + ;; (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + + ;; (defun nd/skip-non-stuck-projects () + ;; "Skip trees that are not stuck projects" + ;; (save-restriction + ;; (widen) + ;; (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + ;; (if (nd/is-project-p) + ;; (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + ;; (has-next )) + ;; (save-excursion + ;; (forward-line 1) + ;; (while (and (not has-next) + ;; (< (point) subtree-end) + ;; (re-search-forward "^\\*+ NEXT " subtree-end t)) + ;; (unless (member "WAITING" (org-get-tags-at)) + ;; (setq has-next t)))) + ;; (if has-next + ;; next-headline + ;; nil)) ; a stuck project, has subtasks but no next task + ;; next-headline)))) ;; project test functions ;; is state @@ -798,21 +799,21 @@ some definitions: ;; skip (either an atomic task or non-todo, return next heading) ;; ) - (defun nd/skip-non-projects () - "Skip trees that are not projects" - ;; (nd/list-sublevels-for-projects-indented) - (if (save-excursion (nd/skip-non-stuck-projects)) - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - nil) - ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) - nil) - (t - subtree-end)))) - (save-excursion (org-end-of-subtree t)))) + ;; (defun nd/skip-non-projects () + ;; "Skip trees that are not projects" + ;; ;; (nd/list-sublevels-for-projects-indented) + ;; (if (save-excursion (nd/skip-non-stuck-projects)) + ;; (save-restriction + ;; (widen) + ;; (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + ;; (cond + ;; ((nd/is-project-p) + ;; nil) + ;; ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) + ;; nil) + ;; (t + ;; subtree-end)))) + ;; (save-excursion (org-end-of-subtree t)))) (defun nd/skip-non-tasks () "Show non-project tasks. From a14650fc162d7d5f84d8f095a7b83f0ad87db3ce Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sun, 1 Apr 2018 18:45:26 -0400 Subject: [PATCH 09/17] implemented skip functions on project and task level --- conf.el | 137 +++++++++++++++++++++++++++++++++++-------------------- conf.org | 137 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 174 insertions(+), 100 deletions(-) diff --git a/conf.el b/conf.el index 2832110..87ecd70 100644 --- a/conf.el +++ b/conf.el @@ -350,42 +350,48 @@ (tags "REFILE" ((org-agenda-overriding-header "Tasks to Refile") (org-tags-match-list-sublevels nil))) - ;; (tags-todo "-NA-CANCELLED/!NEXT" - ;; ((org-agenda-overriding-header (concat "Project Next Tasks" - ;; (if nd/hide-scheduled-and-waiting-next-tasks - ;; "" - ;; " (including WAITING and SCHEDULED tasks)"))) - ;; (org-agenda-skip-function 'nd/skip-projects-and-habits-and-single-tasks) - ;; (org-tags-match-list-sublevels t) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(todo-state-down effort-up category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header (concat "Atomic Tasks")) - ;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - ;; ;;(org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" - ;; ((org-agenda-overriding-header (concat "Project Subtasks" - ;; (if nd/hide-scheduled-and-waiting-next-tasks - ;; "" - ;; " (including WAITING and SCHEDULED tasks)"))) - ;; (org-agenda-skip-function 'nd/skip-non-project-tasks) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-CANCELLED+WAITING|HOLD/!" - ;; ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" - ;; (if nd/hide-scheduled-and-waiting-next-tasks - ;; "" - ;; " (including WAITING and SCHEDULED tasks)"))) - ;; (org-agenda-skip-function 'nd/skip-non-tasks) - ;; (org-tags-match-list-sublevels nil) - ;; (org-agenda-todo-ignore-with-date 'all))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Project Next Tasks")) + (org-agenda-skip-function 'nd/skip-non-next-project-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Project Waiting Tasks")) + (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Project Held Tasks")) + (org-agenda-skip-function 'nd/skip-non-held-project-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Atomic Tasks")) + (org-agenda-skip-function 'nd/skip-non-atomic-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) (tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header "Stuck Projects") (org-agenda-skip-function 'nd/skip-non-stuck-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header "Held Projects") + (org-agenda-skip-function 'nd/skip-non-held-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header "Waiting Projects") + (org-agenda-skip-function 'nd/skip-non-waiting-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header "Active Projects") + (org-agenda-skip-function 'nd/skip-non-active-projects) (org-agenda-sorting-strategy '(category-keep))))) ;; (tags-todo "-NA-REFILE/!" @@ -420,6 +426,8 @@ and retrieve the keyword" (defun nd/heading-has-children () "returns t if heading has todoitems in its immediate subtree" + ;; TODO make this more efficient (and accurate) by only testing + ;; the level immediately below (if it exists) (let ((has-children) (subtree-end (save-excursion (org-end-of-subtree t)))) (save-excursion @@ -448,6 +456,10 @@ and retrieve the keyword" "return todo keyword if heading is task with no parents" (and (not (nd/heading-has-parent)) (nd/is-task-p))) +(defun nd/is-project-task-p () + "return todo keyword if heading is task with no parents" + (and (nd/heading-has-parent) (nd/is-task-p))) + (defun nd/is-scheduled-heading-p () "return timestamp if headline is scheduled" (org-entry-get nil "SCHEDULED")) @@ -484,8 +496,9 @@ function is not meant to be called independently." (org-forward-heading-same-level 1 t))) found-active)) -;; projects that have these keywords are not considered in determining status -(defvar nd/project-skip-keywords '("HOLD" "DONE" "CANCELLED")) +(defconst nd/project-invalid-todostates + '("WAITING" "NEXT") + "projects cannot have these todostates") ;; project level testing (defun nd/descend-into-project () @@ -504,16 +517,19 @@ keyword will override any other WAITING or HELD task present" (outline-next-heading) (while (and (< project-state 3) (> (point) previous-point)) - (let ((keyword (nd/is-todoitem-p))) + (let ((keyword (nd/is-todoitem-p)) + (has-children (nd/heading-has-children))) (if keyword - (let ((cur-state (cond ((and (not (member keyword nd/project-skip-keywords)) - (nd/heading-has-children)) - (nd/descend-into-project)) - ((equal keyword "HOLD") 1) - ((equal keyword "WAITING") 2) - ((equal keyword "NEXT") 3) - ((nd/is-scheduled-heading-p) 3) - (t 0)))) + (let ((cur-state + (if has-children + (cond ((equal keyword "HOLD") 1) + ((equal keyword "TODO") (nd/descend-into-project)) + (t 0)) + (cond ((equal keyword "HOLD") 1) + ((equal keyword "WAITING") 2) + ((equal keyword "NEXT") 3) + ((nd/is-scheduled-heading-p) 3) + (t 0))))) (if (> cur-state project-state) (setq project-state cur-state))))) (setq previous-point (point)) @@ -521,11 +537,12 @@ keyword will override any other WAITING or HELD task present" project-state)) (defun nd/is-project-status-p (statuscode) - ;;TODO maybe return keyword here to consistant? (let ((keyword (nd/is-project-p))) - (and keyword - (not (member keyword nd/project-skip-keywords)) - (equal statuscode (nd/descend-into-project))))) + (if keyword + (cond ((member keyword nd/project-invalid-todostates) nil) + ((and (equal keyword "HOLD") (= statuscode 1)) keyword) + ((and (equal keyword "HOLD") (/= statuscode 1)) nil) + ((= statuscode (nd/descend-into-project)) keyword))))) ;; task skip functions ;; NOTE: use save-restriction and widen if we ever actually use narrowing @@ -533,14 +550,34 @@ keyword will override any other WAITING or HELD task present" (if (not (nd/is-atomic-task-p)) (save-excursion (or (outline-next-heading) (point-max))))) -(defun nd/skip-non-projects () - (if (not (nd/is-project-p)) +(defun nd/skip-non-next-project-tasks () + (if (not (equal (nd/is-project-task-p) "NEXT")) + (save-excursion (or (outline-next-heading) (point-max))))) + +(defun nd/skip-non-waiting-project-tasks () + (if (not (equal (nd/is-project-task-p) "WAITING")) + (save-excursion (or (outline-next-heading) (point-max))))) + +(defun nd/skip-non-held-project-tasks () + (if (not (equal (nd/is-project-task-p) "HOLD")) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-stuck-projects () (if (not (nd/is-project-status-p 0)) (save-excursion (or (outline-next-heading) (point-max))))) +(defun nd/skip-non-held-projects () + (if (not (nd/is-project-status-p 1)) + (save-excursion (or (outline-next-heading) (point-max))))) + +(defun nd/skip-non-waiting-projects () + (if (not (nd/is-project-status-p 2)) + (save-excursion (or (outline-next-heading) (point-max))))) + +(defun nd/skip-non-active-projects () + (if (not (nd/is-project-status-p 3)) + (save-excursion (or (outline-next-heading) (point-max))))) + ;; (defvar nd/hide-scheduled-and-waiting-next-tasks t) ;; (defun nd/toggle-next-task-display () diff --git a/conf.org b/conf.org index c828058..6802f7a 100644 --- a/conf.org +++ b/conf.org @@ -527,42 +527,48 @@ TODO: add meeting template as scheduled+action item thing (tags "REFILE" ((org-agenda-overriding-header "Tasks to Refile") (org-tags-match-list-sublevels nil))) - ;; (tags-todo "-NA-CANCELLED/!NEXT" - ;; ((org-agenda-overriding-header (concat "Project Next Tasks" - ;; (if nd/hide-scheduled-and-waiting-next-tasks - ;; "" - ;; " (including WAITING and SCHEDULED tasks)"))) - ;; (org-agenda-skip-function 'nd/skip-projects-and-habits-and-single-tasks) - ;; (org-tags-match-list-sublevels t) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(todo-state-down effort-up category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header (concat "Atomic Tasks")) - ;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - ;; ;;(org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE-CANCELLED-WAITING-HOLD/!" - ;; ((org-agenda-overriding-header (concat "Project Subtasks" - ;; (if nd/hide-scheduled-and-waiting-next-tasks - ;; "" - ;; " (including WAITING and SCHEDULED tasks)"))) - ;; (org-agenda-skip-function 'nd/skip-non-project-tasks) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-CANCELLED+WAITING|HOLD/!" - ;; ((org-agenda-overriding-header (concat "Waiting and Postponed Tasks" - ;; (if nd/hide-scheduled-and-waiting-next-tasks - ;; "" - ;; " (including WAITING and SCHEDULED tasks)"))) - ;; (org-agenda-skip-function 'nd/skip-non-tasks) - ;; (org-tags-match-list-sublevels nil) - ;; (org-agenda-todo-ignore-with-date 'all))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Project Next Tasks")) + (org-agenda-skip-function 'nd/skip-non-next-project-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Project Waiting Tasks")) + (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Project Held Tasks")) + (org-agenda-skip-function 'nd/skip-non-held-project-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header (concat "Atomic Tasks")) + (org-agenda-skip-function 'nd/skip-non-atomic-tasks) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep)))) (tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header "Stuck Projects") (org-agenda-skip-function 'nd/skip-non-stuck-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header "Held Projects") + (org-agenda-skip-function 'nd/skip-non-held-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header "Waiting Projects") + (org-agenda-skip-function 'nd/skip-non-waiting-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header "Active Projects") + (org-agenda-skip-function 'nd/skip-non-active-projects) (org-agenda-sorting-strategy '(category-keep))))) ;; (tags-todo "-NA-REFILE/!" @@ -613,6 +619,8 @@ some definitions: (defun nd/heading-has-children () "returns t if heading has todoitems in its immediate subtree" + ;; TODO make this more efficient (and accurate) by only testing + ;; the level immediately below (if it exists) (let ((has-children) (subtree-end (save-excursion (org-end-of-subtree t)))) (save-excursion @@ -641,6 +649,10 @@ some definitions: "return todo keyword if heading is task with no parents" (and (not (nd/heading-has-parent)) (nd/is-task-p))) + (defun nd/is-project-task-p () + "return todo keyword if heading is task with no parents" + (and (nd/heading-has-parent) (nd/is-task-p))) + (defun nd/is-scheduled-heading-p () "return timestamp if headline is scheduled" (org-entry-get nil "SCHEDULED")) @@ -677,8 +689,9 @@ some definitions: (org-forward-heading-same-level 1 t))) found-active)) - ;; projects that have these keywords are not considered in determining status - (defvar nd/project-skip-keywords '("HOLD" "DONE" "CANCELLED")) + (defconst nd/project-invalid-todostates + '("WAITING" "NEXT") + "projects cannot have these todostates") ;; project level testing (defun nd/descend-into-project () @@ -697,16 +710,19 @@ some definitions: (outline-next-heading) (while (and (< project-state 3) (> (point) previous-point)) - (let ((keyword (nd/is-todoitem-p))) + (let ((keyword (nd/is-todoitem-p)) + (has-children (nd/heading-has-children))) (if keyword - (let ((cur-state (cond ((and (not (member keyword nd/project-skip-keywords)) - (nd/heading-has-children)) - (nd/descend-into-project)) - ((equal keyword "HOLD") 1) - ((equal keyword "WAITING") 2) - ((equal keyword "NEXT") 3) - ((nd/is-scheduled-heading-p) 3) - (t 0)))) + (let ((cur-state + (if has-children + (cond ((equal keyword "HOLD") 1) + ((equal keyword "TODO") (nd/descend-into-project)) + (t 0)) + (cond ((equal keyword "HOLD") 1) + ((equal keyword "WAITING") 2) + ((equal keyword "NEXT") 3) + ((nd/is-scheduled-heading-p) 3) + (t 0))))) (if (> cur-state project-state) (setq project-state cur-state))))) (setq previous-point (point)) @@ -714,11 +730,12 @@ some definitions: project-state)) (defun nd/is-project-status-p (statuscode) - ;;TODO maybe return keyword here to consistant? (let ((keyword (nd/is-project-p))) - (and keyword - (not (member keyword nd/project-skip-keywords)) - (equal statuscode (nd/descend-into-project))))) + (if keyword + (cond ((member keyword nd/project-invalid-todostates) nil) + ((and (equal keyword "HOLD") (= statuscode 1)) keyword) + ((and (equal keyword "HOLD") (/= statuscode 1)) nil) + ((= statuscode (nd/descend-into-project)) keyword))))) ;; task skip functions ;; NOTE: use save-restriction and widen if we ever actually use narrowing @@ -726,14 +743,34 @@ some definitions: (if (not (nd/is-atomic-task-p)) (save-excursion (or (outline-next-heading) (point-max))))) - (defun nd/skip-non-projects () - (if (not (nd/is-project-p)) + (defun nd/skip-non-next-project-tasks () + (if (not (equal (nd/is-project-task-p) "NEXT")) + (save-excursion (or (outline-next-heading) (point-max))))) + + (defun nd/skip-non-waiting-project-tasks () + (if (not (equal (nd/is-project-task-p) "WAITING")) + (save-excursion (or (outline-next-heading) (point-max))))) + + (defun nd/skip-non-held-project-tasks () + (if (not (equal (nd/is-project-task-p) "HOLD")) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-stuck-projects () (if (not (nd/is-project-status-p 0)) (save-excursion (or (outline-next-heading) (point-max))))) + (defun nd/skip-non-held-projects () + (if (not (nd/is-project-status-p 1)) + (save-excursion (or (outline-next-heading) (point-max))))) + + (defun nd/skip-non-waiting-projects () + (if (not (nd/is-project-status-p 2)) + (save-excursion (or (outline-next-heading) (point-max))))) + + (defun nd/skip-non-active-projects () + (if (not (nd/is-project-status-p 3)) + (save-excursion (or (outline-next-heading) (point-max))))) + ;; (defvar nd/hide-scheduled-and-waiting-next-tasks t) ;; (defun nd/toggle-next-task-display () From ed94b385aebe2a31987d31fc0533a23619dce084 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Mon, 2 Apr 2018 00:40:42 -0400 Subject: [PATCH 10/17] broke down agenda commands --- conf.el | 461 ++++++++++++++++------------------------------------ conf.org | 485 ++++++++++++++++++------------------------------------- 2 files changed, 296 insertions(+), 650 deletions(-) diff --git a/conf.el b/conf.el index 87ecd70..ffcfe45 100644 --- a/conf.el +++ b/conf.el @@ -271,13 +271,6 @@ ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) -(defun org-summary-todo (n-done n-not-done) - "Switch entry to DONE when all subentries are done, to TODO otherwise." - (let (org-log-done org-log-states) ; turn off logging - (org-todo (if (= n-not-done 0) "DONE" "TODO")))) - -(add-hook 'org-after-todo-statistics-hook 'org-summary-todo) - (setq org-tag-alist (quote ((:startgroup) ("@errand" . ?e) ("@work" . ?o) @@ -343,69 +336,6 @@ (setq org-agenda-tags-column (- 4 (window-width))) (org-agenda-align-tags)) -(setq org-agenda-tags-todo-honor-ignore-options t) -(setq org-agenda-custom-commands - (quote ((" " "Agenda" - ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile") - (org-tags-match-list-sublevels nil))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Project Next Tasks")) - (org-agenda-skip-function 'nd/skip-non-next-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Project Waiting Tasks")) - (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Project Held Tasks")) - (org-agenda-skip-function 'nd/skip-non-held-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Atomic Tasks")) - (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Stuck Projects") - (org-agenda-skip-function 'nd/skip-non-stuck-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Held Projects") - (org-agenda-skip-function 'nd/skip-non-held-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Waiting Projects") - (org-agenda-skip-function 'nd/skip-non-waiting-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Active Projects") - (org-agenda-skip-function 'nd/skip-non-active-projects) - (org-agenda-sorting-strategy - '(category-keep))))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Projects") - ;; (org-agenda-skip-function 'nd/skip-non-projects) - ;; (org-tags-match-list-sublevels 'indented) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags "-NA-REFILE/" - ;; ((org-agenda-overriding-header "Tasks to Archive") - ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - ;; (org-tags-match-list-sublevels nil)))) - nil)))) - (defun nd/org-auto-exclude-function (tag) "Automatic task exclusion in the agenda with / RET" (and (cond @@ -416,34 +346,12 @@ (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) (defun nd/is-todoitem-p () - "return todo keyword if present in headline -(which defines the heading as a todoitem) -this is used to both test if a heading is a todoitem -and retrieve the keyword" + "return todo keyword if present in headline (which defines the heading as a todoitem) +this is used to both test if a heading is a todoitem and retrieving the keyword" (let ((keyword (nth 2 (org-heading-components)))) (if (member keyword org-todo-keywords-1) keyword))) -(defun nd/heading-has-children () - "returns t if heading has todoitems in its immediate subtree" - ;; TODO make this more efficient (and accurate) by only testing - ;; the level immediately below (if it exists) - (let ((has-children) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (save-excursion - (outline-next-heading) - (while (and (not has-children) - (< (point) subtree-end)) - (when (nd/is-todoitem-p) - (setq has-children t)) -;; (org-forward-heading-same-level 1 t))) - (outline-next-heading))) - has-children)) - -(defun nd/heading-has-parent () - "returns parent keyword if heading is in the immediate subtree of a todoitem" - (save-excursion (and (org-up-heading-safe) (nd/is-todoitem-p)))) - (defun nd/is-project-p () "return todo keyword if heading is todoitem and has children" (and (nd/heading-has-children) (nd/is-todoitem-p))) @@ -474,8 +382,30 @@ and retrieve the keyword" "return keyword if task is WAITING" (equal (nd/is-task-p) "WAITING")) -;; org-forward-heading-same-level -;; project level testing +(defconst nd/project-invalid-todostates + '("WAITING" "NEXT") + "projects cannot have these todostates") + +(defun nd/heading-has-children () + "returns t if heading has todoitems in its immediate subtree" + ;; TODO make this more efficient (and accurate) by only testing + ;; the level immediately below (if it exists) + (let ((has-children) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (save-excursion + (outline-next-heading) + (while (and (not has-children) + (< (point) subtree-end)) + (when (nd/is-todoitem-p) + (setq has-children t)) +;; (org-forward-heading-same-level 1 t))) + (outline-next-heading))) + has-children)) + +(defun nd/heading-has-parent () + "returns parent keyword if heading is in the immediate subtree of a todoitem" + (save-excursion (and (org-up-heading-safe) (nd/is-todoitem-p)))) + (defun nd/test-first-order-project () "tests the state of a project assuming first order. if not first order, this function will iterate to the next project @@ -496,39 +426,45 @@ function is not meant to be called independently." (org-forward-heading-same-level 1 t))) found-active)) -(defconst nd/project-invalid-todostates - '("WAITING" "NEXT") - "projects cannot have these todostates") - ;; project level testing +;; TODO: is there a better way to handle statuscodes like this??? (array like thingy) (defun nd/descend-into-project () - "returns numeric value according to state of project: -0: stuck -1: held -2: waiting -3: active + "returns statuscode according to state of project: +0: complete +10: stuck +20: held +30: waiting +40: active -Larger values have precedence over smaller (eg a NEXT -keyword will override any other WAITING or HELD task present" +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 means active. NEXT overrides all + +Using this scheme, we simply compare the magnitude of the statuscodes" (let ((project-state 0) (previous-point)) (save-excursion (setq previous-point (point)) (outline-next-heading) - (while (and (< project-state 3) + (while (and (< project-state 40) (> (point) previous-point)) (let ((keyword (nd/is-todoitem-p)) (has-children (nd/heading-has-children))) (if keyword (let ((cur-state (if has-children - (cond ((equal keyword "HOLD") 1) + (cond ((equal keyword "HOLD") 20) ((equal keyword "TODO") (nd/descend-into-project)) + ;; NOTE: all projects are assumed to only have TODO, HOLD, CANCELLED, or DONE, hence the three possible statuscodes (t 0)) - (cond ((equal keyword "HOLD") 1) - ((equal keyword "WAITING") 2) - ((equal keyword "NEXT") 3) - ((nd/is-scheduled-heading-p) 3) + (cond ((equal keyword "TODO") 10) + ((equal keyword "HOLD") 20) + ((equal keyword "WAITING") 30) + ((equal keyword "NEXT") 40) + ((nd/is-scheduled-heading-p) 40) (t 0))))) (if (> cur-state project-state) (setq project-state cur-state))))) @@ -540,11 +476,10 @@ keyword will override any other WAITING or HELD task present" (let ((keyword (nd/is-project-p))) (if keyword (cond ((member keyword nd/project-invalid-todostates) nil) - ((and (equal keyword "HOLD") (= statuscode 1)) keyword) - ((and (equal keyword "HOLD") (/= statuscode 1)) nil) + ((and (equal keyword "HOLD") (= statuscode 20)) keyword) + ((and (equal keyword "HOLD") (/= statuscode 20)) nil) ((= statuscode (nd/descend-into-project)) keyword))))) -;; task skip functions ;; NOTE: use save-restriction and widen if we ever actually use narrowing (defun nd/skip-non-atomic-tasks () (if (not (nd/is-atomic-task-p)) @@ -563,224 +498,110 @@ keyword will override any other WAITING or HELD task present" (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-stuck-projects () - (if (not (nd/is-project-status-p 0)) + (if (not (nd/is-project-status-p 10)) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-held-projects () - (if (not (nd/is-project-status-p 1)) + (if (not (nd/is-project-status-p 20)) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-waiting-projects () - (if (not (nd/is-project-status-p 2)) + (if (not (nd/is-project-status-p 30)) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-active-projects () - (if (not (nd/is-project-status-p 3)) + (if (not (nd/is-project-status-p 40)) (save-excursion (or (outline-next-heading) (point-max))))) -;; (defvar nd/hide-scheduled-and-waiting-next-tasks t) +(defvar nd/agenda-project-view t) -;; (defun nd/toggle-next-task-display () -;; (interactive) -;; (setq nd/hide-scheduled-and-waiting-next-tasks (not nd/hide-scheduled-and-waiting-next-tasks)) -;; (when (equal major-mode 'org-agenda-mode) -;; (org-agenda-redo)) -;; (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) +(defun nd/toggle-project-display () + (interactive) + (setq nd/agenda-project-view (not nd/agenda-project-view)) + (when (equal major-mode 'org-agenda-mode) + (org-agenda-redo)) + (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) -;; (defun nd/skip-non-stuck-projects () -;; "Skip trees that are not stuck projects" -;; (save-restriction -;; (widen) -;; (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) -;; (if (nd/is-project-p) -;; (let* ((subtree-end (save-excursion (org-end-of-subtree t))) -;; (has-next )) -;; (save-excursion -;; (forward-line 1) -;; (while (and (not has-next) -;; (< (point) subtree-end) -;; (re-search-forward "^\\*+ NEXT " subtree-end t)) -;; (unless (member "WAITING" (org-get-tags-at)) -;; (setq has-next t)))) -;; (if has-next -;; next-headline -;; nil)) ; a stuck project, has subtasks but no next task -;; next-headline)))) +(defun nd/agenda-base-task-command (header skip-fun) + ;;(quote + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header header) + (org-agenda-skip-function skip-fun) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep))))) + +;; (defvar nd/agenda-task-commands +;; (quote +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header (concat "Project Next Tasks")) +;; (org-agenda-skip-function 'nd/skip-non-next-project-tasks) +;; (org-agenda-todo-ignore-with-date 'all) +;; (org-agenda-sorting-strategy +;; '(category-keep)))) +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header (concat "Project Waiting Tasks")) +;; (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) +;; (org-agenda-todo-ignore-with-date 'all) +;; (org-agenda-sorting-strategy +;; '(category-keep)))) +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header (concat "Project Held Tasks")) +;; (org-agenda-skip-function 'nd/skip-non-held-project-tasks) +;; (org-agenda-todo-ignore-with-date 'all) +;; (org-agenda-sorting-strategy +;; '(category-keep)))) +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header (concat "Atomic Tasks")) +;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) +;; (org-agenda-todo-ignore-with-date 'all) +;; (org-agenda-sorting-strategy +;; '(category-keep)))))) + +;; (defvar nd/agenda-project-commands +;; (quote +;; ((tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header "Stuck Projects") +;; (org-agenda-skip-function 'nd/skip-non-stuck-projects) +;; (org-agenda-sorting-strategy +;; '(category-keep)))) +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header "Held Projects") +;; (org-agenda-skip-function 'nd/skip-non-held-projects) +;; (org-agenda-sorting-strategy +;; '(category-keep)))) +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header "Waiting Projects") +;; (org-agenda-skip-function 'nd/skip-non-waiting-projects) +;; (org-agenda-sorting-strategy +;; '(category-keep)))) +;; (tags-todo "-NA-REFILE/!" +;; ((org-agenda-overriding-header "Active +;; (org-agenda-skip-function 'nd/skip-non-active-projects) +;; (org-agenda-sorting-strategy +;; '(category-keep))))))) -;; project test functions -;; is state -;; if project -;; if order = 1 -;; return (state is true) -;; else order > 1 -;; call is state (recursive) -;; else if task -;; return (state is true) -;; note: this needs to iterate through lines -;; (defun nd/is-active-project-p () -;; "return true if project has at least one -;; NEXT/scheduled task or active subproject" -;; ;; if not a project then don't bother -;; (if (nd/is-project-p) -;; (let (((subtree-end (save-excursion (org-end-of-subtree t)))) -;; (is-active)) -;; (save-excursion -;; (while (and (not is-active) -;; (< (point) subtree-end)) -;; (outline-heading-next) -;; (cond ((nd/is-active-task-p) (setq is-active t)) -;; ((nd/is-active-project-p) (setq is-active)))))))) - -;; (defun nd/skip-non-stuck-projects () - ;; goto next headline - ;; if project - ;; if project order 1 - ;; if it has NEXT, WAITING, HOLD, or a scheduled task - ;; then skip (return end of subtree) - ;; else stuck project, return nil - ;; else (order > 1) - ;; descend into project (recursion) - ;; skip (either an atomic task or non-todo, return next heading) -;; ) - -;; (defun nd/skip-non-projects () -;; "Skip trees that are not projects" -;; ;; (nd/list-sublevels-for-projects-indented) -;; (if (save-excursion (nd/skip-non-stuck-projects)) -;; (save-restriction -;; (widen) -;; (let ((subtree-end (save-excursion (org-end-of-subtree t)))) -;; (cond -;; ((nd/is-project-p) -;; nil) -;; ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) -;; nil) -;; (t -;; subtree-end)))) -;; (save-excursion (org-end-of-subtree t)))) - -(defun nd/skip-non-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((nd/is-atomic-p) - nil) - (t - next-headline))))) - -(defun nd/skip-project-trees-and-habits () - "Skip trees that are projects" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - subtree-end) - ;; ((org-is-habit-p) - ;; subtree-end) - (t - nil))))) - -(defun nd/skip-projects-and-habits-and-single-tasks () - "Skip trees that are projects, tasks that are habits, single non-project tasks" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ;; ((org-is-habit-p) - ;; next-headline) - ((and nd/hide-scheduled-and-waiting-next-tasks - (member "WAITING" (org-get-tags-at))) - next-headline) - ((nd/is-project-p) - next-headline) - ((and (nd/is-atomic-p) (not (nd/is-subtask-p))) - next-headline) - (t - nil))))) - -(defun nd/skip-project-tasks-maybe () - "Show tasks related to the current restriction. -When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. -When not restricted, skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (limit-to-project (marker-buffer org-agenda-restrict-begin))) - (cond - ((nd/is-project-p) - next-headline) - ;; ((org-is-habit-p) - ;; subtree-end) - ((and (not limit-to-project) - (nd/is-subtask-p)) - subtree-end) - ((and limit-to-project - (nd/is-subtask-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - (t - nil))))) - -(defun nd/skip-project-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - subtree-end) - ;; ((org-is-habit-p) - ;; subtree-end) - ((nd/is-subtask-p) - subtree-end) - (t - nil))))) - -(defun nd/skip-non-project-tasks () - "Show project tasks. -Skip project and sub-project tasks, habits, and loose non-project tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((nd/is-project-p) - next-headline) - ;; ((org-is-habit-p) - ;; subtree-end) - ((and (nd/is-subtask-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - ((not (nd/is-subtask-p)) - subtree-end) - (t - nil))))) - -(defun nd/skip-projects-and-habits () - "Skip trees that are projects and tasks that are habits" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - subtree-end) - ;; ((org-is-habit-p) - ;; subtree-end) - (t - nil))))) - -;; (defun nd/skip-non-subprojects () -;; "Skip trees that are not projects" -;; (let ((next-headline (save-excursion (outline-next-heading)))) -;; (if (nd/is-subproject-p) -;; nil -;; next-headline))) +(setq org-agenda-tags-todo-honor-ignore-options t) +(setq org-agenda-custom-commands + (quote ((" " "Agenda" + (;;(agenda "" nil) + (tags "REFILE" + ((org-agenda-overriding-header "Tasks to Refile") + (org-tags-match-list-sublevels nil))) + nd/agenda-base-task-command) + ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) + ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Projects") + ;; (org-agenda-skip-function 'nd/skip-non-projects) + ;; (org-tags-match-list-sublevels 'indented) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags "-NA-REFILE/" + ;; ((org-agenda-overriding-header "Tasks to Archive") + ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) + ;; (org-tags-match-list-sublevels nil)))) + nil)))) (use-package org-bullets :ensure t diff --git a/conf.org b/conf.org index 6802f7a..0cacd09 100644 --- a/conf.org +++ b/conf.org @@ -417,7 +417,7 @@ vim is all about escape, not...ctrl+g??? ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) #+END_SRC *** subtask autocomplete -#+BEGIN_SRC emacs-lisp ++BEGIN_SRC emacs-lisp (defun org-summary-todo (n-done n-not-done) "Switch entry to DONE when all subentries are done, to TODO otherwise." (let (org-log-done org-log-states) ; turn off logging @@ -518,72 +518,6 @@ TODO: add meeting template as scheduled+action item thing (setq org-agenda-tags-column (- 4 (window-width))) (org-agenda-align-tags)) #+END_SRC -*** custom commands -#+BEGIN_SRC emacs-lisp - (setq org-agenda-tags-todo-honor-ignore-options t) - (setq org-agenda-custom-commands - (quote ((" " "Agenda" - ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile") - (org-tags-match-list-sublevels nil))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Project Next Tasks")) - (org-agenda-skip-function 'nd/skip-non-next-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Project Waiting Tasks")) - (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Project Held Tasks")) - (org-agenda-skip-function 'nd/skip-non-held-project-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header (concat "Atomic Tasks")) - (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Stuck Projects") - (org-agenda-skip-function 'nd/skip-non-stuck-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Held Projects") - (org-agenda-skip-function 'nd/skip-non-held-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Waiting Projects") - (org-agenda-skip-function 'nd/skip-non-waiting-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header "Active Projects") - (org-agenda-skip-function 'nd/skip-non-active-projects) - (org-agenda-sorting-strategy - '(category-keep))))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Projects") - ;; (org-agenda-skip-function 'nd/skip-non-projects) - ;; (org-tags-match-list-sublevels 'indented) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags "-NA-REFILE/" - ;; ((org-agenda-overriding-header "Tasks to Archive") - ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - ;; (org-tags-match-list-sublevels nil)))) - nil)))) - -#+END_SRC *** auto exclusion #+BEGIN_SRC emacs-lisp (defun nd/org-auto-exclude-function (tag) @@ -595,48 +529,16 @@ TODO: add meeting template as scheduled+action item thing (setq org-agenda-auto-exclude-function 'nd/org-auto-exclude-function) #+END_SRC -*** filtering functions -some definitions: -- todoitem: heading with todo state -- task: todo heading with no todo headings beneath it -- project: todo heading with tasks or other project in subtree -- subtask: task that is part of a project -- subproject: project that is part of another project -- atomic task: task that is not part of a project -- project order: quantifies the degree of project nesting. - - First order projects have only subtasks - - Second order projects have subtasks or first order subprojects - - etc +*** task helper functions +These are the building blocks for skip functions. #+BEGIN_SRC emacs-lisp (defun nd/is-todoitem-p () - "return todo keyword if present in headline - (which defines the heading as a todoitem) - this is used to both test if a heading is a todoitem - and retrieve the keyword" + "return todo keyword if present in headline (which defines the heading as a todoitem) + this is used to both test if a heading is a todoitem and retrieving the keyword" (let ((keyword (nth 2 (org-heading-components)))) (if (member keyword org-todo-keywords-1) keyword))) - (defun nd/heading-has-children () - "returns t if heading has todoitems in its immediate subtree" - ;; TODO make this more efficient (and accurate) by only testing - ;; the level immediately below (if it exists) - (let ((has-children) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (save-excursion - (outline-next-heading) - (while (and (not has-children) - (< (point) subtree-end)) - (when (nd/is-todoitem-p) - (setq has-children t)) - ;; (org-forward-heading-same-level 1 t))) - (outline-next-heading))) - has-children)) - - (defun nd/heading-has-parent () - "returns parent keyword if heading is in the immediate subtree of a todoitem" - (save-excursion (and (org-up-heading-safe) (nd/is-todoitem-p)))) - (defun nd/is-project-p () "return todo keyword if heading is todoitem and has children" (and (nd/heading-has-children) (nd/is-todoitem-p))) @@ -667,8 +569,30 @@ some definitions: "return keyword if task is WAITING" (equal (nd/is-task-p) "WAITING")) - ;; org-forward-heading-same-level - ;; project level testing + (defconst nd/project-invalid-todostates + '("WAITING" "NEXT") + "projects cannot have these todostates") + + (defun nd/heading-has-children () + "returns t if heading has todoitems in its immediate subtree" + ;; TODO make this more efficient (and accurate) by only testing + ;; the level immediately below (if it exists) + (let ((has-children) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (save-excursion + (outline-next-heading) + (while (and (not has-children) + (< (point) subtree-end)) + (when (nd/is-todoitem-p) + (setq has-children t)) + ;; (org-forward-heading-same-level 1 t))) + (outline-next-heading))) + has-children)) + + (defun nd/heading-has-parent () + "returns parent keyword if heading is in the immediate subtree of a todoitem" + (save-excursion (and (org-up-heading-safe) (nd/is-todoitem-p)))) + (defun nd/test-first-order-project () "tests the state of a project assuming first order. if not first order, this function will iterate to the next project @@ -689,39 +613,45 @@ some definitions: (org-forward-heading-same-level 1 t))) found-active)) - (defconst nd/project-invalid-todostates - '("WAITING" "NEXT") - "projects cannot have these todostates") - ;; project level testing + ;; TODO: is there a better way to handle statuscodes like this??? (array like thingy) (defun nd/descend-into-project () - "returns numeric value according to state of project: - 0: stuck - 1: held - 2: waiting - 3: active + "returns statuscode according to state of project: + 0: complete + 10: stuck + 20: held + 30: waiting + 40: active - Larger values have precedence over smaller (eg a NEXT - keyword will override any other WAITING or HELD task present" + 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 means active. NEXT overrides all + + Using this scheme, we simply compare the magnitude of the statuscodes" (let ((project-state 0) (previous-point)) (save-excursion (setq previous-point (point)) (outline-next-heading) - (while (and (< project-state 3) + (while (and (< project-state 40) (> (point) previous-point)) (let ((keyword (nd/is-todoitem-p)) (has-children (nd/heading-has-children))) (if keyword (let ((cur-state (if has-children - (cond ((equal keyword "HOLD") 1) + (cond ((equal keyword "HOLD") 20) ((equal keyword "TODO") (nd/descend-into-project)) + ;; NOTE: all projects are assumed to only have TODO, HOLD, CANCELLED, or DONE, hence the three possible statuscodes (t 0)) - (cond ((equal keyword "HOLD") 1) - ((equal keyword "WAITING") 2) - ((equal keyword "NEXT") 3) - ((nd/is-scheduled-heading-p) 3) + (cond ((equal keyword "TODO") 10) + ((equal keyword "HOLD") 20) + ((equal keyword "WAITING") 30) + ((equal keyword "NEXT") 40) + ((nd/is-scheduled-heading-p) 40) (t 0))))) (if (> cur-state project-state) (setq project-state cur-state))))) @@ -733,11 +663,14 @@ some definitions: (let ((keyword (nd/is-project-p))) (if keyword (cond ((member keyword nd/project-invalid-todostates) nil) - ((and (equal keyword "HOLD") (= statuscode 1)) keyword) - ((and (equal keyword "HOLD") (/= statuscode 1)) nil) + ((and (equal keyword "HOLD") (= statuscode 20)) keyword) + ((and (equal keyword "HOLD") (/= statuscode 20)) nil) ((= statuscode (nd/descend-into-project)) keyword))))) - - ;; task skip functions +#+END_SRC +*** skip functions +These are the primary means we use to sort through tasks. Note that we could do this with +tags in the custom commands section but I find this easier to maintain and possibly faster. +#+BEGIN_SRC emacs-lisp ;; NOTE: use save-restriction and widen if we ever actually use narrowing (defun nd/skip-non-atomic-tasks () (if (not (nd/is-atomic-task-p)) @@ -756,224 +689,116 @@ some definitions: (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-stuck-projects () - (if (not (nd/is-project-status-p 0)) + (if (not (nd/is-project-status-p 10)) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-held-projects () - (if (not (nd/is-project-status-p 1)) + (if (not (nd/is-project-status-p 20)) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-waiting-projects () - (if (not (nd/is-project-status-p 2)) + (if (not (nd/is-project-status-p 30)) (save-excursion (or (outline-next-heading) (point-max))))) (defun nd/skip-non-active-projects () - (if (not (nd/is-project-status-p 3)) + (if (not (nd/is-project-status-p 40)) (save-excursion (or (outline-next-heading) (point-max))))) - ;; (defvar nd/hide-scheduled-and-waiting-next-tasks t) +#+END_SRC +*** interactive view functions +#+BEGIN_SRC emacs-lisp + (defvar nd/agenda-project-view t) - ;; (defun nd/toggle-next-task-display () - ;; (interactive) - ;; (setq nd/hide-scheduled-and-waiting-next-tasks (not nd/hide-scheduled-and-waiting-next-tasks)) - ;; (when (equal major-mode 'org-agenda-mode) - ;; (org-agenda-redo)) - ;; (message "%s WAITING and SCHEDULED NEXT Tasks" (if nd/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + (defun nd/toggle-project-display () + (interactive) + (setq nd/agenda-project-view (not nd/agenda-project-view)) + (when (equal major-mode 'org-agenda-mode) + (org-agenda-redo)) + (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) - ;; (defun nd/skip-non-stuck-projects () - ;; "Skip trees that are not stuck projects" - ;; (save-restriction - ;; (widen) - ;; (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - ;; (if (nd/is-project-p) - ;; (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - ;; (has-next )) - ;; (save-excursion - ;; (forward-line 1) - ;; (while (and (not has-next) - ;; (< (point) subtree-end) - ;; (re-search-forward "^\\*+ NEXT " subtree-end t)) - ;; (unless (member "WAITING" (org-get-tags-at)) - ;; (setq has-next t)))) - ;; (if has-next - ;; next-headline - ;; nil)) ; a stuck project, has subtasks but no next task - ;; next-headline)))) + (defun nd/agenda-base-task-command (header skip-fun) + ;;(quote + (tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header header) + (org-agenda-skip-function skip-fun) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy + '(category-keep))))) + + ;; (defvar nd/agenda-task-commands + ;; (quote + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header (concat "Project Next Tasks")) + ;; (org-agenda-skip-function 'nd/skip-non-next-project-tasks) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header (concat "Project Waiting Tasks")) + ;; (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header (concat "Project Held Tasks")) + ;; (org-agenda-skip-function 'nd/skip-non-held-project-tasks) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header (concat "Atomic Tasks")) + ;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) + ;; (org-agenda-todo-ignore-with-date 'all) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))))) + + ;; (defvar nd/agenda-project-commands + ;; (quote + ;; ((tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Stuck Projects") + ;; (org-agenda-skip-function 'nd/skip-non-stuck-projects) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Held Projects") + ;; (org-agenda-skip-function 'nd/skip-non-held-projects) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Waiting Projects") + ;; (org-agenda-skip-function 'nd/skip-non-waiting-projects) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Active + ;; (org-agenda-skip-function 'nd/skip-non-active-projects) + ;; (org-agenda-sorting-strategy + ;; '(category-keep))))))) +#+END_SRC +*** custom commands +#+BEGIN_SRC emacs-lisp + (setq org-agenda-tags-todo-honor-ignore-options t) + (setq org-agenda-custom-commands + (quote ((" " "Agenda" + (;;(agenda "" nil) + (tags "REFILE" + ((org-agenda-overriding-header "Tasks to Refile") + (org-tags-match-list-sublevels nil))) + nd/agenda-base-task-command) + ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) + ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Projects") + ;; (org-agenda-skip-function 'nd/skip-non-projects) + ;; (org-tags-match-list-sublevels 'indented) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags "-NA-REFILE/" + ;; ((org-agenda-overriding-header "Tasks to Archive") + ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) + ;; (org-tags-match-list-sublevels nil)))) + nil)))) - ;; project test functions - ;; is state - ;; if project - ;; if order = 1 - ;; return (state is true) - ;; else order > 1 - ;; call is state (recursive) - ;; else if task - ;; return (state is true) - ;; note: this needs to iterate through lines - ;; (defun nd/is-active-project-p () - ;; "return true if project has at least one - ;; NEXT/scheduled task or active subproject" - ;; ;; if not a project then don't bother - ;; (if (nd/is-project-p) - ;; (let (((subtree-end (save-excursion (org-end-of-subtree t)))) - ;; (is-active)) - ;; (save-excursion - ;; (while (and (not is-active) - ;; (< (point) subtree-end)) - ;; (outline-heading-next) - ;; (cond ((nd/is-active-task-p) (setq is-active t)) - ;; ((nd/is-active-project-p) (setq is-active)))))))) - - ;; (defun nd/skip-non-stuck-projects () - ;; goto next headline - ;; if project - ;; if project order 1 - ;; if it has NEXT, WAITING, HOLD, or a scheduled task - ;; then skip (return end of subtree) - ;; else stuck project, return nil - ;; else (order > 1) - ;; descend into project (recursion) - ;; skip (either an atomic task or non-todo, return next heading) - ;; ) - - ;; (defun nd/skip-non-projects () - ;; "Skip trees that are not projects" - ;; ;; (nd/list-sublevels-for-projects-indented) - ;; (if (save-excursion (nd/skip-non-stuck-projects)) - ;; (save-restriction - ;; (widen) - ;; (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - ;; (cond - ;; ((nd/is-project-p) - ;; nil) - ;; ((and (nd/is-subtask-p) (not (nd/is-atomic-p))) - ;; nil) - ;; (t - ;; subtree-end)))) - ;; (save-excursion (org-end-of-subtree t)))) - - (defun nd/skip-non-tasks () - "Show non-project tasks. - Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((nd/is-atomic-p) - nil) - (t - next-headline))))) - - (defun nd/skip-project-trees-and-habits () - "Skip trees that are projects" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - subtree-end) - ;; ((org-is-habit-p) - ;; subtree-end) - (t - nil))))) - - (defun nd/skip-projects-and-habits-and-single-tasks () - "Skip trees that are projects, tasks that are habits, single non-project tasks" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ;; ((org-is-habit-p) - ;; next-headline) - ((and nd/hide-scheduled-and-waiting-next-tasks - (member "WAITING" (org-get-tags-at))) - next-headline) - ((nd/is-project-p) - next-headline) - ((and (nd/is-atomic-p) (not (nd/is-subtask-p))) - next-headline) - (t - nil))))) - - (defun nd/skip-project-tasks-maybe () - "Show tasks related to the current restriction. - When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. - When not restricted, skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (limit-to-project (marker-buffer org-agenda-restrict-begin))) - (cond - ((nd/is-project-p) - next-headline) - ;; ((org-is-habit-p) - ;; subtree-end) - ((and (not limit-to-project) - (nd/is-subtask-p)) - subtree-end) - ((and limit-to-project - (nd/is-subtask-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - (t - nil))))) - - (defun nd/skip-project-tasks () - "Show non-project tasks. - Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - subtree-end) - ;; ((org-is-habit-p) - ;; subtree-end) - ((nd/is-subtask-p) - subtree-end) - (t - nil))))) - - (defun nd/skip-non-project-tasks () - "Show project tasks. - Skip project and sub-project tasks, habits, and loose non-project tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((nd/is-project-p) - next-headline) - ;; ((org-is-habit-p) - ;; subtree-end) - ((and (nd/is-subtask-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - ((not (nd/is-subtask-p)) - subtree-end) - (t - nil))))) - - (defun nd/skip-projects-and-habits () - "Skip trees that are projects and tasks that are habits" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((nd/is-project-p) - subtree-end) - ;; ((org-is-habit-p) - ;; subtree-end) - (t - nil))))) - - ;; (defun nd/skip-non-subprojects () - ;; "Skip trees that are not projects" - ;; (let ((next-headline (save-excursion (outline-next-heading)))) - ;; (if (nd/is-subproject-p) - ;; nil - ;; next-headline))) #+END_SRC ** ui *** bullets From 4f6a058ec499185479df99db918efdc24a096c09 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Wed, 4 Apr 2018 10:35:42 -0400 Subject: [PATCH 11/17] added macro to simplify agenda commands --- conf.el | 52 +++++++++++++++++++++++++--------------------------- conf.org | 52 +++++++++++++++++++++++++--------------------------- 2 files changed, 50 insertions(+), 54 deletions(-) diff --git a/conf.el b/conf.el index ffcfe45..83b464d 100644 --- a/conf.el +++ b/conf.el @@ -522,14 +522,12 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (org-agenda-redo)) (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) -(defun nd/agenda-base-task-command (header skip-fun) - ;;(quote - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header header) - (org-agenda-skip-function skip-fun) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep))))) +(defmacro nd/agenda-base-task-command (header skip-fun) + `(tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header ,header) + (org-agenda-skip-function ,skip-fun) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy '(category-keep))))) ;; (defvar nd/agenda-task-commands ;; (quote @@ -583,25 +581,25 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (setq org-agenda-tags-todo-honor-ignore-options t) (setq org-agenda-custom-commands - (quote ((" " "Agenda" - (;;(agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile") - (org-tags-match-list-sublevels nil))) - nd/agenda-base-task-command) - ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) - ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Projects") - ;; (org-agenda-skip-function 'nd/skip-non-projects) - ;; (org-tags-match-list-sublevels 'indented) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags "-NA-REFILE/" - ;; ((org-agenda-overriding-header "Tasks to Archive") - ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - ;; (org-tags-match-list-sublevels nil)))) - nil)))) + `((" " "Agenda" + ((agenda "" nil) + (tags "REFILE" + ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) + (org-tags-match-list-sublevels nil))) + ,(macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))) + ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) + ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Projects") + ;; (org-agenda-skip-function 'nd/skip-non-projects) + ;; (org-tags-match-list-sublevels 'indented) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags "-NA-REFILE/" + ;; ((org-agenda-overriding-header "Tasks to Archive") + ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) + ;; (org-tags-match-list-sublevels nil)))) + nil))) (use-package org-bullets :ensure t diff --git a/conf.org b/conf.org index 0cacd09..f003f09 100644 --- a/conf.org +++ b/conf.org @@ -716,14 +716,12 @@ tags in the custom commands section but I find this easier to maintain and possi (org-agenda-redo)) (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) - (defun nd/agenda-base-task-command (header skip-fun) - ;;(quote - (tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header header) - (org-agenda-skip-function skip-fun) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy - '(category-keep))))) + (defmacro nd/agenda-base-task-command (header skip-fun) + `(tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header ,header) + (org-agenda-skip-function ,skip-fun) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy '(category-keep))))) ;; (defvar nd/agenda-task-commands ;; (quote @@ -779,25 +777,25 @@ tags in the custom commands section but I find this easier to maintain and possi #+BEGIN_SRC emacs-lisp (setq org-agenda-tags-todo-honor-ignore-options t) (setq org-agenda-custom-commands - (quote ((" " "Agenda" - (;;(agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile") - (org-tags-match-list-sublevels nil))) - nd/agenda-base-task-command) - ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) - ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Projects") - ;; (org-agenda-skip-function 'nd/skip-non-projects) - ;; (org-tags-match-list-sublevels 'indented) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags "-NA-REFILE/" - ;; ((org-agenda-overriding-header "Tasks to Archive") - ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - ;; (org-tags-match-list-sublevels nil)))) - nil)))) + `((" " "Agenda" + ((agenda "" nil) + (tags "REFILE" + ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) + (org-tags-match-list-sublevels nil))) + ,(macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))) + ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) + ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) + ;; (tags-todo "-NA-REFILE/!" + ;; ((org-agenda-overriding-header "Projects") + ;; (org-agenda-skip-function 'nd/skip-non-projects) + ;; (org-tags-match-list-sublevels 'indented) + ;; (org-agenda-sorting-strategy + ;; '(category-keep)))) + ;; (tags "-NA-REFILE/" + ;; ((org-agenda-overriding-header "Tasks to Archive") + ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) + ;; (org-tags-match-list-sublevels nil)))) + nil))) #+END_SRC ** ui From 2166b247233907d1da21715a507f0e1b0ec2246f Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Thu, 5 Apr 2018 09:29:58 -0400 Subject: [PATCH 12/17] try to combine if logic to agenda views --- conf.el | 39 ++++++++++++--------------------------- conf.org | 39 ++++++++++++--------------------------- 2 files changed, 24 insertions(+), 54 deletions(-) diff --git a/conf.el b/conf.el index 83b464d..c875f61 100644 --- a/conf.el +++ b/conf.el @@ -529,32 +529,15 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (org-agenda-todo-ignore-with-date 'all) (org-agenda-sorting-strategy '(category-keep))))) -;; (defvar nd/agenda-task-commands -;; (quote -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header (concat "Project Next Tasks")) -;; (org-agenda-skip-function 'nd/skip-non-next-project-tasks) -;; (org-agenda-todo-ignore-with-date 'all) -;; (org-agenda-sorting-strategy -;; '(category-keep)))) -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header (concat "Project Waiting Tasks")) -;; (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) -;; (org-agenda-todo-ignore-with-date 'all) -;; (org-agenda-sorting-strategy -;; '(category-keep)))) -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header (concat "Project Held Tasks")) -;; (org-agenda-skip-function 'nd/skip-non-held-project-tasks) -;; (org-agenda-todo-ignore-with-date 'all) -;; (org-agenda-sorting-strategy -;; '(category-keep)))) -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header (concat "Atomic Tasks")) -;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) -;; (org-agenda-todo-ignore-with-date 'all) -;; (org-agenda-sorting-strategy -;; '(category-keep)))))) +(defmacro nd/agenda-base-project-command (header skip-fun) + `(tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header ,header) + (org-agenda-skip-function ,skip-fun) + (org-agenda-sorting-strategy '(category-keep))))) + +;; (defmacro nd/agenda-task-commands () +;; (apply #'values '((macroexpand '(nd/agenda-base-task-command "Project Next Tasks" 'nd/skip-non-next-project-task)) +;; (macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))))) ;; (defvar nd/agenda-project-commands ;; (quote @@ -586,7 +569,9 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (tags "REFILE" ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) (org-tags-match-list-sublevels nil))) - ,(macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))) + (if nd/agenda-project-view + ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) + ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) ;; (tags-todo "-NA-REFILE/!" diff --git a/conf.org b/conf.org index f003f09..52ed2bd 100644 --- a/conf.org +++ b/conf.org @@ -723,32 +723,15 @@ tags in the custom commands section but I find this easier to maintain and possi (org-agenda-todo-ignore-with-date 'all) (org-agenda-sorting-strategy '(category-keep))))) - ;; (defvar nd/agenda-task-commands - ;; (quote - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header (concat "Project Next Tasks")) - ;; (org-agenda-skip-function 'nd/skip-non-next-project-tasks) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header (concat "Project Waiting Tasks")) - ;; (org-agenda-skip-function 'nd/skip-non-waiting-project-tasks) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header (concat "Project Held Tasks")) - ;; (org-agenda-skip-function 'nd/skip-non-held-project-tasks) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header (concat "Atomic Tasks")) - ;; (org-agenda-skip-function 'nd/skip-non-atomic-tasks) - ;; (org-agenda-todo-ignore-with-date 'all) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))))) + (defmacro nd/agenda-base-project-command (header skip-fun) + `(tags-todo "-NA-REFILE/!" + ((org-agenda-overriding-header ,header) + (org-agenda-skip-function ,skip-fun) + (org-agenda-sorting-strategy '(category-keep))))) + + ;; (defmacro nd/agenda-task-commands () + ;; (apply #'values '((macroexpand '(nd/agenda-base-task-command "Project Next Tasks" 'nd/skip-non-next-project-task)) + ;; (macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))))) ;; (defvar nd/agenda-project-commands ;; (quote @@ -782,7 +765,9 @@ tags in the custom commands section but I find this easier to maintain and possi (tags "REFILE" ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) (org-tags-match-list-sublevels nil))) - ,(macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))) + (if nd/agenda-project-view + ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) + ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) ;; (tags-todo "-NA-REFILE/!" From 8269f1774674cba6042d2018642d93230bf61caa Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Thu, 5 Apr 2018 15:39:04 -0400 Subject: [PATCH 13/17] currently debugging agenda commands --- conf.el | 20 ++++++++++---------- conf.org | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/conf.el b/conf.el index c875f61..b54586a 100644 --- a/conf.el +++ b/conf.el @@ -523,14 +523,14 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) (defmacro nd/agenda-base-task-command (header skip-fun) - `(tags-todo "-NA-REFILE/!" + `(list tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header ,header) (org-agenda-skip-function ,skip-fun) (org-agenda-todo-ignore-with-date 'all) (org-agenda-sorting-strategy '(category-keep))))) (defmacro nd/agenda-base-project-command (header skip-fun) - `(tags-todo "-NA-REFILE/!" + `(list tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header ,header) (org-agenda-skip-function ,skip-fun) (org-agenda-sorting-strategy '(category-keep))))) @@ -564,14 +564,14 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (setq org-agenda-tags-todo-honor-ignore-options t) (setq org-agenda-custom-commands - `((" " "Agenda" - ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) - (org-tags-match-list-sublevels nil))) - (if nd/agenda-project-view - ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) - ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) + '((" " "Agenda" + ((if t '(agenda "" nil))) + ;; (tags "REFILE" + ;; ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) + ;; (org-tags-match-list-sublevels nil))) + ;; (if nd/agenda-project-view + ;; ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) + ;; ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) ;; (tags-todo "-NA-REFILE/!" diff --git a/conf.org b/conf.org index 52ed2bd..dfc4ddc 100644 --- a/conf.org +++ b/conf.org @@ -717,14 +717,14 @@ tags in the custom commands section but I find this easier to maintain and possi (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) (defmacro nd/agenda-base-task-command (header skip-fun) - `(tags-todo "-NA-REFILE/!" + `(list tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header ,header) (org-agenda-skip-function ,skip-fun) (org-agenda-todo-ignore-with-date 'all) (org-agenda-sorting-strategy '(category-keep))))) (defmacro nd/agenda-base-project-command (header skip-fun) - `(tags-todo "-NA-REFILE/!" + `(list tags-todo "-NA-REFILE/!" ((org-agenda-overriding-header ,header) (org-agenda-skip-function ,skip-fun) (org-agenda-sorting-strategy '(category-keep))))) @@ -760,14 +760,14 @@ tags in the custom commands section but I find this easier to maintain and possi #+BEGIN_SRC emacs-lisp (setq org-agenda-tags-todo-honor-ignore-options t) (setq org-agenda-custom-commands - `((" " "Agenda" - ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) - (org-tags-match-list-sublevels nil))) - (if nd/agenda-project-view - ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) - ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) + '((" " "Agenda" + ((if t '(agenda "" nil))) + ;; (tags "REFILE" + ;; ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) + ;; (org-tags-match-list-sublevels nil))) + ;; (if nd/agenda-project-view + ;; ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) + ;; ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) ;; (tags-todo "-NA-REFILE/!" From 1702b022afb7e712737ddae4fd180348c3a2f245 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Thu, 5 Apr 2018 23:17:16 -0400 Subject: [PATCH 14/17] cannot do what I want...need to think --- conf.el | 11 ++++++----- conf.org | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/conf.el b/conf.el index b54586a..49ad23a 100644 --- a/conf.el +++ b/conf.el @@ -563,12 +563,13 @@ Using this scheme, we simply compare the magnitude of the statuscodes" ;; '(category-keep))))))) (setq org-agenda-tags-todo-honor-ignore-options t) +(setq testy 'tags) (setq org-agenda-custom-commands - '((" " "Agenda" - ((if t '(agenda "" nil))) - ;; (tags "REFILE" - ;; ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) - ;; (org-tags-match-list-sublevels nil))) + `((" " "Agenda" + ((agenda "" nil) + (,testy "REFILE" + ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) + (org-tags-match-list-sublevels nil)))) ;; (if nd/agenda-project-view ;; ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) ;; ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) diff --git a/conf.org b/conf.org index dfc4ddc..703cea9 100644 --- a/conf.org +++ b/conf.org @@ -761,10 +761,10 @@ tags in the custom commands section but I find this easier to maintain and possi (setq org-agenda-tags-todo-honor-ignore-options t) (setq org-agenda-custom-commands '((" " "Agenda" - ((if t '(agenda "" nil))) - ;; (tags "REFILE" - ;; ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) - ;; (org-tags-match-list-sublevels nil))) + ((agenda "" nil) + (tags "REFILE" + ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) + (org-tags-match-list-sublevels nil)))) ;; (if nd/agenda-project-view ;; ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) ;; ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) From 3aad920ff118be8737df61cca81924295bec9d24 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sat, 7 Apr 2018 21:04:01 -0400 Subject: [PATCH 15/17] completed skip functions and toggle state --- conf.el | 131 +++++++++++++++++++++------------------------------ conf.org | 139 +++++++++++++++++++++++-------------------------------- 2 files changed, 109 insertions(+), 161 deletions(-) diff --git a/conf.el b/conf.el index 49ad23a..6a79645 100644 --- a/conf.el +++ b/conf.el @@ -324,8 +324,9 @@ (setq org-agenda-dim-blocked-tasks nil) (setq org-agenda-compact-blocks t) -(setq org-agenda-span 'day) +(evil-define-key 'motion org-agenda-mode-map "T" 'nd/toggle-project-toplevel-display) +(setq org-agenda-span 'day) (setq org-agenda-time-grid (quote ((daily today remove-match) #("----------------" 0 16 (org-heading t)) (0900 1100 1300 1500 1700)))) @@ -435,6 +436,7 @@ function is not meant to be called independently." 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) @@ -460,11 +462,11 @@ Using this scheme, we simply compare the magnitude of the statuscodes" ((equal keyword "TODO") (nd/descend-into-project)) ;; NOTE: all projects are assumed to only have TODO, HOLD, CANCELLED, or DONE, hence the three possible statuscodes (t 0)) - (cond ((equal keyword "TODO") 10) - ((equal keyword "HOLD") 20) + (cond ((equal keyword "HOLD") 20) ((equal keyword "WAITING") 30) ((equal keyword "NEXT") 40) - ((nd/is-scheduled-heading-p) 40) + ((and (equal keyword "TODO") (nd/is-scheduled-heading-p)) 40) + ((equal keyword "TODO") 10) (t 0))))) (if (> cur-state project-state) (setq project-state cur-state))))) @@ -481,6 +483,7 @@ Using this scheme, we simply compare the magnitude of the statuscodes" ((= statuscode (nd/descend-into-project)) keyword))))) ;; NOTE: use save-restriction and widen if we ever actually use narrowing +;; tasks (defun nd/skip-non-atomic-tasks () (if (not (nd/is-atomic-task-p)) (save-excursion (or (outline-next-heading) (point-max))))) @@ -497,95 +500,65 @@ Using this scheme, we simply compare the magnitude of the statuscodes" (if (not (equal (nd/is-project-task-p) "HOLD")) (save-excursion (or (outline-next-heading) (point-max))))) -(defun nd/skip-non-stuck-projects () - (if (not (nd/is-project-status-p 10)) +;; projects +(defun nd/skip-projects-without-statuscode (statuscode) + (if (not (nd/is-project-status-p statuscode)) (save-excursion (or (outline-next-heading) (point-max))))) -(defun nd/skip-non-held-projects () - (if (not (nd/is-project-status-p 20)) +;; top-level projects +(defun nd/skip-subprojects-without-statuscode (statuscode) + (if (or (nd/heading-has-parent) (not (nd/is-project-status-p statuscode))) (save-excursion (or (outline-next-heading) (point-max))))) -(defun nd/skip-non-waiting-projects () - (if (not (nd/is-project-status-p 30)) - (save-excursion (or (outline-next-heading) (point-max))))) +(defvar nd/agenda-limit-project-toplevel t + "used to filter projects by all levels or top-level only") -(defun nd/skip-non-active-projects () - (if (not (nd/is-project-status-p 40)) - (save-excursion (or (outline-next-heading) (point-max))))) - -(defvar nd/agenda-project-view t) - -(defun nd/toggle-project-display () +(defun nd/toggle-project-toplevel-display () (interactive) - (setq nd/agenda-project-view (not nd/agenda-project-view)) + (setq nd/agenda-limit-project-toplevel (not nd/agenda-limit-project-toplevel)) (when (equal major-mode 'org-agenda-mode) (org-agenda-redo)) - (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) + (message "Showing %s project view in agenda" (if nd/agenda-limit-project-toplevel "toplevel" "complete"))) -(defmacro nd/agenda-base-task-command (header skip-fun) - `(list tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header ,header) - (org-agenda-skip-function ,skip-fun) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy '(category-keep))))) - -(defmacro nd/agenda-base-project-command (header skip-fun) - `(list tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header ,header) - (org-agenda-skip-function ,skip-fun) - (org-agenda-sorting-strategy '(category-keep))))) +(defmacro nd/agenda-base-task-command (keyword skip-fun) + "shorter syntax to define task agenda commands" + `(tags-todo + "-NA-REFILE/!" + ((org-agenda-overriding-header (concat ,keyword " Tasks")) + (org-agenda-skip-function ,skip-fun) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy '(category-keep))))) -;; (defmacro nd/agenda-task-commands () -;; (apply #'values '((macroexpand '(nd/agenda-base-task-command "Project Next Tasks" 'nd/skip-non-next-project-task)) -;; (macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))))) - -;; (defvar nd/agenda-project-commands -;; (quote -;; ((tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header "Stuck Projects") -;; (org-agenda-skip-function 'nd/skip-non-stuck-projects) -;; (org-agenda-sorting-strategy -;; '(category-keep)))) -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header "Held Projects") -;; (org-agenda-skip-function 'nd/skip-non-held-projects) -;; (org-agenda-sorting-strategy -;; '(category-keep)))) -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header "Waiting Projects") -;; (org-agenda-skip-function 'nd/skip-non-waiting-projects) -;; (org-agenda-sorting-strategy -;; '(category-keep)))) -;; (tags-todo "-NA-REFILE/!" -;; ((org-agenda-overriding-header "Active -;; (org-agenda-skip-function 'nd/skip-non-active-projects) -;; (org-agenda-sorting-strategy -;; '(category-keep))))))) +(defmacro nd/agenda-base-project-command (keyword statuscode) + "shorter syntax to define project agenda commands" + `(tags-todo + "-NA-REFILE-ATOMIC/!" + ((org-agenda-overriding-header (concat + (and nd/agenda-limit-project-toplevel "Toplevel ") + ,keyword + " Projects")) + (org-agenda-skip-function (if nd/agenda-limit-project-toplevel + '(nd/skip-subprojects-without-statuscode ,statuscode) + '(nd/skip-projects-without-statuscode ,statuscode))) + (org-agenda-sorting-strategy '(category-keep))))) (setq org-agenda-tags-todo-honor-ignore-options t) -(setq testy 'tags) (setq org-agenda-custom-commands - `((" " "Agenda" + `(("t" "Task view" ((agenda "" nil) - (,testy "REFILE" - ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) - (org-tags-match-list-sublevels nil)))) - ;; (if nd/agenda-project-view - ;; ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) - ;; ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) - ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) - ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Projects") - ;; (org-agenda-skip-function 'nd/skip-non-projects) - ;; (org-tags-match-list-sublevels 'indented) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags "-NA-REFILE/" - ;; ((org-agenda-overriding-header "Tasks to Archive") - ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - ;; (org-tags-match-list-sublevels nil)))) - nil))) + ,(macroexpand '(nd/agenda-base-task-command "Next Project" 'nd/skip-non-next-project-tasks)) + ,(macroexpand '(nd/agenda-base-task-command "Waiting Project" 'nd/skip-non-waiting-project-tasks)) + ,(macroexpand '(nd/agenda-base-task-command "Atomic" 'nd/skip-non-atomic-tasks)) + ,(macroexpand '(nd/agenda-base-task-command "Held Project" 'nd/skip-non-held-project-tasks)))) + ("o" "Project Overview" + (,(macroexpand '(nd/agenda-base-project-command "Stuck" 10)) + ,(macroexpand '(nd/agenda-base-project-command "Waiting" 20)) + ,(macroexpand '(nd/agenda-base-project-command "Active" 40)) + ,(macroexpand '(nd/agenda-base-project-command "Held" 30)))) + ("r" "Refile and errors" + ((tags "REFILE" + ((org-agenda-overriding-header "Tasks to Refile")) + (org-tags-match-list-sublevels nil)))))) (use-package org-bullets :ensure t diff --git a/conf.org b/conf.org index 703cea9..a9aeafe 100644 --- a/conf.org +++ b/conf.org @@ -499,18 +499,20 @@ TODO: add meeting template as scheduled+action item thing (setq org-agenda-dim-blocked-tasks nil) (setq org-agenda-compact-blocks t) #+END_SRC +*** keymap +#+BEGIN_SRC emacs-lisp + (evil-define-key 'motion org-agenda-mode-map "T" 'nd/toggle-project-toplevel-display) +#+END_SRC *** views -**** show only today +**** calendar display #+BEGIN_SRC emacs-lisp (setq org-agenda-span 'day) -#+End_src -**** display time grid -#+BEGIN_SRC emacs-lisp (setq org-agenda-time-grid (quote ((daily today remove-match) #("----------------" 0 16 (org-heading t)) (0900 1100 1300 1500 1700)))) -#+END_SRC +#+End_src **** right align tags +the agenda does not do this by default...it's annoying #+BEGIN_SRC emacs-lisp (add-hook 'org-finalize-agenda-hook 'place-agenda-tags) (defun place-agenda-tags () @@ -622,6 +624,7 @@ These are the building blocks for skip functions. 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) @@ -647,11 +650,11 @@ These are the building blocks for skip functions. ((equal keyword "TODO") (nd/descend-into-project)) ;; NOTE: all projects are assumed to only have TODO, HOLD, CANCELLED, or DONE, hence the three possible statuscodes (t 0)) - (cond ((equal keyword "TODO") 10) - ((equal keyword "HOLD") 20) + (cond ((equal keyword "HOLD") 20) ((equal keyword "WAITING") 30) ((equal keyword "NEXT") 40) - ((nd/is-scheduled-heading-p) 40) + ((and (equal keyword "TODO") (nd/is-scheduled-heading-p)) 40) + ((equal keyword "TODO") 10) (t 0))))) (if (> cur-state project-state) (setq project-state cur-state))))) @@ -672,6 +675,7 @@ These are the primary means we use to sort through tasks. Note that we could do tags in the custom commands section but I find this easier to maintain and possibly faster. #+BEGIN_SRC emacs-lisp ;; NOTE: use save-restriction and widen if we ever actually use narrowing + ;; tasks (defun nd/skip-non-atomic-tasks () (if (not (nd/is-atomic-task-p)) (save-excursion (or (outline-next-heading) (point-max))))) @@ -688,99 +692,70 @@ tags in the custom commands section but I find this easier to maintain and possi (if (not (equal (nd/is-project-task-p) "HOLD")) (save-excursion (or (outline-next-heading) (point-max))))) - (defun nd/skip-non-stuck-projects () - (if (not (nd/is-project-status-p 10)) + ;; projects + (defun nd/skip-projects-without-statuscode (statuscode) + (if (not (nd/is-project-status-p statuscode)) (save-excursion (or (outline-next-heading) (point-max))))) - (defun nd/skip-non-held-projects () - (if (not (nd/is-project-status-p 20)) + ;; top-level projects + (defun nd/skip-subprojects-without-statuscode (statuscode) + (if (or (nd/heading-has-parent) (not (nd/is-project-status-p statuscode))) (save-excursion (or (outline-next-heading) (point-max))))) - - (defun nd/skip-non-waiting-projects () - (if (not (nd/is-project-status-p 30)) - (save-excursion (or (outline-next-heading) (point-max))))) - - (defun nd/skip-non-active-projects () - (if (not (nd/is-project-status-p 40)) - (save-excursion (or (outline-next-heading) (point-max))))) - #+END_SRC *** interactive view functions #+BEGIN_SRC emacs-lisp - (defvar nd/agenda-project-view t) + (defvar nd/agenda-limit-project-toplevel t + "used to filter projects by all levels or top-level only") - (defun nd/toggle-project-display () + (defun nd/toggle-project-toplevel-display () (interactive) - (setq nd/agenda-project-view (not nd/agenda-project-view)) + (setq nd/agenda-limit-project-toplevel (not nd/agenda-limit-project-toplevel)) (when (equal major-mode 'org-agenda-mode) (org-agenda-redo)) - (message "%s project view in agenda" (if nd/agenda-project-view "Showing" "Hiding"))) + (message "Showing %s project view in agenda" (if nd/agenda-limit-project-toplevel "toplevel" "complete"))) - (defmacro nd/agenda-base-task-command (header skip-fun) - `(list tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header ,header) - (org-agenda-skip-function ,skip-fun) - (org-agenda-todo-ignore-with-date 'all) - (org-agenda-sorting-strategy '(category-keep))))) - - (defmacro nd/agenda-base-project-command (header skip-fun) - `(list tags-todo "-NA-REFILE/!" - ((org-agenda-overriding-header ,header) - (org-agenda-skip-function ,skip-fun) - (org-agenda-sorting-strategy '(category-keep))))) + (defmacro nd/agenda-base-task-command (keyword skip-fun) + "shorter syntax to define task agenda commands" + `(tags-todo + "-NA-REFILE/!" + ((org-agenda-overriding-header (concat ,keyword " Tasks")) + (org-agenda-skip-function ,skip-fun) + (org-agenda-todo-ignore-with-date 'all) + (org-agenda-sorting-strategy '(category-keep))))) - ;; (defmacro nd/agenda-task-commands () - ;; (apply #'values '((macroexpand '(nd/agenda-base-task-command "Project Next Tasks" 'nd/skip-non-next-project-task)) - ;; (macroexpand '(nd/agenda-base-task-command "Atomic tasks" 'nd/skip-non-atomic-tasks))))) + (defmacro nd/agenda-base-project-command (keyword statuscode) + "shorter syntax to define project agenda commands" + `(tags-todo + "-NA-REFILE-ATOMIC/!" + ((org-agenda-overriding-header (concat + (and nd/agenda-limit-project-toplevel "Toplevel ") + ,keyword + " Projects")) + (org-agenda-skip-function (if nd/agenda-limit-project-toplevel + '(nd/skip-subprojects-without-statuscode ,statuscode) + '(nd/skip-projects-without-statuscode ,statuscode))) + (org-agenda-sorting-strategy '(category-keep))))) - ;; (defvar nd/agenda-project-commands - ;; (quote - ;; ((tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Stuck Projects") - ;; (org-agenda-skip-function 'nd/skip-non-stuck-projects) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Held Projects") - ;; (org-agenda-skip-function 'nd/skip-non-held-projects) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Waiting Projects") - ;; (org-agenda-skip-function 'nd/skip-non-waiting-projects) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Active - ;; (org-agenda-skip-function 'nd/skip-non-active-projects) - ;; (org-agenda-sorting-strategy - ;; '(category-keep))))))) #+END_SRC *** custom commands #+BEGIN_SRC emacs-lisp (setq org-agenda-tags-todo-honor-ignore-options t) (setq org-agenda-custom-commands - '((" " "Agenda" + `(("t" "Task view" ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header (if nd/agenda-project-view "Tasks to Refile" "Herro")) - (org-tags-match-list-sublevels nil)))) - ;; (if nd/agenda-project-view - ;; ,(macroexpand '(nd/agenda-base-task-command "Atomic Tasks" 'nd/skip-non-atomic-tasks)) - ;; ,(macroexpand '(nd/agenda-base-project-command "Active Projects" 'nd/skip-non-active-projects)))) - ;;(nd/agenda-base-task-command "Project next tasks" 'nd/skip-non-next-project-tasks)) - ;;(if nd/agenda-project-view nd/agenda-project-commands nd/agenda-task-commands)) - ;; (tags-todo "-NA-REFILE/!" - ;; ((org-agenda-overriding-header "Projects") - ;; (org-agenda-skip-function 'nd/skip-non-projects) - ;; (org-tags-match-list-sublevels 'indented) - ;; (org-agenda-sorting-strategy - ;; '(category-keep)))) - ;; (tags "-NA-REFILE/" - ;; ((org-agenda-overriding-header "Tasks to Archive") - ;; (org-agenda-skip-function 'nd/skip-non-archivable-tasks) - ;; (org-tags-match-list-sublevels nil)))) - nil))) + ,(macroexpand '(nd/agenda-base-task-command "Next Project" 'nd/skip-non-next-project-tasks)) + ,(macroexpand '(nd/agenda-base-task-command "Waiting Project" 'nd/skip-non-waiting-project-tasks)) + ,(macroexpand '(nd/agenda-base-task-command "Atomic" 'nd/skip-non-atomic-tasks)) + ,(macroexpand '(nd/agenda-base-task-command "Held Project" 'nd/skip-non-held-project-tasks)))) + ("o" "Project Overview" + (,(macroexpand '(nd/agenda-base-project-command "Stuck" 10)) + ,(macroexpand '(nd/agenda-base-project-command "Waiting" 20)) + ,(macroexpand '(nd/agenda-base-project-command "Active" 40)) + ,(macroexpand '(nd/agenda-base-project-command "Held" 30)))) + ("r" "Refile and errors" + ((tags "REFILE" + ((org-agenda-overriding-header "Tasks to Refile")) + (org-tags-match-list-sublevels nil)))))) #+END_SRC ** ui From e114a114d226746115181d30a053ca917e944231 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sat, 7 Apr 2018 23:47:08 -0400 Subject: [PATCH 16/17] removed triggers and top down DONE state enforcement --- conf.el | 9 --------- conf.org | 20 -------------------- 2 files changed, 29 deletions(-) diff --git a/conf.el b/conf.el index 6a79645..13efc93 100644 --- a/conf.el +++ b/conf.el @@ -262,15 +262,6 @@ ("HOLD" :foreground "violet" :weight bold) ("CANCELLED" :foreground "deep sky blue" :weight bold)))) -(setq org-todo-state-tags-triggers - (quote (("CANCELLED" ("CANCELLED" . t)) - ("WAITING" ("WAITING" . t)) - ("HOLD" ("WAITING") ("HOLD" . t)) - (done ("WAITING") ("HOLD")) - ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) - ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) - ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) - (setq org-tag-alist (quote ((:startgroup) ("@errand" . ?e) ("@work" . ?o) diff --git a/conf.org b/conf.org index a9aeafe..5f2e4e7 100644 --- a/conf.org +++ b/conf.org @@ -405,26 +405,6 @@ vim is all about escape, not...ctrl+g??? ("HOLD" :foreground "violet" :weight bold) ("CANCELLED" :foreground "deep sky blue" :weight bold)))) #+END_SRC -*** triggers -#+BEGIN_SRC emacs-lisp -(setq org-todo-state-tags-triggers - (quote (("CANCELLED" ("CANCELLED" . t)) - ("WAITING" ("WAITING" . t)) - ("HOLD" ("WAITING") ("HOLD" . t)) - (done ("WAITING") ("HOLD")) - ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) - ("NEXT" ("WAITING") ("CANCELLED") ("HOLD")) - ("DONE" ("WAITING") ("CANCELLED") ("HOLD"))))) -#+END_SRC -*** subtask autocomplete -+BEGIN_SRC emacs-lisp - (defun org-summary-todo (n-done n-not-done) - "Switch entry to DONE when all subentries are done, to TODO otherwise." - (let (org-log-done org-log-states) ; turn off logging - (org-todo (if (= n-not-done 0) "DONE" "TODO")))) - - (add-hook 'org-after-todo-statistics-hook 'org-summary-todo) -#+END_SRC ** tag selection keys #+BEGIN_SRC emacs-lisp (setq org-tag-alist (quote ((:startgroup) From 8cde66d3031c855903a5b0f543a0f53e43202b08 Mon Sep 17 00:00:00 2001 From: petrucci4prez Date: Sun, 8 Apr 2018 01:10:01 -0400 Subject: [PATCH 17/17] modded some keymaps and tags faces --- conf.el | 60 ++++++++++++++++++++++++---------------------- conf.org | 73 ++++++++++++++++++++++++++++---------------------------- 2 files changed, 68 insertions(+), 65 deletions(-) diff --git a/conf.el b/conf.el index 13efc93..7c0c3a2 100644 --- a/conf.el +++ b/conf.el @@ -65,6 +65,10 @@ (global-set-key (kbd "C-h a") 'apropos) +(global-set-key (kbd "") 'org-agenda) +(global-set-key (kbd "") 'org-capture) +(global-set-key (kbd "") 'org-iswitchb) + (use-package delight :ensure t) @@ -226,7 +230,7 @@ (load "ess-site") (setq ess-history-file "session.Rhistory") (setq ess-history-directory - (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) + (substitute-in-file-name "${XDG_CONFIG_HOME}/r/")) (setq org-log-done t) (setq org-src-window-setup 'current-window) @@ -239,20 +243,13 @@ (add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC")) -(global-set-key "\C-cl" 'org-store-link) -(global-set-key "\C-ca" 'org-agenda) -(global-set-key "\C-cb" 'org-iswitchb) -(global-set-key (kbd "C-c c") 'org-capture) - -;; consider adding f1-12 shortcuts for org things that must be a) fast and b) work in any mode - (setq org-special-ctrl-a/e t) (setq org-special-ctrl-k t) (setq org-yank-adjusted-subtrees t) (setq org-todo-keywords - (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") - (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)")))) + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") + (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)"))) (setq org-todo-keyword-faces (quote (("TODO" :foreground "light coral" :weight bold) @@ -264,33 +261,38 @@ (setq org-tag-alist (quote ((:startgroup) ("@errand" . ?e) - ("@work" . ?o) + ("@work" . ?w) ("@home" . ?h) ("@travel" . ?f) (:endgroup) ("LAPTOP" . ?L) - ("WAITING" . ?W) - ("HOLD" . ?H) ("PERSONAL" . ?P) - ("WORK" . ?O) + ("WORK" . ?W) ("NOTE" . ?N) - ("CANCELLED" . ?C) ("FLAGGED" . ??)))) -(setq org-capture-templates - (quote (("t" "todo" entry (file "~/Org/capture.org") "* TODO %?\n%U\n") - ("n" "note" entry (file "~/Org/capture.org") "* %? :NOTE:\n%U\n" ) - ("a" "appointment" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t\n" ) - ("m" "multi-day" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t--%^t\n" ) - ("d" "deadline" entry (file "~/Org/capture.org") "* TODO %?\nDEADLINE: %^t\n%U\n" ) +;; TODO I'm sure there is a better way to do this in lisp +(setq org-tag-faces + '(("LAPTOP" . (:foreground "PaleGreen")) + ("PERSONAL" . (:foreground "PaleGreen")) + ("WORK" . (:foreground "PaleGreen")) + ("NOTE" . (:foreground "PaleGreen")) + ("FLAGGED" . (:foreground "PaleGreen")))) - ("j" "journal" entry (file+datetree "~/Org/diary.org") "* %?\n%U\n") - ("p" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") - "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") - ("L" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") - "* %? [[%:link][%:description]] \nCaptured On: %U") - ("h" "habit" entry (file "~/Org/capture.org") - "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n")))) +(setq org-capture-templates + '(("t" "todo" entry (file "~/Org/capture.org") "* TODO %?\n%U\n") + ("n" "note" entry (file "~/Org/capture.org") "* %? :NOTE:\n%U\n" ) + ("a" "appointment" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t\n" ) + ("m" "multi-day" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t--%^t\n" ) + ("d" "deadline" entry (file "~/Org/capture.org") "* TODO %?\nDEADLINE: %^t\n%U\n" ) + + ("j" "journal" entry (file+datetree "~/Org/diary.org") "* %?\n%U\n") + ("p" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") + "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") + ("L" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") + "* %? [[%:link][%:description]] \nCaptured On: %U") + ("h" "habit" entry (file "~/Org/capture.org") + "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n"))) (setq org-refile-targets (quote ((nil :maxlevel . 9) ("~/Org/reference/idea.org" :maxlevel . 9) @@ -300,7 +302,7 @@ (setq org-outline-path-complete-in-steps nil) (setq org-completion-use-ido t) -(setq org-refile-allow-creating-parent-nodes (quote confirm)) +(setq org-refile-allow-creating-parent-nodes 'confirm) (setq org-indirect-buffer-display 'current-window) diff --git a/conf.org b/conf.org index 5f2e4e7..0b52893 100644 --- a/conf.org +++ b/conf.org @@ -101,9 +101,16 @@ NOTE: this only works if we start term after gui, and term has light bg. not big (setq dashboard-items '((recents . 10)))) #+END_SRC * keybindings -** apropros +** overrides #+BEGIN_SRC emacs-lisp -(global-set-key (kbd "C-h a") 'apropos) + (global-set-key (kbd "C-h a") 'apropos) +#+END_SRC +** modeless bindings +These are commands that should work in any mode. Make the assumption that function keys are pretty much free in any major/minor mode +#+BEGIN_SRC emacs-lisp + (global-set-key (kbd "") 'org-agenda) + (global-set-key (kbd "") 'org-capture) + (global-set-key (kbd "") 'org-iswitchb) #+END_SRC * printing ** @@ -373,15 +380,6 @@ vim is all about escape, not...ctrl+g??? '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC")) #+END_SRC ** keyboard shortcuts -*** global -#+BEGIN_SRC emacs-lisp - (global-set-key "\C-cl" 'org-store-link) - (global-set-key "\C-ca" 'org-agenda) - (global-set-key "\C-cb" 'org-iswitchb) - (global-set-key (kbd "C-c c") 'org-capture) - - ;; consider adding f1-12 shortcuts for org things that must be a) fast and b) work in any mode -#+END_SRC *** navigation #+BEGIN_SRC emacs-lisp (setq org-special-ctrl-a/e t) @@ -392,8 +390,8 @@ vim is all about escape, not...ctrl+g??? *** sequences #+BEGIN_SRC emacs-lisp (setq org-todo-keywords - (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") - (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)")))) + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") + (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)"))) #+END_SRC *** colors #+BEGIN_SRC emacs-lisp @@ -405,42 +403,45 @@ vim is all about escape, not...ctrl+g??? ("HOLD" :foreground "violet" :weight bold) ("CANCELLED" :foreground "deep sky blue" :weight bold)))) #+END_SRC -** tag selection keys +** tags +I use tags for filtering in the agenda view to narrow down tasks by project/context. I don't use tags for custom commands (easier with skip functions). I make the tags here brightly colored to distinguish from those set in FILETAGS #+BEGIN_SRC emacs-lisp (setq org-tag-alist (quote ((:startgroup) ("@errand" . ?e) - ("@work" . ?o) + ("@work" . ?w) ("@home" . ?h) ("@travel" . ?f) (:endgroup) ("LAPTOP" . ?L) - ("WAITING" . ?W) - ("HOLD" . ?H) ("PERSONAL" . ?P) - ("WORK" . ?O) + ("WORK" . ?W) ("NOTE" . ?N) - ("CANCELLED" . ?C) ("FLAGGED" . ??)))) + + ;; TODO I'm sure there is a better way to do this in lisp + (setq org-tag-faces + '(("LAPTOP" . (:foreground "PaleGreen")) + ("PERSONAL" . (:foreground "PaleGreen")) + ("WORK" . (:foreground "PaleGreen")) + ("NOTE" . (:foreground "PaleGreen")) + ("FLAGGED" . (:foreground "PaleGreen")))) #+END_SRC ** capture templates -TODO, use %a to link to calling buffer -TODO: add fast way to immediately schedule an event or appointment -TODO: add meeting template as scheduled+action item thing #+BEGIN_SRC emacs-lisp (setq org-capture-templates - (quote (("t" "todo" entry (file "~/Org/capture.org") "* TODO %?\n%U\n") - ("n" "note" entry (file "~/Org/capture.org") "* %? :NOTE:\n%U\n" ) - ("a" "appointment" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t\n" ) - ("m" "multi-day" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t--%^t\n" ) - ("d" "deadline" entry (file "~/Org/capture.org") "* TODO %?\nDEADLINE: %^t\n%U\n" ) - - ("j" "journal" entry (file+datetree "~/Org/diary.org") "* %?\n%U\n") - ("p" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") - "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") - ("L" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") - "* %? [[%:link][%:description]] \nCaptured On: %U") - ("h" "habit" entry (file "~/Org/capture.org") - "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n")))) + '(("t" "todo" entry (file "~/Org/capture.org") "* TODO %?\n%U\n") + ("n" "note" entry (file "~/Org/capture.org") "* %? :NOTE:\n%U\n" ) + ("a" "appointment" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t\n" ) + ("m" "multi-day" entry (file "~/Org/capture.org") "* TODO %?\n%U\n%^t--%^t\n" ) + ("d" "deadline" entry (file "~/Org/capture.org") "* TODO %?\nDEADLINE: %^t\n%U\n" ) + + ("j" "journal" entry (file+datetree "~/Org/diary.org") "* %?\n%U\n") + ("p" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") + "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") + ("L" "org-protocol" entry (file+headline ,(concat org-directory "~/Org/capture.org") "Inbox") + "* %? [[%:link][%:description]] \nCaptured On: %U") + ("h" "habit" entry (file "~/Org/capture.org") + "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n"))) #+END_SRC ** refile *** targets @@ -457,7 +458,7 @@ TODO: add meeting template as scheduled+action item thing #+END_SRC *** node creation #+BEGIN_SRC emacs-lisp - (setq org-refile-allow-creating-parent-nodes (quote confirm)) + (setq org-refile-allow-creating-parent-nodes 'confirm) #+END_SRC *** use current window #+BEGIN_SRC emacs-lisp