Process Org Files Programmatically

Published on Mar 13, 2022, by Junji Zhi

Writing some elisp code can go a long way to automate org files related tasks, espeically when your org files are structured.

I list my notes below about the commonly used elisp functions. They

Loop through org headings with org-map-entries

The org-mode API doc is a bit short and doesn't contain examples. But org-map-entries is convenient to loop through headings.

The usage is something like:

(find-file "")
 'my-function                           ; Apply to every entry

The above snippet loops through all top-level headings and apply my-function to each heading.

For the definition my-function, it doesn't accept any argument. Instead, you assume the point is at the beginning of the heading, and invoke editing function accordingly.

As a made-up example, we could add the updated timestamp under each top level heading (and define the editing function as a lambda):

(find-file "")
 (lambda ()
   (insert (format "Edited at %s" (format-time-string "%Y-%m-%d %H:%M")))

Note that "+LEVEL=1" here is the argument for MATCH argument. Fortunately, the Org Manual has good examples to show how to build matching tags and properties string.

You can build complex matching logic based on tags and properties. For example, the following string:


matches any level two heading with a "work" tag and property "A", yet without a "boss" tag.

Get org file title

Use org-collect-keywords:

(cadar (org-collect-keywords '("TITLE")))

Move current heading (and all its subheadings) down a level

Use org-demote-subtree.