23 March 2013

Migrating to the new Org-mode exporter (Org version 8.0)


I recently took the plunge and updated to the most current version of Emacs Org-mode, which uses "the new exporter," written by Nicolas Goaziou. For those unfamiliar with Org-mode, it's a fairly incredible bit of software: outlining/notes, todos (including scheduling/deadlines/prioritzation), writing and executing code, and document authoring (output to LaTeX/PDF, html, Open Document Format, and many others) all in one.

If you're already familiar with Emacs, let me sell it to you another way: I was not familiar at all with Emacs and I literally endured learning Emacs for Org-mode.

This post will walk through my migration from the "old exporter" to the new framework. There are lots of posts to the mailing list these days about wrapping one's head around the various changes and I hope this helps some in the transition.

Current .emacs

Here's my current emacs config file, with the exception of some Sunrise Commander and Open With settings at the end through custom-set-variables.

  ;; set load paths
  ;; set load dirs
  (add-to-list 'load-path "~/.elisp/org.git/lisp/")
  (add-to-list 'load-path "~/.elisp/org.git/contrib/lisp/")
  (add-to-list 'load-path "~/.elisp/site-lisp/")
  (add-to-list 'load-path "~/.elisp/site-lisp/ess/lisp/")

  ;; setup babel languages
  '((latex . t)
  (emacs-lisp . t)
  (org . t)
  (R . t)
  (sh . t)
  (python .t )))

  ;; load org-based config
  (org-babel-load-file "~/org/aux/")
Note that last line; it calls ~/org/aux/, which contains the rest of my configuration options.

I've taken to liking the use of an orgmode file itself to contain my settings in babel code blocks. It's easier to organize and understand, in my opinion. Here's a link to the file so you can check out my various options. In particular, here are the ones relevant to exporting:

  (require 'org-latex)
  (require 'org-taskjuggler)

  ;; taskjuggler options
  (setq org-export-taskjuggler-target-version 3.1)
  (setq org-export-taskjuggler-default-reports (quote (
    "include \"reports.tji\"")))

  ;; export options
  (setq org-export-html-validation-link "")
  (setq org-export-latex-tag-markup "\\hfill\\textbf{%s}")

  ;; booktabs tables
  (setq org-export-latex-tables-hline "\\midrule")
  (setq org-export-latex-tables-tstart "\\toprule")
  (setq org-export-latex-tables-tend "\\bottomrule")


The actual changes

So you know, I'm literally writing this post as I go. Despite news of the new expoter being out for some time, I've done nothing with it yet. Bastien, the current Org-mode maintainer, sent out a link a while ago that I've kept in my inbox about switching to the new exporter, so I'm going to by that. It links here which subsequently links to here.

I'll simply start with the Worg (Org-mode's wiki) page and work my way through.

Before having to do anything, though... we have to update Org-mode. I suggest using git, as described in the installation instructions. That made my upgrade as easy as:

  $ cd ~/.elisp/org.git
  $ git pull
  $ make clean && make

Now, on to the changes. (The rest of the post assumes you're following along with the transition guide/notes for upgrading to v8.0.)

Moved files

There are a bunch of moved files. Since I already have the contrib/ directory in load=path, the only bit that applied to me was changing org-taskjuggler.el. I changed the line in to (require 'ox-taskjuggler), saved, and started a new Emacs window with no errors. So far so good.

Changed options

Looks like the changed options shouldn't bother me until I actually need to export something. I set options on a per-file basis anyway, so I don't have any config files to tweak based on the new syntax. I am taking note of the new #+TOC settings, though. I use that for reports at work in LaTeX, so that's of definite interest.

Skimming the rest, seems like more syntax stuff that I typically look up as needed anyway, so I'll simply continue to do so and refer to the updated manual/Worg syntax for the future.

Other changes of interest

There were some last noted syntax changes that definitely apply. I keep a file with my commonly used Org-mode options in and then use it in almost all .org files that I have:

    #+AUTHOR:    John Henderson
    #+startup: lognotestate
    #+OPTIONS:   toc:nil *:t TeX:t LaTeX:t H:5 tags:nil todo:nil <:nil num:nil
    #+latex_header: \usepackage[hmargin=2.5cm,vmargin=2.5cm]{geometry}
    #+latex_header: \usepackage{mathpazo} \usepackage{paralist}
    #+latex_header: \usepackage{enumitem}
    #+latex_header: \usepackage{comment}
    #+latex_header: \usepackage{tikz}
    #+latex_header: \usetikzlibrary{shapes, positioning}
    #+latex_header: \setlength{\parskip}{0.5cm} \setlength{\parindent}{0cm}
    #+latex_header: \usepackage{lscape}
    #+latex_header: \usepackage{booktabs}
    #+latex_header: \hypersetup{colorlinks=true,linkcolor=blue,urlcolor=blue}
    #+style: <link rel="stylesheet" type="text/css" href="http://path" />
    #+BIND: org-export-latex-title-command ""
    #+tags: work related tags go here
The first two affect my setupfile settings. I've changed my #+style: option where I link to a css file I like for html export from this:

  #+style: <link rel="stylesheet" type="text/css" href="http://path" />
To this:

  #+html_head: <link rel="stylesheet" type="text/css" href="http://path" />
And in all files in which I've had this line to set options via the setupfile above:

  #+setupfile: ~/org/aux/
I need to change them to:

  #+include: "~/org/aux/"
Pay attention to the quoted path in the latter vs. the unquoted path used in the former. The first time I updated my setup from #+setupfile to #+include, Org-mode gave me an error on export since I didn't quote the path.

The last big change that will have a huge effect if I re-export any of my existing files has to do with setting attributes like the dimensions of included graphics. This is where things got a bit confusing for me. The guide says:
Attribute lines now take plists:
    #+attr_latex :width "5cm"
    #+attr_beamer :options "width=5cm"
In chasing this around and actually trying it, there's been changes since that document was written. See some of the mailing list posts here and here about that. Basically, instead of the syntax above (:options "value") for width, it's just :width value (no quotes).

I've got options like this throughout tons of papers and Beamer presentations, so I'll have to make sure I switch the syntax above to the more "babel-like" syntax from the previous syntax of:

   #+attr_latex: width=value

Applying the changes

I need to customize org-export-backends to make sure whatever formats I want to export will be available. So, with an M-x customize-variable RET org-export-backends RET, I'm greeted with a nice interface to access the various options:

       Operate on all settings in this buffer:
       Set for current session   Save for future sessions 
       Undo edits   Reset to saved   Erase customizations     Exit 

       Hide Org Export Backends:
       [X]    ascii       Export buffer to ASCII format
       [X]    beamer      Export buffer to Beamer presentation
       [X]    html        Export buffer to HTML format
       [ ]    icalendar   Export buffer to iCalendar format
       [X]    latex       Export buffer to LaTeX format
       [ ]    man         Export buffer to MAN format
       [X]    md          Export buffer to Markdown format
       [X]    odt         Export buffer to ODT format
       [ ]    texinfo     Export buffer to Texinfo format
       [ ] C  confluence  Export buffer to Confluence Wiki format
       [ ] C  deck        Export buffer to deck.js presentations
       [ ] C  freemind    Export buffer to Freemind mindmap format
       [ ] C  groff       Export buffer to Groff format
       [ ] C  koma-letter Export buffer to KOMA Scrlttrl2 format
       [ ] C  RSS 2.0     Export buffer to RSS 2.0 format
       [X] C  s5          Export buffer to s5 presentations
       [X] C  taskjuggler Export buffer to TaskJuggler format
I choose the ones I want and then navigate to "Save for future sessions" and hit return. I do this because I never remember .emacs syntax, so I go to .emacs and look in the custom-set-variables section for what  was written, and then move that to my actual config file. For example, this is what customize-variable added:

       '(org-export-backends (quote (ascii beamer html latex md odt s5 taskjuggler)))
And I put that in ~/org/aux/ like so:

       (setq org-export-backends (quote (
I will only regularly use LaTeX, but the others were still cool. md was of definite interest to me, as I've recently gotten into R Studio a bit and wonder if something like slidify could be made to work on an md file. That or knitr in order to have the images actually embedded into the html vs. only linked via <img> tags.

Now I'm just reading through Nicolas Goaziou's (the new exporter's creator) announcement on the Org-mode mailing list to see if there's anything else I need to know about. Read finished, and looks good.

The last bit of customization that seems to be required has to do with setting up Beamer export. This amounted to just adding a definition for a beamer document class to the emacs config file. The rest seemed fairly analogous to the previous export engine.

Note on .emacs settings

After trying to export and running into some issues, I tried to customize some variables in a new Emacs session and noticed that I couldn't find them, which brought to mind this bit from Nicolas' email:
3 Installation
There are two ways to install export back-ends.
  1. You may customize `org-export-backends' variable. It contains the list of back-ends that should always be available.
  2. You can also simply require the back-end libraries (e.g. `(require 'ox-icalendar)' for the iCalendar back-end). Note that with method 1, the back-ends will be loaded only when the export framework is used for the first time.
So… since I used the first method above, the backends weren't actually loaded in a new session since I hadn't exported anything! Thus, Emacs was oblivious to any of the corresponding options and variables that get brought in by loading those backends.

So, contrary to the above, I'm going with the second method for now, in order to have the variables loaded in case I want to change them via the customize buffer. Perhaps I'll migrate to the first method once I have everything set and save on Emacs startup time (assuming that's the benefit).

Also of note: it appears that if you load libraries directly, the values passed to org-export-backends, if any, are ignored. If you do the reverse, both apply. Take this as an example:

(require 'ox-latex)
    (require 'ox-html)

    (setq org-export-backends (quote (taskjuggler)))
This will load LaTeX and html backends, making Emacs aware of variables org-latex-* and org-html-* in a new session (recall that per the transition guide, the backend-specific options are now set to org-backend-*). However, Emacs will be ignorant to org-taskjuggler-* variables. Switching the order seems to make all three sets available. I'm a bit confused by this... probably best to just use one method or the other.

Test drive!

I created two files to test export, one for LaTeX/html, and one for a Beamer presentation. Both worked pretty well except for the html image width options. Despite the hoopla above and mailing list posts about the universal syntax of :width value (no quotes), I couldn't get that to work for html export. I was getting :width 200px converted to:

       <img src="http://path/to/image.jpg" :width 200px alt="" />
I created a new mailing list post about this... and it's now fixed! Now, it really is just as simple as:

   #+attr_latex: :width 5cm
   #+attr_html: :width 200px

So, other than that, everything exported as I'd expect!

To end and so there's no confusion, here's the final I ended up with. It seems to be compatible the new exporter so far. This file is called by my ~/.emacs at the beginning of this post, which remained unchanged. Note that toward the end of the Org-mode options section (in, I commented out some bits having to do with html export variables and the booktabs package for LaTeX tables. I did this so that I can set them properly in the new exporter, just in case the variable names aren't the same anymore. For example, I noticed that the new exporter appears to have some booktabs specific options now, so I might not need the "hack" that I've been using from a bit back.

That's all for now -- hope this helps with your own migration!