On Sat, 28 Mar 2026 at 17:47, Ihor Radchenko <[email protected]> wrote:
> Pedro Andres Aranda Gutierrez <[email protected]> writes: > > > just a bit of editing comfort. Current behaviour is preserved. > > 100% backward compatible. > > Thanks! > > > +*** Square brackets around LATEX_CLASS_OPTIONS are now optional. > > + > > +Square brackets around the LATEX_CLASS_OPTIONS may be ommited. > > Maybe put an example here - just as in the manual. > Otherwise, you have two sentences that are almost the same - that very > strange to read. > Right... done > +(defun org-latex--mk-options (str) > > + "Make STR be enclosed in [ ] or return an empty string if nil or > empty. > > + > > +If STR is nil or an empty string, return an empty string. > > +If STR is a traditional LATEX_CLASS_OPTIONS enclosed in [ ], return it > as is. > > +If the square brackets are missing, return STR enclosed in square > brackets." > > + (if (or (not str) (length= str 0)) "" > > + (save-match-data > > + (concat "[" (replace-regexp-in-string > > + "\\[?\\([^]]+\\)\\]?" "\\1" str) > > + "]")))) > > What about > > #+LATEX_CLASS_OPTIONS: [foo{[}bar{]}] > > I admit that it is very unlikely to happen, but I think we can change > regexp to capture the last ] greedily. > I've rewritten it to make sure that there's only one square bracket at the beginning of the string and one at the end in the LaTeX. No comment on the actual need for it... coming from a situation where nothing was checked. -- > Ihor Radchenko // yantar92, > Org mode maintainer, > Learn more about Org mode at <https://orgmode.org/>. > Support Org development at <https://liberapay.com/org-mode>, > or support my work at <https://liberapay.com/yantar92> > -- Fragen sind nicht da, um beantwortet zu werden, Fragen sind da um gestellt zu werden Georg Kreisler "Sagen's Paradeiser" (ORF: Als Radiohören gefährlich war) => write BE! Year 2 of the New Koprocracy
From 148a759e72f6c4e2c8c804b4ff8094c89644e3eb Mon Sep 17 00:00:00 2001 From: "Pedro A. Aranda" <[email protected]> Date: Sun, 29 Mar 2026 08:33:50 +0200 Subject: [PATCH] ox-latex: Make brackets around LATEX_CLASS_OPTIONS optional * doc/org-manual.org: Document that square brackets around the LATEX_CLASS_OPTIONS is optional. * etc/ORG-NEWS: Announce the new behaviour. * lisp/ox-latex.el: (org-latex--mk-options, org-latex-make-preamble) (org-latex--mk-options): New function to add square brackets around a string if needed. (org-latex-make-preamble): use (org-latex--mk-options) * testing/lisp/test-ox-latex.el: (test-ox-latex/latex-class-options1, test-ox-latex/latex-class-options2) (test-ox-latex/latex-class-options1): test that the old way works correctly. (test-ox-latex/latex-class-options2): test new way of setting the document class options. --- doc/org-manual.org | 16 ++++++++++++---- etc/ORG-NEWS | 10 ++++++++++ lisp/ox-latex.el | 15 ++++++++++++++- testing/lisp/test-ox-latex.el | 30 ++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index 904e1270d..95e2ee81b 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -14250,7 +14250,9 @@ general options (see [[*Export Settings]]). #+cindex: @samp{LATEX_CLASS_OPTIONS}, keyword Options the LaTeX export backend uses when calling the LaTeX - document class. + document class. Square brackets around the class options are + optional. If missing, they will be added by Org. + - =LATEX_COMPILER= :: @@ -14338,10 +14340,16 @@ custom sectioning or custom classes. The LaTeX export backend sends the =LATEX_CLASS_OPTIONS= keyword and =EXPORT_LATEX_CLASS_OPTIONS= property as options to the LaTeX ~\documentclass~ macro. The options and the syntax for specifying -them, including enclosing them in square brackets, follow LaTeX -conventions. +them, follow LaTeX conventions. Square brackets around them are +optional: + +: #+LATEX_CLASS_OPTIONS: a4paper,11pt,twoside,twocolumn + +and + +: #+LATEX_CLASS_OPTIONS: a4paper,11pt,twoside,twocolumn -: #+LATEX_CLASS_OPTIONS: [a4paper,11pt,twoside,twocolumn] +are equivalent. #+cindex: @samp{LATEX_HEADER}, keyword #+cindex: @samp{LATEX_HEADER_EXTRA}, keyword diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 2dcd86aee..fe35c73b3 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -97,6 +97,16 @@ This tangles the block to four files: You can set the LaTeX environment used in ~example~ blocks with this variable. +*** Square brackets around LATEX_CLASS_OPTIONS are now optional. + +#+BEGIN_SRC org +,#+LATEX_CLASS_OPTIONS: [a4paper,12pt] +#+END_SRC +can be also written as: +#+BEGIN_SRC org +,#+LATEX_CLASS_OPTIONS: a4paper,12pt +#+END_SRC + ** New functions and changes in function arguments # This also includes changes in function behavior from Elisp perspective. diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 500137d32..84aeceeb5 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -2017,6 +2017,19 @@ The default behaviour is to typeset with the Roman font family." ;;; Template +(defun org-latex--mk-options (str) + "Make STR be enclosed in [ ] or return an empty string if nil or empty. + +If STR is nil or an empty string, return an empty string. +If STR is a traditional LATEX_CLASS_OPTIONS enclosed in [ ], return it as is. +If the square brackets are missing, return STR enclosed in square brackets." + (if (or (not str) (length= str 0)) "" + (save-match-data ; just in case it is used in a search/replace context + (let ((str (concat "[" str "]"))) ; make sure it is enclosed in [] + (replace-regexp-in-string ; remove excess [ at the beginning + "\\`\\[+" "[" + (replace-regexp-in-string ; remove excess ] at the end + "]+\\'" "]" str)))))) ;;;###autoload (defun org-latex-make-preamble (info &optional template snippet?) @@ -2030,7 +2043,7 @@ specified in `org-latex-default-packages-alist' or (let* ((class (plist-get info :latex-class)) (class-template (or template - (let* ((class-options (plist-get info :latex-class-options)) + (let* ((class-options (org-latex--mk-options (plist-get info :latex-class-options))) (header (nth 1 (assoc class (plist-get info :latex-classes))))) (and (stringp header) (mapconcat #'org-element-normalize-string diff --git a/testing/lisp/test-ox-latex.el b/testing/lisp/test-ox-latex.el index 2c3b8f3bf..e99aac3c4 100644 --- a/testing/lisp/test-ox-latex.el +++ b/testing/lisp/test-ox-latex.el @@ -372,6 +372,36 @@ Fake test document (should (search-forward "\\documentclass" nil t)) ;; And after this (should (search-forward "\\begin{document}" nil t)))) + +(ert-deftest test-ox-latex/latex-class-options1 () + "Test #+LATEX_CLASS_OPTIONS with square brackets." + (org-test-with-exported-text 'latex + "#+LATEX_CLASS: article +#+LATEX_CLASS_OPTIONS: [a4paper,12pt] +#+TITLE: Confirm legagy class options + +* Test + +Fake test document +" + (goto-char (point-min)) + (should (search-forward "\\documentclass[a4paper,12pt]{article}" nil t)))) + +(ert-deftest test-ox-latex/latex-class-options2 () + "Test #+LATEX_CLASS_OPTIONS without square brackets." + (org-test-with-exported-text 'latex + "#+LATEX_CLASS: article +#+LATEX_CLASS_OPTIONS: a4paper,12pt +#+TITLE: Confirm class options without square brackets + +* Test + +Fake test document +" + (goto-char (point-min)) + (should (search-forward "\\documentclass[a4paper,12pt]{article}" nil t)))) + + (ert-deftest test-ox-latex/latex-default-example-with-options () "Test #+ATTR_LATEX: :options with custom environment." (let ((org-latex-default-example-environment "Verbatim")) -- 2.43.0
