Wednesday, 4 November 2009

orgtbl-mode

I've been using org-mode for some time for basic task planning, and occasionally for tracking time, but it always seems to have that bit more to learn. One of the really cool features with org-mode is its table editor: it makes it absolutely trivial to create and manipulate ASCII tables in plain text files (see here for more).

Carsten Dominik's org-mode presentation at Google intrigued me with the possibility of using that table editor in non-org files, but I lacked the inclination to investigate further until I stumbled across this video showing the feature off by generating an HTML table from an org-mode table source.

If you're still interested, you should watch that now. I'll do my best to explain how it's done when you're finished.

....

Creating an HTML table with orgtbl-mode



Quite simply, orgtbl-mode is an Emacs minor mode that embeds into whichever major mode you happen to be working in. Within the context of an org-mode table within that document, org-mode table commands apply. Elsewhere in the document, your major mode (java-mode, cperl-mode, etc.) is in charge.

The Insertion Point for the HTML Table



You specify where the org table is going to appear with a pair of markers.


#BEGIN RECEIVE ORGTBL books
#END RECEIVE ORGTBL books


The first character there ('#') should be whichever comment character makes sense for your major mode. So you'll use '//' for Java, C and C++, '%' for LaTeX, <!-- ... --> for HTML and XML, etc. The reason for this simple: you don't want these markers polluting the textual sources that you're composing in whichever major mode you're in.

The orgtbl Source Table



Next, you'll define (somewhere in the document) a section for you to specify the org table. It helps here if your language has a block-comment structure (like the above HTML style comment, or /* ... */ for C, or the comment package for LaTeX).


<!--
#+ORGTBL: SEND books orgtbl-to-html
| Title | Cost |
|---------------------+-------|
| Programming Clojure | 30.00 |
| Programming Perl | 25.00 |
|---------------------+-------|
| TOTAL | |
-->


(The reason I advise about block comments is that I was seeing problems generating the table unless #+ORGTBL: was a the beginning of the line).

The #+ORGTBL line includes the SEND command (the counterpart to the RECEIVE in the previous markup); the table name (to match up with the appropriate RECEIVE: there could be many); and the translation function that takes the org-mode table and produces the HTML, LaTeX, or whatever output.

Once you've got the table above, with the cursor in the field where you want the table to go, type C-u C-c =. At this point, focus will be transferred to the minibuffer, which will look like this:


Field formula B4= 


Here, you can enter spreadsheet-like formulae. I'm still learning here, but a good answer to the prompt is:


vsum(@I..@II)


...which will neatly place a total for the Cost field in that slot (and also place a formula definition under the table), so that it looks like:


<!--
#+ORGTBL: SEND books orgtbl-to-html
| Book | Cost |
|---------------------+-------|
| Programming Clojure | 20.00 |
| Programming Perl | 25.00 |
|---------------------+-------|
| TOTAL | 45. |
#+TBLFM: @4$2=vsum(@I..@II)
-->


@4$2 is the specifier for the cell where the total is to appear (row 4, column 2). Formulae are automatically updated as you move columns around, insert new ones, add new rows, etc., but when you're done editing, hit C-c C-c on the formula line to update the table values.

Generating the HTML Table



On the #+ORGTBL: line, hit C-c C-c, and the HTML for your table will automatically be generated from the orgtbl source and be inserted between the BEGIN RECEIVE and END RECEIVE markers.

Updating the HTML Table



When you want to change your HTML table, just change the org-mode table, update the formula with C-c C-c on the formula line, and then regenerate with the same keystrokes on the SEND line, and your HTML table will be refreshed with the new state.

1 comment:

  1. http://www.youtube.com/watch?v=EQAd41VAXWo shows it in action. :)

    ReplyDelete