emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* noweb-start and noweb-end header args
@ 2024-03-05 19:22 Amy Grinn
  2024-03-05 22:41 ` termux
                   ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Amy Grinn @ 2024-03-05 19:22 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 716 bytes --]


I would like to add support for setting 'org-babel-noweb-wrap-start and
'org-babel-noweb-wrap-end for each src block individually using the
header args :noweb-start and :noweb-end:

#+name: firewall-safe-mode
#+begin_src sh
  echo "Firewall is now in safe mode."
#+end_src

#+name: firewall
#+begin_src sh  :noweb yes :noweb-start <<< :noweb-end >>>
  safe_mode () {
      echo "Error encountered, switching to safe mode."
      <<<firewall-safe-mode>>>
      exit 1
  }

  setup-firewall || safe_mode
#+end_src

#+begin_src sh :noweb yes :noweb-start ":-) " :noweb-end " (-:" :tangle "test.sh"
  # Setup firewall
  :-) firewall (-:

  # Do other things
#+end_src


Here is a simple way to implement this feature.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: noweb extra header args --]
[-- Type: text/x-patch, Size: 1480 bytes --]

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 4dcfbd3b0..0be19ff06 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -194,15 +194,17 @@ This string must include a \"%s\" which will be replaced by the results."
   :package-version '(Org . "9.1")
   :safe #'booleanp)
 
-(defun org-babel-noweb-wrap (&optional regexp)
+(defun org-babel-noweb-wrap (&optional regexp info)
   "Return regexp matching a Noweb reference.
 
 Match any reference, or only those matching REGEXP, if non-nil.
 
 When matching, reference is stored in match group 1."
-  (concat (regexp-quote org-babel-noweb-wrap-start)
+  (concat (regexp-quote (or (cdr (assq :noweb-start (nth 2 info)))
+                            org-babel-noweb-wrap-start))
 	  (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
-	  (regexp-quote org-babel-noweb-wrap-end)))
+	  (regexp-quote (or (cdr (assq :noweb-end (nth 2 info)))
+                            org-babel-noweb-wrap-end))))
 
 (defvar org-babel-src-name-regexp
   "^[ \t]*#\\+name:[ \t]*"
@@ -3116,7 +3118,7 @@ block but are passed literally to the \"example-block\"."
                                   (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
-			     (org-babel-noweb-wrap)))))
+			     (org-babel-noweb-wrap nil info)))))
     (unless (equal (cons parent-buffer
                          (with-current-buffer parent-buffer
                            (buffer-chars-modified-tick)))

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-05 19:22 noweb-start and noweb-end header args Amy Grinn
@ 2024-03-05 22:41 ` termux
  2024-03-06 11:21 ` Ihor Radchenko
  2024-03-07 14:04 ` Ihor Radchenko
  2 siblings, 0 replies; 26+ messages in thread
From: termux @ 2024-03-05 22:41 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 790 bytes --]

Amy Grinn <grinn.amy@gmail.com> writes:

> I would like to add support for setting 'org-babel-noweb-wrap-start and
> 'org-babel-noweb-wrap-end for each src block individually using the
> header args :noweb-start and :noweb-end:

Here's another possible syntax we could use:

:noweb <context> [wrap-start] [wrap-end]

#+name: message
#+begin_src elisp
  "Firewall is now in safe mode."
#+end_src

#+name: firewall-safe-mode
#+begin_src sh :noweb yes
  echo <<message>>
#+end_src

#+name: firewall
#+begin_src sh :noweb yes <<< >>>
  safe_mode () {
      echo "Error encountered, switching to safe mode."
      <<<firewall-safe-mode>>>
      exit 1
  }
#+end_src

#+begin_src sh :noweb yes ":-) " " (-:" :tangle "test.sh"
  # Setup firewall
  :-) firewall (-:

  # Do other things
#+end_src


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Noweb header argument new syntax --]
[-- Type: text/x-patch, Size: 1663 bytes --]

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 4dcfbd3b0..f60b4be12 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -194,15 +194,20 @@ This string must include a \"%s\" which will be replaced by the results."
   :package-version '(Org . "9.1")
   :safe #'booleanp)
 
-(defun org-babel-noweb-wrap (&optional regexp)
+(defun org-babel-noweb-wrap (&optional regexp info)
   "Return regexp matching a Noweb reference.
 
 Match any reference, or only those matching REGEXP, if non-nil.
 
 When matching, reference is stored in match group 1."
-  (concat (regexp-quote org-babel-noweb-wrap-start)
-	  (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
-	  (regexp-quote org-babel-noweb-wrap-end)))
+  (let ((noweb (mapcar
+                (lambda (token)
+                  (if (stringp token) token (symbol-name token)))
+                (org-babel-read
+                 (format "'(%s)" (cdr (assq :noweb (nth 2 info))))))))
+    (concat (regexp-quote (or (nth 1 noweb) org-babel-noweb-wrap-start))
+	    (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
+	    (regexp-quote (or (nth 2 noweb) org-babel-noweb-wrap-end)))))
 
 (defvar org-babel-src-name-regexp
   "^[ \t]*#\\+name:[ \t]*"
@@ -3116,7 +3121,7 @@ block but are passed literally to the \"example-block\"."
                                   (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
-			     (org-babel-noweb-wrap)))))
+			     (org-babel-noweb-wrap nil info)))))
     (unless (equal (cons parent-buffer
                          (with-current-buffer parent-buffer
                            (buffer-chars-modified-tick)))

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-05 19:22 noweb-start and noweb-end header args Amy Grinn
  2024-03-05 22:41 ` termux
@ 2024-03-06 11:21 ` Ihor Radchenko
  2024-03-06 11:40   ` Amy Grinn
  2024-03-07 14:04 ` Ihor Radchenko
  2 siblings, 1 reply; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-06 11:21 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

> I would like to add support for setting 'org-babel-noweb-wrap-start and
> 'org-babel-noweb-wrap-end for each src block individually using the
> header args :noweb-start and :noweb-end:
> ...
> #+name: firewall
> #+begin_src sh  :noweb yes :noweb-start <<< :noweb-end >>>

May you please explain the use case when changing the default values is useful?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 11:21 ` Ihor Radchenko
@ 2024-03-06 11:40   ` Amy Grinn
  2024-03-06 11:47     ` Ihor Radchenko
  2024-03-06 23:07     ` Amy Grinn
  0 siblings, 2 replies; 26+ messages in thread
From: Amy Grinn @ 2024-03-06 11:40 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>> I would like to add support for setting 'org-babel-noweb-wrap-start and
>> 'org-babel-noweb-wrap-end for each src block individually using the
>> header args :noweb-start and :noweb-end:
>> ...
>> #+name: firewall
>> #+begin_src sh  :noweb yes :noweb-start <<< :noweb-end >>>
>
> May you please explain the use case when changing the default values
> is useful?

Of course!  Changing the default values can be useful to prevent syntax
highlighting errors in a specific language.  In the example I gave, <<<
and >>> aren't recognized as the beginning of a heredoc in a shell
script the way <<firewall-safe-mode>> would be.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 11:40   ` Amy Grinn
@ 2024-03-06 11:47     ` Ihor Radchenko
  2024-03-06 12:05       ` Amy Grinn
  2024-03-06 23:07     ` Amy Grinn
  1 sibling, 1 reply; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-06 11:47 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

>>> #+name: firewall
>>> #+begin_src sh  :noweb yes :noweb-start <<< :noweb-end >>>
>>
>> May you please explain the use case when changing the default values
>> is useful?
>
> Of course!  Changing the default values can be useful to prevent syntax
> highlighting errors in a specific language.  In the example I gave, <<<
> and >>> aren't recognized as the beginning of a heredoc in a shell
> script the way <<firewall-safe-mode>> would be.

This sounds like XY problem then.
If the real problem you want to solve is fontification, we may instead
adjust Org mode fontification of source blocks to exclude noweb
references.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 11:47     ` Ihor Radchenko
@ 2024-03-06 12:05       ` Amy Grinn
  2024-03-06 13:33         ` Ihor Radchenko
  0 siblings, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-03-06 12:05 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>>>> #+name: firewall
>>>> #+begin_src sh  :noweb yes :noweb-start <<< :noweb-end >>>
>>>
>>> May you please explain the use case when changing the default values
>>> is useful?
>>
>> Of course!  Changing the default values can be useful to prevent syntax
>> highlighting errors in a specific language.  In the example I gave, <<<
>> and >>> aren't recognized as the beginning of a heredoc in a shell
>> script the way <<firewall-safe-mode>> would be.
>
> This sounds like XY problem then.
> If the real problem you want to solve is fontification, we may instead
> adjust Org mode fontification of source blocks to exclude noweb
> references.

I see a problem with multiple possible solutions, some more involved
than others.  The org-babel-noweb-wrap-* variables are already
customizeable and, in researching a solution to this problem, I have
found users who set these variables on a file or directory-local level
already.

How much does org mode modify the fontification for an indirect buffer?
Without having looked into it, I assume not much or at all.  I think
that approach could be more complex, especially when dealing with a
theoretically infinite number of major modes.

Both solutions could be implemented at the same time.  We could build on
the existing functionality of the wrap-end and wrap-start variables
while also looking at ways to modify the syntax highlighting without
user intervention.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 12:05       ` Amy Grinn
@ 2024-03-06 13:33         ` Ihor Radchenko
  2024-03-06 16:04           ` Amy Grinn
  0 siblings, 1 reply; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-06 13:33 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

>> This sounds like XY problem then.
>> If the real problem you want to solve is fontification, we may instead
>> adjust Org mode fontification of source blocks to exclude noweb
>> references.
>
> I see a problem with multiple possible solutions, some more involved
> than others.  The org-babel-noweb-wrap-* variables are already
> customizeable and, in researching a solution to this problem, I have
> found users who set these variables on a file or directory-local level
> already.

Yup. And most of these customizations are aiming to solve the
fontification problem. If we did not have the problem to start with,
re-defining the noweb wrap syntax would be unnecessary in many cases.

> How much does org mode modify the fontification for an indirect buffer?
> Without having looked into it, I assume not much or at all.
> ... I think
> that approach could be more complex, especially when dealing with a
> theoretically infinite number of major modes.

Org mode does not _currently_ modify the code. But that's actually wrong
- things like escaped ,* or indentation sometimes also stay on the way
and produce incorrect fontification. So, rewriting the fontification of
src blocks to cleanup the code before fontification is long due.
noweb references is just another manifestation of this problem.

> Both solutions could be implemented at the same time.  We could build on
> the existing functionality of the wrap-end and wrap-start variables
> while also looking at ways to modify the syntax highlighting without
> user intervention.

I am not in favor of adding features that aim to serve as workarounds to
Org mode.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 13:33         ` Ihor Radchenko
@ 2024-03-06 16:04           ` Amy Grinn
  2024-03-07 13:50             ` Ihor Radchenko
  0 siblings, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-03-06 16:04 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>> How much does org mode modify the fontification for an indirect buffer?
>> Without having looked into it, I assume not much or at all.
>> ... I think
>> that approach could be more complex, especially when dealing with a
>> theoretically infinite number of major modes.
>
> Org mode does not _currently_ modify the code. But that's actually wrong
> - things like escaped ,* or indentation sometimes also stay on the way
> and produce incorrect fontification. So, rewriting the fontification of
> src blocks to cleanup the code before fontification is long due.
> noweb references is just another manifestation of this problem.

I think we're talking past each other a little.  I'm not talking about
changing the text content of a src block, I'm talking about modifying
the syntax table of a major mode such as sh-mode to ignore or handle
<<noweb>> syntax in an "edit-special" buffer.  That was my
interpretation of your suggestion of using fontification to solve this
issue.  And if that's the case, I foresee a lot of edge cases for
modifying the display of major modes.

>> Both solutions could be implemented at the same time.  We could build on
>> the existing functionality of the wrap-end and wrap-start variables
>> while also looking at ways to modify the syntax highlighting without
>> user intervention.
>
> I am not in favor of adding features that aim to serve as workarounds to
> Org mode.

This discussion is not about whether to allow users to modify noweb
syntax.  That feature is already a part of Org, well documented, and
utilized.  The feature request I'm making is to allow that modification
to be done on a per-block level.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 11:40   ` Amy Grinn
  2024-03-06 11:47     ` Ihor Radchenko
@ 2024-03-06 23:07     ` Amy Grinn
  2024-03-07 13:58       ` Ihor Radchenko
  1 sibling, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-03-06 23:07 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

> Ihor Radchenko <yantar92@posteo.net> writes:
>
>> Amy Grinn <grinn.amy@gmail.com> writes:
>>
>>> I would like to add support for setting 'org-babel-noweb-wrap-start and
>>> 'org-babel-noweb-wrap-end for each src block individually
>>
>> May you please explain the use case when changing the default values
>> is useful?
>
> Of course!  Changing the default values can be useful to prevent syntax
> highlighting errors in a specific language.  In the example I gave, <<<
> and >>> aren't recognized as the beginning of a heredoc in a shell
> script the way <<firewall-safe-mode>> would be.

To expand on this, some major modes can fundamentally conflict with the
default noweb syntax.  Here is a valid shell script *and* a valid noweb
reference to a block named EOF:

cat <<EOF>> file.txt
Hello
EOF

I hope this helps explain why the wrap-start and wrap-end options were
necessary to include more than a decade ago.  In terms of actually using
them, it's a bit cumbersome, especially in Org mode buffers that use
multiple languages.

The second diff I sent (under the termux handle, accidentally) is my
preferred solution (:noweb yes <<< >>>).  This would avoid the need for
new header arguments to be introduced while maintaining backwards
compatibility.  It also feels natural to specify the two options
together: I can't think of a good reason to only need to specify the
wrap-end option.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 16:04           ` Amy Grinn
@ 2024-03-07 13:50             ` Ihor Radchenko
  0 siblings, 0 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-07 13:50 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

>> Org mode does not _currently_ modify the code. But that's actually wrong
>> - things like escaped ,* or indentation sometimes also stay on the way
>> and produce incorrect fontification. So, rewriting the fontification of
>> src blocks to cleanup the code before fontification is long due.
>> noweb references is just another manifestation of this problem.
>
> I think we're talking past each other a little.  I'm not talking about
> changing the text content of a src block, I'm talking about modifying
> the syntax table of a major mode such as sh-mode to ignore or handle
> <<noweb>> syntax in an "edit-special" buffer.  That was my
> interpretation of your suggestion of using fontification to solve this
> issue.  And if that's the case, I foresee a lot of edge cases for
> modifying the display of major modes.

That's not what I had in mind. I thought of resolving/replacing noweb
references before fontifying the code. That way, the major mode for src
block will simply not see <<noweb>> text and will not be confused.

>> I am not in favor of adding features that aim to serve as workarounds to
>> Org mode.
>
> This discussion is not about whether to allow users to modify noweb
> syntax.  That feature is already a part of Org, well documented, and
> utilized.  The feature request I'm making is to allow that modification
> to be done on a per-block level.

Sure, but I wanted to hear why such feature is useful in practice. Your
example with fontification is not something I consider as a good
justification for adding a new feature. You another email provides a
better justification though.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-06 23:07     ` Amy Grinn
@ 2024-03-07 13:58       ` Ihor Radchenko
  2024-03-07 14:33         ` Amy Grinn
  0 siblings, 1 reply; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-07 13:58 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

> To expand on this, some major modes can fundamentally conflict with the
> default noweb syntax.  Here is a valid shell script *and* a valid noweb
> reference to a block named EOF:
>
> cat <<EOF>> file.txt
> Hello
> EOF
>
> I hope this helps explain why the wrap-start and wrap-end options were
> necessary to include more than a decade ago.  In terms of actually using
> them, it's a bit cumbersome, especially in Org mode buffers that use
> multiple languages.

This makes sense.
I agree that setting noweb reference syntax per-language is useful in
some cases.

> The second diff I sent (under the termux handle, accidentally) is my
> preferred solution (:noweb yes <<< >>>).  This would avoid the need for
> new header arguments to be introduced while maintaining backwards
> compatibility.  It also feels natural to specify the two options
> together: I can't think of a good reason to only need to specify the
> wrap-end option.

:noweb yes <<< >>> is actually backwards-incompatible. Consider
third-party code that makes assumptions about possible values of :noweb
header argument. If third-party code does a check like
(equal noweb-value "yes"), the new syntax can break such code.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-05 19:22 noweb-start and noweb-end header args Amy Grinn
  2024-03-05 22:41 ` termux
  2024-03-06 11:21 ` Ihor Radchenko
@ 2024-03-07 14:04 ` Ihor Radchenko
  2024-03-07 15:06   ` Amy Grinn
  2024-04-08 14:04   ` [FR] :noweb-wrap header arg Amy Grinn
  2 siblings, 2 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-07 14:04 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

> Here is a simple way to implement this feature.
> ...
> -(defun org-babel-noweb-wrap (&optional regexp)
> +(defun org-babel-noweb-wrap (&optional regexp info)
>    "Return regexp matching a Noweb reference.
>  
>  Match any reference, or only those matching REGEXP, if non-nil.
>  
>  When matching, reference is stored in match group 1."

INFO argument needs to be documented.

> -			     (org-babel-noweb-wrap)))))
> +			     (org-babel-noweb-wrap nil info)))))

Please, also update all other cases when `org-babel-noweb-wrap' is
called.

Also, `org-babel-goto-named-src-block' uses
org-babel-noweb-wrap-start/end directly. It should be adjusted.

Since you are adding a new feature, it should have (1) test coverage;
(2) be documented in the manual; (3) be announced in etc/ORG-NEWS.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-07 13:58       ` Ihor Radchenko
@ 2024-03-07 14:33         ` Amy Grinn
  2024-03-07 14:49           ` Ihor Radchenko
  0 siblings, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-03-07 14:33 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> :noweb yes <<< >>> is actually backwards-incompatible. Consider
> third-party code that makes assumptions about possible values of
> :noweb
> header argument. If third-party code does a check like
> (equal noweb-value "yes"), the new syntax can break such code.

I kinda disagree with your reasoning but I agree with your conclusion.
I think it would be strange for third party or user configuration to
parse the value of a noweb header argument directly.  Org provides a
lublic api for this which should be backwards compatible:

  (org-babel-noweb-p (nth 2 (org-babel-get-src-block-info t)) :tangle)

However, other parsers besides Emacs exist for Org mode and they may
directly compare the entire noweb argument.

The middle way is to create just one new header arg:

:noweb-wrap <start> [end]


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-07 14:33         ` Amy Grinn
@ 2024-03-07 14:49           ` Ihor Radchenko
  0 siblings, 0 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-03-07 14:49 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

> I kinda disagree with your reasoning but I agree with your conclusion.
> I think it would be strange for third party or user configuration to
> parse the value of a noweb header argument directly.  Org provides a
> lublic api for this which should be backwards compatible:
>
>   (org-babel-noweb-p (nth 2 (org-babel-get-src-block-info t)) :tangle)

Yeah, but this API is not uniform. Most other header arguments must be
retrieved using `assq'. So, it is very common to use `assq' for
everything, even if there is a specific API.
(Ideally, we need to implement a uniform API to retrieve header argument
values)

> The middle way is to create just one new header arg:
>
> :noweb-wrap <start> [end]

Maybe <end> should be mandatory. Otherwise, LGTM.


-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: noweb-start and noweb-end header args
  2024-03-07 14:04 ` Ihor Radchenko
@ 2024-03-07 15:06   ` Amy Grinn
  2024-04-08 14:04   ` [FR] :noweb-wrap header arg Amy Grinn
  1 sibling, 0 replies; 26+ messages in thread
From: Amy Grinn @ 2024-03-07 15:06 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>> Here is a simple way to implement this feature.
>
> Since you are adding a new feature, it should have (1) test coverage;
> (2) be documented in the manual; (3) be announced in etc/ORG-NEWS.

Thank you for the tips, will do!


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FR] :noweb-wrap header arg
  2024-03-07 14:04 ` Ihor Radchenko
  2024-03-07 15:06   ` Amy Grinn
@ 2024-04-08 14:04   ` Amy Grinn
  2024-04-11 14:03     ` Ihor Radchenko
  1 sibling, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-04-08 14:04 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1303 bytes --]


Hi!

I'm working on the :noweb-wrap header argument which controls the syntax
of noweb references in a babel src block. For example:

#+name: foo
#+begin_src elisp
  :foo
#+end_src

#+begin_src elisp :noweb yes :noweb-wrap <<< >>>
  <<<foo>>>
#+end_src

And I would like some feedback...

First of all, I would like to change (defalias) the function name
org-babel-noweb-wrap to org-babel-noweb-make-regexp. I think this in
more in line with other functions which create regular expressions.

The new way to retrieve the regular expression matching a noweb
reference in the source block at point would be:

(org-babel-noweb-make-regexp nil (org-babel-get-noweb-wrap info))

Where info can be nil or the result of calling
(org-babel-get-src-block-info).

Second, the command org-babel-tangle-clean is not able to determine
which noweb syntax is being used in any tangled source file because the
header arguments are not tangled along with the source code.

My proposal is to add an additional warning to this command, stating:

"""
Warning, this command removes any lines containing constructs which
resemble Org file links or noweb references.  It also cannot determine
which noweb syntax is being used for any given source file, if
:noweb-wrap was specified in the original Org file.
"""

Best,

Amy


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: noweb-wrap header arg --]
[-- Type: text/x-patch, Size: 10701 bytes --]

From 1dc8aebcc45447d3b5b38ea3c7700ae2b2686c9d Mon Sep 17 00:00:00 2001
From: Amy Grinn <grinn.amy@gmail.com>
Date: Mon, 8 Apr 2024 09:05:02 -0400
Subject: [PATCH] (WIP) lisp/ob-core.el: New :noweb-wrap header arg

* lisp/ob-core: (org-babel-noweb-wrap): Add optional third parameter
'wrap'.
* lisp/ob-core: (org-babel-get-noweb-wrap): New function for parsing
:noweb-wrap header arg.
* etc/ORG-NEWS (New =:noweb-wrap= babel header argument): Describe new
argument.
* others...
---
 etc/ORG-NEWS                | 14 ++++++++++
 lisp/ob-core.el             | 51 ++++++++++++++++++++++++++++------
 lisp/ob-exp.el              |  3 +-
 lisp/ob-tangle.el           |  6 +++-
 testing/examples/babel.org  | 17 ++++++++++++
 testing/lisp/test-ob-exp.el | 55 +++++++++++++++++++++++++++++++++++++
 testing/lisp/test-ob.el     | 15 ++++++++++
 7 files changed, 150 insertions(+), 11 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index aeb7ffd4b..162e7f035 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -621,6 +621,20 @@ link when storing any type of external link type in an Org file, not
 just =id:= links.
 
 ** New and changed options
+*** New =:noweb-wrap= babel header argument
+
+This argument changes the default noweb reference syntax by masking
+the options ~org-babel-noweb-wrap-start~ and
+~org-babel-noweb-wrap-end~.
+
+=:noweb-wrap= takes two parameters, start and end, corresponding to
+each option.
+
+For example:
+: #+begin_src sh :noweb-wrap <<< >>>
+:   echo <<<message>>>
+: #+end_src
+
 *** =.avif= images are now recognized in ~org-html-inline-image-rules~
 
 In =ox-html=, =.avif= image links are now inlined by default.
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 8dfc07a4e..843794322 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -194,15 +194,21 @@ This string must include a \"%s\" which will be replaced by the results."
   :package-version '(Org . "9.1")
   :safe #'booleanp)
 
-(defun org-babel-noweb-wrap (&optional regexp)
+(defun org-babel-noweb-wrap (&optional regexp wrap)
   "Return regexp matching a Noweb reference.
 
 Match any reference, or only those matching REGEXP, if non-nil.
 
+If WRAP is provided, it should be a list of 2 strings describing
+the start and end of a noweb reference, such as that returned by
+`org-babel-get-noweb-wrap'.  Otherwise
+`org-babel-noweb-wrap-start' and `org-babel-noweb-wrap-end' will
+be used.
+
 When matching, reference is stored in match group 1."
-  (concat (regexp-quote org-babel-noweb-wrap-start)
-	  (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
-	  (regexp-quote org-babel-noweb-wrap-end)))
+  (concat (regexp-quote (or (car wrap) org-babel-noweb-wrap-start))
+	    (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
+	    (regexp-quote (or (cadr wrap) org-babel-noweb-wrap-end))))
 
 (defvar org-babel-src-name-regexp
   "^[ \t]*#\\+name:[ \t]*"
@@ -1963,6 +1969,27 @@ src block, then return nil."
   (let ((head (org-babel-where-is-src-block-head)))
     (if head (goto-char head) (error "Not currently in a code block"))))
 
+(defun org-babel-get-noweb-wrap (&optional info)
+  "Retrieve a description the :noweb-wrap header arg from INFO.
+
+The description will be in the form of a list of two of strings
+for the start and end of a reference.  INFO can be the result of
+`org-babel-get-src-block-info' otherwise this function will parse
+info at point."
+  (unless info
+    (setq info (org-babel-get-src-block-info 'no-eval)))
+  (when-let ((raw (cdr (assq :noweb-wrap (nth 2 info)))))
+    (let (result)
+      (with-temp-buffer
+        (insert raw)
+        (goto-char (point-min))
+        (while (< (point) (point-max))
+          (unless (looking-at " *\"\\([^\"]+\\)\" *")
+            (looking-at " *\\([^ ]+\\)"))
+          (goto-char (match-end 0))
+          (push (match-string 1) result)))
+      (reverse result))))
+
 ;;;###autoload
 (defun org-babel-goto-named-src-block (name)
   "Go to a source-code block with NAME."
@@ -1974,14 +2001,18 @@ src block, then return nil."
 	    "source-block name: " all-block-names nil t
 	    (let* ((context (org-element-context))
 		   (type (org-element-type context))
+                   (noweb-wrap (org-babel-get-noweb-wrap))
 		   (noweb-ref
 		    (and (memq type '(inline-src-block src-block))
-			 (org-in-regexp (org-babel-noweb-wrap)))))
+			 (org-in-regexp (org-babel-noweb-wrap
+                                         nil noweb-wrap)))))
 	      (cond
 	       (noweb-ref
 		(buffer-substring
-		 (+ (car noweb-ref) (length org-babel-noweb-wrap-start))
-		 (- (cdr noweb-ref) (length org-babel-noweb-wrap-end))))
+		 (+ (car noweb-ref) (length (or (car noweb-wrap)
+                                                org-babel-noweb-wrap-start)))
+		 (- (cdr noweb-ref) (length (or (cadr noweb-wrap)
+                                                org-babel-noweb-wrap-end)))))
 	       ((memq type '(babel-call inline-babel-call)) ;#+CALL:
 		(org-element-property :call context))
 	       ((car (org-element-property :results context))) ;#+RESULTS:
@@ -3125,7 +3156,8 @@ block but are passed literally to the \"example-block\"."
                                   (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
-			     (org-babel-noweb-wrap)))))
+			     (org-babel-noweb-wrap
+                              nil (org-babel-get-noweb-wrap info))))))
     (unless (equal (cons parent-buffer
                          (with-current-buffer parent-buffer
                            (buffer-chars-modified-tick)))
@@ -3175,7 +3207,8 @@ block but are passed literally to the \"example-block\"."
 	              ((guard (or org-babel-noweb-error-all-langs
 			          (member lang org-babel-noweb-error-langs)))
 	               (error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
-		              (org-babel-noweb-wrap ,ref)))
+		              (org-babel-noweb-wrap
+                               ,ref (org-babel-get-noweb-wrap))))
 	              (_ ""))))
       (replace-regexp-in-string
        noweb-re
diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index af726dc2c..1311813c5 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -414,7 +414,8 @@ replaced with its value."
   (setf (nth 1 info)
 	(if (string= "strip-export" (cdr (assq :noweb (nth 2 info))))
 	    (replace-regexp-in-string
-	     (org-babel-noweb-wrap) "" (nth 1 info))
+	     (org-babel-noweb-wrap nil (org-babel-get-noweb-wrap info))
+             "" (nth 1 info))
 	  (if (org-babel-noweb-p (nth 2 info) :export)
 	      (org-babel-expand-noweb-references
 	       info org-babel-exp-reference-buffer)
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 79fe6448b..17c4e7096 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -580,7 +580,11 @@ non-nil, return the full association list to be used by
 	  ;; Run the tangle-body-hook.
           (let ((body (if (org-babel-noweb-p params :tangle)
                           (if (string= "strip-tangle" (cdr (assq :noweb (nth 2 info))))
-                            (replace-regexp-in-string (org-babel-noweb-wrap) "" (nth 1 info))
+                              (replace-regexp-in-string
+			       (org-babel-noweb-wrap
+				nil (org-babel-get-noweb-wrap info))
+			       ""
+			       (nth 1 info))
 			    (org-babel-expand-noweb-references info))
 			(nth 1 info))))
 	    (with-temp-buffer
diff --git a/testing/examples/babel.org b/testing/examples/babel.org
index d46afeb5e..680d4bf3e 100644
--- a/testing/examples/babel.org
+++ b/testing/examples/babel.org
@@ -346,6 +346,23 @@ Here is a call line with more than just the results exported.
   echo "1$i"
 #+END_SRC
 
+* strip noweb references with alternative wrap
+  :PROPERTIES:
+  :ID:       da9bcfdd-c1bd-47b4-b520-67974b9f9856
+  :END:
+
+#+name: strip-export-2
+#+BEGIN_SRC sh :exports none
+  i="10"
+#+END_SRC
+
+#+RESULTS: strip-export-2
+
+#+BEGIN_SRC sh :noweb strip-export :noweb-wrap #[[ ]] :exports code :results silent
+  #[[strip-export-2]]
+  echo "1$i"
+#+END_SRC
+
 * use case of reading entry properties
   :PROPERTIES:
   :ID:       cc5fbc20-bca5-437a-a7b8-2b4d7a03f820
diff --git a/testing/lisp/test-ob-exp.el b/testing/lisp/test-ob-exp.el
index e6fbf14a1..8c4f4e9a1 100644
--- a/testing/lisp/test-ob-exp.el
+++ b/testing/lisp/test-ob-exp.el
@@ -394,6 +394,61 @@ be evaluated."
 		 (regexp-quote " :foo  :bar \n")
 		 ascii))))))
 
+(ert-deftest ob-exp/noweb-wrap-header-arg ()
+  (let ((org-export-use-babel t))
+    (org-test-with-temp-text
+	"
+#+Title: exporting from a temporary buffer
+
+#+name: foo
+#+BEGIN_SRC emacs-lisp
+  :foo
+#+END_SRC
+
+#+BEGIN_SRC emacs-lisp :noweb yes :noweb-wrap {{ }} :exports results
+  (list {{foo}})
+#+END_SRC
+"
+      (let* ((ascii (org-export-as 'ascii)))
+	(should (string-match
+		 (regexp-quote " :foo \n")
+		 ascii))))))
+
+(ert-deftest ob-exp/noweb-strip-export-with-wrap ()
+  (org-test-at-id "da9bcfdd-c1bd-47b4-b520-67974b9f9856"
+    (org-narrow-to-subtree)
+    (org-babel-next-src-block 1)
+    (org-babel-execute-src-block)
+    (let ((result (org-test-with-expanded-babel-code (buffer-string))))
+      (should-not (string-match (regexp-quote "#[[strip-export-2]]") result))
+      (should-not (string-match (regexp-quote "i=\"10\"") result)))))
+
+(ert-deftest ob-exp/noweb-wrap-strip-export ()
+  (let ((org-export-use-babel t))
+    (org-test-with-temp-text
+	"
+#+Title: exporting from a temporary buffer
+
+#+name: foo
+#+BEGIN_SRC emacs-lisp
+  :foo
+#+END_SRC
+
+#+name: bar
+#+BEGIN_SRC emacs-lisp
+  :bar
+#+END_SRC
+
+#+BEGIN_SRC emacs-lisp :noweb yes :noweb-wrap {{ }} :exports results
+  (list {{foo}} {{bar}})
+#+END_SRC
+"
+      (let* ((ascii (org-export-as 'ascii)))
+        
+	(should (string-match
+		 (regexp-quote ":foo  :bar")
+		 ascii))))))
+
 (ert-deftest ob-export/export-with-results-before-block ()
   "Test export when results are inserted before source block."
   (let ((org-export-use-babel t))
diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el
index c088af7c8..bd143be8b 100644
--- a/testing/lisp/test-ob.el
+++ b/testing/lisp/test-ob.el
@@ -988,6 +988,21 @@ x
             (search-forward "begin_src")
             (org-babel-expand-noweb-references)))))
 
+(ert-deftest test-ob/noweb-wrap ()
+  ;; Standard test.
+  (should
+   (string=
+    "bar"
+    (org-test-with-temp-text "#+begin_src sh :results output :tangle yes :noweb-wrap <<< >>>
+  <<<foo>>>
+#+end_src
+
+#+name: foo
+#+begin_src sh
+  bar
+#+end_src"
+        (org-babel-expand-noweb-references)))))
+
 (ert-deftest test-ob/splitting-variable-lists-in-references ()
   (org-test-with-temp-text ""
     (should (= 1 (length (org-babel-ref-split-args
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-04-08 14:04   ` [FR] :noweb-wrap header arg Amy Grinn
@ 2024-04-11 14:03     ` Ihor Radchenko
  2024-04-11 18:46       ` Amy Grinn
  2024-05-11 16:01       ` Amy Grinn
  0 siblings, 2 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-04-11 14:03 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

> First of all, I would like to change (defalias) the function name
> org-babel-noweb-wrap to org-babel-noweb-make-regexp. I think this in
> more in line with other functions which create regular expressions.

+1
You may even use obsolete alias (add it to lisp/org-compat.el)

> Second, the command org-babel-tangle-clean is not able to determine
> which noweb syntax is being used in any tangled source file because the
> header arguments are not tangled along with the source code.
>
> My proposal is to add an additional warning to this command, stating:
>
> """
> Warning, this command removes any lines containing constructs which
> resemble Org file links or noweb references.  It also cannot determine
> which noweb syntax is being used for any given source file, if
> :noweb-wrap was specified in the original Org file.
> """

Makes sense.
Ideally, this function should try to follow the link and lookup code
block headers, but it is already short of doing this. Improving
`org-babel-tangle-clean' is out of scope of your patch.

> +(defun org-babel-get-noweb-wrap (&optional info)
> +  "Retrieve a description the :noweb-wrap header arg from INFO.
> +
> +The description will be in the form of a list of two of strings
> +for the start and end of a reference.  INFO can be the result of
> +`org-babel-get-src-block-info' otherwise this function will parse
> +info at point."
> +  (unless info
> +    (setq info (org-babel-get-src-block-info 'no-eval)))
> +  (when-let ((raw (cdr (assq :noweb-wrap (nth 2 info)))))
> +    (let (result)
> +      (with-temp-buffer

Please, avoid creating throwaway buffers and work with strings instead.
Creating buffers (even temporary buffers) may be costly for some users
who heavily customized buffer hooks.

> +        (insert raw)
> +        (goto-char (point-min))
> +        (while (< (point) (point-max))
> +          (unless (looking-at " *\"\\([^\"]+\\)\" *")
> +            (looking-at " *\\([^ ]+\\)"))

May you please explain the rationale behind this regexp? AFAIU, it
implies that you want to allow whitespace characters inside :noweb-wrap
boundaries. But I do not think that we need to complicate things so much.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-04-11 14:03     ` Ihor Radchenko
@ 2024-04-11 18:46       ` Amy Grinn
  2024-04-13 13:17         ` Ihor Radchenko
  2024-05-11 16:01       ` Amy Grinn
  1 sibling, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-04-11 18:46 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>> +        (insert raw)
>> +        (goto-char (point-min))
>> +        (while (< (point) (point-max))
>> +          (unless (looking-at " *\"\\([^\"]+\\)\" *")
>> +            (looking-at " *\\([^ ]+\\)"))
>
> May you please explain the rationale behind this regexp? AFAIU, it
> implies that you want to allow whitespace characters inside :noweb-wrap
> boundaries. But I do not think that we need to complicate things so much.

That is exactly what I was going for.  I thought about the ways this
could be used and the most general-purpose, non-syntax-breaking,
easily-recognizable way I could think of was to use the language's
line-comment construct followed by the standard << >> characters.

# <<foo>>
;; <<bar>>
// <<baz>>

I can see how it might be harder to maintain to allow whitespace in the
noweb-wrap header arg.  I could create a separate org-parse-arg-list
function to ease that burden somewhat.  My opinion is that having the
option to use the examples above is preferable to using non-standard
wrappers, from a third-person point-of-view.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-04-11 18:46       ` Amy Grinn
@ 2024-04-13 13:17         ` Ihor Radchenko
  0 siblings, 0 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-04-13 13:17 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

>>> +        (while (< (point) (point-max))
>>> +          (unless (looking-at " *\"\\([^\"]+\\)\" *")
>>> +            (looking-at " *\\([^ ]+\\)"))
>>
>> May you please explain the rationale behind this regexp? AFAIU, it
>> implies that you want to allow whitespace characters inside :noweb-wrap
>> boundaries. But I do not think that we need to complicate things so much.
>
> That is exactly what I was going for.  I thought about the ways this
> could be used and the most general-purpose, non-syntax-breaking,
> easily-recognizable way I could think of was to use the language's
> line-comment construct followed by the standard << >> characters.
>
> # <<foo>>
> ;; <<bar>>
> // <<baz>>
>
> I can see how it might be harder to maintain to allow whitespace in the
> noweb-wrap header arg.  I could create a separate org-parse-arg-list
> function to ease that burden somewhat.  My opinion is that having the
> option to use the examples above is preferable to using non-standard
> wrappers, from a third-person point-of-view.

Makes sense. Also, see a similar idea being discussed in
https://list.orgmode.org/orgmode/87o7jlzxgn.fsf@localhost/

I recommend the following:

If the value starts from ", use Elisp's `read':
   |"# <<" ">>"
   (read (current-buffer)) ; => "# <<"
   otherwise, consider read until the first whitespace.
   |#<<; >>;
   (re-search-forward (rx (1+ (not whitespace))))
   #<<;|
   
However, there may be edge cases like

"<< >>"
"<< >>
<< << >>
<< "asd" >>

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-04-11 14:03     ` Ihor Radchenko
  2024-04-11 18:46       ` Amy Grinn
@ 2024-05-11 16:01       ` Amy Grinn
  2024-05-12 10:48         ` Ihor Radchenko
  1 sibling, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-05-11 16:01 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 454 bytes --]

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>> First of all, I would like to change (defalias) the function name
>> org-babel-noweb-wrap to org-babel-noweb-make-regexp. I think this in
>> more in line with other functions which create regular expressions.
>
> +1
> You may even use obsolete alias (add it to lisp/org-compat.el)

Here's a patch to rename org-babel-noweb-wrap to
org-babel-noweb-make-regexp.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Rename org-babel-noweb-wrap to org-babel-noweb-make-regexp --]
[-- Type: text/x-patch, Size: 5677 bytes --]

From b318fef6af8ae47b7e6d0371ccc87a01ed1a7755 Mon Sep 17 00:00:00 2001
From: Amy Grinn <grinn.amy@gmail.com>
Date: Wed, 17 Apr 2024 16:01:40 -0400
Subject: [PATCH] lisp/ob-core.el: (org-babel-noweb-wrap): renamed to
 org-babel-noweb-make-regexp

* etc/ORG-NEWS (~org-babel-noweb-wrap~ is now
~org-babel-noweb-make-regexp~): Announce the change.
* lisp/org-compat.el: Declare org-babel-noweb-wrap to be an obselete
function alias for org-babel-noweb-make-regexp.
* lisp/ob-core.el (org-babel-noweb-make-regexp): Rename the function.
(org-babel-goto-named-src-block):
(org-babel-expand-noweb-references):
* lisp/ob-exp.el (org-babel-exp-code):
* lisp/ob-tangle.el (org-babel-tangle-clean):
(org-babel-tangle-single-block): Use the new function name.
---
 etc/ORG-NEWS       | 6 ++++++
 lisp/ob-core.el    | 8 ++++----
 lisp/ob-exp.el     | 2 +-
 lisp/ob-tangle.el  | 5 +++--
 lisp/org-compat.el | 2 +-
 5 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 978882a7a..97e2f2e3f 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -1563,6 +1563,12 @@ optional argument =NEW-HEADING-CONTAINER= specifies where in the
 buffer it will be added.  If not specified, new headings are created
 at level 1 at the end of the accessible part of the buffer, as before.
 
+** Removed or renamed functions and variables
+*** ~org-babel-noweb-wrap~ is now ~org-babel-noweb-make-regexp~
+
+This is more in line with other functions that return a regular
+expression.
+
 ** Miscellaneous
 *** =org-crypt.el= now applies initial visibility settings to decrypted entries
 
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index c5dd20b0e..1518d7726 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -194,7 +194,7 @@ This string must include a \"%s\" which will be replaced by the results."
   :package-version '(Org . "9.1")
   :safe #'booleanp)
 
-(defun org-babel-noweb-wrap (&optional regexp)
+(defun org-babel-noweb-make-regexp (&optional regexp)
   "Return regexp matching a Noweb reference.
 
 Match any reference, or only those matching REGEXP, if non-nil.
@@ -1976,7 +1976,7 @@ src block, then return nil."
 		   (type (org-element-type context))
 		   (noweb-ref
 		    (and (memq type '(inline-src-block src-block))
-			 (org-in-regexp (org-babel-noweb-wrap)))))
+			 (org-in-regexp (org-babel-noweb-make-regexp)))))
 	      (cond
 	       (noweb-ref
 		(buffer-substring
@@ -3125,7 +3125,7 @@ block but are passed literally to the \"example-block\"."
                                   (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
-			     (org-babel-noweb-wrap)))))
+			     (org-babel-noweb-make-regexp)))))
     (unless (equal (cons parent-buffer
                          (with-current-buffer parent-buffer
                            (buffer-chars-modified-tick)))
@@ -3175,7 +3175,7 @@ block but are passed literally to the \"example-block\"."
 	               ((guard (or org-babel-noweb-error-all-langs
 			           (member lang org-babel-noweb-error-langs)))
 	                (error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
-		               (org-babel-noweb-wrap ,ref)))
+		               (org-babel-noweb-make-regexp ,ref)))
 	               (_ ""))))
       (replace-regexp-in-string
        noweb-re
diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index 80eaeeb27..a61b26ed5 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -419,7 +419,7 @@ replaced with its value."
   (setf (nth 1 info)
 	(if (string= "strip-export" (cdr (assq :noweb (nth 2 info))))
 	    (replace-regexp-in-string
-	     (org-babel-noweb-wrap) "" (nth 1 info))
+	     (org-babel-noweb-make-regexp) "" (nth 1 info))
 	  (if (org-babel-noweb-p (nth 2 info) :export)
 	      (org-babel-expand-noweb-references
 	       info org-babel-exp-reference-buffer)
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 79fe6448b..4427250ae 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -412,7 +412,7 @@ references."
   (interactive)
   (goto-char (point-min))
   (while (or (re-search-forward "\\[\\[file:.*\\]\\[.*\\]\\]" nil t)
-             (re-search-forward (org-babel-noweb-wrap) nil t))
+             (re-search-forward (org-babel-noweb-make-regexp) nil t))
     (delete-region (save-excursion (forward-line) (point))
                    (save-excursion (end-of-line 1) (forward-char 1) (point)))))
 
@@ -580,7 +580,8 @@ non-nil, return the full association list to be used by
 	  ;; Run the tangle-body-hook.
           (let ((body (if (org-babel-noweb-p params :tangle)
                           (if (string= "strip-tangle" (cdr (assq :noweb (nth 2 info))))
-                            (replace-regexp-in-string (org-babel-noweb-wrap) "" (nth 1 info))
+                              (replace-regexp-in-string (org-babel-noweb-make-regexp)
+                                                        "" (nth 1 info))
 			    (org-babel-expand-noweb-references info))
 			(nth 1 info))))
 	    (with-temp-buffer
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 92cad3d6e..ce46fd399 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -433,7 +433,7 @@ This is a floating point number if the size is too large for an integer."
 (define-obsolete-function-alias 'org-show-context 'org-fold-show-context "9.6")
 (define-obsolete-function-alias 'org-show-entry 'org-fold-show-entry "9.6")
 (define-obsolete-function-alias 'org-show-children 'org-fold-show-children "9.6")
-
+(define-obsolete-function-alias 'org-babel-noweb-wrap 'org-babel-noweb-make-regexp "9.7")
 
 (defmacro org-re (s)
   "Replace posix classes in regular expression S."
-- 
2.39.2


[-- Attachment #3: Type: text/plain, Size: 15 bytes --]

-- 
Best,

Amy

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-05-11 16:01       ` Amy Grinn
@ 2024-05-12 10:48         ` Ihor Radchenko
  2024-05-22 23:17           ` Amy Grinn
  0 siblings, 1 reply; 26+ messages in thread
From: Ihor Radchenko @ 2024-05-12 10:48 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

>> +1
>> You may even use obsolete alias (add it to lisp/org-compat.el)
>
> Here's a patch to rename org-babel-noweb-wrap to
> org-babel-noweb-make-regexp.

Thanks!
News entry is not necessary here - we are just renaming a function.
Otherwise, the patch looks good.
I am not yet merging it though - let's have all the patches you plan for
the new noweb-wrap argument first and then apply them together.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-05-12 10:48         ` Ihor Radchenko
@ 2024-05-22 23:17           ` Amy Grinn
  2024-05-23 11:27             ` Ihor Radchenko
  0 siblings, 1 reply; 26+ messages in thread
From: Amy Grinn @ 2024-05-22 23:17 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 2803 bytes --]

Ihor Radchenko <yantar92@posteo.net> writes:

> Amy Grinn <grinn.amy@gmail.com> writes:
>
>>> +1
>>> You may even use obsolete alias (add it to lisp/org-compat.el)
>>
>> Here's a patch to rename org-babel-noweb-wrap to
>> org-babel-noweb-make-regexp.
>
> Thanks!
> News entry is not necessary here - we are just renaming a function.
> Otherwise, the patch looks good.
> I am not yet merging it though - let's have all the patches you plan for
> the new noweb-wrap argument first and then apply them together.

Got it, not a problem!  I've attached both patches here.

Regarding the other conversation,

>>>> +        (while (< (point) (point-max))
>>>> +          (unless (looking-at " *\"\\([^\"]+\\)\" *")
>>>> +            (looking-at " *\\([^ ]+\\)"))
>>>
>>> May you please explain the rationale behind this regexp? AFAIU, it
>>> implies that you want to allow whitespace characters inside :noweb-wrap
>>> boundaries. But I do not think that we need to complicate things so much.
>>
>> That is exactly what I was going for.  I thought about the ways this
>> could be used and the most general-purpose, non-syntax-breaking,
>> easily-recognizable way I could think of was to use the language's
>> line-comment construct followed by the standard << >> characters.
>>
>> # <<foo>>
>> ;; <<bar>>
>> // <<baz>>
>>
>> I can see how it might be harder to maintain to allow whitespace in the
>> noweb-wrap header arg.  I could create a separate org-parse-arg-list
>> function to ease that burden somewhat.  My opinion is that having the
>> option to use the examples above is preferable to using non-standard
>> wrappers, from a third-person point-of-view.
>
> Makes sense. Also, see a similar idea being discussed in
> https://list.orgmode.org/orgmode/87o7jlzxgn.fsf@localhost/
>
> I recommend the following:
>
> If the value starts from ", use Elisp's `read':
>    |"# <<" ">>"
>    (read (current-buffer)) ; => "# <<"
>    otherwise, consider read until the first whitespace.
>    |#<<; >>;
>    (re-search-forward (rx (1+ (not whitespace))))
>    #<<;|
>
> However, there may be edge cases like
>
> "<< >>"
> "<< >>
> << << >>
> << "asd" >>

I didn't implement this recommendation yet; I still think the regex is a
more clear way of putting it, even without using a temporary buffer:

    ;; If a pair of " is found separated by one or more
    ;; characters, capture those characters as a group
    (unless (eq i (string-match (rx (* space) ?\"
                                    (group (+ (not ?\")))
                                    ?\" (* space))
                                raw i))
      ;; Otherwise, capture the next non-whitespace group of
      ;; characters
      (string-match (rx (* space) (group (* (not space))) (* space))
                    raw i))

Let me know what you think!

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: rename to org-babel-noweb-make-regexp --]
[-- Type: text/x-patch, Size: 4910 bytes --]

From 9442c029a7b2f1ec061e42a047b3d1bff88441d8 Mon Sep 17 00:00:00 2001
From: Amy Grinn <grinn.amy@gmail.com>
Date: Wed, 17 Apr 2024 16:01:40 -0400
Subject: [PATCH 1/2] lisp/ob-core.el: (org-babel-noweb-wrap): renamed to
 org-babel-noweb-make-regexp

* lisp/org-compat.el: Declare org-babel-noweb-wrap to be an obselete
function alias for org-babel-noweb-make-regexp.
* lisp/ob-core.el (org-babel-noweb-make-regexp): Rename the function.
(org-babel-goto-named-src-block):
(org-babel-expand-noweb-references):
* lisp/ob-exp.el (org-babel-exp-code):
* lisp/ob-tangle.el (org-babel-tangle-clean):
(org-babel-tangle-single-block): Use the new function name.
---
 lisp/ob-core.el    | 8 ++++----
 lisp/ob-exp.el     | 2 +-
 lisp/ob-tangle.el  | 5 +++--
 lisp/org-compat.el | 2 +-
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index c5dd20b0e..1518d7726 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -194,7 +194,7 @@ This string must include a \"%s\" which will be replaced by the results."
   :package-version '(Org . "9.1")
   :safe #'booleanp)
 
-(defun org-babel-noweb-wrap (&optional regexp)
+(defun org-babel-noweb-make-regexp (&optional regexp)
   "Return regexp matching a Noweb reference.
 
 Match any reference, or only those matching REGEXP, if non-nil.
@@ -1976,7 +1976,7 @@ src block, then return nil."
 		   (type (org-element-type context))
 		   (noweb-ref
 		    (and (memq type '(inline-src-block src-block))
-			 (org-in-regexp (org-babel-noweb-wrap)))))
+			 (org-in-regexp (org-babel-noweb-make-regexp)))))
 	      (cond
 	       (noweb-ref
 		(buffer-substring
@@ -3125,7 +3125,7 @@ block but are passed literally to the \"example-block\"."
                                   (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
-			     (org-babel-noweb-wrap)))))
+			     (org-babel-noweb-make-regexp)))))
     (unless (equal (cons parent-buffer
                          (with-current-buffer parent-buffer
                            (buffer-chars-modified-tick)))
@@ -3175,7 +3175,7 @@ block but are passed literally to the \"example-block\"."
 	               ((guard (or org-babel-noweb-error-all-langs
 			           (member lang org-babel-noweb-error-langs)))
 	                (error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
-		               (org-babel-noweb-wrap ,ref)))
+		               (org-babel-noweb-make-regexp ,ref)))
 	               (_ ""))))
       (replace-regexp-in-string
        noweb-re
diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index 34f12fdcc..33de7a4aa 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -418,7 +418,7 @@ replaced with its value."
   (setf (nth 1 info)
 	(if (string= "strip-export" (cdr (assq :noweb (nth 2 info))))
 	    (replace-regexp-in-string
-	     (org-babel-noweb-wrap) "" (nth 1 info))
+	     (org-babel-noweb-make-regexp) "" (nth 1 info))
 	  (if (org-babel-noweb-p (nth 2 info) :export)
 	      (org-babel-expand-noweb-references
 	       info org-babel-exp-reference-buffer)
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 79fe6448b..4427250ae 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -412,7 +412,7 @@ references."
   (interactive)
   (goto-char (point-min))
   (while (or (re-search-forward "\\[\\[file:.*\\]\\[.*\\]\\]" nil t)
-             (re-search-forward (org-babel-noweb-wrap) nil t))
+             (re-search-forward (org-babel-noweb-make-regexp) nil t))
     (delete-region (save-excursion (forward-line) (point))
                    (save-excursion (end-of-line 1) (forward-char 1) (point)))))
 
@@ -580,7 +580,8 @@ non-nil, return the full association list to be used by
 	  ;; Run the tangle-body-hook.
           (let ((body (if (org-babel-noweb-p params :tangle)
                           (if (string= "strip-tangle" (cdr (assq :noweb (nth 2 info))))
-                            (replace-regexp-in-string (org-babel-noweb-wrap) "" (nth 1 info))
+                              (replace-regexp-in-string (org-babel-noweb-make-regexp)
+                                                        "" (nth 1 info))
 			    (org-babel-expand-noweb-references info))
 			(nth 1 info))))
 	    (with-temp-buffer
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 92cad3d6e..ce46fd399 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -433,7 +433,7 @@ This is a floating point number if the size is too large for an integer."
 (define-obsolete-function-alias 'org-show-context 'org-fold-show-context "9.6")
 (define-obsolete-function-alias 'org-show-entry 'org-fold-show-entry "9.6")
 (define-obsolete-function-alias 'org-show-children 'org-fold-show-children "9.6")
-
+(define-obsolete-function-alias 'org-babel-noweb-wrap 'org-babel-noweb-make-regexp "9.7")
 
 (defmacro org-re (s)
   "Replace posix classes in regular expression S."
-- 
2.39.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: new header argument :noweb-wrap --]
[-- Type: text/x-patch, Size: 13399 bytes --]

From aad9b3926c711dfed411e2f439ae8b0fe3db7d10 Mon Sep 17 00:00:00 2001
From: Amy Grinn <grinn.amy@gmail.com>
Date: Wed, 17 Apr 2024 16:56:37 -0400
Subject: [PATCH 2/2] org-babel: New header argument :noweb-wrap

* lisp/ob-core.el (org-babel-get-noweb-wrap): New API function that
parses the :noweb-wrap parameter of a babel src block.
(org-babel-noweb-make-regexp): Add a new optional parameter 'wrap' to
control how noweb references are wrapped.
(org-babel-goto-named-src-block):
(org-babel-expand-noweb-references):
* lisp/ob-exp.el (org-babel-exp-code):
* lisp/ob-tangle.el (org-babel-tangle-single-block): Use the new
org-babel-get-noweb-wrap function as the new optional parameter to
org-babel-noweb-make-regexp.
* lisp/ob-tangle.el (org-babel-tangle-clean): Add an additional
warning about not being able to resolve noweb references if :noweb
wrap was specified.
* etc/ORG-NEWS (New =:noweb-wrap= babel header argument): Describe new
argument.
* testing/examples/babel.org:
* testing/lisp/test-ob-exp.el:
* testing/lisp/test-ob.el: Add tests which use alternate wrapping
syntax for noweb references.
---
 etc/ORG-NEWS                | 14 +++++++++
 lisp/ob-core.el             | 57 +++++++++++++++++++++++++++++++------
 lisp/ob-exp.el              |  3 +-
 lisp/ob-tangle.el           | 12 +++++---
 testing/examples/babel.org  | 17 +++++++++++
 testing/lisp/test-ob-exp.el | 55 +++++++++++++++++++++++++++++++++++
 testing/lisp/test-ob.el     | 32 +++++++++++++++++++++
 7 files changed, 176 insertions(+), 14 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 585b2b262..e1fb95744 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -589,6 +589,20 @@ Org mode provides 3 possible values for ~org-sort-function~:
    and on MacOS.
 3. Custom function, if the above does not fit the needs.
 
+*** New =:noweb-wrap= babel header argument
+
+This argument changes the default noweb reference syntax by masking
+the options ~org-babel-noweb-wrap-start~ and
+~org-babel-noweb-wrap-end~.
+
+=:noweb-wrap= takes two parameters, start and end, corresponding to
+each option.
+
+For example:
+: #+begin_src sh :noweb-wrap <<< >>>
+:   echo <<<message>>>
+: #+end_src
+
 *** =ob-latex= now uses a new option ~org-babel-latex-process-alist~ to generate png output
 
 Previously, =ob-latex= used ~org-preview-latex-default-process~ from
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 1518d7726..4f286c64c 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -194,15 +194,21 @@ This string must include a \"%s\" which will be replaced by the results."
   :package-version '(Org . "9.1")
   :safe #'booleanp)
 
-(defun org-babel-noweb-make-regexp (&optional regexp)
+(defun org-babel-noweb-make-regexp (&optional regexp wrap)
   "Return regexp matching a Noweb reference.
 
 Match any reference, or only those matching REGEXP, if non-nil.
 
+If WRAP is provided, it should be a list of 2 strings describing
+the start and end of a noweb reference, such as that returned by
+`org-babel-get-noweb-wrap'.  Otherwise
+`org-babel-noweb-wrap-start' and `org-babel-noweb-wrap-end' will
+be used.
+
 When matching, reference is stored in match group 1."
-  (concat (regexp-quote org-babel-noweb-wrap-start)
-	  (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
-	  (regexp-quote org-babel-noweb-wrap-end)))
+  (concat (regexp-quote (or (car wrap) org-babel-noweb-wrap-start))
+	    (or regexp "\\([^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
+	    (regexp-quote (or (cadr wrap) org-babel-noweb-wrap-end))))
 
 (defvar org-babel-src-name-regexp
   "^[ \t]*#\\+name:[ \t]*"
@@ -1963,6 +1969,33 @@ src block, then return nil."
   (let ((head (org-babel-where-is-src-block-head)))
     (if head (goto-char head) (error "Not currently in a code block"))))
 
+(defun org-babel-get-noweb-wrap (&optional info)
+  "Retrieve a description the :noweb-wrap header arg from INFO.
+
+The description will be in the form of a list of two of strings
+for the start and end of a reference.  INFO can be the result of
+`org-babel-get-src-block-info' otherwise this function will parse
+info at point."
+  (unless info
+    (setq info (org-babel-get-src-block-info 'no-eval)))
+  (when-let* ((raw (cdr (assq :noweb-wrap (nth 2 info))))
+              (len (length raw)))
+    (let ((i 0) result)
+      (while (< i len)
+        ;; If a pair of " is found separated by one or more
+        ;; characters, capture those characters as a group
+        (unless (eq i (string-match (rx (* space) ?\"
+                                        (group (+ (not ?\")))
+                                        ?\" (* space))
+                                    raw i))
+          ;; Otherwise, capture the next non-whitespace group of
+          ;; characters
+          (string-match (rx (* space) (group (* (not space))) (* space))
+                        raw i))
+        (setq i (match-end 0))
+        (push (match-string 1 raw) result))
+      (reverse result))))
+
 ;;;###autoload
 (defun org-babel-goto-named-src-block (name)
   "Go to a source-code block with NAME."
@@ -1974,14 +2007,18 @@ src block, then return nil."
 	    "source-block name: " all-block-names nil t
 	    (let* ((context (org-element-context))
 		   (type (org-element-type context))
+                   (noweb-wrap (org-babel-get-noweb-wrap))
 		   (noweb-ref
 		    (and (memq type '(inline-src-block src-block))
-			 (org-in-regexp (org-babel-noweb-make-regexp)))))
+			 (org-in-regexp (org-babel-noweb-make-regexp
+                                         nil noweb-wrap)))))
 	      (cond
 	       (noweb-ref
 		(buffer-substring
-		 (+ (car noweb-ref) (length org-babel-noweb-wrap-start))
-		 (- (cdr noweb-ref) (length org-babel-noweb-wrap-end))))
+		 (+ (car noweb-ref) (length (or (car noweb-wrap)
+                                                org-babel-noweb-wrap-start)))
+		 (- (cdr noweb-ref) (length (or (cadr noweb-wrap)
+                                                org-babel-noweb-wrap-end)))))
 	       ((memq type '(babel-call inline-babel-call)) ;#+CALL:
 		(org-element-property :call context))
 	       ((car (org-element-property :results context))) ;#+RESULTS:
@@ -3125,7 +3162,8 @@ block but are passed literally to the \"example-block\"."
                                   (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
-			     (org-babel-noweb-make-regexp)))))
+			     (org-babel-noweb-make-regexp
+                              nil (org-babel-get-noweb-wrap info))))))
     (unless (equal (cons parent-buffer
                          (with-current-buffer parent-buffer
                            (buffer-chars-modified-tick)))
@@ -3175,7 +3213,8 @@ block but are passed literally to the \"example-block\"."
 	               ((guard (or org-babel-noweb-error-all-langs
 			           (member lang org-babel-noweb-error-langs)))
 	                (error "Cannot resolve %s (see `org-babel-noweb-error-langs')"
-		               (org-babel-noweb-make-regexp ,ref)))
+		               (org-babel-noweb-make-regexp
+                                ,ref (org-babel-get-noweb-wrap))))
 	               (_ ""))))
       (replace-regexp-in-string
        noweb-re
diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el
index 33de7a4aa..14a32a8e6 100644
--- a/lisp/ob-exp.el
+++ b/lisp/ob-exp.el
@@ -418,7 +418,8 @@ replaced with its value."
   (setf (nth 1 info)
 	(if (string= "strip-export" (cdr (assq :noweb (nth 2 info))))
 	    (replace-regexp-in-string
-	     (org-babel-noweb-make-regexp) "" (nth 1 info))
+	     (org-babel-noweb-make-regexp nil (org-babel-get-noweb-wrap info))
+             "" (nth 1 info))
 	  (if (org-babel-noweb-p (nth 2 info) :export)
 	      (org-babel-expand-noweb-references
 	       info org-babel-exp-reference-buffer)
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 4427250ae..5fcb40443 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -406,9 +406,11 @@ Did you give the decimal value %1$d by mistake?" mode)))
   "Remove comments inserted by `org-babel-tangle'.
 Call this function inside of a source-code file generated by
 `org-babel-tangle' to remove all comments inserted automatically
-by `org-babel-tangle'.  Warning, this comment removes any lines
+by `org-babel-tangle'.  Warning, this command removes any lines
 containing constructs which resemble Org file links or noweb
-references."
+references.  It also cannot determine which noweb syntax is being
+used for any given source file, if :noweb-wrap was specified in
+the original Org file."
   (interactive)
   (goto-char (point-min))
   (while (or (re-search-forward "\\[\\[file:.*\\]\\[.*\\]\\]" nil t)
@@ -580,8 +582,10 @@ non-nil, return the full association list to be used by
 	  ;; Run the tangle-body-hook.
           (let ((body (if (org-babel-noweb-p params :tangle)
                           (if (string= "strip-tangle" (cdr (assq :noweb (nth 2 info))))
-                              (replace-regexp-in-string (org-babel-noweb-make-regexp)
-                                                        "" (nth 1 info))
+                              (replace-regexp-in-string
+			       (org-babel-noweb-make-regexp
+				nil (org-babel-get-noweb-wrap info))
+			       "" (nth 1 info))
 			    (org-babel-expand-noweb-references info))
 			(nth 1 info))))
 	    (with-temp-buffer
diff --git a/testing/examples/babel.org b/testing/examples/babel.org
index d46afeb5e..680d4bf3e 100644
--- a/testing/examples/babel.org
+++ b/testing/examples/babel.org
@@ -346,6 +346,23 @@ Here is a call line with more than just the results exported.
   echo "1$i"
 #+END_SRC
 
+* strip noweb references with alternative wrap
+  :PROPERTIES:
+  :ID:       da9bcfdd-c1bd-47b4-b520-67974b9f9856
+  :END:
+
+#+name: strip-export-2
+#+BEGIN_SRC sh :exports none
+  i="10"
+#+END_SRC
+
+#+RESULTS: strip-export-2
+
+#+BEGIN_SRC sh :noweb strip-export :noweb-wrap #[[ ]] :exports code :results silent
+  #[[strip-export-2]]
+  echo "1$i"
+#+END_SRC
+
 * use case of reading entry properties
   :PROPERTIES:
   :ID:       cc5fbc20-bca5-437a-a7b8-2b4d7a03f820
diff --git a/testing/lisp/test-ob-exp.el b/testing/lisp/test-ob-exp.el
index d029dadfb..abfda4368 100644
--- a/testing/lisp/test-ob-exp.el
+++ b/testing/lisp/test-ob-exp.el
@@ -394,6 +394,61 @@ be evaluated."
 		 (regexp-quote " :foo  :bar \n")
 		 ascii))))))
 
+(ert-deftest ob-exp/noweb-wrap-header-arg ()
+  (let ((org-export-use-babel t))
+    (org-test-with-temp-text
+	"
+#+Title: exporting from a temporary buffer
+
+#+name: foo
+#+BEGIN_SRC emacs-lisp
+  :foo
+#+END_SRC
+
+#+BEGIN_SRC emacs-lisp :noweb yes :noweb-wrap {{ }} :exports results
+  (list {{foo}})
+#+END_SRC
+"
+      (let* ((ascii (org-export-as 'ascii)))
+	(should (string-match
+		 (regexp-quote " :foo \n")
+		 ascii))))))
+
+(ert-deftest ob-exp/noweb-strip-export-with-wrap ()
+  (org-test-at-id "da9bcfdd-c1bd-47b4-b520-67974b9f9856"
+    (org-narrow-to-subtree)
+    (org-babel-next-src-block 1)
+    (org-babel-execute-src-block)
+    (let ((result (org-test-with-expanded-babel-code (buffer-string))))
+      (should-not (string-match (regexp-quote "#[[strip-export-2]]") result))
+      (should-not (string-match (regexp-quote "i=\"10\"") result)))))
+
+(ert-deftest ob-exp/noweb-wrap-strip-export ()
+  (let ((org-export-use-babel t))
+    (org-test-with-temp-text
+	"
+#+Title: exporting from a temporary buffer
+
+#+name: foo
+#+BEGIN_SRC emacs-lisp
+  :foo
+#+END_SRC
+
+#+name: bar
+#+BEGIN_SRC emacs-lisp
+  :bar
+#+END_SRC
+
+#+BEGIN_SRC emacs-lisp :noweb yes :noweb-wrap {{ }} :exports results
+  (list {{foo}} {{bar}})
+#+END_SRC
+"
+      (let* ((ascii (org-export-as 'ascii)))
+        
+	(should (string-match
+		 (regexp-quote ":foo  :bar")
+		 ascii))))))
+
 (ert-deftest ob-export/export-with-results-before-block ()
   "Test export when results are inserted before source block."
   (let ((org-export-use-babel t))
diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el
index 544e68267..b0051d2a2 100644
--- a/testing/lisp/test-ob.el
+++ b/testing/lisp/test-ob.el
@@ -988,6 +988,38 @@ x
             (search-forward "begin_src")
             (org-babel-expand-noweb-references)))))
 
+(ert-deftest test-ob/noweb-wrap ()
+  ;; Standard test.
+  (should
+   (string=
+    "bar"
+    (org-test-with-temp-text "#+begin_src sh :results output :tangle yes :noweb-wrap <<< >>>
+  <<<foo>>>
+#+end_src
+
+#+name: foo
+#+begin_src sh
+  bar
+#+end_src"
+        (org-babel-expand-noweb-references)))))
+
+(ert-deftest test-ob/get-noweb-wrap ()
+  (should (equal '("<< >>")
+                 (org-babel-get-noweb-wrap
+                  '(nil nil ((:noweb-wrap . "\"<< >>\""))))))
+  (should (equal '("\"<<" ">>")
+                 (org-babel-get-noweb-wrap
+                  '(nil nil ((:noweb-wrap . "\"<< >>"))))))
+  (should (equal '("<<" "<<" ">>")
+                 (org-babel-get-noweb-wrap
+                  '(nil nil ((:noweb-wrap . "<< << >>"))))))
+  (should (equal '("<<" "asd" ">>")
+                 (org-babel-get-noweb-wrap
+                  '(nil nil ((:noweb-wrap . "<< \"asd\" >>"))))))
+  (should (equal '("\"\"\"" ">>>")
+                 (org-babel-get-noweb-wrap
+                  '(nil nil ((:noweb-wrap . "\"\"\" >>>")))))))
+
 (ert-deftest test-ob/splitting-variable-lists-in-references ()
   (org-test-with-temp-text ""
     (should (= 1 (length (org-babel-ref-split-args
-- 
2.39.2


[-- Attachment #4: Type: text/plain, Size: 14 bytes --]

--
Best,

Amy

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-05-22 23:17           ` Amy Grinn
@ 2024-05-23 11:27             ` Ihor Radchenko
  2024-07-01  9:56               ` Ihor Radchenko
  2024-12-08 10:20               ` Ihor Radchenko
  0 siblings, 2 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-05-23 11:27 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Amy Grinn <grinn.amy@gmail.com> writes:

>> I recommend the following:
>>
>> If the value starts from ", use Elisp's `read':
>>    |"# <<" ">>"
>>    (read (current-buffer)) ; => "# <<"
>>    otherwise, consider read until the first whitespace.
>>    |#<<; >>;
>>    (re-search-forward (rx (1+ (not whitespace))))
>>    #<<;|
>>
>> However, there may be edge cases like
>>
>> "<< >>"
>> "<< >>
>> << << >>
>> << "asd" >>
>
> I didn't implement this recommendation yet; I still think the regex is a
> more clear way of putting it, even without using a temporary buffer:
>
>     ;; If a pair of " is found separated by one or more
>     ;; characters, capture those characters as a group
>     (unless (eq i (string-match (rx (* space) ?\"
>                                     (group (+ (not ?\")))
>                                     ?\" (* space))
>                                 raw i))
>       ;; Otherwise, capture the next non-whitespace group of
>       ;; characters
>       (string-match (rx (* space) (group (* (not space))) (* space))
>                     raw i))
>
> Let me know what you think!

Consider cases like

"< \"" "\" >"

or

"< >"

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-05-23 11:27             ` Ihor Radchenko
@ 2024-07-01  9:56               ` Ihor Radchenko
  2024-12-08 10:20               ` Ihor Radchenko
  1 sibling, 0 replies; 26+ messages in thread
From: Ihor Radchenko @ 2024-07-01  9:56 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

>> Let me know what you think!
>
> Consider cases like
> ...

It has been over a month since the last message in this thread.
Amy, may I know if you are still working on the patch?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-05-23 11:27             ` Ihor Radchenko
  2024-07-01  9:56               ` Ihor Radchenko
@ 2024-12-08 10:20               ` Ihor Radchenko
  2024-12-10 15:28                 ` Suhail Singh
  1 sibling, 1 reply; 26+ messages in thread
From: Ihor Radchenko @ 2024-12-08 10:20 UTC (permalink / raw)
  To: Amy Grinn; +Cc: emacs-orgmode


Ihor Radchenko <yantar92@posteo.net> writes:
> Amy Grinn <grinn.amy@gmail.com> writes:
>
>>> I recommend the following:
>>>
>>> If the value starts from ", use Elisp's `read':
>>>    |"# <<" ">>"
>>>    (read (current-buffer)) ; => "# <<"
>>>    otherwise, consider read until the first whitespace.
>>>    |#<<; >>;
>>>    (re-search-forward (rx (1+ (not whitespace))))
>>>    #<<;|
>>>
>>> However, there may be edge cases like
> ...

Thinking about this more in the context of the past meetup discussion,
maybe we can just go with two header arguments? :noweb-start :noweb-end?
Or, alternatively, we can use a single string and a placeholder for the
noweb reference name. Something like :noweb-wrap "# <<%s>>"

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FR] :noweb-wrap header arg
  2024-12-08 10:20               ` Ihor Radchenko
@ 2024-12-10 15:28                 ` Suhail Singh
  0 siblings, 0 replies; 26+ messages in thread
From: Suhail Singh @ 2024-12-10 15:28 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Amy Grinn, emacs-orgmode

Ihor Radchenko <yantar92@posteo.net> writes:

> Thinking about this more in the context of the past meetup discussion,
> maybe we can just go with two header arguments? :noweb-start :noweb-end?
> Or, alternatively, we can use a single string and a placeholder for the
> noweb reference name. Something like :noweb-wrap "# <<%s>>"

FWIW, IMO, if the goal is for :noweb-start to always be provided with
:noweb-end (and vice-versa), it would be better to use a format-string
like approach, i.e., a single :noweb-wrap.

-- 
Suhail


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2024-12-10 18:37 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-05 19:22 noweb-start and noweb-end header args Amy Grinn
2024-03-05 22:41 ` termux
2024-03-06 11:21 ` Ihor Radchenko
2024-03-06 11:40   ` Amy Grinn
2024-03-06 11:47     ` Ihor Radchenko
2024-03-06 12:05       ` Amy Grinn
2024-03-06 13:33         ` Ihor Radchenko
2024-03-06 16:04           ` Amy Grinn
2024-03-07 13:50             ` Ihor Radchenko
2024-03-06 23:07     ` Amy Grinn
2024-03-07 13:58       ` Ihor Radchenko
2024-03-07 14:33         ` Amy Grinn
2024-03-07 14:49           ` Ihor Radchenko
2024-03-07 14:04 ` Ihor Radchenko
2024-03-07 15:06   ` Amy Grinn
2024-04-08 14:04   ` [FR] :noweb-wrap header arg Amy Grinn
2024-04-11 14:03     ` Ihor Radchenko
2024-04-11 18:46       ` Amy Grinn
2024-04-13 13:17         ` Ihor Radchenko
2024-05-11 16:01       ` Amy Grinn
2024-05-12 10:48         ` Ihor Radchenko
2024-05-22 23:17           ` Amy Grinn
2024-05-23 11:27             ` Ihor Radchenko
2024-07-01  9:56               ` Ihor Radchenko
2024-12-08 10:20               ` Ihor Radchenko
2024-12-10 15:28                 ` Suhail Singh

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).