From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id IGelCi5o42KSVQEAbAwnHQ (envelope-from ) for ; Fri, 29 Jul 2022 06:55:10 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id COe6Ci5o42JBYgEA9RJhRA (envelope-from ) for ; Fri, 29 Jul 2022 06:55:10 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id EAABE35FAF for ; Fri, 29 Jul 2022 06:55:08 +0200 (CEST) Received: from localhost ([::1]:53712 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oHI1j-00046n-I5 for larch@yhetil.org; Fri, 29 Jul 2022 00:55:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:53090) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <01070182484e44f3-f0fd271a-def3-4c86-961f-9a4bb63949d5-000000@eu-central-1.amazonses.com>) id 1oHI18-00046R-NL for emacs-orgmode@gnu.org; Fri, 29 Jul 2022 00:54:30 -0400 Received: from b224-7.smtp-out.eu-central-1.amazonses.com ([69.169.224.7]:34409) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.90_1) (envelope-from <01070182484e44f3-f0fd271a-def3-4c86-961f-9a4bb63949d5-000000@eu-central-1.amazonses.com>) id 1oHI16-0005a4-Lc for emacs-orgmode@gnu.org; Fri, 29 Jul 2022 00:54:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=dslly3sakxv6ucutmcab4r63q65kb4ak; d=0brg.net; t=1659070465; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding; bh=JkJbDB6iFt11gErHwNJm5Ui2d5gh5BiA4+KyvwAbJXs=; b=OwUZFrD0I37FJXVd58H6zmdFiqNhUzMmAOACsrGxRUD13iASmvDgu8Lm84Xv16uc +fztAyp6ZNITpC1wt4Jj18UNGHoOqOU7oqCfI7gdtq35uLwbiY/1Z3Lc5gCKnyRhlDR QnvEs3xrHK+EmPhOgvGLPEamM9L9kSO6UqlUf4nNY/b5zUztA+FKXn6/8VcPl77nyPq nmmbybolrXNzDniOgAZpyGis6XzW5Lbns0fTWIGPJw2lk15D52LmqVETB5+vXEcuj3C p3LjVFFg8R7zlbXQzzWUvqv9/lrVdRxqF1IoUrhAn8jIyDRI/tDLQecrLJF+OxHxcy1 TNlHzjKyyQ== DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=54ecsf3zk7z4mwxwwox7z7bg6e5gwjsz; d=amazonses.com; t=1659070465; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Feedback-ID; bh=JkJbDB6iFt11gErHwNJm5Ui2d5gh5BiA4+KyvwAbJXs=; b=OcyA94esSjBs7T9jhKFpYb9Zu2kGZ0nGNDcE0sPRayEW0BMZX8jbFDvaI0SLJJwA K/mrQ69SOBIjR1tpHkcNKOd+grB779YfkfcgKQMpnANnQuin5IlbpxoXnF1m/t7wrIW bpNZLLTauHqGUeVpNy+qPQX03hlUOccRj/1tvHbQ= From: Hraban Luyat To: emacs-orgmode@gnu.org Cc: hraban@0brg.net Subject: [PATCH] =?UTF-8?q?ob-tangle.el:=20fix=20=E2=80=98:comments=20nowe?= =?UTF-8?q?b=E2=80=99=20double=20linking?= Date: Fri, 29 Jul 2022 04:54:25 +0000 Message-ID: <01070182484e44f3-f0fd271a-def3-4c86-961f-9a4bb63949d5-000000@eu-central-1.amazonses.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; charset=utf-8 Content-Transfer-Encoding: quoted-printable Feedback-ID: 1.eu-central-1.RIJ1Zn/ks6EbNO6+Y6S8S9+ZbPNF5phw4jUcN7uFwY8=:AmazonSES X-SES-Outgoing: 2022.07.29-69.169.224.7 Received-SPF: pass client-ip=69.169.224.7; envelope-from=01070182484e44f3-f0fd271a-def3-4c86-961f-9a4bb63949d5-000000@eu-central-1.amazonses.com; helo=b224-7.smtp-out.eu-central-1.amazonses.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1659070509; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:list-id:list-help: list-unsubscribe:list-subscribe:list-post:dkim-signature; bh=nK75vEJwPEjFleBFogNmh4CawWdkO85LLRlRav8BsHw=; b=BpudMhpMiaeS2jrK/Io/v1UmzA1tiW2nho4NwDsAxIunLp4gNyo+69NiwbyU8XPyhDOr5p d0JSd3xQ1bxKR/Uw5UL4ECni/wHixxRgE35N/RTvnRLI2eb35AXZvTUu4ux60CdOSDdMp0 kKdlAKQVe0R6vBOoF/wtCqX1G3z3fOVUAJYcQ4Dm9o4C5xkIsDGWKtPhtsE2DyN3Ti3LWz WlAFY6nETE6L+fED/xR0w5nCvmunpyXjZU0COcBF5eaFgMTV3SaP0OVEimeDQV0ksen5ls coaVeBT8Qx1QIOPv2pEqEXSVh/kct6qOYuI+cpdxCGgOq8jj1yd3Tz1eT51HBQ== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1659070509; a=rsa-sha256; cv=none; b=Bms53/S2YxAUb009uRTnfHC3f2nOcR23z+XBrZYlZkqpnbUGJRl5DZAObk408B3FahsLIH 9wxpKhLo49+PCNgzksTcqVflctxgdwxrdBAb4j9LPICT+7KeQsw/V7e8dWhl1o2jMAiGaT 0tPdyg6Ah9lZkIHPZh3ZmbrhHrsRJwsfV8CACcKCMW9dC5RWf81LyUY0hi9zc15d/uXPaW gjtCpSXQihMG+Vb7JJ3rzw8kBST7or0wiuf5LeWRNv/2DzIZFh7T0Zagjt6d9OIpu6QKd0 VY2Tu6VKmKSa1VQGFun5Sm8SRVJEhlpddPCMk+uEHCbKw15bAfuPqwL17de0TQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=0brg.net header.s=dslly3sakxv6ucutmcab4r63q65kb4ak header.b=OwUZFrD0; dkim=pass header.d=amazonses.com header.s=54ecsf3zk7z4mwxwwox7z7bg6e5gwjsz header.b=OcyA94es; dmarc=pass (policy=reject) header.from=0brg.net; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -2.43 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=0brg.net header.s=dslly3sakxv6ucutmcab4r63q65kb4ak header.b=OwUZFrD0; dkim=pass header.d=amazonses.com header.s=54ecsf3zk7z4mwxwwox7z7bg6e5gwjsz header.b=OcyA94es; dmarc=pass (policy=reject) header.from=0brg.net; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: EAABE35FAF X-Spam-Score: -2.43 X-Migadu-Scanner: scn1.migadu.com X-TUID: d06B+d67MiQd * 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 =E2=80=98:comments noweb=E2= =80=99 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 <> #+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 This is my first org-mode patch, all comments welcome :). I signed a copyright assignment to the FSF 2021-07-12. --- lisp/ob-tangle.el | 54 ++++++++++++++++---------------- testing/lisp/test-ob-tangle.el | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 27 deletions(-) diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index fdba72278..078b1c77a 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -469,6 +469,29 @@ code blocks by target file." (mapcar (lambda (b) (cons (car b) (nreverse (cdr b)))) (nreverse blocks)))) =20 +(defun org-babel-tangle--unbracketed-link (params) + "Get a raw link to the src block at point, without brackets. + +The PARAMS are the 3rd element of the info for the same src block. +" + (let* (;; The created link is transient. Using ID is not necessary, + ;; but could have side-effects if used. An ID property may + ;; be added to existing entries thus creatin unexpected file + ;; modifications. + (org-id-link-to-org-use-id nil) + (l (org-no-properties (org-store-link nil))) + (bare (and (string-match org-link-bracket-re l) + (match-string 1 l)))) + (when bare + (if (and org-babel-tangle-use-relative-file-links + (string-match org-link-types-re bare) + (string=3D (match-string 1 bare) "file")) + (concat "file:" + (file-relative-name (substring bare (match-end 0)) + (file-name-directory + (cdr (assq :tangle params))))) + bare)))) + (defun org-babel-tangle-single-block (block-counter &optional only-this-bl= ock) "Collect the tangled source for current block. Return the list of block attributes needed by @@ -485,16 +508,7 @@ non-nil, return the full association list to be used by (extra (nth 3 info)) (coderef (nth 6 info)) (cref-regexp (org-src-coderef-regexp coderef)) - (link (let* ( - ;; The created link is transient. Using ID is - ;; not necessary, but could have side-effects if - ;; used. An ID property may be added to - ;; existing entries thus creatin unexpected file - ;; modifications. - (org-id-link-to-org-use-id nil) - (l (org-no-properties (org-store-link nil)))) - (and (string-match org-link-bracket-re l) - (match-string 1 l)))) + (link (org-babel-tangle--unbracketed-link params)) (source-name (or (nth 4 info) (format "%s:%d" @@ -548,15 +562,7 @@ non-nil, return the full association list to be used by (if org-babel-tangle-use-relative-file-links (file-relative-name file) file) - (if (and org-babel-tangle-use-relative-file-links - (string-match org-link-types-re link) - (string=3D (match-string 1 link) "file") - (stringp src-tfile)) - (concat "file:" - (file-relative-name (substring link (match-end 0)) - (file-name-directory - src-tfile))) - link) + link source-name params (if org-src-preserve-indentation @@ -574,18 +580,12 @@ non-nil, return the full association list to be used = by INFO, when non nil, is the source block information, as returned by `org-babel-get-src-block-info'." (let ((link-data (pcase (or info (org-babel-get-src-block-info 'light)) - (`(,_ ,_ ,_ ,_ ,name ,start ,_) + (`(,_ ,_ ,params ,_ ,name ,start ,_) `(("start-line" . ,(org-with-point-at start (number-to-string (line-number-at-pos)))) ("file" . ,(buffer-file-name)) - ("link" . ,(let (;; The created link is transient. Using ID is - ;; not necessary, but could have = side-effects if - ;; used. An ID property may be a= dded to - ;; existing entries thus creatin = unexpected file - ;; modifications. - (org-id-link-to-org-use-id nil)) - (org-no-properties (org-store-link ni= l)))) + ("link" . ,(org-babel-tangle--unbracketed-link params)) ("source-name" . ,name)))))) (list (org-fill-template org-babel-tangle-comment-format-beg link-data) (org-fill-template org-babel-tangle-comment-format-end link-data)))) diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el index 2ed4ba0da..fecb105ba 100644 --- a/testing/lisp/test-ob-tangle.el +++ b/testing/lisp/test-ob-tangle.el @@ -159,6 +159,62 @@ echo 1 (search-forward (concat "[file:" file) nil t))) (delete-file "test-ob-tangle.el"))))) =20 +(ert-deftest ob-tangle/comment-noweb-relative () + "Test :comments noweb tangling with relative file paths" + (should + (org-test-with-temp-text-in-file + "* Inner +#+name: inner +#+begin_src emacs-lisp +2 +#+end_src + +* Main +#+header: :tangle \"test-ob-tangle.el\" :comments noweb :noweb yes +#+begin_src emacs-lisp +1 +<> +#+end_src" + (unwind-protect + (let ((org-babel-tangle-use-relative-file-links t)) + (org-babel-tangle) + (with-temp-buffer + (insert-file-contents "test-ob-tangle.el") + (buffer-string) + (goto-char (point-min)) + (and + (search-forward (concat ";; [[file:" (file-name-nondirectory= file) "::inner") nil t) + (search-forward ";; inner ends here" nil t)))) + (delete-file "test-ob-tangle.el"))))) + +(ert-deftest ob-tangle/comment-noweb-absolute () + "Test :comments noweb tangling with absolute file path" + (should + (org-test-with-temp-text-in-file + "* Inner +#+name: inner +#+begin_src emacs-lisp +2 +#+end_src + +* Main +#+header: :tangle \"test-ob-tangle.el\" :comments noweb :noweb yes +#+begin_src emacs-lisp +1 +<> +#+end_src" + (unwind-protect + (let ((org-babel-tangle-use-relative-file-links nil)) + (org-babel-tangle) + (with-temp-buffer + (insert-file-contents "test-ob-tangle.el") + (buffer-string) + (goto-char (point-min)) + (and + (search-forward (concat ";; [[file:" file "::inner") nil t) + (search-forward ";; inner ends here" nil t)))) + (delete-file "test-ob-tangle.el"))))) + (ert-deftest ob-tangle/jump-to-org () "Test `org-babel-tangle-jump-to-org' specifications." ;; Standard test. --=20 2.36.1