Simple Org Mode setup to get things done

As previously written on this blog, I do like to use plain text (even more if supported on a GNU Emacs mode) whenever possible and if not possible, I like to rely on a specification. One of these cases is CalDAV's tasks. As a happy Mailbox user, I can totally say that their approach to using defined protocols over proprietary formats is awesome. Using their calendar (that has CalDAV support) is something that helps me a lot as I can sync all my devices' calendars at once.

Still, I miss being able to use GNU Emacs to write tasks... The fact that you can use Org Capture to take quick notes that can be anything from simple /TODO/s to file references that you might want to check later is something too big to miss out. I know that there's org-caldav, but I never got it working properly with CalDAV tasks1.

Ok, with this in mind, I decided that I'm going to separate things in two categories here. Personal life tasks and computer tasks. Personal life tasks are related to tasks such as doctor appointments, tax filling, "buy X" and more. Computer tasks are related to personal programming projects, open source contributions and work. In this case, personal life tasks are going to stay at Mailbox's Calendar and computer tasks are going with Org Mode.

Wrapping up the idea

As the post's description details, this should require a small setup and be fast to get used to. Given this requirement, let's build a small plan:

  • Setup a private Git Repository (will be skipped on this article)
  • Setup a GNU Emacs configuration with the following
    • Org Capture keybindings to take notes faster
    • org-super-agenda to get a nice view of the things to be done

Configuring Org Mode

Alright, our first step here will be setting up our Org Capture keybindings. Taking into account that we will only have two different categories: Personal and Work, this should be pretty straightforward.

(setq +org-capture-todo-file (concat org-directory "/todo.org")
      org-capture-templates '(("p" "Personal")
			            ("pt" "Personal todo" entry
				     (file+headline +org-capture-todo-file "Personal")
				     "* TODO %?  :personal:\n" :prepend t)
				    ("pn" "Personal note" entry
				     (file+headline +org-capture-todo-file "Personal")
				     "* TODO %?  :personal:\n%i\n%a" :prepend t)
				    ("w" "Work")
				    ("wt" "Work todo" entry
				     (file+headline +org-capture-todo-file "Work")
				     "* TODO %?  :work:\n%i\n" :prepend t)
				    ("wn" "Work note" entry
				     (file+headline +org-capture-todo-file "Work")
				     "* TODO %?  :work:\n%i\n%a" :prepend t)))

Let's unwrap this real quick. The variable +org-capture-todo-file is here just to help us avoid writing our todo.org's file path over and over. Now, for the capture templates, we define two keys. p for our Personal captures and w for Work captures. Inside these keys I define other two keys [pw]t and [pw]n. My idea here is that the t keys should be used for TODOs and n keys should reference files that I want to take a look later. Check out the list of template expansions for more understanding on what the lines such as * TODO %? :work:\n%i\n%a means.

Configuring org-super-agenda

Is it worth doing all of this if there's no quick way to check on what needs to be done? I don't think so and in this case I setup a compact org-super-agenda view to help me. Check the documentation to know more about its capabilities.

(setq org-agenda-files (list org-directory)
      org-agenda-skip-scheduled-if-done t
      org-agenda-skip-deadline-if-done t
      org-agenda-include-deadlines t
      org-agenda-block-separator nil
      ;; from testing this seems to be a good value
      org-agenda-tags-column 100
      org-agenda-compact-blocks t
      org-agenda-custom-commands
        '(("o" "Overview"
	        ((agenda "" ((org-agenda-span 'day)
			     (org-super-agenda-groups
			      '((:name "Today"
				       :time-grid t
				       :date today
				       :todo "TODAY"
				       :scheduled today
				       :order 1)))))
		 (alltodo "" ((org-agenda-overriding-header "")
			      (org-super-agenda-groups
			       '((:name "Important"    :tag "Important" :priority "A" :order 6)
				 (:name "Due Today"    :deadline today  :order 2)
				 (:name "Due Soon"     :deadline future :order 8)
				 (:name "Overdue"      :deadline past   :face error :order 7)
				 (:name "Future Ideas" :todo "IDEA"     :order 14)
				 (:name "To read"      :tag "read"      :order 30)
				 (:name "Waiting"      :todo "WAIT"     :order 20)
				 (:name "Work"         :tag "work"      :order 32)
				 (:name "Personal"     :tag "personal"  :order 32)))))))))

I know that this is a lot of code to understand right away, but all the org-agenda* variables are extensively documented on GNU Emacs and the only important part here is the org-agenda-custom-commands. You can see that I've setup a Today group to show me what I need to get done right away and a whole bunch of other groups that are self-explanatory.

{{< image src="/blog/simple-org-mode-setup-things-done/org-agenda-view.png" side="center" >}} Sample Org Agenda's view. {{< /image >}}

Configuring age to encrypt files

I started using my Yubikey as a SSH key. This opened up a whole bunch of possibilities, as most of my computing needs are now supported with SSH keys instead of being PGP-only. This means that I can encrypt with age, sign my Git commits and configure my servers to use my physical keys.

Unfortunately, I still didn't try to integrate this workflow with my Org files but I'll definitely try it in the future.

  1. This might be a perfect opportunity to kill two birds with one stone. Contribute code back and learn Emacs Lisp.