Using Emacs Advice to use templates with org-journal


I’m not an Emacs poweruser by any means, but after using it for ~10 years I am at least aware of many of its capabilities. And yet, today I learned something new: Advice.

Advising is similar to hooks in the sense that it allows us to extend a particular function. Hooks usually get the job done, but sometimes they cannot be used because either the maintainer just didn’t add them to their mode, or because they don’t run in the place you need them. This is where Advice come handy.

Advising a function allows us to execute custom code before, after, or surrounding the function. Any function. And this makes them really powerful.

For example, I’m starting to use org-journal after a stint with org-roam, logseq, and obsidian, by that order (this in itself deserves its own post). One thing I like about logseq and obsidian is that they allow to easily add templates to your notes. In particular, I have a template set for my daily notes, as they always follow the same structure. Alas, there’s no easy way to do it in org-journal.

Luckily (I thought), org-journal-new-entry provides a hook. Surely I will be able to use that! Well, not so fast. Because of reasons my template was inserted correctly, but the date was added after the rest of the fields. After an hour of debugging I couldn’t for the life of me figure out why that was happening. What I did notice was that the hook org-journal-after-entry-create-hook wasn’t called exactly at the end of the function, but somewhere in the middle. So some elisp magic was happening between the hook and the end result.

Right when I was starting to modify the package code to suit my functionality, I stumbled upon Advice. And that’s exactly what I needed in this case! I absolutely want to run my piece of code to insert a template after org-journal-new-entry has finished running:

  (defun dani/insert-journal-template (&rest r)
    (when (not (file-exists-p (buffer-file-name (current-buffer))))
      (save-excursion
        (insert
         (concat "\n** ✅ To Do Today [/]\n"
                 "- [ ]\n"
                 "- [ ]\n"
                 "- [ ]\n"
                 "- [ ]\n"
                 "- [ ]\n"
                 "** 📝 Notes\n"
                 "** 📓 Interstitial Journal\n"
                 "** ⚡ Outcomes\n"
                 "*** Summary\n"
                 "*** Artifacts\n")))))

  (advice-add 'org-journal-new-entry :after #dani/insert-journal-template)

The advising function (dani/insert-journal-template) takes the same arguments as the advised function (org-journal-new-entry). Since I really don’t care about the arguments, I capture them with &rest, which puts them in a list, r, where they are never used. faslkdfajs;l