Emacs Carnival: Org Mode Completions
I’m so happy to be joining this month’s emacs carnival! I love the idea behind these carnivals and I think it’s such a good way of building community virtually.
This month’s topic is Emacs completions. I’m going to share a sort of “hack”… a way that I’ve been able to achieve completions within core org mode.
Org Mode Tempo Templates
Org Mode has long supported a template expansion mechanism, some times called “easy templates” or “structured templates”.
The default behavior changed dramatically in version 9.2, and is now built on top of the Emacs builtin tempo.el.
Essentially, you start a new line with <X (where X is a pre-defined key), then hit TAB to have the template expanded.
For example, starting a new line with:
<sand hitting TAB will expand to:
#+begin_src
#+end_srcSuper handy and very easy to remember.
Default templates
The default are not entirely documented, though most are listed on the Structured Templates manual page.
Listed again here for convenience:
| Key | Expansion |
|---|---|
| <a | #+BEGIN_EXPORT ascii … #+END_EXPORT |
| <c | #+BEGIN_CENTER … #+END_CENTER |
| <C | #+BEGIN_COMMENT … #+END_COMMENT |
| <e | #+BEGIN_EXAMPLE … #+END_EXAMPLE |
| <E | #+BEGIN_EXPORT … #+END_EXPORT |
| <h | #+BEGIN_EXPORT html … #+END_EXPORT |
| <l | #+BEGIN_EXPORT latex … #+END_EXPORT |
| <q | #+BEGIN_QUOTE … #+END_QUOTE |
| <s | #+BEGIN_SRC … #+END_SRC |
| <v | #+BEGIN_VERSE … #+END_VERSE |
In addition to those blocks, there are also some quick tags:
| Key | Expansion |
|---|---|
| <L | #+latex: |
| <H | #+html: |
| <A | #+ascii: |
| <i | #+index: |
| <I | #+include: (will interactively find file to include) |
You can see that there is sort of a convention, uppercase letters usually insert a tag, whereas lowercase letters are mainly for blocks (though it’s definitely not perfect).
Additional Templates
Some additional templates can be defined by packages. For example, the org-re-reveal package adds:
| Key | Expansion |
|---|---|
| <n | #+begin_notes ... #+end_notes |
Basic Customization
You can add your own tags and blocks. In fact, there is actually no need for the “keys” to single characters.
Adding Tags
Adding another tag is very easy, seen here:
(add-to-list 'org-tempo-keywords-alist '("N" . "name"))Which results in this completion:
| Key | Expansion |
|---|---|
| <N | #+name: |
Create a New Hotkey
I don’t like the <E hotkey for export block, instead I would like that to be <x.
That is easily added with:
(add-to-list 'org-tempo-tags '("<x" . tempo-template-org-export))Create a Completion
You can define your own completion with the tempo-define-template function (see the doc string for full details).
It is very flexible!
You can specify where the cursor (or “prompt”) ends up after the completion, or you can interactively prompt (via the minibuffer) for additional details.
There are more advance features, including auto indentation and dealing with regions.
My Custom Completions
There is no requirement that these templates be simply blocks or tags. I’ve implemented about 5 custom templates, but here are a few that I think would be most useful for others.
Properties Drawer1
Org headings can have properties, specified by the properties drawer:
:PROPERTIES:
:END:I add this as <p via this implementation code:
(tempo-define-template "org-properties-block"
'(":PROPERTIES:" n
(p) n
":END:" n %))
(add-to-list 'org-tempo-tags '("<p" . tempo-template-org-properties-block))Title Block
This is one that I use most frequently.
It’s a title block that I start all my org documents with.
It also executes a function call to format-time-string to get today’s date in my preferred format.
By having this completion, all of my org documents get a title with a date and I always know when I started working on a document!
My desired result:
#+title:
#+author: Elsa Gonsiorowski
#+date: February 28, 2026The implementation code:
(tempo-define-template "org-title-block"
'("#+title: " (p) n
"#+author: Elsa Gonsiorowski" n
(concat "#+date: " (format-time-string "%B %e, %Y")) n %))
(add-to-list 'org-tempo-tags '("<t" . tempo-template-org-title-block))I also implement another completion that is a slightly different title block which I use for starting all my blog posts. It includes the all the options that I want by default.
Finally
In writing this article I stumbled across orgmode documentation page for Completions.
I had no idea these M-tab completions existed!
(Clearly, since I implemented my own completion for the properties drawer).
I’ll definitely be trying these out.
Footnotes
1 The :properties: keyword can also be added with the M-tab completion on :
Comments
Comments are sent directly to me and may or may not be posted for display on this page.