From 888ebfdeaf373012c7e7975aa05ef95f1892dd57 Mon Sep 17 00:00:00 2001 From: Rasmus Date: Sun, 22 May 2016 20:33:06 +0200 Subject: [PATCH] ox-latex: More robust repeated footnote references * lisp/ox-latex.el (org-latex--delayed-footnotes-definitions): Fix typo in docstring. (org-latex-footnote-defined-format): New defcustom. (org-latex-footnote-reference): Refer to repeated footnotes using labels. Format using new defcustom. * etc/ORG-NEWS: Mention change. * doc/org.texi (Publishing options): Add new defcustom. --- doc/org.texi | 1 + etc/ORG-NEWS | 3 ++ lisp/ox-latex.el | 74 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 45400bdfa..9d899751b 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -14483,6 +14483,7 @@ however, override everything. @item @code{:latex-default-table-environment} @tab @code{org-latex-default-table-environment} @item @code{:latex-default-table-mode} @tab @code{org-latex-default-table-mode} @item @code{:latex-diary-timestamp-format} @tab @code{org-latex-diary-timestamp-format} +@item @code{:latex-footnote-defined-format} @tab @code{org-latex-footnote-defined-format} @item @code{:latex-footnote-separator} @tab @code{org-latex-footnote-separator} @item @code{:latex-format-drawer-function} @tab @code{org-latex-format-drawer-function} @item @code{:latex-format-headline-function} @tab @code{org-latex-format-headline-function} diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index 3e1444d4f..72f8d5c0e 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -282,6 +282,9 @@ When set to ~smart~, the new variable ~org-occur-case-fold-search~ allows to mimic =isearch.el=: if the regexp searched contains any upper case character (or character class), the search is case sensitive. Otherwise, it is case insensitive. +*** More robust repeated =ox-latex= footnote handling +Repeated footnotes are now numbered by referring to a label in the +first footnote. ** New functions *** ~org-next-line-empty-p~ It replaces the deprecated ~next~ argument to ~org-previous-line-empty-p~. diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el index 0946fe435..2c1163b4d 100644 --- a/lisp/ox-latex.el +++ b/lisp/ox-latex.el @@ -118,6 +118,7 @@ (:latex-default-table-environment nil nil org-latex-default-table-environment) (:latex-default-table-mode nil nil org-latex-default-table-mode) (:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format) + (:latex-footnote-defined-format nil nil org-latex-footnote-defined-format) (:latex-footnote-separator nil nil org-latex-footnote-separator) (:latex-format-drawer-function nil nil org-latex-format-drawer-function) (:latex-format-headline-function nil nil org-latex-format-headline-function) @@ -651,6 +652,16 @@ The function result will be used in the section format string." :group 'org-export-latex :type 'string) +(defcustom org-latex-footnote-defined-format "\\textsuperscript{\\ref{%s}}" + "Format string used to format reference to footnote already defined. +%s will be replaced by the label of the referred footnote." + :group 'org-export-latex + :type '(choice + (const :tag "Use plain superscript (default)" "\\textsuperscript{\\ref{%s}}") + (const :tag "Use Memoir/KOMA-Script footref" "\\footref{%s}") + (string :tag "Other format string")) + :version "25.2" + :package-version '(Org . "9.0")) ;;;; Timestamps @@ -1498,7 +1509,7 @@ INFO is a plist used as a communication channel. See INFO is a plist used as a communication channel. -Footnotes definitions are returned within \"\\footnotetxt{}\" +Footnotes definitions are returned within \"\\footnotetext{}\" commands. This function is used within constructs that don't support @@ -1804,30 +1815,43 @@ CONTENTS is nil. INFO is a plist holding contextual information." (defun org-latex-footnote-reference (footnote-reference _contents info) "Transcode a FOOTNOTE-REFERENCE element from Org to LaTeX. CONTENTS is nil. INFO is a plist holding contextual information." - (concat - ;; Insert separator between two footnotes in a row. - (let ((prev (org-export-get-previous-element footnote-reference info))) - (when (eq (org-element-type prev) 'footnote-reference) - (plist-get info :latex-footnote-separator))) - (cond - ;; Use \footnotemark if the footnote has already been defined. - ((not (org-export-footnote-first-reference-p footnote-reference info)) - (format "\\footnotemark[%s]{}" - (org-export-get-footnote-number footnote-reference info))) - ;; Use \footnotemark if reference is within another footnote - ;; reference, footnote definition or table cell. - ((org-element-lineage footnote-reference - '(footnote-reference footnote-definition table-cell)) - "\\footnotemark") - ;; Otherwise, define it with \footnote command. - (t - (let ((def (org-export-get-footnote-definition footnote-reference info))) - (concat - (format "\\footnote{%s}" (org-trim (org-export-data def info))) - ;; Retrieve all footnote references within the footnote and - ;; add their definition after it, since LaTeX doesn't support - ;; them inside. - (org-latex--delayed-footnotes-definitions def info))))))) + (let ((label (org-element-property :label footnote-reference))) + (concat + ;; Insert separator between two footnotes in a row. + (let ((prev (org-export-get-previous-element footnote-reference info))) + (when (eq (org-element-type prev) 'footnote-reference) + (plist-get info :latex-footnote-separator))) + (cond + ;; Use `:latex-footnote-defined-format' if the footnote has + ;; already been defined. + ((not (org-export-footnote-first-reference-p footnote-reference info)) + (format (plist-get info :latex-footnote-defined-format) + (org-latex--label + (org-export-get-footnote-definition footnote-reference info) + info t))) + ;; Use \footnotemark if reference is within another footnote + ;; reference, footnote definition or table cell. + ((org-element-lineage footnote-reference + '(footnote-reference footnote-definition table-cell)) + "\\footnotemark") + ;; Otherwise, define it with \footnote command. + (t + (let ((def (org-export-get-footnote-definition footnote-reference info))) + (concat + (format "\\footnote{%s%s}" (org-trim (org-export-data def info)) + ;; Only insert a \label if there exist another + ;; reference to def. + (or (org-element-map (plist-get info :parse-tree) 'footnote-reference + (lambda (f) + (and (not (eq f footnote-reference)) + (equal (org-element-property :label f) label) + (org-trim (org-latex--label def info t t)))) + info t) + "")) + ;; Retrieve all footnote references within the footnote and + ;; add their definition after it, since LaTeX doesn't support + ;; them inside. + (org-latex--delayed-footnotes-definitions def info)))))))) ;;;; Headline