A YASnippet for org-mode publishing
First published: August 26, 2018
Last updated: January 8, 2023
I love standards and templates. Cookiecutter is my favorite command line template generator and I use a custom template for my lab projects.
When it comes to emacs programming and org-mode, I use the amazing YASnippet for generating templates from files called snippets. I introduced a simple snippet in my post on adding and parsing edn metadata for my static website, and here I have an expanded version that I am happy with for posts to my website.
I have a standard format for all my pages on my website, and the default org-mode export options and standard format rarely change. The format requires the following:
edn
metadata at the top with a set of specific keys- Standard org-mode export options
- The date the page was created
- A note as to whether the page was updated and when
The snippet
Below is the text of my snippet. I will add comments in the lisp style with ;
. Anything following the ;;
is NOT part of the snippet, but is only there for annotation.
;; yas-snippet # -*- mode: snippet -*- # name: blog # key: blog # -- #+HTML: <div id="edn"> #+HTML: {:topic "programming" :title "${1:title}" :date "`(format-time-string "%Y-%m-%d")`" :tags ${2:["clojure"]}} #+HTML: </div> ;; 1 #+OPTIONS: \n:1 toc:nil num:nil todo:nil ^:{} title:nil ;; 2 #+PROPERTY: header-args :eval never-export ;; 2 #+DATE: `(format-time-string "%Y-%m-%d %a")` ;; 3 #+TITLE $1 ;; 4 #+HTML:<h1 id="mainTitle">$1</h1> ;; 5 #+HTML:<div id="timedate"> ;; 6 /First published: {{{date}}}/ ;; 7 /Last updated: {{{time(%Y-%m-%d %a)}}}/ ;; 8 #+HTML:</div> ${3:#+TOC: headlines 2} ;; 9 $0
You can activate a snippet by typing its key
and then pushing TAB
. So whenever I make a new blog post, I type blog<TAB>
and this snippet expands and prompts me for input.
- This is where the
div
for myedn
metadata is generated. I wrote about it briefly in this post. In org-mode,#+HTML
will export as literal html. So I am first prompted to enter a title"${1:title}"
, then the:date
is automatically inserted with the emacs-lisp code snippet surrounded by back ticks, and I am then prompted to enter a few tags in what will be parsed as a Clojure vector. - The
#+OPTIONS
line and#+PROPERTY
set some sane defaults for org-mode export. #+DATE
is an org-mode metadata item where I have also inserted emacs-lisp code to generate the date. Yup, you can insert arbitrary emacs-lisp code in snippets to execute when expanded.- This line establishes the title for the post, will mirror whatever my title is (
$1
mirrors${1:title}
). - This line will be exported as raw html and establishes a special
<h1 id>
for my main title. Again,$1
mirrors the title. - Here I am starting another html
div
that will control another metadata feature. - The
{{{}}}
is for org-mode org-mode macro replacement. Thedate
inside this replacement macro will insert the value#+DATE
variable into that location upon export. - This org-mode macro inserts the date of last export.
- Optional table of contents. Org-mode will automatically generate a table of contents and it will be inserted wherever I put this line. I usually don't want a table of contents, so I typically delete this part but it is there just in case.
I really like this format. It allows me to standardize the metadata of my files and provides a really nice automatic record of when I posted and updated different posts. When I first publish an article, the date
and macro described in #7 will be the same, as #+DATE
is set once when the snippet is first generated. If I ever update and re-export a file, then #7 will re-evaluate and display the date of the most recent export!
More snippets
I have a bunch more snippets, which you can see in my emacs-config. I stole a lot from different places on the internet, but most of these are customized to address specific problems I had or to optimize for a specific workflow. For example, I made another snippet for my regular science writing workflow called pre sets up all of my normal export options and org-ref
settings.
YASnippet's are just another reason why org-mode and emacs rock!