Skip to content

Commit 9f452e8

Browse files
committed
Custom agenda view
1 parent 6e7b055 commit 9f452e8

File tree

1 file changed

+203
-0
lines changed

1 file changed

+203
-0
lines changed

emacs.d/packages/org-package.el

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,209 @@
1616
("NEXT" ("WAITING") ("CANCELLED") ("HOLD"))
1717
("DONE" ("WAITING") ("CANCELLED") ("HOLD")))))
1818

19+
;; Do not dim blocked tasks
20+
(setq org-agenda-dim-blocked-tasks nil)
21+
22+
;; Compact the block agenda view
23+
(setq org-agenda-compact-blocks t)
24+
25+
;; Custom agenda command definitions
26+
(setq org-agenda-custom-commands
27+
(quote (("N" "Notes" tags "NOTE"
28+
((org-agenda-overriding-header "Notes")
29+
(org-tags-match-list-sublevels t)))
30+
(" " "Agenda"
31+
((agenda "" nil)
32+
(tags "REFILE"
33+
((org-agenda-overriding-header "Tasks to Refile")
34+
(org-tags-match-list-sublevels nil)))
35+
(tags-todo "-CANCELLED/!"
36+
((org-agenda-overriding-header "Stuck Projects")
37+
(org-agenda-skip-function 'tw/skip-non-stuck-projects)
38+
(org-agenda-sorting-strategy
39+
'(category-keep))))
40+
(tags-todo "-HOLD-CANCELLED/!"
41+
((org-agenda-overriding-header "Projects")
42+
(org-agenda-skip-function 'tw/skip-non-projects)
43+
(org-tags-match-list-sublevels 'indented)
44+
(org-agenda-sorting-strategy
45+
'(category-keep))))
46+
(tags-todo "-CANCELLED/!NEXT"
47+
((org-agenda-overriding-header "Project Next Tasks")
48+
(org-agenda-skip-function 'tw/skip-projects-and-habits-and-single-tasks)
49+
(org-tags-match-list-sublevels t)
50+
(org-agenda-sorting-strategy
51+
'(todo-state-down effort-up category-keep))))
52+
(tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!"
53+
((org-agenda-overriding-header "Project Subtasks")
54+
(org-agenda-skip-function 'tw/skip-non-project-tasks)
55+
(org-agenda-sorting-strategy
56+
'(category-keep))))
57+
(tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!"
58+
((org-agenda-overriding-header "Standalone Tasks")
59+
(org-agenda-skip-function 'tw/skip-project-tasks)
60+
(org-agenda-sorting-strategy
61+
'(category-keep))))
62+
(tags-todo "-CANCELLED+WAITING|HOLD/!"
63+
((org-agenda-overriding-header "Waiting and Postponed Tasks")
64+
(org-agenda-skip-function 'tw/skip-non-tasks)
65+
(org-tags-match-list-sublevels nil)))
66+
(tags "-REFILE/"
67+
((org-agenda-overriding-header "Tasks to Archive")
68+
(org-agenda-skip-function 'tw/skip-non-archivable-tasks)
69+
(org-tags-match-list-sublevels nil))))
70+
nil))))
71+
72+
(defun tw/find-project-task ()
73+
"Move point to the parent (project) task if any"
74+
(save-restriction
75+
(widen)
76+
(let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point))))
77+
(while (org-up-heading-safe)
78+
(when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
79+
(setq parent-task (point))))
80+
(goto-char parent-task)
81+
parent-task)))
82+
83+
(defun tw/is-project-p ()
84+
"Any task with a todo keyword subtask"
85+
(save-restriction
86+
(widen)
87+
(let ((has-subtask)
88+
(subtree-end (save-excursion (org-end-of-subtree t)))
89+
(is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
90+
(save-excursion
91+
(forward-line 1)
92+
(while (and (not has-subtask)
93+
(< (point) subtree-end)
94+
(re-search-forward "^\*+ " subtree-end t))
95+
(when (member (org-get-todo-state) org-todo-keywords-1)
96+
(setq has-subtask t))))
97+
(and is-a-task has-subtask))))
98+
99+
(defun tw/is-project-subtree-p ()
100+
"Any task with a todo keyword that is in a project subtree.
101+
Callers of this function already widen the buffer view."
102+
(let ((task (save-excursion (org-back-to-heading 'invisible-ok)
103+
(point))))
104+
(save-excursion
105+
(tw/find-project-task)
106+
(if (equal (point) task)
107+
nil
108+
t))))
109+
110+
(defun tw/is-task-p ()
111+
"Any task with a todo keyword and no subtask"
112+
(save-restriction
113+
(widen)
114+
(let ((has-subtask)
115+
(subtree-end (save-excursion (org-end-of-subtree t)))
116+
(is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
117+
(save-excursion
118+
(forward-line 1)
119+
(while (and (not has-subtask)
120+
(< (point) subtree-end)
121+
(re-search-forward "^\*+ " subtree-end t))
122+
(when (member (org-get-todo-state) org-todo-keywords-1)
123+
(setq has-subtask t))))
124+
(and is-a-task (not has-subtask)))))
125+
126+
(defvar tw/hide-scheduled-and-waiting-next-tasks t)
127+
128+
(defun tw/skip-non-stuck-projects ()
129+
"Skip trees that are not stuck projects"
130+
(save-restriction
131+
(widen)
132+
(let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
133+
(if (tw/is-project-p)
134+
(let* ((subtree-end (save-excursion (org-end-of-subtree t)))
135+
(has-next ))
136+
(save-excursion
137+
(forward-line 1)
138+
(while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t))
139+
(unless (member "WAITING" (org-get-tags-at))
140+
(setq has-next t))))
141+
(if has-next
142+
next-headline
143+
nil)) ; a stuck project, has subtasks but no next task
144+
next-headline))))
145+
146+
(defun tw/skip-non-projects ()
147+
"Skip trees that are not projects"
148+
(if (save-excursion (tw/skip-non-stuck-projects))
149+
(save-restriction
150+
(widen)
151+
(let ((subtree-end (save-excursion (org-end-of-subtree t))))
152+
(cond
153+
((tw/is-project-p)
154+
nil)
155+
((and (tw/is-project-subtree-p) (not (tw/is-task-p)))
156+
nil)
157+
(t
158+
subtree-end))))
159+
(save-excursion (org-end-of-subtree t))))
160+
161+
(defun tw/skip-non-tasks ()
162+
"Show non-project tasks.
163+
Skip project and sub-project tasks, habits, and project related tasks."
164+
(save-restriction
165+
(widen)
166+
(let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
167+
(cond
168+
((tw/is-task-p)
169+
nil)
170+
(t
171+
next-headline)))))
172+
173+
174+
(defun tw/skip-projects-and-habits-and-single-tasks ()
175+
"Skip trees that are projects, tasks that are habits, single non-project tasks"
176+
(save-restriction
177+
(widen)
178+
(let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
179+
(cond
180+
((and tw/hide-scheduled-and-waiting-next-tasks
181+
(member "WAITING" (org-get-tags-at)))
182+
next-headline)
183+
((tw/is-project-p)
184+
next-headline)
185+
((and (tw/is-task-p) (not (tw/is-project-subtree-p)))
186+
next-headline)
187+
(t
188+
nil)))))
189+
190+
(defun tw/skip-project-tasks ()
191+
"Show non-project tasks.
192+
Skip project and sub-project tasks, habits, and project related tasks."
193+
(save-restriction
194+
(widen)
195+
(let* ((subtree-end (save-excursion (org-end-of-subtree t))))
196+
(cond
197+
((tw/is-project-p)
198+
subtree-end)
199+
((tw/is-project-subtree-p)
200+
subtree-end)
201+
(t
202+
nil)))))
203+
204+
(defun tw/skip-non-project-tasks ()
205+
"Show project tasks.
206+
Skip project and sub-project tasks, habits, and loose non-project tasks."
207+
(save-restriction
208+
(widen)
209+
(let* ((subtree-end (save-excursion (org-end-of-subtree t)))
210+
(next-headline (save-excursion (or (outline-next-heading) (point-max)))))
211+
(cond
212+
((tw/is-project-p)
213+
next-headline)
214+
((and (tw/is-project-subtree-p)
215+
(member (org-get-todo-state) (list "NEXT")))
216+
subtree-end)
217+
((not (tw/is-project-subtree-p))
218+
subtree-end)
219+
(t
220+
nil)))))
221+
19222
(defun construct-filename (directory filename)
20223
(concat (file-name-as-directory directory) filename))
21224

0 commit comments

Comments
 (0)