diff --git a/lisp/ox.el b/lisp/ox.el index 3c83006ca..e3b86eb0e 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -3983,26 +3983,28 @@ This only applies to links without a description." INFO is a plist used as a communication channel. Return associated line number in source code, or REF itself, -depending on src-block or example element's switches." - (org-element-map (plist-get info :parse-tree) '(example-block src-block) - (lambda (el) - (with-temp-buffer - (insert (org-trim (org-element-property :value el))) - (let* ((label-fmt (regexp-quote - (or (org-element-property :label-fmt el) - org-coderef-label-format))) - (ref-re - (format "^.*?\\S-.*?\\([ \t]*\\(%s\\)\\)[ \t]*$" - (replace-regexp-in-string "%s" ref label-fmt nil t)))) - ;; Element containing REF is found. Resolve it to either - ;; a label or a line number, as needed. - (when (re-search-backward ref-re nil t) - (cond - ((org-element-property :use-labels el) ref) - ((eq (org-element-property :number-lines el) 'continued) - (+ (org-export-get-loc el info) (line-number-at-pos))) - (t (line-number-at-pos))))))) - info 'first-match)) +depending on src-block or example element's switches. Throw an +error if no block contains REF." + (or (org-element-map (plist-get info :parse-tree) '(example-block src-block) + (lambda (el) + (with-temp-buffer + (insert (org-trim (org-element-property :value el))) + (let* ((label-fmt (regexp-quote + (or (org-element-property :label-fmt el) + org-coderef-label-format))) + (ref-re + (format "^.*?\\S-.*?\\([ \t]*\\(%s\\)\\)[ \t]*$" + (format label-fmt ref)))) + ;; Element containing REF is found. Resolve it to + ;; either a label or a line number, as needed. + (when (re-search-backward ref-re nil t) + (cond + ((org-element-property :use-labels el) ref) + ((eq (org-element-property :number-lines el) 'continued) + (+ (org-export-get-loc el info) (line-number-at-pos))) + (t (line-number-at-pos))))))) + info 'first-match) + (user-error "Unable to resolve code reference: %s" ref))) (defun org-export-resolve-fuzzy-link (link info) "Return LINK destination. diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el index 7b862862e..46ef46cca 100644 --- a/testing/lisp/test-ox.el +++ b/testing/lisp/test-ox.el @@ -2372,46 +2372,66 @@ Paragraph[1][2][fn:lbl3:C<>][[test]][[target]]\n[1] A\n\n[2] <>B" (ert-deftest test-org-export/resolve-coderef () "Test `org-export-resolve-coderef' specifications." (let ((org-coderef-label-format "(ref:%s)")) - ;; 1. A link to a "-n -k -r" block returns line number. - (org-test-with-parsed-data - "#+BEGIN_EXAMPLE -n -k -r\nText (ref:coderef)\n#+END_EXAMPLE" - (should (= (org-export-resolve-coderef "coderef" info) 1))) - (org-test-with-parsed-data - "#+BEGIN_SRC emacs-lisp -n -k -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (should (= (org-export-resolve-coderef "coderef" info) 1))) - ;; 2. A link to a "-n -r" block returns line number. - (org-test-with-parsed-data - "#+BEGIN_EXAMPLE -n -r\nText (ref:coderef)\n#+END_EXAMPLE" - (should (= (org-export-resolve-coderef "coderef" info) 1))) - (org-test-with-parsed-data - "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (should (= (org-export-resolve-coderef "coderef" info) 1))) - ;; 3. A link to a "-n" block returns coderef. - (org-test-with-parsed-data - "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (should (equal (org-export-resolve-coderef "coderef" info) "coderef"))) - (org-test-with-parsed-data - "#+BEGIN_EXAMPLE -n\nText (ref:coderef)\n#+END_EXAMPLE" - (should (equal (org-export-resolve-coderef "coderef" info) "coderef"))) - ;; 4. A link to a "-r" block returns line number. - (org-test-with-parsed-data - "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (should (= (org-export-resolve-coderef "coderef" info) 1))) - (org-test-with-parsed-data - "#+BEGIN_EXAMPLE -r\nText (ref:coderef)\n#+END_EXAMPLE" - (should (= (org-export-resolve-coderef "coderef" info) 1))) - ;; 5. A link to a block without a switch returns coderef. - (org-test-with-parsed-data - "#+BEGIN_SRC emacs-lisp\n(+ 1 1) (ref:coderef)\n#+END_SRC" - (should (equal (org-export-resolve-coderef "coderef" info) "coderef"))) + ;; A link to a "-n -k -r" block returns line number. + (should + (= 1 + (org-test-with-parsed-data + "#+BEGIN_EXAMPLE -n -k -r\nText (ref:coderef)\n#+END_EXAMPLE" + (org-export-resolve-coderef "coderef" info)))) + (should + (= 1 + (org-test-with-parsed-data + "#+BEGIN_SRC emacs-lisp -n -k -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" + (org-export-resolve-coderef "coderef" info)))) + ;; A link to a "-n -r" block returns line number. + (should + (= 1 + (org-test-with-parsed-data + "#+BEGIN_EXAMPLE -n -r\nText (ref:coderef)\n#+END_EXAMPLE" + (org-export-resolve-coderef "coderef" info)))) + (should + (= 1 + (org-test-with-parsed-data + "#+BEGIN_SRC emacs-lisp -n -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" + (org-export-resolve-coderef "coderef" info)))) + ;; A link to a "-n" block returns coderef. + (should + (equal "coderef" + (org-test-with-parsed-data + "#+BEGIN_SRC emacs-lisp -n\n(+ 1 1) (ref:coderef)\n#+END_SRC" + (org-export-resolve-coderef "coderef" info)))) + (should + (equal "coderef" + (org-test-with-parsed-data + "#+BEGIN_EXAMPLE -n\nText (ref:coderef)\n#+END_EXAMPLE" + (org-export-resolve-coderef "coderef" info)))) + ;; A link to a "-r" block returns line number. + (should + (= 1 + (org-test-with-parsed-data + "#+BEGIN_SRC emacs-lisp -r\n(+ 1 1) (ref:coderef)\n#+END_SRC" + (org-export-resolve-coderef "coderef" info)))) + (should + (= 1 + (org-test-with-parsed-data + "#+BEGIN_EXAMPLE -r\nText (ref:coderef)\n#+END_EXAMPLE" + (org-export-resolve-coderef "coderef" info)))) + ;; A link to a block without a switch returns coderef. + (should + (equal "coderef" + (org-test-with-parsed-data + "#+BEGIN_SRC emacs-lisp\n(+ 1 1) (ref:coderef)\n#+END_SRC" + (org-export-resolve-coderef "coderef" info)))) (org-test-with-parsed-data "#+BEGIN_EXAMPLE\nText (ref:coderef)\n#+END_EXAMPLE" (should (equal (org-export-resolve-coderef "coderef" info) "coderef"))) - ;; 6. Correctly handle continued line numbers. A "+n" switch - ;; should resume numbering from previous block with numbered - ;; lines, ignoring blocks not numbering lines in the process. - ;; A "-n" switch resets count. - (org-test-with-parsed-data " + ;; Correctly handle continued line numbers. A "+n" switch should + ;; resume numbering from previous block with numbered lines, + ;; ignoring blocks not numbering lines in the process. A "-n" + ;; switch resets count. + (should + (equal '(2 1) + (org-test-with-parsed-data " #+BEGIN_EXAMPLE -n Text. #+END_EXAMPLE @@ -2427,12 +2447,18 @@ Text. #+BEGIN_EXAMPLE -n -r Another text. (ref:text) #+END_EXAMPLE" - (should (= (org-export-resolve-coderef "addition" info) 2)) - (should (= (org-export-resolve-coderef "text" info) 1))) - ;; 7. Recognize coderef with user-specified syntax. - (org-test-with-parsed-data - "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText. [ref:text]\n#+END_EXAMPLE" - (should (equal (org-export-resolve-coderef "text" info) "text"))))) + (list (org-export-resolve-coderef "addition" info) + (org-export-resolve-coderef "text" info))))) + ;; Recognize coderef with user-specified syntax. + (should + (equal "text" + (org-test-with-parsed-data + "#+BEGIN_EXAMPLE -l \"[ref:%s]\"\nText. [ref:text]\n#+END_EXAMPLE" + (org-export-resolve-coderef "text" info)))) + ;; Unresolved coderefs throw an error. + (should-error + (org-test-with-parsed-data "#+BEGIN_SRC emacs-lisp\n(+ 1 1)\n#+END_SRC" + (org-export-resolve-coderef "unknown" info))))) (ert-deftest test-org-export/resolve-fuzzy-link () "Test `org-export-resolve-fuzzy-link' specifications."