summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Goaziou <n.goaziou@gmail.com>2012-06-07 00:06:19 +0200
committerNicolas Goaziou <n.goaziou@gmail.com>2012-06-07 00:06:19 +0200
commit451191bc41d5a05f65714fa2b1340f20fa88baed (patch)
tree4c52f831fd0f5492833e839feade9c838bd0bbb9
parentad235400a6e311891b012d60c366ade60ba3dc81 (diff)
downloadorg-mode-451191bc41d5a05f65714fa2b1340f20fa88baed.tar.gz
org-export: Correctly resolve fuzzy links whose path starts with *
* contrib/lisp/org-export.el (org-export-resolve-fuzzy-link): Correctly resolve fuzzy links whose path starts with * * testing/lisp/test-org-export.el: Add tests.
-rw-r--r--contrib/lisp/org-export.el55
-rw-r--r--testing/lisp/test-org-export.el170
2 files changed, 141 insertions, 84 deletions
diff --git a/contrib/lisp/org-export.el b/contrib/lisp/org-export.el
index f81a9f6..9434cfe 100644
--- a/contrib/lisp/org-export.el
+++ b/contrib/lisp/org-export.el
@@ -2949,18 +2949,19 @@ Return value can be an object, an element, or nil:
- Otherwise, return nil.
Assume LINK type is \"fuzzy\"."
- (let ((path (org-element-property :path link)))
+ (let* ((path (org-element-property :path link))
+ (match-title-p (eq (aref path 0) ?*)))
(cond
;; First try to find a matching "<<path>>" unless user specified
;; he was looking for an headline (path starts with a *
;; character).
- ((and (not (eq (substring path 0 1) ?*))
+ ((and (not match-title-p)
(loop for target in (plist-get info :target-list)
when (string= (org-element-property :value target) path)
return target)))
;; Then try to find an element with a matching "#+NAME: path"
;; affiliated keyword.
- ((and (not (eq (substring path 0 1) ?*))
+ ((and (not match-title-p)
(org-element-map
(plist-get info :parse-tree) org-element-all-elements
(lambda (el)
@@ -2972,29 +2973,31 @@ Assume LINK type is \"fuzzy\"."
;; is found, return it, otherwise return nil.
(t
(let ((find-headline
- (function
- ;; Return first headline whose `:raw-value' property
- ;; is NAME in parse tree DATA, or nil.
- (lambda (name data)
- (org-element-map
- data 'headline
- (lambda (headline)
- (when (string=
- (org-element-property :raw-value headline)
- name)
- headline))
- info 'first-match)))))
- ;; Search among headlines sharing an ancestor with link,
- ;; from closest to farthest.
- (or (catch 'exit
- (mapc
- (lambda (parent)
- (when (eq (org-element-type parent) 'headline)
- (let ((foundp (funcall find-headline path parent)))
- (when foundp (throw 'exit foundp)))))
- (org-export-get-genealogy link info)) nil)
- ;; No match with a common ancestor: try the full parse-tree.
- (funcall find-headline path (plist-get info :parse-tree))))))))
+ (function
+ ;; Return first headline whose `:raw-value' property
+ ;; is NAME in parse tree DATA, or nil.
+ (lambda (name data)
+ (org-element-map
+ data 'headline
+ (lambda (headline)
+ (when (string=
+ (org-element-property :raw-value headline)
+ name)
+ headline))
+ info 'first-match)))))
+ ;; Search among headlines sharing an ancestor with link,
+ ;; from closest to farthest.
+ (or (catch 'exit
+ (mapc
+ (lambda (parent)
+ (when (eq (org-element-type parent) 'headline)
+ (let ((foundp (funcall find-headline path parent)))
+ (when foundp (throw 'exit foundp)))))
+ (org-export-get-genealogy link info)) nil)
+ ;; No match with a common ancestor: try the full parse-tree.
+ (funcall find-headline
+ (if match-title-p (substring path 1) path)
+ (plist-get info :parse-tree))))))))
(defun org-export-resolve-id-link (link info)
"Return headline referenced as LINK destination.
diff --git a/testing/lisp/test-org-export.el b/testing/lisp/test-org-export.el
index 8ed47fb..86453d7 100644
--- a/testing/lisp/test-org-export.el
+++ b/testing/lisp/test-org-export.el
@@ -478,6 +478,73 @@ Paragraph[fn:1]"
;;; Links
+(ert-deftest test-org-export/fuzzy-link ()
+ "Test fuzzy links specifications."
+ ;; 1. Links to invisible (keyword) targets should be ignored.
+ (org-test-with-parsed-data
+ "Paragraph.\n#+TARGET: Test\n[[Test]]"
+ (should-not
+ (org-element-map
+ tree 'link
+ (lambda (link)
+ (org-export-get-ordinal
+ (org-export-resolve-fuzzy-link link info) info)) info)))
+ ;; 2. Link to an headline should return headline's number.
+ (org-test-with-parsed-data
+ "Paragraph.\n* Head1\n* Head2\n* Head3\n[[Head2]]"
+ (should
+ ;; Note: Headline's number is in fact a list of numbers.
+ (equal '(2)
+ (org-element-map
+ tree 'link
+ (lambda (link)
+ (org-export-get-ordinal
+ (org-export-resolve-fuzzy-link link info) info)) info t))))
+ ;; 3. Link to a target in an item should return item's number.
+ (org-test-with-parsed-data
+ "- Item1\n - Item11\n - <<test>>Item12\n- Item2\n\n\n[[test]]"
+ (should
+ ;; Note: Item's number is in fact a list of numbers.
+ (equal '(1 2)
+ (org-element-map
+ tree 'link
+ (lambda (link)
+ (org-export-get-ordinal
+ (org-export-resolve-fuzzy-link link info) info)) info t))))
+ ;; 4. Link to a target in a footnote should return footnote's
+ ;; number.
+ (org-test-with-parsed-data "
+Paragraph[1][2][fn:lbl3:C<<target>>][[test]][[target]]\n[1] A\n\n[2] <<test>>B"
+ (should
+ (equal '(2 3)
+ (org-element-map
+ tree 'link
+ (lambda (link)
+ (org-export-get-ordinal
+ (org-export-resolve-fuzzy-link link info) info)) info))))
+ ;; 5. Link to a named element should return sequence number of that
+ ;; element.
+ (org-test-with-parsed-data
+ "#+NAME: tbl1\n|1|2|\n#+NAME: tbl2\n|3|4|\n#+NAME: tbl3\n|5|6|\n[[tbl2]]"
+ (should
+ (= 2
+ (org-element-map
+ tree 'link
+ (lambda (link)
+ (org-export-get-ordinal
+ (org-export-resolve-fuzzy-link link info) info)) info t))))
+ ;; 6. Link to a target not within an item, a table, a footnote
+ ;; reference or definition should return section number.
+ (org-test-with-parsed-data
+ "* Head1\n* Head2\nParagraph<<target>>\n* Head3\n[[target]]"
+ (should
+ (equal '(2)
+ (org-element-map
+ tree 'link
+ (lambda (link)
+ (org-export-get-ordinal
+ (org-export-resolve-fuzzy-link link info) info)) info t)))))
+
(ert-deftest test-org-export/resolve-coderef ()
"Test `org-export-resolve-coderef' specifications."
(let ((org-coderef-label-format "(ref:%s)"))
@@ -543,72 +610,59 @@ Another text. (ref:text)
"#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText. [ref:text]\n#+END_EXAMPLE"
(should (equal (org-export-resolve-coderef "text" info) "text")))))
-(ert-deftest test-org-export/resolve-fuzzy-link ()
+(ert-deftest test-org-exprot/resolve-fuzzy-link ()
"Test `org-export-resolve-fuzzy-link' specifications."
- ;; 1. Links to invisible (keyword) targets should be ignored.
- (org-test-with-parsed-data
- "Paragraph.\n#+TARGET: Test\n[[Test]]"
- (should-not
- (org-element-map
- tree 'link
- (lambda (link)
- (org-export-get-ordinal
- (org-export-resolve-fuzzy-link link info) info)) info)))
- ;; 2. Link to an headline should return headline's number.
- (org-test-with-parsed-data
- "Paragraph.\n* Head1\n* Head2\n* Head3\n[[Head2]]"
+ ;; 1. Match target objects.
+ (org-test-with-parsed-data "<<target>> [[target]]"
(should
- ;; Note: Headline's number is in fact a list of numbers.
- (equal '(2)
- (org-element-map
- tree 'link
- (lambda (link)
- (org-export-get-ordinal
- (org-export-resolve-fuzzy-link link info) info)) info t))))
- ;; 3. Link to a target in an item should return item's number.
- (org-test-with-parsed-data
- "- Item1\n - Item11\n - <<test>>Item12\n- Item2\n\n\n[[test]]"
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))
+ ;; 2. Match target elements.
+ (org-test-with-parsed-data "#+TARGET: target\n[[target]]"
(should
- ;; Note: Item's number is in fact a list of numbers.
- (equal '(1 2)
- (org-element-map
- tree 'link
- (lambda (link)
- (org-export-get-ordinal
- (org-export-resolve-fuzzy-link link info) info)) info t))))
- ;; 4. Link to a target in a footnote should return footnote's
- ;; number.
- (org-test-with-parsed-data "
-Paragraph[1][2][fn:lbl3:C<<target>>][[test]][[target]]\n[1] A\n\n[2] <<test>>B"
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))
+ ;; 3. Match named elements.
+ (org-test-with-parsed-data "#+NAME: target\nParagraph\n\n[[target]]"
(should
- (equal '(2 3)
- (org-element-map
- tree 'link
- (lambda (link)
- (org-export-get-ordinal
- (org-export-resolve-fuzzy-link link info) info)) info))))
- ;; 5. Link to a named element should return sequence number of that
- ;; element.
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))
+ ;; 4. Match exact headline's name.
+ (org-test-with-parsed-data "* My headline\n[[My headline]]"
+ (should
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))
+ ;; 5. Targets objects have priority over named elements and headline
+ ;; titles.
(org-test-with-parsed-data
- "#+NAME: tbl1\n|1|2|\n#+NAME: tbl2\n|3|4|\n#+NAME: tbl3\n|5|6|\n[[tbl2]]"
+ "* target\n#+NAME: target\n<<target>>\n\n[[target]]"
(should
- (= 2
- (org-element-map
- tree 'link
- (lambda (link)
- (org-export-get-ordinal
- (org-export-resolve-fuzzy-link link info) info)) info t))))
- ;; 6. Link to a target not within an item, a table, a footnote
- ;; reference or definition should return section number.
+ (eq 'target
+ (org-element-type
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))))
+ ;; 6. Named elements have priority over headline titles.
(org-test-with-parsed-data
- "* Head1\n* Head2\nParagraph<<target>>\n* Head3\n[[target]]"
+ "* target\n#+NAME: target\nParagraph\n\n[[target]]"
(should
- (equal '(2)
- (org-element-map
- tree 'link
- (lambda (link)
- (org-export-get-ordinal
- (org-export-resolve-fuzzy-link link info) info)) info t)))))
+ (eq 'paragraph
+ (org-element-type
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))))
+ ;; 7. If link's path starts with a "*", only match headline titles,
+ ;; though.
+ (org-test-with-parsed-data
+ "* target\n#+NAME: target\n<<target>>\n\n[[*target]]"
+ (should
+ (eq 'headline
+ (org-element-type
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info)))))
+ ;; 8. Return nil if no match.
+ (org-test-with-parsed-data "[[target]]"
+ (should-not
+ (org-export-resolve-fuzzy-link
+ (org-element-map tree 'link 'identity info t) info))))
(ert-deftest test-org-export/resolve-id-link ()
"Test `org-export-resolve-id-link' specifications."