RSS Amplifier

naff.dev · May 15, 2025

Automatically Sorting Org Headings

0
Sign in to vote or save

naff.dev

One of the many things I use Org Mode for is tracking media I’d like to consume: books, films, TV shows, etc. To do this, I have a big Org file divided into sections:

* Books
** The Canterbury Tales
** Southern Reach Series
*** Annihilation
*** Authority
*** Acceptance
*** Absolution
* Movies
** Citizen Kane
** Solaris
* TV
** Game of Thrones
** Breaking Bad

As you can see, I keep each item as a headline in its own right, and make subsections for series. The latter is mostly for books, which is by far the longest section.

To make it easier to find things, I want to keep each section in alphabetic order. Org provides org-sort-entries to do this, but you have to call that manually. Indeed, in the example above, I’ve conveniently forgotten to sort the TV section. Additionally, we don’t want to sort every section—the order is meaningful for series. Therefore, I decided to explicitly mark the sections I wanted to stay sorted.

Here’s the Emacs Lisp I wrote to accomplish this:

(defun org-autosort ()
  (interactive)
  (unless (derived-mode-p 'org-mode) (error "Error: run in non-org buffer"))
  (let ((home (point)))
    (org-map-entries (lambda ()
                       (let ((was_folded (save-excursion (end-of-line) (outline-invisible-p))))
                          (org-sort-entries nil ?a)
                          (if was_folded (outline-hide-subtree) (outline-show-subtree))
                        ))
                     "autosort=\"t\"")
    (goto-char home)))

(add-hook 'before-save-hook (lambda () (if (derived-mode-p 'org-mode) (org-autosort))))

This code will automatically sort any section with the property :autosort: t when an Org file is saved. Explicitly, assigning that property looks like this:

* TV
:PROPERTIES:
:autosort: t
:END:
** Breaking Bad
** Game of Thrones

save-excursion is a very useful function which lets you save a bunch of editor state, do some operations that might move the cursor or change buffer, and automatically return to where you started from. Unfortunately, org-sort-entries seems to break this, so I’ve resorted to manually storing the location of the cursor before doing anything and returning there at the end. We also save and restore whether each section was folded, because org-sort-entries can affect that too.

This solution isn’t perfect (subsections of an autosorted section will unfold on save, for instance). Nonetheless, it’s worked well enough for me, and it marks the first time I’ve written some more substantial Emacs Lisp for myself, which feels like an important milestone in my Emacs career.

Thank you to Christian Tietze, whose article covering a different, and simpler, way of doing a very similar thing motivated me to write up my solution.

Read the original on naff.dev

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.