ox-latex: Protect [...] after \\ to be interpreted as LaTeX argument

* lisp/ox-latex.el (org-latex-linebreak-safe): New constant holding
safe version of LaTeX line break.
(org-latex-table-matrix-macros):
(org-latex-clock):
(org-latex-line-break):
(org-latex-plain-text):
(org-latex-planning):
(org-latex--org-table):
(org-latex--math-table):
(org-latex-table-row):
(org-latex-verse-block): Use the new constant.

* testing/lisp/test-org-table.el (test-org-table/to-latex): Update
tests.

Reported-by: Stewart Thomas <sjt015@bucknell.edu>
Link: https://orgmode.org/list/ce760fc3-5aae-144d-2d02-7dea215f73fc@gmail.com
This commit is contained in:
Ihor Radchenko 2022-10-07 16:24:32 +08:00
parent 4d07df718b
commit 3f60acff77
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 36 additions and 17 deletions

View File

@ -278,10 +278,23 @@ list can be:
- `:lang-name' the actual name of the language.")
(defconst org-latex-line-break-safe "\\\\\\relax"
"Linebreak protecting the following [...].
(defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr")
Without \"\\relax\" it would be interpreted as an optional argument to
the \\\\.
This constant, for example, makes the below code not err:
\\begin{tabular}{c|c}
[t] & s\\\\\\relax
[I] & A\\\\\\relax
[m] & kg
\\end{tabular}")
(defconst org-latex-table-matrix-macros `(("bordermatrix" . "\\cr")
("qbordermatrix" . "\\cr")
("kbordermatrix" . "\\\\"))
("kbordermatrix" . ,org-latex-line-break-safe))
"Alist between matrix macros and their row ending.")
(defconst org-latex-math-environments-re
@ -2062,7 +2075,7 @@ information."
(concat (org-timestamp-translate (org-element-property :value clock))
(let ((time (org-element-property :duration clock)))
(and time (format " (%s)" time)))))
"\\\\"))
org-latex-line-break-safe))
;;;; Code
@ -2659,7 +2672,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(defun org-latex-line-break (_line-break _contents _info)
"Transcode a LINE-BREAK object from Org to LaTeX.
CONTENTS is nil. INFO is a plist holding contextual information."
"\\\\\n")
(concat org-latex-line-break-safe "\n"))
;;;; Link
@ -3005,7 +3018,9 @@ contextual information."
;; Handle break preservation if required.
(when (plist-get info :preserve-breaks)
(setq output (replace-regexp-in-string
"\\(?:[ \t]*\\\\\\\\\\)?[ \t]*\n" "\\\\\n" output nil t)))
"\\(?:[ \t]*\\\\\\\\\\)?[ \t]*\n"
(concat org-latex-line-break-safe "\n")
output nil t)))
;; Return value.
output))
@ -3041,7 +3056,7 @@ information."
(format (plist-get info :latex-active-timestamp-format)
(org-timestamp-translate scheduled)))))))
" ")
"\\\\"))
org-latex-line-break-safe))
;;;; Property Drawer
@ -3821,11 +3836,11 @@ This function assumes TABLE has `org' as its `:type' property and
(format "\\begin{%s}%s{%s}\n" table-env width alignment)
(and above?
(org-string-nw-p caption)
(concat caption "\\\\\n"))
(concat caption org-latex-line-break-safe "\n"))
contents
(and (not above?)
(org-string-nw-p caption)
(concat caption "\\\\\n"))
(concat caption org-latex-line-break-safe "\n"))
(format "\\end{%s}" table-env)
(and fontsize "}"))))
(t
@ -3910,7 +3925,7 @@ This function assumes TABLE has `org' as its `:type' property and
(lambda (cell)
(substring (org-element-interpret-data cell) 0 -1))
(org-element-map row 'table-cell #'identity info) "&")
(or (cdr (assoc env org-latex-table-matrix-macros)) "\\\\")
(or (cdr (assoc env org-latex-table-matrix-macros)) org-latex-line-break-safe)
"\n")))
(org-element-map table 'table-row #'identity info) "")))
(concat
@ -3982,7 +3997,7 @@ a communication channel."
;; hline was specifically marked.
(and booktabsp (not (org-export-get-previous-element table-row info))
"\\toprule\n")
contents "\\\\\n"
contents org-latex-line-break-safe "\n"
(cond
;; Special case for long tables. Define header and footers.
((and longtablep (org-export-table-row-ends-header-p table-row info))
@ -3990,9 +4005,9 @@ a communication channel."
(org-export-get-parent-table table-row) info))))
(format "%s
\\endfirsthead
\\multicolumn{%d}{l}{%s} \\\\
\\multicolumn{%d}{l}{%s} \\\\\\relax
%s
%s \\\\\n
%s \\\\\\relax\n
%s
\\endhead
%s\\multicolumn{%d}{r}{%s} \\\\
@ -4092,8 +4107,12 @@ contextual information."
(replace-regexp-in-string
"^[ \t]*\\\\\\\\$" "\\vspace*{1em}"
(replace-regexp-in-string
"\\([ \t]*\\\\\\\\\\)?[ \t]*\n" "\\\\\n"
contents nil t) nil t) nil t) linreset)
"\\([ \t]*\\\\\\\\\\)?[ \t]*\n"
(concat org-latex-line-break-safe "\n")
contents nil t)
nil t)
nil t)
linreset)
info)
;; Insert footnote definitions, if any, after the environment, so
;; the special formatting above is not applied to them.

View File

@ -1635,11 +1635,11 @@ See also `test-org-table/copy-field'."
(ert-deftest test-org-table/to-latex ()
"Test `orgtbl-to-latex' specifications."
(should
(equal "\\begin{tabular}{l}\na\\\\\n\\end{tabular}"
(equal "\\begin{tabular}{l}\na\\\\\\relax\n\\end{tabular}"
(orgtbl-to-latex (org-table-to-lisp "| a |") nil)))
;; Test :environment parameter.
(should
(equal "\\begin{tabularx}{l}\na\\\\\n\\end{tabularx}"
(equal "\\begin{tabularx}{l}\na\\\\\\relax\n\\end{tabularx}"
(orgtbl-to-latex (org-table-to-lisp "| a |")
'(:environment "tabularx"))))
;; Test :booktabs parameter.
@ -1648,7 +1648,7 @@ See also `test-org-table/copy-field'."
"\\toprule" (orgtbl-to-latex (org-table-to-lisp "| a |") '(:booktabs t))))
;; Handle LaTeX snippets.
(should
(equal "\\begin{tabular}{l}\n\\(x\\)\\\\\n\\end{tabular}"
(equal "\\begin{tabular}{l}\n\\(x\\)\\\\\\relax\n\\end{tabular}"
(orgtbl-to-latex (org-table-to-lisp "| $x$ |") nil)))
;; Test pseudo objects and :raw parameter.
(should