Skip to content

Commit 8a781d3

Browse files
hrabanyantar92
authored andcommitted
ob-tangle.el: fix ‘:comments noweb’ double linking
* lisp/ob-tangle.el: Refactor the double implementation to a single helper function. This avoids the double link wrapping. * testing/lisp/test-ob-tangle.el: Add unit tests. Babel tangle allows inserting comments at the tangled site which link back to the source in the org file. This linking was implemented twice, to handle separate cases, but when using ‘:comments noweb’ it ended up going through both codepaths. This resulted in doubly wrapped links. By refactoring all link generation into a single function, this double wrapping is avoided. Example file, /tmp/test.org: * Inner #+name: inner #+begin_src emacs-lisp 2 #+end_src * Main #+header: :tangle test.el :comments noweb :noweb yes #+begin_src emacs-lisp 1 <<inner>> #+end_src Before: ;; [[file:test.org::*Main][Main:1]] 1 ;; [[[[file:/tmp/test.org::inner][inner]]][inner]] 2 ;; inner ends here ;; Main:1 ends here After: ;; [[file:test.org::*Main][Main:1]] 1 ;; [[file:test.org::inner][inner]] 2 ;; inner ends here ;; Main:1 ends here
1 parent b428839 commit 8a781d3

File tree

2 files changed

+87
-31
lines changed

2 files changed

+87
-31
lines changed

lisp/ob-tangle.el

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,33 @@ code blocks by target file."
469469
(mapcar (lambda (b) (cons (car b) (nreverse (cdr b))))
470470
(nreverse blocks))))
471471

472+
(defun org-babel-tangle--unbracketed-link (params)
473+
"Get a raw link to the src block at point, without brackets.
474+
475+
The PARAMS are the 3rd element of the info for the same src block."
476+
(unless (string= "no" (cdr (assq :comments params)))
477+
(save-match-data
478+
(let* (;; The created link is transient. Using ID is not necessary,
479+
;; but could have side-effects if used. An ID property may
480+
;; be added to existing entries thus creating unexpected file
481+
;; modifications.
482+
(org-id-link-to-org-use-id nil)
483+
(l (org-no-properties
484+
(cl-letf (((symbol-function 'org-store-link-functions)
485+
(lambda () nil)))
486+
(org-store-link nil))))
487+
(bare (and (string-match org-link-bracket-re l)
488+
(match-string 1 l))))
489+
(when bare
490+
(if (and org-babel-tangle-use-relative-file-links
491+
(string-match org-link-types-re bare)
492+
(string= (match-string 1 bare) "file"))
493+
(concat "file:"
494+
(file-relative-name (substring bare (match-end 0))
495+
(file-name-directory
496+
(cdr (assq :tangle params)))))
497+
bare))))))
498+
472499
(defun org-babel-tangle-single-block (block-counter &optional only-this-block)
473500
"Collect the tangled source for current block.
474501
Return the list of block attributes needed by
@@ -485,20 +512,7 @@ non-nil, return the full association list to be used by
485512
(extra (nth 3 info))
486513
(coderef (nth 6 info))
487514
(cref-regexp (org-src-coderef-regexp coderef))
488-
(link (if (string= "no" (cdr (assq :comments params))) ""
489-
(let* (
490-
;; The created link is transient. Using ID is
491-
;; not necessary, but could have side-effects if
492-
;; used. An ID property may be added to
493-
;; existing entries thus creating unexpected
494-
;; file modifications.
495-
(org-id-link-to-org-use-id nil)
496-
(l (org-no-properties
497-
(cl-letf (((symbol-function 'org-store-link-functions)
498-
(lambda () nil)))
499-
(org-store-link nil)))))
500-
(and (string-match org-link-bracket-re l)
501-
(match-string 1 l)))))
515+
(link (org-babel-tangle--unbracketed-link params))
502516
(source-name
503517
(or (nth 4 info)
504518
(format "%s:%d"
@@ -552,15 +566,7 @@ non-nil, return the full association list to be used by
552566
(if org-babel-tangle-use-relative-file-links
553567
(file-relative-name file)
554568
file)
555-
(if (and org-babel-tangle-use-relative-file-links
556-
(string-match org-link-types-re link)
557-
(string= (match-string 1 link) "file")
558-
(stringp src-tfile))
559-
(concat "file:"
560-
(file-relative-name (substring link (match-end 0))
561-
(file-name-directory
562-
src-tfile)))
563-
link)
569+
link
564570
source-name
565571
params
566572
(if org-src-preserve-indentation
@@ -578,18 +584,12 @@ non-nil, return the full association list to be used by
578584
INFO, when non nil, is the source block information, as returned
579585
by `org-babel-get-src-block-info'."
580586
(let ((link-data (pcase (or info (org-babel-get-src-block-info 'light))
581-
(`(,_ ,_ ,_ ,_ ,name ,start ,_)
587+
(`(,_ ,_ ,params ,_ ,name ,start ,_)
582588
`(("start-line" . ,(org-with-point-at start
583589
(number-to-string
584590
(line-number-at-pos))))
585591
("file" . ,(buffer-file-name))
586-
("link" . ,(let (;; The created link is transient. Using ID is
587-
;; not necessary, but could have side-effects if
588-
;; used. An ID property may be added to
589-
;; existing entries thus creatin unexpected file
590-
;; modifications.
591-
(org-id-link-to-org-use-id nil))
592-
(org-no-properties (org-store-link nil))))
592+
("link" . ,(org-babel-tangle--unbracketed-link params))
593593
("source-name" . ,name))))))
594594
(list (org-fill-template org-babel-tangle-comment-format-beg link-data)
595595
(org-fill-template org-babel-tangle-comment-format-end link-data))))

testing/lisp/test-ob-tangle.el

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,62 @@ echo 1
159159
(search-forward (concat "[file:" file) nil t)))
160160
(delete-file "test-ob-tangle.el")))))
161161

162+
(ert-deftest ob-tangle/comment-noweb-relative ()
163+
"Test :comments noweb tangling with relative file paths."
164+
(should
165+
(org-test-with-temp-text-in-file
166+
"* Inner
167+
#+name: inner
168+
#+begin_src emacs-lisp
169+
2
170+
#+end_src
171+
172+
* Main
173+
#+header: :tangle \"test-ob-tangle.el\" :comments noweb :noweb yes
174+
#+begin_src emacs-lisp
175+
1
176+
<<inner>>
177+
#+end_src"
178+
(unwind-protect
179+
(let ((org-babel-tangle-use-relative-file-links t))
180+
(org-babel-tangle)
181+
(with-temp-buffer
182+
(insert-file-contents "test-ob-tangle.el")
183+
(buffer-string)
184+
(goto-char (point-min))
185+
(and
186+
(search-forward (concat ";; [[file:" (file-name-nondirectory file) "::inner") nil t)
187+
(search-forward ";; inner ends here" nil t))))
188+
(delete-file "test-ob-tangle.el")))))
189+
190+
(ert-deftest ob-tangle/comment-noweb-absolute ()
191+
"Test :comments noweb tangling with absolute file path."
192+
(should
193+
(org-test-with-temp-text-in-file
194+
"* Inner
195+
#+name: inner
196+
#+begin_src emacs-lisp
197+
2
198+
#+end_src
199+
200+
* Main
201+
#+header: :tangle \"test-ob-tangle.el\" :comments noweb :noweb yes
202+
#+begin_src emacs-lisp
203+
1
204+
<<inner>>
205+
#+end_src"
206+
(unwind-protect
207+
(let ((org-babel-tangle-use-relative-file-links nil))
208+
(org-babel-tangle)
209+
(with-temp-buffer
210+
(insert-file-contents "test-ob-tangle.el")
211+
(buffer-string)
212+
(goto-char (point-min))
213+
(and
214+
(search-forward (concat ";; [[file:" file "::inner") nil t)
215+
(search-forward ";; inner ends here" nil t))))
216+
(delete-file "test-ob-tangle.el")))))
217+
162218
(ert-deftest ob-tangle/jump-to-org ()
163219
"Test `org-babel-tangle-jump-to-org' specifications."
164220
;; Standard test.

0 commit comments

Comments
 (0)