org-element: Remove dependency on org-footnote predicates
* contrib/lisp/org-element.el (org-element-footnote-definition-parser): Remove the need for `org-footnote-at-definition-p'. (org-element-footnote-reference-parser): Remove the need for `org-footnote-at-reference-p'. (org-element-footnote-reference-successor): Do not use `org-footnote-get-next-reference'. * testing/lisp/test-org-element.el: Add test.
This commit is contained in:
parent
4019559ee2
commit
8453ac1bf3
|
@ -273,20 +273,27 @@ CONTENTS is the contents of the element."
|
||||||
(defun org-element-footnote-definition-parser ()
|
(defun org-element-footnote-definition-parser ()
|
||||||
"Parse a footnote definition.
|
"Parse a footnote definition.
|
||||||
|
|
||||||
Return a list whose car is `footnote-definition' and cdr is
|
Return a list whose CAR is `footnote-definition' and CDR is
|
||||||
a plist containing `:label', `:begin' `:end', `:contents-begin',
|
a plist containing `:label', `:begin' `:end', `:contents-begin',
|
||||||
`:contents-end' and `:post-blank' keywords."
|
`:contents-end' and `:post-blank' keywords.
|
||||||
|
|
||||||
|
Assume point is at the beginning of the footnote definition."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let* ((f-def (org-footnote-at-definition-p))
|
(looking-at org-footnote-definition-re)
|
||||||
(label (car f-def))
|
(let* ((label (org-match-string-no-properties 1))
|
||||||
(keywords (progn (goto-char (nth 1 f-def))
|
(keywords (org-element-collect-affiliated-keywords))
|
||||||
(org-element-collect-affiliated-keywords)))
|
|
||||||
(begin (car keywords))
|
(begin (car keywords))
|
||||||
(contents-begin (progn (looking-at (concat "\\[" label "\\]"))
|
(contents-begin (progn (search-forward "]")
|
||||||
(goto-char (match-end 0))
|
|
||||||
(org-skip-whitespace)
|
(org-skip-whitespace)
|
||||||
(point)))
|
(point)))
|
||||||
(contents-end (goto-char (nth 2 f-def)))
|
(contents-end (if (progn
|
||||||
|
(end-of-line)
|
||||||
|
(re-search-forward
|
||||||
|
(concat org-outline-regexp-bol "\\|"
|
||||||
|
org-footnote-definition-re "\\|"
|
||||||
|
"^[ \t]*$") nil t))
|
||||||
|
(match-beginning 0)
|
||||||
|
(point-max)))
|
||||||
(end (progn (org-skip-whitespace)
|
(end (progn (org-skip-whitespace)
|
||||||
(if (eobp) (point) (point-at-bol)))))
|
(if (eobp) (point) (point-at-bol)))))
|
||||||
`(footnote-definition
|
`(footnote-definition
|
||||||
|
@ -1783,28 +1790,37 @@ its beginning position."
|
||||||
(defun org-element-footnote-reference-parser ()
|
(defun org-element-footnote-reference-parser ()
|
||||||
"Parse footnote reference at point.
|
"Parse footnote reference at point.
|
||||||
|
|
||||||
Return a list whose car is `footnote-reference' and cdr a plist
|
Return a list whose CAR is `footnote-reference' and CDR a plist
|
||||||
with `:label', `:type', `:inline-definition', `:begin', `:end'
|
with `:label', `:type', `:inline-definition', `:begin', `:end'
|
||||||
and `:post-blank' as keywords."
|
and `:post-blank' as keywords."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let* ((ref (org-footnote-at-reference-p))
|
(looking-at org-footnote-re)
|
||||||
(label (car ref))
|
(let* ((begin (point))
|
||||||
(inline-def
|
(label (or (org-match-string-no-properties 2)
|
||||||
(let ((raw-def (nth 3 ref)))
|
(org-match-string-no-properties 3)
|
||||||
(and raw-def
|
(and (match-string 1)
|
||||||
(org-element-parse-secondary-string
|
(concat "fn:" (org-match-string-no-properties 1)))))
|
||||||
raw-def
|
(type (if (or (not label) (match-string 1)) 'inline 'standard))
|
||||||
(cdr (assq 'footnote-reference
|
(inner-begin (match-end 0))
|
||||||
org-element-string-restrictions))))))
|
(inner-end
|
||||||
(type (if (nth 3 ref) 'inline 'standard))
|
(let ((count 1))
|
||||||
(begin (nth 1 ref))
|
(forward-char)
|
||||||
(post-blank (progn (goto-char (nth 2 ref))
|
(while (and (> count 0) (re-search-forward "[][]" nil t))
|
||||||
|
(if (equal (match-string 0) "[") (incf count) (decf count)))
|
||||||
|
(1- (point))))
|
||||||
|
(post-blank (progn (goto-char (1+ inner-end))
|
||||||
(skip-chars-forward " \t")))
|
(skip-chars-forward " \t")))
|
||||||
(end (point)))
|
(end (point))
|
||||||
|
(inline-definition
|
||||||
|
(and (eq type 'inline)
|
||||||
|
(org-element-parse-secondary-string
|
||||||
|
(buffer-substring inner-begin inner-end)
|
||||||
|
(cdr (assq 'footnote-reference
|
||||||
|
org-element-string-restrictions))))))
|
||||||
`(footnote-reference
|
`(footnote-reference
|
||||||
(:label ,label
|
(:label ,label
|
||||||
:type ,type
|
:type ,type
|
||||||
:inline-definition ,inline-def
|
:inline-definition ,inline-definition
|
||||||
:begin ,begin
|
:begin ,begin
|
||||||
:end ,end
|
:end ,end
|
||||||
:post-blank ,post-blank)))))
|
:post-blank ,post-blank)))))
|
||||||
|
@ -1825,11 +1841,19 @@ CONTENTS is nil."
|
||||||
|
|
||||||
LIMIT bounds the search.
|
LIMIT bounds the search.
|
||||||
|
|
||||||
Return value is a cons cell whose car is `footnote-reference' and
|
Return value is a cons cell whose CAR is `footnote-reference' and
|
||||||
cdr is beginning position."
|
CDR is beginning position."
|
||||||
(let (fn-ref)
|
(save-excursion
|
||||||
(when (setq fn-ref (org-footnote-get-next-reference nil nil limit))
|
(catch 'exit
|
||||||
(cons 'footnote-reference (nth 1 fn-ref)))))
|
(while (re-search-forward org-footnote-re limit t)
|
||||||
|
(save-excursion
|
||||||
|
(let ((beg (match-beginning 0))
|
||||||
|
(count 1))
|
||||||
|
(backward-char)
|
||||||
|
(while (re-search-forward "[][]" limit t)
|
||||||
|
(if (equal (match-string 0) "[") (incf count) (decf count))
|
||||||
|
(when (zerop count)
|
||||||
|
(throw 'exit (cons 'footnote-reference beg))))))))))
|
||||||
|
|
||||||
|
|
||||||
;;;; Inline Babel Call
|
;;;; Inline Babel Call
|
||||||
|
|
|
@ -203,6 +203,63 @@
|
||||||
(equal (org-element-property :label-fmt element) "[ref:%s]"))))))
|
(equal (org-element-property :label-fmt element) "[ref:%s]"))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;;;; Footnotes references and definitions
|
||||||
|
|
||||||
|
(ert-deftest test-org-element/footnote-reference ()
|
||||||
|
"Test footnote-reference parsing."
|
||||||
|
;; 1. Parse a standard reference.
|
||||||
|
(org-test-with-temp-text "[fn:label]"
|
||||||
|
(should (equal (org-element-footnote-reference-parser)
|
||||||
|
'(footnote-reference
|
||||||
|
(:label "fn:label" :type standard :inline-definition nil
|
||||||
|
:begin 1 :end 11 :post-blank 0)))))
|
||||||
|
;; 2. Parse a normalized reference.
|
||||||
|
(org-test-with-temp-text "[1]"
|
||||||
|
(should (equal (org-element-footnote-reference-parser)
|
||||||
|
'(footnote-reference
|
||||||
|
(:label "1" :type standard :inline-definition nil
|
||||||
|
:begin 1 :end 4 :post-blank 0)))))
|
||||||
|
;; 3. Parse an inline reference.
|
||||||
|
(org-test-with-temp-text "[fn:test:def]"
|
||||||
|
(should (equal (org-element-footnote-reference-parser)
|
||||||
|
'(footnote-reference
|
||||||
|
(:label "fn:test" :type inline :inline-definition ("def")
|
||||||
|
:begin 1 :end 14 :post-blank 0)))))
|
||||||
|
;; 4. Parse an anonymous reference.
|
||||||
|
(org-test-with-temp-text "[fn::def]"
|
||||||
|
(should (equal (org-element-footnote-reference-parser)
|
||||||
|
'(footnote-reference
|
||||||
|
(:label nil :type inline :inline-definition ("def")
|
||||||
|
:begin 1 :end 10 :post-blank 0)))))
|
||||||
|
;; 5. Parse nested footnotes.
|
||||||
|
(org-test-with-temp-text "[fn::def [fn:label]]"
|
||||||
|
(should
|
||||||
|
(equal
|
||||||
|
(org-element-footnote-reference-parser)
|
||||||
|
'(footnote-reference
|
||||||
|
(:label nil :type inline
|
||||||
|
:inline-definition
|
||||||
|
("def "
|
||||||
|
(footnote-reference
|
||||||
|
(:label "fn:label" :type standard :inline-definition nil
|
||||||
|
:begin 5 :end 15 :post-blank 0)))
|
||||||
|
:begin 1 :end 21 :post-blank 0)))))
|
||||||
|
;; 6. Parse adjacent footnotes.
|
||||||
|
(org-test-with-temp-text "[fn:label1][fn:label2]"
|
||||||
|
(should
|
||||||
|
(equal
|
||||||
|
(org-element-footnote-reference-parser)
|
||||||
|
'(footnote-reference
|
||||||
|
(:label "fn:label1" :type standard :inline-definition nil :begin 1
|
||||||
|
:end 12 :post-blank 0)))))
|
||||||
|
;; 7. Only properly closed footnotes are recognized as such.
|
||||||
|
(org-test-with-temp-text "Text [fn:label"
|
||||||
|
(should-not
|
||||||
|
(org-element-map
|
||||||
|
(org-element-parse-buffer) 'footnote-reference 'identity))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; Granularity
|
;;; Granularity
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue