Writing posts with emacs

4 minute read

Published:

I tried lately to get a bit more into emacs, by rewriting my configuration, and try to learn bits of emacs-lisp in the process. It lead me to try to be able to maintain this website, and to create posts using org-mode, and automating the process the best I could. Indeed, I found the process of writing in markdown, whose syntax is close albeit different enough from the org-mode quite painful.

For this, I use a combination of org-mode, yasnippet, all of this wrapped in a simple function. This is mainly stitching together various pieces I found here and there, and trying to understand the process. I am by no means an expert in anything and I do this for my own entertainment.

Create the file using a elisp function

Definition of the function

We are going to define a function, which creates the proper file, with the proper formatting etc. This function is taken from here.

(defun create-blogpost (x)
    "Create a new blogpost."
    (interactive "sPost title: ")
    (let ((date (shell-command-to-string "echo -n $(date +%Y-%m-%d)"))
          (title (s-replace " " "-" x))
          filename filepath)
      (setf filename (concat date "-" title ".org"))
      (setf filepath (concat "~/vtrappler.github.io/org_posts/" filename))
      (write-region "" 0 filepath t)
      (find-file filepath))
      (insert "jekyll-autofilled-frontmatter") ;; use the yassnippet
      (yas-expand)
      )

This function will then be called using M-x create-blogpost.

Step by step description

Let us describe step by step how this function is created:

(interactive "sPost title:")

This prompts an user input, in this case the title of the post we wish to create. The seemingly missplaced s is not a typo, but a code letter indicating that the format of the input is a string. This defines x, as it is not stated when calling the function.

(let ((date (shell-command-to-string "echo -n $(date +%Y-%m-%d)"))
              (title (s-replace " " "-" x))
              filename filepath)

The bash command "echo -n $(date +%Y-%m-%d)" here outputs the current date, in the format YYYY-MM-DD, and we assign the output string to the variable date. Then we replace all the whitespaces in the title by dashes, and assign it to the variable title. Finally, the filename and filepath variables are declared. Their values are set next:

(setf filename (concat date "-" title ".org"))
(setf filepath (concat "~/vtrappler.github.io/org_posts/" filename))

The filename is then in the format YYYY-MM-DD-title-with-dashes.org, as recognized by Jekyll.

The next two calls ensures that this file can and is created.

(write-region "" 0 filepath t)
(find-file filepath)) ;;Closes the parenthesis of (let ...

The last calls inside the function insert the text necessary to incorporate the Jekyll frontmatter.

(insert "jekyll-autofilled-frontmatter") ;; insert the key of the snippet
(yas-expand) 

The snippet is described in the next section

Using yassnippets for the frontmatter used in jekyll

We created in a separate file the following snippet to generate properly the Jekyll frontmatter. As one can execute directly elisp code at the insertion of the snippet, we can exploit this property in order to get the correct format for the file. To avoid passing arguments from the create-blogpost, we are going to simply retrieve all the info, by stripping the filename of the dashes, while the current date and the .org extension are removed in a hardcoded manner.

# -*- mode: snippet -*-
# name: jekyll-frontmatter-create
# key: jekyll-autofilled-frontmatter
# --

#+BEGIN_EXPORT html
---
title: `(s-replace "-" " " (substring (buffer-name) 11 -4))`
date: `(shell-command-to-string "echo -n $(date +%Y-%m-%d)"))`
permalink: /posts/`(shell-command-to-string "echo -n $(date +%Y/%m)")`/`(substring (buffer-name) 11 -4)`
tags:
---
#+END_EXPORT
#+OPTIONS: toc:nil
#+OPTIONS: num:nil

Export org files to html

Finally, once the org file is written, we are going to export it to html: the parameters of publication are adapted from there

(setq org-publish-project-alist
;; https://thackl.github.io/blogging-with-emacs-org-mode-and-jekyll
      '(("vtrappler.github.io" ;; name of the page )
         ;; Path to org files.
         :base-directory "~/vtrappler.github.io/org_posts/"
         :base-extension "org"
         ;; Path to Jekyll Posts
         :publishing-directory "~/vtrappler.github.io/_posts/"
         :recursive t
         :publishing-function org-html-publish-to-html
         :headline-levels 4
         :html-extension "html"
         :body-only t
         )))

Final process

The final process of writing a blog post is then

  • M-x create-blogpost, and type the title of the post when prompted
  • Write the post
  • C-c C-e P f, publish to html
  • Add, commit and push if applicable to update your website