* Re: Customize list of blocks that use "\footnotemark" in `org-latex-footnote-reference'
2024-09-12 10:18 ` Juan Manuel Macías
@ 2024-12-25 9:21 ` Ihor Radchenko
0 siblings, 0 replies; 3+ messages in thread
From: Ihor Radchenko @ 2024-12-25 9:21 UTC (permalink / raw)
To: Juan Manuel Macías; +Cc: 8dcc, emacs-orgmode
[-- Attachment #1: Type: text/plain, Size: 951 bytes --]
Juan Manuel Macías <maciaschain@posteo.net> writes:
> 8dcc writes:
>
>> I am exporting an Org file that contains a large verse block to
>> LaTeX. This verse block contains footnotes, but they appear in the page
>> where the LaTeX verse environment ends. I looked at the exported .tex
>> file and I noticed that it was using "\footnotemark" and
>> "\footnotetext[N]{...}", instead of "\footnote{...}".
> ...
> I seem to remember that the problem you describe goes back to how Org
> understood the footnote text. When exporting to LaTeX, each line of a
> footnote was understood as if it were a verse, and Org added \\ at the
> end. Hence the use of \footnotemark and the
> ‘org-latex--delayed-footnotes-definitions’ function.
Please try the attached tentative fix.
I limited special verse contents processing to plain-text directly
inside verse blocks (as in Org AST), except plain text inside inline
footnote definitions.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ox-latex-Put-footnotes-near-their-first-reference-in.patch --]
[-- Type: text/x-patch, Size: 9170 bytes --]
From 5c50a75c9014d8712a239bd48293114d6520384a Mon Sep 17 00:00:00 2001
Message-ID: <5c50a75c9014d8712a239bd48293114d6520384a.1735118328.git.yantar92@posteo.net>
From: Ihor Radchenko <yantar92@posteo.net>
Date: Wed, 25 Dec 2024 10:15:39 +0100
Subject: [PATCH] ox-latex: Put footnotes near their first reference in verses
* lisp/ox-latex.el (org-latex-footnote-reference): Do not push
footnote definition to the end of the verse. When verse spans
multiple pages, this makes all the footnotes appear at the last page
rather than near the page where a footnote is defined/references.
(org-latex--plain-text-verse-block): New helper function preserving
special verse formatting. Extracted from `org-latex-verse-block'.
(org-latex-plain-text): Limit special formatting of verse block
contents to plain text only, and only for plain text nodes that
are inside verse block, but not inside (inline) footnote rereferences.
(org-latex-verse-block): Rely upon CONTENTS being properly formatted
already via plain-text transcoder. Except trailing and leading blank
lines that may not be reliably detected before we assemble to full
CONTENTS.
This implements an alternative fix to
https://list.orgmode.org/orgmode/87sg8prant.fsf@posteo.net/ that does
not have a downside of putting all the references to the last page of
the verse.
Reported-by: 8dcc <8dcc.git@gmail.com>
Link: https://orgmode.org/list/87bk0u9k6l.fsf@gmail.com
---
lisp/ox-latex.el | 115 +++++++++++++++++++---------------
testing/lisp/test-ox-latex.el | 27 ++++++++
2 files changed, 91 insertions(+), 51 deletions(-)
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 4b2e797d08..743c6340d4 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -2237,11 +2237,10 @@ (defun org-latex-footnote-reference (footnote-reference _contents info)
(org-export-get-footnote-definition footnote-reference info)
info t)))
;; Use \footnotemark if reference is within another footnote
- ;; reference, footnote definition, table cell, verse block, or
- ;; item's tag.
+ ;; reference, footnote definition, table cell, or item's tag.
((or (org-element-lineage footnote-reference
- '(footnote-reference footnote-definition
- table-cell verse-block))
+ '( footnote-reference footnote-definition
+ table-cell))
(org-element-type-p
(org-element-parent-element footnote-reference) 'item))
"\\footnotemark")
@@ -3119,6 +3118,8 @@ (defun org-latex-plain-text (text info)
"{[}"
output
nil nil 1))
+ ;; When inside verse block, use special rules.
+ (setq output (org-latex--plain-text-verse-block output text))
;; Return value.
output))
@@ -4188,6 +4189,48 @@ (defun org-latex-verbatim (verbatim _contents info)
;;;; Verse Block
+(defun org-latex--plain-text-verse-block (contents plain-text)
+ "Format CONTENTS if PLAIN-TEXT is inside verse environment.
+INFO is the communication plist.
+Return CONTENTS unchanged when TEXT is not inside verse environment or
+when TEXT is a part of footnote reference.
+
+In a verse environment, add a line break to each newline character and
+change each white space at beginning of a line into a normal space,
+calculated with `\\fontdimen2\\font'. One or more blank lines between
+lines are exported as a single blank line. If the `:lines' attribute
+is used, the last verse of each stanza ends with the string `\\!',
+according to the syntax of the `verse' package. The separation between
+stanzas can be controlled with the length `\\stanzaskip', of the
+aforementioned package. If the `:literal' attribute is used, all
+blank lines are preserved and exported as `\\vspace*{\\baselineskip}',
+including the blank lines before or after CONTENTS."
+ (if-let* ((verse-block (org-element-lineage plain-text 'verse-block))
+ ;; VALUEFORM
+ ((not (org-element-lineage plain-text 'footnote-reference))))
+ (let* ((lin (org-export-read-attribute :attr_latex verse-block :lines))
+ (lit (org-export-read-attribute :attr_latex verse-block :literal)))
+ (replace-regexp-in-string
+ "^[ \t]+" (lambda (m) (format "\\hspace*{%d\\fontdimen2\\font}" (length m)))
+ (replace-regexp-in-string
+ (if (not lit)
+ (rx-to-string
+ `(seq (group "\\\\\n")
+ (1+ (group line-start (0+ space) "\\\\\n"))))
+ "^[ \t]*\\\\$")
+ (if (not lit)
+ (if lin "\\\\!\n\n" "\n\n")
+ "\\vspace*{\\baselineskip}")
+ (replace-regexp-in-string
+ "\\([ \t]*\\\\\\\\\\)?[ \t]*\n"
+ "\\\\\n"
+ contents
+ nil t)
+ nil t)
+ nil t))
+ ;; Not in verse block, return CONTENTS unchanged.
+ contents))
+
(defun org-latex-verse-block (verse-block contents info)
"Transcode a VERSE-BLOCK element from Org to LaTeX.
CONTENTS is verse block contents. INFO is a plist holding
@@ -4195,57 +4238,27 @@ (defun org-latex-verse-block (verse-block contents info)
(let* ((lin (org-export-read-attribute :attr_latex verse-block :lines))
(latcode (org-export-read-attribute :attr_latex verse-block :latexcode))
(cent (org-export-read-attribute :attr_latex verse-block :center))
- (lit (org-export-read-attribute :attr_latex verse-block :literal))
(attr (concat
- (if cent "[\\versewidth]" "")
- (if lin (format "\n\\poemlines{%s}" lin) "")
- (if latcode (format "\n%s" latcode) "")))
+ (if cent "[\\versewidth]" "")
+ (if lin (format "\n\\poemlines{%s}" lin) "")
+ (if latcode (format "\n%s" latcode) "")))
+ (lit (org-export-read-attribute :attr_latex verse-block :literal))
(versewidth (org-export-read-attribute :attr_latex verse-block :versewidth))
(vwidth (if versewidth (format "\\settowidth{\\versewidth}{%s}\n" versewidth) ""))
(linreset (if lin "\n\\poemlines{0}" "")))
- (concat
- (org-latex--wrap-label
- verse-block
- ;; In a verse environment, add a line break to each newline
- ;; character and change each white space at beginning of a line
- ;; into a normal space, calculated with `\fontdimen2\font'. One
- ;; or more blank lines between lines are exported as a single
- ;; blank line. If the `:lines' attribute is used, the last
- ;; verse of each stanza ends with the string `\\!', according to
- ;; the syntax of the `verse' package. The separation between
- ;; stanzas can be controlled with the length `\stanzaskip', of
- ;; the aforementioned package. If the `:literal' attribute is
- ;; used, all blank lines are preserved and exported as
- ;; `\vspace*{\baselineskip}', including the blank lines before
- ;; or after CONTENTS.
- (format "%s\\begin{verse}%s\n%s\\end{verse}%s"
- vwidth
- attr
- (replace-regexp-in-string
- "^[ \t]+" (lambda (m) (format "\\hspace*{%d\\fontdimen2\\font}" (length m)))
- (replace-regexp-in-string
- (if (not lit)
- (rx-to-string
- `(seq (group "\\\\\n")
- (1+ (group line-start (0+ space) "\\\\\n"))))
- "^[ \t]*\\\\$")
- (if (not lit)
- (if lin "\\\\!\n\n" "\n\n")
- "\\vspace*{\\baselineskip}")
- (replace-regexp-in-string
- "\\([ \t]*\\\\\\\\\\)?[ \t]*\n"
- "\\\\\n"
- (if (not lit)
- (concat (org-trim contents t) "\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.
- (org-latex--delayed-footnotes-definitions verse-block info))))
+ (org-latex--wrap-label
+ verse-block
+ (format "%s\\begin{verse}%s\n%s\\end{verse}%s"
+ vwidth attr
+ ;; If the `:literal' attribute is used, all blank lines
+ ;; are preserved and exported as
+ ;; `\\vspace*{\\baselineskip}', including the blank lines
+ ;; before or after CONTENTS.
+ (if (not lit)
+ (concat (org-trim contents t) "\n")
+ contents)
+ linreset)
+ info)))
\f
;;; End-user functions
diff --git a/testing/lisp/test-ox-latex.el b/testing/lisp/test-ox-latex.el
index 892ac44374..b75921ae78 100644
--- a/testing/lisp/test-ox-latex.el
+++ b/testing/lisp/test-ox-latex.el
@@ -79,6 +79,33 @@ (ert-deftest test-ox-latex/verse ()
lorem ipsum dolor\\\\
lorem ipsum dolor\\\\
+\\end{verse}")))
+ ;; Footnotes inside verse blocks
+ (org-test-with-exported-text
+ 'latex
+ "#+begin_verse
+lorem
+ipsum[fn::Foo
+
+bar]
+dolor
+#+end_verse
+
+[fn:1] Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
+Donec hendrerit tempor.
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
+hendrerit tempor tellus.
+"
+ (goto-char (point-min))
+ (should
+ (search-forward
+ "\\begin{verse}
+lorem\\\\
+ipsum\\footnote{Foo
+
+bar}\\\\
+dolor\\\\
\\end{verse}"))))
(ert-deftest test-ox-latex/longtable ()
--
2.47.1
[-- Attachment #3: Type: text/plain, Size: 223 bytes --]
--
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 related [flat|nested] 3+ messages in thread