2022-01-24 Journaling with Org-mode

OK, so let’s admit it. I’ve been journaling with Org-mode for more than 6½ years now. Every day (well, almost every day) I sit down and make notes of important things that happened that day. What constitutes “important things”? Well, basically things that don’t normally happen. Doctor’s appointments. (This is extremely useful, especially with kids.) Cars breaking down and getting fixed. Schooldays missed. Friends coming to us. We visiting friends. You get the idea.

The way I do this with Org-mode is easy – I have set up a capture template looking like this:

(setq org-capture-templates
 '(("j" "Journal entry" plain
    (file+olp+datetree "~/path/to/my/journal.org")
    "**** %i%?\n"
    :time-prompt t
    :unnarrowed t)))

When the time comes to fill the journal for today, I hit C-c c j, fill in the journal entry, press C-c C-c – and that’s it.

If this were all there’s to it, I probably wouldn’t blog about it – after all, it’s in the Org manual, nothing new. But the cool thing about over 6 years’ worth of journal is that is actually meaningful (and pretty cool!) to look at all journal entries done on that date in previous years. So, here’s one simple way to do it:

(defun org-journal-on-this-day ()
  "Show entries for this day on all previous years."
  (with-temp-buffer-window "*On this day*" nil nil
      (insert-file-contents "~/path/to/my/journal.org")
      (goto-char (point-min))
      (let ((regex (format-time-string "^\\*\\*\\* [0-9]\\{4\\}-%m-%d")))
	(while (re-search-forward regex nil t)
	  (let* ((elt (org-element-at-point))
		 (begin (org-element-property :begin elt))
		 (end (org-element-property :contents-end elt))
		 (contents (buffer-substring begin end)))
	    (princ contents))))))
  (with-current-buffer "*On this day*"

It is probably far from optimal – for instance, it would be better to put the *On this day* buffer in a variant of special-mode such that pressing RET on a headline would jump to the corresponding place in the original journal file, pressing q would restore the window configuration etc., while still having Org-mode font-locking. But given that I spent some 15 minutes writing that code (and that I don’t really intend spending more time on this), it’s certainly good enough for me.

By the way, the above code uses yet another Elisp feature very specific to the fact that Elisp is not a general-purpose language but a language for writing text editors in: streams and output. It turns out that quite a few functions producing text (like princ) are capable of sending this text to various places. It’s definitely not something you’d use every day, but it can be very useful sometimes (especially when writing Elisp scripts to be run from the command line instead of in an interactive Emacs session!) It also makes use of the famous Org element API to get the contents of the journal headlines we need.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode