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.