MonadicT
I see dead objects!
Search

Blogging with emacs and org-mode

I do most of my work in emacs and blogging is no exception. But, everytime I start a blog post, I go through a small learning curve around the tools I use. I am going to put an end to it, once and for all :)

Emacs setup

Obviously, you need org-mode. Version 8.* is preferred and there are many breaking changes from its previous versions. If you are using a recent vintage emacs, org-mode is already bundled. Unless you are running into a bug involving advanced usage, there should be no need to upgrade org-mode. But, I do recommend cloning repo org-mode and installing it from the source. It's really fun to experience how smooth building it is compared to some of our internal software!

We need to tell org-mode what source languages to process for export and whether it should prompt before processing a source block written in some language. We do that by customizing org-babel-load-langauges variable. We redefine org-confirm-babel-evaluate to skip asking for confirmation for the languages.

We also set org-src-fontify-natively so that the source blocks are fontified as well.

;; Load org export extensions
(require 'ox-latex)

;; org-mode should process these languages
(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (python . t)
   (clojure . t)
   (latex . t)))

;; We don't want the "confirm evaluation" prompt for these languages
(defun my-org-confirm-babel-evaluate (lang body)
  (not (or (string= lang "python")
           (string= lang "emacs-lisp")
           (string= lang "dot")
           (string= lang "latex"))))
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
(setq org-src-fontify-natively t)

Source blocks

Source code blocks are delimited by #+BEGIN_SRC lang and #+END_SRC. emacs evaluates the source block and uses the result in export. Source block parameters, :results and :exports are particularly useful in this context.

:results can have the following options specified.

collection is either value or output. The first option instructs org-mode to capture the return value of evaluation and use it in exporting. The second option causes any output written to STDOUT to be used as the value of the source block.

type is one of table, vector, list, scalar, verbatim or file. By default, result is handled as a table or scalar depending on the value. Results of type scalar or verbatim are not converted to tables. A result type of file points to the file where the result is stored and causes a file link to be inserted.

format is one of:

  • raw results are inserted directly into the buffer
  • org results are enclosed in a #+BEGIN_SRC org block
  • html results are assumed to be HTML and enclosed in a #+BEGIN_SRC html block
  • latex results assumed to be LaTeX and are enclosed in a BEGINLaTeX block
  • code result are assumed to be parsable code and are enclosed in a code block
  • pp result is converted to pretty-printed code and is enclosed in a code block.
  • drawer result is wrapped in a RESULTS drawer

handling is one of

  • silent results are not inserted into the buffer
  • replace any existing value is replaced with value
  • append result is appended to existing
  • prepend reslult is prepended to existing

:exports can have one of the following values.

  • code body of source block is inserted into the buffer
  • results result of source block evaluation is inserted into the buffer
  • both code and results are inserted into the buffer
  • none neither code nor results are inserted into the buffer

Here is a Python source code block which exports code and results.

#+BEGIN_SRC python :results value :exports both
# A simple Python source block
return 42
#+END_SRC
# A simple Python source block
return 42
42

Here is another Python source block whose output is captured and only the results is exported.

#+BEGIN_SRC python :results output :exports results
print "Hello, world!"
return 42
#+END_SRC

Blog post

Header

A blog post begins with the following.

#+TITLE: Blogging with org-mode
#+tags: emacs org-mode blogging
#+options: toc:nil num:nil tex:t LaTeX:t

Including a \LaTeX generated figure

Here is a \LaTeX{} block to generate an image in the exported document. By default, the result type is latex and the output is wrapped in #:BEGIN_LaTeX...#:END_LaTeX block. Note that there are no temporary graphics files generated at all.

\let\earth\relax
\input{eltex1}
\begin{figure}
\begin{center}
\begin{picture}(40,60)(0,0)
\grid{10}{8}
\end{picture}
\end{center}
\end{figure}

For latex source code blocks, default value of :results is output and :exports is results.

In contrast, the following block creates a graphic file as specified by :file argument. :results is specified as output file raw which causes the output to be interpreted as a file link. Note the use of raw without which the file link will be wrapped into a latex block.

Including a graphviz diagram

We need to have graphviz installed on the system. emacs should be able to find dot command. As usual, Windows is a pain but I have become comfortably numb :)

You might need to locate and copy ob-dot.el to a location where emacs will find it.

dotfig.png

Publishing

My blogging host is at https://mondiact.github.io. My Github user id is MonadicT and the repo named https://github.com/MonadicT/MonadicT.github.io is the source of posts. Github runs a restricted version of Jekyll on this repo and generates a static website which is published on github.io. Unfortunately, the restricted version doesn't let us do tags and a blog post without tags is not all that useful.

The workaround is to do all the processing locally and generate the static website and push it to github. And, we tell github to not run Jekyll on our repo. The presence of .nojekyll in the root directory tells github to run Jekyll.

All we need is a way to generate the posts locally and make it available. While it can be done with Jekyll running on our system, I chose to use a tool called Static implemented in Clojure. The following bash command starts static and rebuilds the site when posts change.

java -jar ../static/target/static-app.jar --watch

When the post is complete, we need to commit all the files to git and push it to Github.

git status
git add <new posts>
git commit -am "Commit message"
git push

Just like that, the new post appears on Github in all its glory.

Troubleshooting

There are many moving parts in org-mode and when things go wrong, debugging is taxing. Google is our friend and one particularly nasty bug I hit was the messed up state of org-mode. This magical sequence, C-U M-x org-reload, fixed my issue with "wrong type argument" error.