With orgtbl, how to ensure that braces and dollars are not escaped?

The minor mode orgtbl is a wonderful tool for easily creating latex tables (you should check it out!).

However, I am running into an issue with its exporter. If I have content surrounded by braces in a cell, the braces will be escaped with backslashes. Additionally, if this content contains dollars, they will be escaped too.

It does not happen if the braces are delimiting arguments for a macro that AUCTeX knows of (see the second cell in the MWE below), but if the macro is unknown, it does happen.

Surrounding content with braces, even without a macro, is sometimes desirable, for example it is required by siunitx for content which only looks like data.

The org manual mentions the option :no-escape t, but it only protects &%#_^ from escaping (no offense). However, I am almost certain that this is a change in behavior, because in the same situation, one year ago, this option was fixing the issue.

"almost" is important, though... was the situation really the same? Also, I was working with a different computer, a different version of emacs and a different version of org back then, so downgrading is not an option for settling that up.

So, the question(s): If it is indeed a change of behavior, what is the rationale, and is there a known work-around? And if I am wrong and it has always been like that, is there an easy work-around? Or should I try to understand orgtbl-to-generic and suggest a patch?

MWE (both input and output):

\documentclass{article}

\usepackage{verbatim}
\usepackage{amsmath}

\begin{document}

Without no-escape:
\begin{tabular}{ll}
Col 1 & Col 2 \\
\{Braced content\} & $\text{Math content}$ \\
\{\$\text{Braced and math!}\$\} &  \\
\end{tabular}
\begin{comment}
#+ORGTBL: SEND Without orgtbl-to-latex :splice nil :skip 0
| Col 1                       | Col 2                 |
| {Braced content}            | $\text{Math content}$ |
| {$\text{Braced and math!}$} |                       |
\end{comment}

\vspace{2cm}

With no-escape:
\begin{tabular}{ll}
Col 1 & Col 2 \\
\{Braced content\} & $\text{Math content}$ \\
\{\$\text{Braced and math!}\$\} &  \\
\end{tabular}
\begin{comment}
#+ORGTBL: SEND With orgtbl-to-latex :splice nil :skip 0 :no-escape t
| Col 1                       | Col 2                 |
| {Braced content}            | $\text{Math content}$ |
| {$\text{Braced and math!}$} |                       |
\end{comment}

Expected output:
\begin{tabular}{ll}
Col 1 & Col 2 \\
{Braced content} & $\text{Math content}$ \\
{$\text{Braced and math!}$} &  \\
\end{tabular}

\end{document}

%%% Local Variables:
%%% mode: latex
%%% eval: (turn-on-orgtbl)
%%% TeX-master: t
%%% End:


In case someone observes a different behavior, here is my environment:

• GNU Emacs 24.3.1 (x86_64-redhat-linux-gnu)
• Org-mode version 8.2.6

The problem does not seem to be related to any latex-related modes, since it also occurs if I open the above example in fundamental-mode and then turn orgtbl on.

• It seems the characters &%#_^ are hardcoded inside the orgtbl-send-table function. – giordano Jun 25 '14 at 17:03
• Hm... Indeed you are right. Then who is to blame for escaping these braces and dollars? – T. Verron Jun 25 '14 at 18:24
• @T.Verron I would not use orgtbl to create static tabulars. The nice thing is to use orgtbl for calculations, so that you have the power of the calc package of emacs inside LaTeX-tabular. To get numbers printed out nicely, one has to splice the tabular and make columns with the numprint package. If you are interested, ask. – Keks Dose Jun 25 '14 at 19:48
• @KeksDose The MWE is a static tabular because the problem at stake does not require anything more, but the complete usecase is not. Also, in my workflow, the tabular is indeed spliced, and the columns formatted with siunitx (I do not know numprint, but I'll assume it does more or less the same job). I would be reluctant to take the next step completely forgetting about the original org-table, only working with the latex table, for several reasons: ease of editting, spreadsheet calculations, and the ability to apply specific per-column elisp transformations without changing the raw data. – T. Verron Jun 25 '14 at 22:31
• @T.Verron Well, probably you'll get an answer, if you ask here: lists.gnu.org/mailman/listinfo/emacs-orgmode Your question aims at the internals of orgtbl. – Keks Dose Jun 26 '14 at 8:32

(Edit 2020) At some point in the past 6 years, a :raw parameter was added to the export function, which does exactly as it says: setting it to anything but nil turns off any fancy transformation org would otherwise be doing.

What follows is only for history. :)

After digging further into the code, I came up with this dirty replacement for orgtbl-to-latex:

(defun tv/orgtbl-to-latex (table params)
(cl-flet ((org-export-string-as (string backend &optional b e) string))
(orgtbl-to-latex table params)))


The effect is to bypass all of org's export functions for this matter, and simply output the cell contents verbatim. In practice, it does solve my problem, however I cannot be sure that it will not raise more problems in the future.

Edit: Based on the discussion on the orgmode mailing list, the definition of orgtbl-to-latex given in the manual was changed at some point, and it still works as I expected:

(defun orgtbl-to-latex-verbatim (table params)
"Convert the Orgtbl mode TABLE to LaTeX."
(let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
org-table-last-alignment ""))
(params2
(list
:tstart (concat "\\begin{tabular}{" alignment "}")
:tend "\\end{tabular}"
:lstart "" :lend " \\\\" :sep " & "
:efmt "%s\\,(%s)" :hline "\\hline")))
(orgtbl-to-generic table (org-combine-plists params2 params))))


In recent versions of org-mode, orgtbl-to-generic is given an additional parameter specifying the exportation backend, and in turns the content of the cells is read as some org code to be transformed into latex, rather than some latex code.

For those who would prefer to use only one exportation function, but a parameter to toggle the verbatim export, the following definition seems to work. Use :from-org t if you want org to perform its exportation magic. Without a flag, this redefinition reverts the current default behavior (as of 8.2.6) to what it was a few months ago. If you prefer to not change the default, change the flag name and its interpretation (ask me in the comments if you need more details.

(defun orgtbl-to-latex (table params)
"Convert the orgtbl-mode TABLE to LaTeX.
TABLE is a list, each entry either the symbol hline' for a horizontal
separator line, or a list of fields for that line.
PARAMS is a property list of parameters that can influence the conversion.
Supports all parameters from orgtbl-to-generic'.  Most important for
LaTeX are:

:splice    When set to t, return only table body lines, don't wrap
them into a tabular environment.  Default is nil.

:fmt       A format to be used to wrap the field, should contain %s for the
original field value.  For example, to wrap everything in dollars,
use :fmt \"$%s$\".  This may also be a property list with column
numbers and formats.  For example :fmt (2 \"$%s$\" 4 \"%s%%\")
The format may also be a function that formats its one argument.

:efmt      Format for transforming numbers with exponentials.  The format
should have %s twice for inserting mantissa and exponent, for
example \"%s\\\\times10^{%s}\".  LaTeX default is \"%s\\\\,(%s)\".
This may also be a property list with column numbers and formats.
The format may also be a function that formats its two arguments.

:llend     If you find too much space below the last line of a table,
pass a value of \"\" for :llend to suppress the final \\\\.

The general parameters :skip and :skipcols have already been applied when
this function is called."
(let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
org-table-last-alignment ""))
(params2
(list
:tstart (concat "\\begin{tabular}{" alignment "}")
:tend "\\end{tabular}"
:lstart "" :lend " \\\\" :sep " & "
:efmt "%s\\,(%s)" :hline "\\hline")))
(require 'ox-latex)
(let* ((*orgtbl-transform* (plist-get params :from-org))
(backend (if *orgtbl-transform* 'latex nil)))
(orgtbl-to-generic table (org-combine-plists params2 params) backend))))