Spool Five

Org Agenda

As with many features of org/emacs, it can be a bit intimidating at first. However, if you spend about 30 minutes digging into it, it becomes much simpler. Or, at least, it can be as simple or as complicated as you need it to be.

Org contains a list of org-agenda-files. These files are parsed for things like tags, TODO states, dates, etc., and then can be presented in the Agenda Buffer(view). The default agenda view is the days of the week with any scheduled tasks. It is also possible to create custom agenda views.

My custom agenda

When tracking my ‘TODO’s, I use a custom tag TT. Partly, this is as a result of nostalgia from working at amazon data centre where we had to work on “Trouble Tickets (TTs)”. The other purpose of this is for clearly distinguishing between general ‘TODOs’, which I may put in different files as kind of ‘reminders’ for when I revisit the files, and “TTs” which are “Next Actions” that I specifically want to mark at add to my agenda view.

I have a short elisp snippet for counting the number of open and closed TTs.

(defun no-of-TTs ()
  (number-to-string (length (org-map-entries t "/+TT" 'agenda))))

(defun completed-YTD ()
   (- (length
       (org-map-entries t "/+DONE"
			'("~/docs/org/act/archive.org"))) 4)))

I also have some functions for parsing my notes directory for journal entries that were written on the same day in previous years:

(setq my/daily-dir "~/docs/org/notes/")
(setq my/daily-files (seq-filter (lambda (x) (string-match "_journal" x))
				 (directory-files my/daily-dir nil ".org$" t)))

(defun my/insert-current-date-MonthDayT () (interactive)
       (shell-command-to-string "echo -n $(date +%m%d)T"))

(defun my/get-matching-dailies (date)
    (seq-filter (lambda (x) (string-match date x)) my/daily-files))

(defun my/make-dailies-link (file)
  (let ((text "[This Day in Previous Years - ")
	(year (substring file 0 4)))
    (concat "[[" (concat my/daily-dir file) "]"
	    year "]]" "\n")))

(defun my/agenda-past-dailies ()
  (let ((x (my/get-matching-dailies (my/insert-current-date-MonthDayT))))
    (if x
	 (lambda (x)
	   (my/make-dailies-link x))
	 x) "")))

(defun my/print-elements-of-list (list)
  "Print each element of LIST on a line of its own."
  (if (eq list "") ""
    (while list
      (insert (car list))
      (setq list (cdr list)))))

Here is the code for my custom agenda, based on the Getting Things Done workflow:

(defun no-of-TTs ()
  (number-to-string (length (org-map-entries t "/+TT" 'agenda))))

(defun completed-YTD ()
   (- (length
       (org-map-entries t "/+DONE"
			'("~/docs/org/act/archive.org"))) 4)))

(setq gtd/next-action-head (concat "NEXT ACTIONS " "-" (no-of-TTs) " -" (completed-YTD))
      gtd/waiting-head "Waiting on"
      gtd/project-head "Projects"
      gtd/read-head "Reading List"
      gtd/watch-head "Watch List"
      gtd/shop-head "Shopping"
      gtd/someday-head "Someday/maybe")

(setq org-agenda-custom-commands
	("g" "GTD view"
	  (my/print-elements-of-list (my/agenda-past-dailies))
	  (todo "TT" ((org-agenda-overriding-header gtd/next-action-head)))
	  (agenda "" ((org-agenda-span 'day)
		      (org-agenda-start-day 'nil))) ;; this is needed because doom starts agenda with day set to -3d
	  (todo "PROJ" ((org-agenda-overriding-header gtd/project-head)))
	  (todo "WAIT" ((org-agenda-overriding-header gtd/waiting-head)))
	  (tags-todo "read" ((org-agenda-overriding-header gtd/read-head)))
	  (tags-todo "watch" ((org-agenda-overriding-header gtd/watch-head)))
	  (todo "BUY"  ((org-agenda-overriding-header gtd/shop-head)))))
	("s" "Someday"
	 ((todo "SOMEDAY" ((org-agenda-overriding-header gtd/someday-head)))))))

Using this, any items I mark with TT (Todo - ‘Ticket’), Proj (Project), WAIT (A task waiting on something/someone else), BUY (shopping lists), SOMEDAY (future projects), will appear in the relevant sections on the agenda view, along with the tasks marked for that day.

Links to this note

Random Note