How to define a custom
org-global-cycle-like command that collapses
only the Org subtrees with specific properties.
I start this post by introducing what the Org mode global cycling command does, what kind of subtree folding I actually need, and then share the solution with code snippets.
Org Global Cycle #
Org mode has a built-in
org-global-cycle command that you might be
familiar with. It’s bound by default to the
S-TAB key. Each time
this command is called, the Org buffer will cycle through these
- Overview: Show only the Level 1 headings and collapse everything underneath.
- Contents: Show only the Org headings and collapse all the content.
- Show All: Expand all the headings and show their contents too.
If a numeric prefix N is used with this command, it will show only
the Org headings up to Level N. For example,
C-2 S-TAB will show
only the headings up to Level 2.
This is a really helpful command, but I needed something different ..
Skeleton of only Post headings #
I maintain most of this website’s content in a single Org file. I have dozens of blog posts organized in Org subtrees, which I further organize under “category” headings .. It kind of looks like the below mock-up: It’s amazing how many features PlantUML has. If you are interested in creating diagrams like these, check out the PlantUML Salt syntax.
As we can see,
- All the post subtrees are not at Level 1 headings.
- They are also not at a fixed Level N.
- The heading level of the post depends on how many parent categories that post has (and that will also change over time).
I needed to basically show everything leading up to a post subtree heading, and then collapse all the content under that post; even the sub-headings.
The “Collapse All Posts” function #
modi/org-hugo-collapse-all-posts function defined below meets
the above requirement:
- It first widens the whole buffer and expands all the headings.
- Then it loops through all the headings and collapses all the post
subtrees i.e. all the subtrees that have the
EXPORT_FILE_NAMEproperty set. This is where I use the
- Finally it looks for Org headings that begin with “Footnotes” or “COMMENT” and collapses them as well.
I am using the development version of Org mode (version 9.6, yet to be
released as of
library. This library obsoletes the use of
outline.el library and
other code-folding related functions in Org mode. So
used to create function symbol aliases that use the
functions if available, otherwise they fall back to the legacy
C-u C-c TAB #
The function is ready, but let’s now add a bit of convenience to it.
If a point is under a subtree,
C-c TAB will collapse that subtree
while showing only Level 1 headings, and if a numeric prefix is used,
it will show only those many levels of headings. I decided to bind the
above function to
C-u C-c TAB because,
- The behavior of
modi/org-hugo-collapse-all-postsfalls in the same category as that of
C-u C-c ..binding rolls off the fingers pretty nicely 😃.
This binding is achieved using one of my favorite Emacs features
.. the advice system. The
:before-until Advice Combinator is used
here, which means that if the advising function (below) returns a
nil, the advised or the original function
org-ctrl-c-tab is not
The advising function below detects if the
C-u prefix argument is
used. If it is, the
modi/org-hugo-collapse-all-posts function is
called, otherwise the original
org-ctrl-c-tab function is called.
After evaluating the above two snippets, when I do
C-u C-c TAB in
my “blog posts” Org buffer, I see this:
It matches that earlier mockup — Mission accomplished! 💯