* PATCH: fix ToC generation in the Latex exporter
@ 2025-01-07 16:34 Pedro Andres Aranda Gutierrez
2025-01-11 8:47 ` Ihor Radchenko
0 siblings, 1 reply; 2+ messages in thread
From: Pedro Andres Aranda Gutierrez @ 2025-01-07 16:34 UTC (permalink / raw)
To: Org Mode List, Ihor Radchenko, Ihor Radchenko; +Cc: rudolf
[-- Attachment #1.1: Type: text/plain, Size: 529 bytes --]
Hi
Please find attached a patch to fix ToC generation in the LaTeX exporter.
With this, you don't need to reach back to @@latex @@ constructs to get
your ToC alright. I have added an option to generate ToC's that is closer
to LaTeX (num:latex) tha to org
Let me know... /PA
--
Fragen sind nicht da, um beantwortet zu werden,
Fragen sind da um gestellt zu werden
Georg Kreisler
Headaches with a Juju log:
unit-basic-16: 09:17:36 WARNING juju.worker.uniter.operation we should run
a leader-deposed hook here, but we can't yet
[-- Attachment #1.2: Type: text/html, Size: 887 bytes --]
[-- Attachment #2: 0001-ox-latex-fix-toc-generation.patch --]
[-- Type: text/x-patch, Size: 10403 bytes --]
From a2819314514ddd4e2ccd48301827ed4c1c875d85 Mon Sep 17 00:00:00 2001
From: "Pedro A. Aranda Gutiérrez" <paaguti@gmail.com>
Date: Tue, 7 Jan 2025 17:20:26 +0100
Subject: [PATCH] ox-latex: fix toc generation
* lisp/ox-latex.el: Add variable `org-latex-unnumbered-section-re'
to filter the unnumbered section.
(org-latex-headline): fix 'num:t' toc generation to match other
exporters and add a new 'num:latex' option that behaves closer to
toc generation criteria in LaTeX
* testing/lisp/test-ox-latex.el: test the fix and new toc generation
option.
* doc/org-manual.org: Document the fix and new toc generation option
* etc/ORG-NEWS: Announce fix to toc generation and the new `num:latex'
option
---
doc/org-manual.org | 25 ++++++++
etc/ORG-NEWS | 13 ++++
lisp/ox-latex.el | 46 ++++++++++++--
testing/lisp/test-ox-latex.el | 111 ++++++++++++++++++++++++++++++++++
4 files changed, 189 insertions(+), 6 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index e88317379..186ad1258 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -14852,6 +14852,31 @@ some text in German...
\end{foreigndisplayquote}
#+end_example
+*** Controlling the way the table of contents is generated
+
+=org= handles the table of contents slightly different as LaTeX. It
+will be generated when the =#+OPTIONS:= include =toc:t= and include
+all headings, regardless of whether they are numbered (=num:t= )or
+unnumbered (=num:nil=).
+
+If you want the table of contents to follow the LaTeX behaviour
+closer, you will can set =num:latex= in the options line. In this
+case, the following rules apply:
+
+1. Numbered headings are included in the header. If you want an
+ alternative title to appear in the table of contents, use the
+ =:ALT_TITLE:= property for the section.
+
+2. Unnumbered headings are not included in the table of contents,
+ unless you set the =:UNNUMBERED:= property to =toc= or you include
+ the =:ALT_TITLE:= property in the section's properies.
+
+If your LaTeX output uses special commands for unnumbered headings
+instead of the expected =\chapter*{}= or =\section*{}=,
+=\subsection*{}= etc. you need to configure
+=org-latex-unnumbered-section-re= to add the headings to the
+table of contents.
+
** Markdown Export
:PROPERTIES:
:DESCRIPTION: Exporting to Markdown.
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index c9bb192de..c9cb3980e 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -291,6 +291,19 @@ slide to specific animation steps.
This text will be displayed on animation step 2 and later.
#+END_SRC
+*** ox-latex: The way the table of contents handles unnumbered sections has changed
+
+The document option ~num~ can now be ~t~, ~nil~ or ~latex~. The LaTeX
+exporter will now follow the convention of the other exporters and
+export all unnumbered sections to the table of contents (ToC).
+
+If you want to follow your "LaTeX intuition" and control which unnumbered
+sections appear in the ToC, set ~num:latex~ in the document
+~#+OPTIONS:~. In this case, you will be able include the unnumbered
+section in the table of contents by either adding an ~:ALT_TITLE:~ or
+setting ~:UNNUMBERED:~ to ~toc~. Setting ~:UNNUMBERED:~ to ~t~ will
+exclude the section from the ToC.
+
** 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 16f8f5af2..3acc24e20 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -319,6 +319,10 @@ cdr is a property list. Valid keywords for this list can be:
"empheq")))
"Regexp of LaTeX math environments.")
+(defconst org-latex-unnumbered-section-re
+ "^\\\\\\(chapter\\|\\(sub\\)*section\\)[*]"
+ "Regexp to get the unnumbered section tag")
+
\f
;;; User Configurable Variables
@@ -2276,6 +2280,8 @@ holding contextual information."
(unless (org-element-property :footnote-section-p headline)
(let* ((class (plist-get info :latex-class))
(level (org-export-get-relative-level headline info))
+ (sec-num (plist-get info :section-numbers))
+ (unnumbered-type (org-export-get-node-property :UNNUMBERED headline t))
(numberedp (org-export-numbered-headline-p headline info))
(class-sectioning (assoc class (plist-get info :latex-classes)))
;; Section formatting will set two placeholders: one for
@@ -2378,7 +2384,8 @@ holding contextual information."
;; This is a standard headline. Export it as a section. Add
;; an alternative heading when possible, and when this is not
;; identical to the usual heading.
- (let ((opt-title
+ (let (;; (alt-title (org-export-get-alt-title headline info))
+ (opt-title
(funcall (plist-get info :latex-format-headline-function)
todo todo-type priority
(org-export-data-with-backend
@@ -2402,10 +2409,10 @@ holding contextual information."
(string-match-p "\\<local\\>" v)
(format "\\stopcontents[level-%d]" level)))))
info t)))))
- (if (and (or (and opt-title (not (equal opt-title full-text)))
+ (if (and numberedp (or (and opt-title (not (equal opt-title full-text)))
;; Heading contains footnotes. Add optional title
;; version without footnotes to avoid footnotes in
- ;; TOC/footers.
+ ;; TOC/footers for numbered sections *only*
(and (not (equal full-text-no-footnote full-text))
(setq opt-title full-text-no-footnote)))
(string-match "\\`\\\\\\(.+?\\){" section-fmt))
@@ -2418,9 +2425,36 @@ holding contextual information."
full-text
(concat headline-label pre-blanks contents))
;; Impossible to add an alternative heading. Fallback to
- ;; regular sectioning format string.
- (format section-fmt full-text
- (concat headline-label pre-blanks contents))))))))
+ ;; regular sectioning format string for a numbered section
+ (if numberedp
+ (format section-fmt full-text
+ (concat headline-label pre-blanks contents))
+ ;; If the section is unnumbered, we can still do something
+ ;;
+ (save-match-data
+ (let ((candidate (string-match org-latex-unnumbered-section-re section-fmt)))
+
+ (when (or
+ ;; Always suppress :UNNUMBERED: notoc
+ (string= unnumbered-type "notoc")
+ ;; When numbering mode is 'latex'
+ ;; suppress unnumbered 't' without alternative title
+ ;; :ALT_TITLE:
+ (and (string= sec-num "latex")
+ (string= unnumbered-type "t")
+ (string= opt-title full-text)))
+ (setq candidate nil))
+ (format section-fmt full-text
+ (concat
+ ;; Match only the 'canonical' chapter, section,subsection, etc
+ (when candidate
+ ;; opt-title carries the section carries ALT_TITLE if defined
+ ;; or the subsection title if ALT_TITLE is not defined (!)
+ (format "\\addcontentsline{toc}{%s}{%s}\n"
+ (match-string 1 section-fmt)
+ opt-title))
+ headline-label
+ pre-blanks contents)))))))))))
(defun org-latex-format-headline-default-function
(todo _todo-type priority text tags _info)
diff --git a/testing/lisp/test-ox-latex.el b/testing/lisp/test-ox-latex.el
index 892ac4437..fd3c2444d 100644
--- a/testing/lisp/test-ox-latex.el
+++ b/testing/lisp/test-ox-latex.el
@@ -127,5 +127,116 @@ Column & Column \\\\
(search-forward
"\\href{https://orgmode.org/worg/images/orgmode/org-mode-unicorn.svg}{\\includegraphics[width=.9\\linewidth]{/wallpaper.png}}"))))
+(ert-deftest test-ox-latex/num-latex ()
+ "Test toc treatment for num:latex"
+ (org-test-with-exported-text
+ 'latex
+ "#+TITLE: num-latex
+#+OPTIONS: toc:t H:3 num:latex
+
+* Section
+
+** Subsection 1
+:PROPERTIES:
+:UNNUMBERED: t
+:END:
+
+** Subsection 2
+:PROPERTIES:
+:UNNUMBERED: toc
+:END:
+
+** Subsection 3
+:PROPERTIES:
+:UNNUMBERED: toc
+:ALT_TITLE: Alternative
+:END:
+
+* Section 2
+:PROPERTIES:
+:ALT_TITLE: SECTION 2
+:END:
+"
+ (goto-char (point-min))
+ (should
+ (search-forward "\\begin{document}
+
+\\maketitle
+\\tableofcontents
+
+\\section{Section}
+\\label{"))
+ (should (search-forward "}
+
+\\subsection*{Subsection 1}
+\\label{"))
+ (should (search-forward "}
+\\subsection*{Subsection 2}
+\\addcontentsline{toc}{subsection}{Subsection 2}
+\\label{"))
+ (should (search-forward "}
+\\subsection*{Subsection 3}
+\\addcontentsline{toc}{subsection}{Alternative}
+\\label{"))
+ (should (search-forward "}
+\\section[SECTION 2]{Section 2}
+\\label{"))
+ (should (search-forward "}
+\\end{document}"))))
+
+(ert-deftest test-ox-latex/org-toc ()
+ "Test table of contents generation à la org"
+ (org-test-with-exported-text
+ 'latex
+ "#+TITLE: num-latex
+#+OPTIONS: toc:t H:3 num:t
+
+* Section
+
+** Subsection 1
+:PROPERTIES:
+:UNNUMBERED: t
+:END:
+
+** Subsection 2
+:PROPERTIES:
+:UNNUMBERED: toc
+:END:
+
+** Subsection 3
+:PROPERTIES:
+:UNNUMBERED: toc
+:ALT_TITLE: Alternative
+:END:
+
+* Section 2
+:PROPERTIES:
+:ALT_TITLE: SECTION 2
+:END:
+"
+ (should
+ (search-forward "\\begin{document}
+
+\\maketitle
+\\tableofcontents"))
+ (should
+ (search-forward "\\section{Section}
+\\label{"))
+ (should ;; test :UNNUMBERED: t
+ (search-forward "\\subsection*{Subsection 1}
+\\addcontentsline{toc}{subsection}{Subsection 1}
+\\label{"))
+ (should ;; test :UNNUMBERED: toc
+ (search-forward "\\subsection*{Subsection 2}
+\\addcontentsline{toc}{subsection}{Subsection 2}
+\\label{"))
+ (should ;; test :UNNUMBERED: t with :ALT_TITLE:
+ (search-forward "\\subsection*{Subsection 3}
+\\addcontentsline{toc}{subsection}{Alternative}
+\\label{"))
+ (should ;; test :ALT_TITLE: only
+ (search-forward "\\section[SECTION 2]{Section 2}
+\\label{"))))
+
(provide 'test-ox-latex)
;;; test-ox-latex.el ends here
--
2.34.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: PATCH: fix ToC generation in the Latex exporter
2025-01-07 16:34 PATCH: fix ToC generation in the Latex exporter Pedro Andres Aranda Gutierrez
@ 2025-01-11 8:47 ` Ihor Radchenko
0 siblings, 0 replies; 2+ messages in thread
From: Ihor Radchenko @ 2025-01-11 8:47 UTC (permalink / raw)
To: Pedro Andres Aranda Gutierrez; +Cc: Org Mode List, Ihor Radchenko, rudolf
Pedro Andres Aranda Gutierrez <paaguti@gmail.com> writes:
> Please find attached a patch to fix ToC generation in the LaTeX exporter.
> With this, you don't need to reach back to @@latex @@ constructs to get
> your ToC alright. I have added an option to generate ToC's that is closer
> to LaTeX (num:latex) tha to org
Thanks!
I have been thinking about the consequences of changing the TOC
generation defaults, and my conclusion so far is that we risk breaking
way too many legacy .org documents.
And since old .org documents tend to have "num:t" inside, we cannot rely
upon num:latex returning to the previous behavior.
I think that a more backwards-compatible solution would be creating a
new custom option that will control how ox-latex treats "num:t". By
default, that custom option will keep the old behavior. (This option is
on top of what you have already done).
WDYT?
--
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>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-01-11 8:45 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-07 16:34 PATCH: fix ToC generation in the Latex exporter Pedro Andres Aranda Gutierrez
2025-01-11 8:47 ` Ihor Radchenko
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).