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 :)
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 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 bufferorg results are enclosed in a #+BEGIN_SRC org blockhtml results are assumed to be HTML and enclosed in a #+BEGIN_SRC html blocklatex results assumed to be LaTeX and are enclosed in a BEGINLaTeX blockcode result are assumed to be parsable code and are enclosed in a code blockpp result is converted to pretty-printed code and is enclosed in a code block.drawer result is wrapped in a RESULTS drawerhandling is one of
silent results are not inserted into the bufferreplace any existing value is replaced with valueappend result is appended to existingprepend reslult is prepended to existing
:exports can have one of the following values.
code body of source block is inserted into the bufferresults result of source block evaluation is inserted into the bufferboth code and results are inserted into the buffernone neither code nor results are inserted into the bufferHere 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
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
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.
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.
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.
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.