summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2012-04-06 23:50:00 +0200
committerNicolas Goaziou <n.goaziou@gmail.com>2012-04-06 23:50:00 +0200
commit8453ac1bf327015a2f587f69eaae3d64eeca3219 (patch)
treebf5c73fed90409011e4c464426b4afe145488019
parent4019559ee2f9aba372860b59c35d25de03761605 (diff)
downloadorg-mode-8453ac1bf327015a2f587f69eaae3d64eeca3219.tar.gz
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.
-rw-r--r--contrib/lisp/org-element.el82
-rw-r--r--testing/lisp/test-org-element.el57
2 files changed, 110 insertions, 29 deletions
diff --git a/contrib/lisp/org-element.el b/contrib/lisp/org-element.el
index 7414dbf..849eae0 100644
--- a/contrib/lisp/org-element.el
+++ b/contrib/lisp/org-element.el
@@ -273,20 +273,27 @@ CONTENTS is the contents of the element."
(defun org-element-footnote-definition-parser ()
"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',
-`:contents-end' and `:post-blank' keywords."
+`:contents-end' and `:post-blank' keywords.
+
+Assume point is at the beginning of the footnote definition."
(save-excursion
- (let* ((f-def (org-footnote-at-definition-p))
- (label (car f-def))
- (keywords (progn (goto-char (nth 1 f-def))
- (org-element-collect-affiliated-keywords)))
+ (looking-at org-footnote-definition-re)
+ (let* ((label (org-match-string-no-properties 1))
+ (keywords (org-element-collect-affiliated-keywords))
(begin (car keywords))
- (contents-begin (progn (looking-at (concat "\\[" label "\\]"))
- (goto-char (match-end 0))
+ (contents-begin (progn (search-forward "]")
(org-skip-whitespace)
(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)
(if (eobp) (point) (point-at-bol)))))
`(footnote-definition
@@ -1783,28 +1790,37 @@ its beginning position."
(defun org-element-footnote-reference-parser ()
"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'
and `:post-blank' as keywords."
(save-excursion
- (let* ((ref (org-footnote-at-reference-p))
- (label (car ref))
- (inline-def
- (let ((raw-def (nth 3 ref)))
- (and raw-def
- (org-element-parse-secondary-string
- raw-def
- (cdr (assq 'footnote-reference
- org-element-string-restrictions))))))
- (type (if (nth 3 ref) 'inline 'standard))
- (begin (nth 1 ref))
- (post-blank (progn (goto-char (nth 2 ref))
+ (looking-at org-footnote-re)
+ (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)))))
+ (type (if (or (not label) (match-string 1)) 'inline 'standard))
+ (inner-begin (match-end 0))
+ (inner-end
+ (let ((count 1))
+ (forward-char)
+ (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")))
- (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
(:label ,label
:type ,type
- :inline-definition ,inline-def
+ :inline-definition ,inline-definition
:begin ,begin
:end ,end
:post-blank ,post-blank)))))
@@ -1825,11 +1841,19 @@ CONTENTS is nil."
LIMIT bounds the search.
-Return value is a cons cell whose car is `footnote-reference' and
-cdr is beginning position."
- (let (fn-ref)
- (when (setq fn-ref (org-footnote-get-next-reference nil nil limit))
- (cons 'footnote-reference (nth 1 fn-ref)))))
+Return value is a cons cell whose CAR is `footnote-reference' and
+CDR is beginning position."
+ (save-excursion
+ (catch 'exit
+ (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
diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el
index 385cc6b..040f35d 100644
--- a/testing/lisp/test-org-element.el
+++ b/testing/lisp/test-org-element.el
@@ -204,6 +204,63 @@
+;;;; 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
(ert-deftest test-org-element/granularity ()