org-element: Remove :inline-definition from inline footnotes

* lisp/org-element.el (org-element-recursive-objects): Add
  `footnote-reference'.
(org-element-secondary-value-alist): Remove reference to
`footnote-reference'.
(org-element-footnote-reference-parser): Definition for inline
references is stored as the contents of the reference, not in
a secondary string.
(org-element-footnote-reference-interpreter): Apply changes from
parser.

* lisp/ox.el (org-export-get-footnote-definition,
  org-export-get-environment): Apply changes from parser.

* testing/lisp/test-org-element.el (test-org-element/footnote-reference-parser):
  Update test.
(test-org-element/context): Add test.

Storing definition in a secondary string was a poor design choice as
there is no "primary" string anyway.  This also prevents
`org-element-context' from finding objects within the inline
definition.
This commit is contained in:
Nicolas Goaziou 2014-07-06 11:08:57 +02:00
parent df9ccbd119
commit ca6ecf9e49
3 changed files with 87 additions and 78 deletions

View File

@ -194,8 +194,8 @@ is not sufficient to know if point is at a paragraph ending. See
"Complete list of object types.")
(defconst org-element-recursive-objects
'(bold italic link subscript radio-target strike-through superscript
table-cell underline)
'(bold footnote-reference italic link subscript radio-target strike-through
superscript table-cell underline)
"List of recursive object types.")
(defvar org-element-block-name-alist
@ -341,8 +341,7 @@ still has an entry since one of its properties (`:title') does.")
(defconst org-element-secondary-value-alist
'((headline . :title)
(inlinetask . :title)
(item . :tag)
(footnote-reference . :inline-definition))
(item . :tag))
"Alist between element types and location of secondary value.")
(defconst org-element-object-variables '(org-link-abbrev-alist-local)
@ -2755,16 +2754,17 @@ CONTENTS is nil."
When at a footnote reference, return a list whose car is
`footnote-reference' and cdr a plist with `:label', `:type',
`:inline-definition', `:begin', `:end' and `:post-blank' as
keywords. Otherwise, return nil."
`:begin', `:end', `:content-begin', `:contents-end' and
`:post-blank' as keywords. Otherwise, return nil."
(catch 'no-object
(when (looking-at org-footnote-re)
(save-excursion
(let* ((begin (point))
(label (or (org-match-string-no-properties 2)
(org-match-string-no-properties 3)
(and (match-string 1)
(concat "fn:" (org-match-string-no-properties 1)))))
(label
(or (org-match-string-no-properties 2)
(org-match-string-no-properties 3)
(and (match-string 1)
(concat "fn:" (org-match-string-no-properties 1)))))
(type (if (or (not label) (match-string 1)) 'inline 'standard))
(inner-begin (match-end 0))
(inner-end
@ -2776,32 +2776,22 @@ keywords. Otherwise, return nil."
(1- (point))))
(post-blank (progn (goto-char (1+ inner-end))
(skip-chars-forward " \t")))
(end (point))
(footnote-reference
(list 'footnote-reference
(list :label label
:type type
:begin begin
:end end
:post-blank post-blank))))
(org-element-put-property
footnote-reference :inline-definition
(and (eq type 'inline)
(org-element-parse-secondary-string
(buffer-substring inner-begin inner-end)
(org-element-restriction 'footnote-reference)
footnote-reference))))))))
(end (point)))
(list 'footnote-reference
(list :label label
:type type
:begin begin
:end end
:contents-begin (and (eq type 'inline) inner-begin)
:contents-end (and (eq type 'inline) inner-end)
:post-blank post-blank)))))))
(defun org-element-footnote-reference-interpreter (footnote-reference contents)
"Interpret FOOTNOTE-REFERENCE object as Org syntax.
CONTENTS is nil."
(let ((label (or (org-element-property :label footnote-reference) "fn:"))
(def
(let ((inline-def
(org-element-property :inline-definition footnote-reference)))
(if (not inline-def) ""
(concat ":" (org-element-interpret-data inline-def))))))
(format "[%s]" (concat label def))))
(format "[%s]"
(concat (or (org-element-property :label footnote-reference) "fn:")
(and contents (concat ":" contents)))))
;;;; Inline Babel Call

View File

@ -1579,17 +1579,31 @@ inferior to file-local settings."
(let (alist)
(org-with-wide-buffer
(goto-char (point-min))
(while (re-search-forward org-footnote-definition-re nil t)
(let ((def (save-match-data (org-element-at-point))))
(when (eq (org-element-type def) 'footnote-definition)
(push
(cons (org-element-property :label def)
(let ((cbeg (org-element-property :contents-begin def)))
(when cbeg
(org-element--parse-elements
cbeg (org-element-property :contents-end def)
nil nil nil nil (list 'org-data nil)))))
alist))))
(while (re-search-forward org-footnote-re nil t)
(backward-char)
(let ((fn (save-match-data (org-element-context))))
(case (org-element-type fn)
(footnote-definition
(push
(cons (org-element-property :label fn)
(let ((cbeg (org-element-property :contents-begin fn)))
(when cbeg
(org-element--parse-elements
cbeg (org-element-property :contents-end fn)
nil nil nil nil (list 'org-data nil)))))
alist))
(footnote-reference
(let ((label (org-element-property :label fn))
(cbeg (org-element-property :contents-begin fn)))
(when (and label cbeg
(eq (org-element-property :type fn) 'inline))
(push
(cons label
(org-element-parse-secondary-string
(buffer-substring
cbeg (org-element-property :contents-end fn))
(org-element-restriction 'footnote-reference)))
alist)))))))
alist))
:id-alist
;; Collect id references.
@ -3689,11 +3703,11 @@ INFO is the plist used as a communication channel."
(defun org-export-get-footnote-definition (footnote-reference info)
"Return definition of FOOTNOTE-REFERENCE as parsed data.
INFO is the plist used as a communication channel. If no such
definition can be found, return the \"DEFINITION NOT FOUND\"
string."
definition can be found, return \"DEFINITION NOT FOUND\"."
(let ((label (org-element-property :label footnote-reference)))
(or (org-element-property :inline-definition footnote-reference)
(cdr (assoc label (plist-get info :footnote-definition-alist)))
(or (if label
(cdr (assoc label (plist-get info :footnote-definition-alist)))
(org-element-contents footnote-reference))
"DEFINITION NOT FOUND.")))
(defun org-export-get-footnote-number (footnote info)

View File

@ -891,45 +891,45 @@ Some other text
(ert-deftest test-org-element/footnote-reference-parser ()
"Test `footnote-reference' parser."
;; 1. Parse a standard reference.
(org-test-with-temp-text "Text[fn:label]"
(should
;; Parse a standard reference.
(should
(org-test-with-temp-text "Text[fn:label]"
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; 2. Parse a normalized reference.
(org-test-with-temp-text "Text[1]"
(should
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; Parse a normalized reference.
(should
(org-test-with-temp-text "Text[1]"
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; 3. Parse an inline reference.
(org-test-with-temp-text "Text[fn:test:def]"
(should
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; Parse an inline reference.
(should
(org-test-with-temp-text "Text[fn:test:def]"
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; 4. Parse an anonymous reference.
(org-test-with-temp-text "Text[fn::def]"
(should
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; Parse an anonymous reference.
(should
(org-test-with-temp-text "Text[fn::def]"
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; 5. Parse nested footnotes.
(org-test-with-temp-text "Text[fn::def [fn:label]]"
(should
(org-element-parse-buffer) 'footnote-reference 'identity)))
;; Parse nested footnotes.
(should
(= 2
(length
(org-test-with-temp-text "Text[fn::def [fn:label]]"
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))))
;; Parse adjacent footnotes.
(should
(org-test-with-temp-text "Text[fn:label1][fn:label2]"
(= 2
(length
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))))
;; 6. Parse adjacent footnotes.
(org-test-with-temp-text "Text[fn:label1][fn:label2]"
(should
(= 2
(length
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity)))))
;; 7. Only properly closed footnotes are recognized as such.
(org-test-with-temp-text "Text[fn:label"
(should-not
(org-element-parse-buffer) 'footnote-reference 'identity)))))
;; Only properly closed footnotes are recognized as such.
(should-not
(org-test-with-temp-text "Text[fn:label"
(org-element-map
(org-element-parse-buffer) 'footnote-reference 'identity))))
(org-element-parse-buffer) 'footnote-reference 'identity))))
;;;; Headline
@ -3136,6 +3136,11 @@ Paragraph \\alpha."
(eq 'table-cell
(org-test-with-temp-text "|a|b|c"
(goto-char (point-max))
(org-element-type (org-element-context)))))
;; Special case: objects in inline footnotes.
(should
(eq 'link
(org-test-with-temp-text "[fn::[[<point>http://orgmode.org]]]"
(org-element-type (org-element-context))))))