summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2015-02-21 09:34:15 +0100
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2015-02-21 11:29:40 +0100
commitfa145361ec10a503fa004c7073edc40b27e11268 (patch)
tree409fd00719cc013b33c8224139f0c007291f2f64
parent719dda85ea50d0cb70e7e76731ab71922db87932 (diff)
downloadorg-mode-fa145361ec10a503fa004c7073edc40b27e11268.tar.gz
ox: Allow to narrow scope in footnotes API
* lisp/ox.el (org-export--footnote-reference-map, org-export-collect-footnote-definitions, org-export-footnote-first-reference-p, org-export-get-footnote-number): Allow to specify scope, through a new optional argument. * lisp/ox-odt.el (org-odt-footnote-reference): Apply API change. * testing/lisp/test-ox.el (test-org-export/footnote-first-reference-p, test-org-export/get-footnote-number, test-org-export/collect-footnote-definitions): Update tests.
-rw-r--r--lisp/ox-odt.el5
-rw-r--r--lisp/ox.el30
-rw-r--r--testing/lisp/test-ox.el72
3 files changed, 88 insertions, 19 deletions
diff --git a/lisp/ox-odt.el b/lisp/ox-odt.el
index 4a94de1..f960271 100644
--- a/lisp/ox-odt.el
+++ b/lisp/ox-odt.el
@@ -1740,9 +1740,10 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(format "<text:span text:style-name=\"%s\">%s</text:span>"
"OrgSuperscript" ",")))
;; Transcode footnote reference.
- (let ((n (org-export-get-footnote-number footnote-reference info t)))
+ (let ((n (org-export-get-footnote-number footnote-reference info nil t)))
(cond
- ((not (org-export-footnote-first-reference-p footnote-reference info t))
+ ((not
+ (org-export-footnote-first-reference-p footnote-reference info nil t))
(funcall --format-footnote-reference n))
;; Inline definitions are secondary strings.
;; Non-inline footnotes definitions are full Org data.
diff --git a/lisp/ox.el b/lisp/ox.el
index f2f220b..ee7e197 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -3556,8 +3556,9 @@ definition can be found, raise an error."
(org-element-contents footnote-reference))
(error "Definition not found for footnote %s" label))))
-(defun org-export--footnote-reference-map (function info &optional body-first)
- "Apply FUNCTION on every footnote reference in parse tree.
+(defun org-export--footnote-reference-map
+ (function data info &optional body-first)
+ "Apply FUNCTION on every footnote reference in DATA.
INFO is a plist containing export state. By default, as soon as
a new footnote reference is encountered, FUNCTION is called onto
its definition. However, if BODY-FIRST is non-nil, this step is
@@ -3597,15 +3598,18 @@ delayed until the end of the process."
;; definitions of inline references.
(if delayp '(footnote-definition footnote-reference)
'footnote-definition)))))
- (funcall search-ref (plist-get info :parse-tree) body-first)
+ (funcall search-ref data body-first)
(funcall search-ref (nreverse definitions) nil)))
-(defun org-export-collect-footnote-definitions (info &optional body-first)
+(defun org-export-collect-footnote-definitions (info &optional data body-first)
"Return an alist between footnote numbers, labels and definitions.
INFO is the current export state, as a plist.
-Definitions are sorted by order of references. As soon as a new
+Definitions are collected throughout the whole parse tree, or
+DATA when non-nil.
+
+Sorting is done by order of references. As soon as a new
reference is encountered, other references are searched within
its definition. However, if BODY-FIRST is non-nil, this step is
delayed after the whole tree is checked. This alters results
@@ -3623,16 +3627,19 @@ for inlined footnotes. Unreferenced definitions are ignored."
(incf n)
(push (list n l d) alist))
(when l (push l labels))))
- info body-first)
+ (or data (plist-get info :parse-tree)) info body-first)
(nreverse alist)))
(defun org-export-footnote-first-reference-p
- (footnote-reference info &optional body-first)
+ (footnote-reference info &optional data body-first)
"Non-nil when a footnote reference is the first one for its label.
FOOTNOTE-REFERENCE is the footnote reference being considered.
INFO is a plist containing current export state.
+Search is done throughout the whole parse tree, or DATA when
+non-nil.
+
By default, as soon as a new footnote reference is encountered,
other references are searched within its definition. However, if
BODY-FIRST is non-nil, this step is delayed after the whole tree
@@ -3647,14 +3654,17 @@ footnote definitions."
(let ((l (org-element-property :label f)))
(when (and l label (string= label l))
(throw 'exit (eq footnote-reference f)))))
- info body-first)))))
+ (or data (plist-get info :parse-tree)) info body-first)))))
-(defun org-export-get-footnote-number (footnote info &optional body-first)
+(defun org-export-get-footnote-number (footnote info &optional data body-first)
"Return number associated to a footnote.
FOOTNOTE is either a footnote reference or a footnote definition.
INFO is the plist containing export state.
+Number is unique throughout the whole parse tree, or DATA, when
+non-nil.
+
By default, as soon as a new footnote reference is encountered,
counting process moves into its definition. However, if
BODY-FIRST is non-nil, this step is delayed until the end of the
@@ -3675,7 +3685,7 @@ process, leading to a different order when footnotes are nested."
;; wasn't encountered yet.
((not l) (incf count))
((not (member l seen)) (push l seen) (incf count)))))
- info body-first))))
+ (or data (plist-get info :parse-tree)) info body-first))))
;;;; For Headlines
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 5afe11d..1ea5120 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -1557,6 +1557,30 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
(paragraph . (lambda (p c i) c))))
nil nil nil '(:with-footnotes t))
(nreverse result)))))
+ ;; Limit check to DATA, when non-nil.
+ (should
+ (equal
+ '(nil t)
+ (org-test-with-parsed-data "Text[fn:1]\n* H\nText[fn:1]\n\n[fn:1] D1"
+ (let (result)
+ (org-element-map tree 'footnote-reference
+ (lambda (ref)
+ (push
+ (org-export-footnote-first-reference-p
+ ref info (org-element-map tree 'headline #'identity info t))
+ result))
+ info)
+ (nreverse result)))))
+ (should
+ (equal
+ '(t nil)
+ (org-test-with-parsed-data "Text[fn:1]\n* H\nText[fn:1]\n\n[fn:1] D1"
+ (let (result)
+ (org-element-map tree 'footnote-reference
+ (lambda (ref)
+ (push (org-export-footnote-first-reference-p ref info) result))
+ info)
+ (nreverse result)))))
;; If optional argument BODY-FIRST is non-nil, first find footnote
;; in the main body of the document. Otherwise, enter footnote
;; definitions when they are encountered.
@@ -1593,7 +1617,7 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
`(,(cons 'footnote-reference
(lambda (f c i)
(when (org-element-lineage f '(drawer))
- (push (org-export-footnote-first-reference-p f info t)
+ (push (org-export-footnote-first-reference-p f info nil t)
result))
""))
(drawer . (lambda (d c i) c))
@@ -1631,8 +1655,27 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
(cons (org-export-get-footnote-number ref info)
(org-element-property :label ref)))
info))))
- ;; With a non-nil optional argument, first check body, then footnote
- ;; definitions.
+ ;; Limit number to provided DATA, when non-nil.
+ (should
+ (equal
+ '(1)
+ (org-test-with-parsed-data
+ "Text[fn:1]\n* H\nText[fn:2]\n\n[fn:1] D1\n[fn:2] D2"
+ (org-element-map tree 'footnote-reference
+ (lambda (ref)
+ (org-export-get-footnote-number
+ ref info (org-element-map tree 'headline #'identity info t)))
+ info))))
+ (should
+ (equal
+ '(1 2)
+ (org-test-with-parsed-data
+ "Text[fn:1]\n* H\nText[fn:2]\n\n[fn:1] D1\n[fn:2]"
+ (org-element-map tree 'footnote-reference
+ (lambda (ref) (org-export-get-footnote-number ref info))
+ info))))
+ ;; With a non-nil BODY-FIRST optional argument, first check body,
+ ;; then footnote definitions.
(should
(equal
'(("fn:1" . 1) ("fn:2" . 2) ("fn:3" . 3) ("fn:3" . 3))
@@ -1641,7 +1684,7 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
(org-element-map tree 'footnote-reference
(lambda (ref)
(cons (org-element-property :label ref)
- (org-export-get-footnote-number ref info t)))
+ (org-export-get-footnote-number ref info nil t)))
info))))
(should
(equal
@@ -1664,8 +1707,23 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
\[fn:3] C."
(length (org-export-collect-footnote-definitions info)))))
- ;; With optional argument, first check body, then footnote
- ;; definitions.
+ ;; Limit number to provided DATA, when non-nil.
+ (should
+ (equal
+ '((1 "fn:2"))
+ (org-test-with-parsed-data
+ "Text[fn:1]\n* H\nText[fn:2]\n\n[fn:1] D1\n[fn:2] D2"
+ (mapcar #'butlast
+ (org-export-collect-footnote-definitions
+ info (org-element-map tree 'headline #'identity info t))))))
+ (should
+ (equal
+ '((1 "fn:1") (2 "fn:2"))
+ (org-test-with-parsed-data
+ "Text[fn:1]\n* H\nText[fn:2]\n\n[fn:1] D1\n[fn:2] D2"
+ (mapcar #'butlast (org-export-collect-footnote-definitions info)))))
+ ;; With optional argument BODY-FIRST, first check body, then
+ ;; footnote definitions.
(should
(equal '("fn:1" "fn:3" "fn:2" nil)
(org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3].
@@ -1674,7 +1732,7 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
\[fn:3] C."
(mapcar (lambda (e) (nth 1 e))
- (org-export-collect-footnote-definitions info t)))))
+ (org-export-collect-footnote-definitions info nil t)))))
(should-not
(equal '("fn:1" "fn:3" "fn:2" nil)
(org-test-with-parsed-data "Text[fn:1:A[fn:2]] [fn:3].