emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
@ 2022-01-15 10:42 Sébastien Miquel
  2022-04-28 13:45 ` Ihor Radchenko
  0 siblings, 1 reply; 17+ messages in thread
From: Sébastien Miquel @ 2022-01-15 10:42 UTC (permalink / raw)
  To: emacs-orgmode

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

Hi,

The attached patch adds support for two new babel header arguments:
=:noweb-prefix= and =:noweb-trans=.

=:noweb-prefix= can be set to =no= to disable the noweb prefix
behaviour, where prefix characters are repeated when expanding a
multiline noweb reference.

=:noweb-trans= can be set to =prin1-to-string= to insert a lisp string
representing the content of the referenced src block.

The goal is to allow one to use, say, a LaTeX src block to represent
some LaTeX snippet to be tangled into a string in some lisp (or other)
code. This isn't possible currently, and one has to manually string
escape the LaTeX code.

As an example, the following two blocks

#+BEGIN_SRC LaTeX :tangle no :noweb-ref nw
\usepackage{…}
\usepackage{…}
#+END_SRC

#+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no 
:noweb-trans prin1-to-string
(setq latex-header <<nw>>)
#+END_SRC

would tangle to

#+BEGIN_SRC emacs-lisp
(setq latex-header "\\usepackage{…}
\\usepackage{…}")
#+END_SRC

I've left undocumented the possibility of setting =:noweb-trans= to
another function. I wonder if anyone can think of some other use.

Regards,

-- 
Sébastien Miquel

[-- Attachment #2: 0001-ob-core.el-Add-noweb-prefix-noweb-trans-babel-header.patch --]
[-- Type: text/x-patch, Size: 5996 bytes --]

From 66f271225767d07e12bcc73a1ddbadf038d245fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Miquel?= <sebastien.miquel@posteo.eu>
Date: Mon, 6 Sep 2021 18:45:42 +0200
Subject: [PATCH] ob-core.el: Add `:noweb-prefix`, `:noweb-trans` babel header
 arguments

* lisp/ob-core.el (org-babel-expand-noweb-references): Add support for
`noweb-prefix' header argument, to not repeat the prefix characters
when expanding a noweb reference. Add support for `noweb-trans' header
argument, to apply a function to the noweb content upon
expansion.
(org-babel-common-header-args-w-values):
(org-babel-safe-header-args): Add `noweb-prefix' and `noweb-trans' values.
* doc/org-manual.org: Document `noweb-prefix' and `noweb-trans' babel header
arguments.
* etc/NEWS: Document `:noweb-prefix' and `:noweb-trans'.
---
 doc/org-manual.org | 34 ++++++++++++++++++++++++++++++----
 etc/ORG-NEWS       |  9 +++++++++
 lisp/ob-core.el    | 26 ++++++++++++++++++++------
 3 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index b4c20f252..d7b1c4203 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -18554,10 +18554,11 @@ Note that the expansion now contains the results of the code block
 : 100
 
 Noweb insertions honor prefix characters that appear before the noweb
-syntax reference.  This behavior is illustrated in the following
-example.  Because the =<<example>>= noweb reference appears behind the
-SQL comment syntax, each line of the expanded noweb reference is
-commented.  With:
+syntax reference. This behavior can be turned off by setting the
+=noweb-prefix= header argument to =no= and is illustrated in the
+following example. Because the =<<example>>= noweb reference appears
+behind the SQL comment syntax, each line of the expanded noweb
+reference is commented. With:
 
 #+begin_example
 ,#+NAME: example
@@ -18626,6 +18627,31 @@ else:
     print('do things when false')
 #+end_example
 
+The header argument =noweb-trans= can be set to =prin1-to-string= to
+insert a lisp string representing the content of the referenced src
+block. With:
+
+#+begin_example
+,#+NAME: latex-header
+,#+BEGIN_SRC latex
+  \usepackage{amsmath}
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+this code block:
+
+#+begin_example
+,#+BEGIN_SRC elisp :noweb yes
+  (setq header <<latex-header>>)
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+expands to:
+
+: (setq header "\\usepackage{amsmath}")
+
 When in doubt about the outcome of a source code block expansion, you
 can preview the results with the following command:
 
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 335db4139..6fa808645 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -63,6 +63,15 @@ list of various table options (between brackets in LaTeX export),
 since certain tabular environments, such as longtblr of the
 tabularray LaTeX package, provides this structure.
 
+*** New =:noweb-prefix= and =:noweb-trans= babel header arguments
+
+=:noweb-prefix= can be set to =no= to prevent the prefix characters
+from being repeated when expanding a multiline noweb reference.
+
+=:noweb-trans= can be set to =prin1-to-string=. Noweb reference
+therein will be expanded to an elisp string representation of their
+content.
+
 ** New functions and changes in function arguments
 
 *** New function ~org-element-cache-map~ for quick mapping across Org elements
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 239a57f96..1d5d1bedc 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -411,6 +411,8 @@ then run `org-babel-switch-to-session'."
     (noweb	. ((yes no tangle no-export strip-export)))
     (noweb-ref	. :any)
     (noweb-sep  . :any)
+    (noweb-prefix . ((no yes)))
+    (noweb-trans  . ((prin1-to-string)))
     (output-dir . :any)
     (padline	. ((yes no)))
     (post       . :any)
@@ -436,9 +438,10 @@ specific header arguments as well.")
 
 (defconst org-babel-safe-header-args
   '(:cache :colnames :comments :exports :epilogue :hlines :noeval
-	   :noweb :noweb-ref :noweb-sep :padline :prologue :rownames
-	   :sep :session :tangle :wrap
+	   :noweb :noweb-ref :noweb-sep :noweb-prefix :padline
+           :prologue :rownames :sep :session :tangle :wrap
 	   (:eval . ("never" "query"))
+           (:noweb-trans . ("prin1-to-string"))
 	   (:results . (lambda (str) (not (string-match "file" str)))))
   "A list of safe header arguments for babel source blocks.
 
@@ -2825,6 +2828,12 @@ block but are passed literally to the \"example-block\"."
          (lang (nth 0 info))
          (body (nth 1 info))
 	 (comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
+	 (noweb-trans (when (cdr (assq :noweb-trans (nth 2 info)))
+                        (intern (cdr (assq :noweb-trans (nth 2 info))))))
+         (noweb-prefix (let ((v (assq :noweb-prefix (nth 2 info))))
+                         (or (not v)
+                             (and (org-not-nil (cdr v))
+                                  (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
 			     (org-babel-noweb-wrap))))
@@ -2919,11 +2928,16 @@ block but are passed literally to the \"example-block\"."
 			  (let* ((info (org-babel-get-src-block-info t))
 				 (ref (cdr (assq :noweb-ref (nth 2 info)))))
 			    (push info (gethash ref cache))))))
-		     (funcall expand-references id cache)))))
+		     (funcall expand-references id cache))))
+                  (expansion (if (functionp noweb-trans)
+                                 (funcall noweb-trans expansion)
+                               expansion)))
 	     ;; Interpose PREFIX between every line.
-	     (mapconcat #'identity
-			(split-string expansion "[\n\r]")
-			(concat "\n" prefix))))))
+	     (if noweb-prefix
+                 (mapconcat #'identity
+			    (split-string expansion "[\n\r]")
+			    (concat "\n" prefix))
+               expansion)))))
      body t t 2)))
 
 (defun org-babel--script-escape-inner (str)
-- 
2.34.1


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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-01-15 10:42 [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments Sébastien Miquel
@ 2022-04-28 13:45 ` Ihor Radchenko
  2022-04-29 14:27   ` Sébastien Miquel
  0 siblings, 1 reply; 17+ messages in thread
From: Ihor Radchenko @ 2022-04-28 13:45 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

> The attached patch adds support for two new babel header arguments:
> =:noweb-prefix= and =:noweb-trans=.
>
> =:noweb-prefix= can be set to =no= to disable the noweb prefix
> behaviour, where prefix characters are repeated when expanding a
> multiline noweb reference.

Thanks for the patch! The idea about :noweb-prefix looks useful.

> =:noweb-trans= can be set to =prin1-to-string= to insert a lisp string
> representing the content of the referenced src block.
>
> The goal is to allow one to use, say, a LaTeX src block to represent
> some LaTeX snippet to be tangled into a string in some lisp (or other)
> code. This isn't possible currently, and one has to manually string
> escape the LaTeX code.
> ...
> I've left undocumented the possibility of setting =:noweb-trans= to
> another function. I wonder if anyone can think of some other use.

prin1-to-string is too specific and only solves a single use-case.

Consider the following example:

#+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no :noweb-trans prin1-to-string
<<preamble>>
(setq latex-header <<nw>>)
#+END_SRC

There are two noweb references here. Setting source block-wide
:noweb-trans is not helpful because the first reference will be
incorrectly filtered through prin1-to-string.

I'd rather introduce a new syntax to transform the noweb reference
inline. Something like

#+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no
<<preamble>>
(setq latex-header <<(prin1-to-string nw)>>)
#+END_SRC

>  Noweb insertions honor prefix characters that appear before the noweb
> -syntax reference.  This behavior is illustrated in the following
> -example.  Because the =<<example>>= noweb reference appears behind the
> -SQL comment syntax, each line of the expanded noweb reference is
> -commented.  With:
> +syntax reference. This behavior can be turned off by setting the
> +=noweb-prefix= header argument to =no= and is illustrated in the
> +following example. Because the =<<example>>= noweb reference appears
> +behind the SQL comment syntax, each line of the expanded noweb
> +reference is commented. With:

This sounds a bit confusing. I would also add an example where it is
useful to set :noweb-prefix to no.
  
Best,
Ihor


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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-04-28 13:45 ` Ihor Radchenko
@ 2022-04-29 14:27   ` Sébastien Miquel
  2022-04-30  6:05     ` Ihor Radchenko
  0 siblings, 1 reply; 17+ messages in thread
From: Sébastien Miquel @ 2022-04-29 14:27 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode


[-- Attachment #1.1: Type: text/plain, Size: 1788 bytes --]

Hi,

Ihor Radchenko writes:
> prin1-to-string is too specific and only solves a single use-case.
prin1-to-string is actually universal in a way, since any other
manipulation can then be achieved with

: (setq var (do-something <<nw>>))

at least as long as you're tangling to a programming language, that
can read lisp strings.
> Consider the following example:
>
> #+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no :noweb-trans prin1-to-string
> <<preamble>>
> (setq latex-header <<nw>>)
> #+END_SRC
>
> There are two noweb references here. Setting source block-wide
> :noweb-trans is not helpful because the first reference will be
> incorrectly filtered through prin1-to-string.
Indeed. Originally I had thought of adding a new syntax <<"nw">> to
insert a string representation. I've attached a new patch, that does
this instead of introducing :noweb-trans. Now that I think of the
universality of prin1-to-string, I actually like it slightly better
than :noweb-trans. It would break existing "nw"-like noweb references.

Of course, one can work around this easily enough by using two blocks.
> I'd rather introduce a new syntax to transform the noweb reference
> inline. Something like
>
> #+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no
> <<preamble>>
> (setq latex-header <<(prin1-to-string nw)>>)
> #+END_SRC
You'd need to only allow a single function call with only one
argument, or use something like <<(prin1-to-string <<nw>>)>>. The
change would be much more complex than what I propose, for maybe
little benefit.
>> [...]
> This sounds a bit confusing. I would also add an example where it is
> useful to set :noweb-prefix to no.

I've added such an example in the revised patch attached.

Thanks for the feedback.

Regards,

-- 
Sébastien Miquel

[-- Attachment #1.2: Type: text/html, Size: 3394 bytes --]

[-- Attachment #2: 0001-ob-core.el-Add-noweb-prefix-noweb-trans-babel-header.patch --]
[-- Type: text/x-patch, Size: 6090 bytes --]

From 99d043b9d837a2658e60fb4b4913454d9566519b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Miquel?= <sebastien.miquel@posteo.eu>
Date: Mon, 6 Sep 2021 18:45:42 +0200
Subject: [PATCH] ob-core.el: Add `:noweb-prefix`, `:noweb-trans` babel header
 arguments

* lisp/ob-core.el (org-babel-expand-noweb-references): Add support for
`noweb-prefix' header argument, to not repeat the prefix characters
when expanding a noweb reference. Add support for `noweb-trans' header
argument, to apply a function to the noweb content upon
expansion.
(org-babel-common-header-args-w-values):
(org-babel-safe-header-args): Add `noweb-prefix' and `noweb-trans' values.
* doc/org-manual.org: Document `noweb-prefix' and `noweb-trans' babel header
arguments.
* etc/ORG-NEWS: Document `:noweb-prefix' and `:noweb-trans'.
---
 doc/org-manual.org | 42 ++++++++++++++++++++++++++++++++++++++++++
 etc/ORG-NEWS       | 10 +++++++++-
 lisp/ob-core.el    | 26 ++++++++++++++++++++------
 3 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index 6768ca98d..5ef8e2f8b 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -18760,6 +18760,48 @@ else:
     print('do things when false')
 #+end_example
 
+This prefix behavior can be turned off in a block by setting the
+=noweb-prefix= header argument to =no=, as in:
+
+#+begin_example
+,#+BEGIN_SRC elisp :noweb-prefix no
+  (setq example-data "<<example>>")
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+which expands to:
+
+#+begin_example
+(setq example-data "this is the
+multi-line body of example")
+#+end_example
+
+The header argument =noweb-trans= can be set to =prin1-to-string= to
+insert a lisp string representing the content of the referenced src
+block. With:
+
+#+begin_example
+,#+NAME: latex-header
+,#+BEGIN_SRC latex
+  \usepackage{amsmath}
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+this code block:
+
+#+begin_example
+,#+BEGIN_SRC elisp :noweb yes :noweb-trans prin1-to-string
+  (setq header <<latex-header>>)
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+expands to:
+
+: (setq header "\\usepackage{amsmath}")
+
 When in doubt about the outcome of a source code block expansion, you
 can preview the results with the following command:
 
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 2b539d305..70f7606db 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -150,7 +150,7 @@ The entry points are ~org-persist-register~, ~org-persist-unregister~,
 ~org-persist-read~, and ~org-persist-read-all~.  Storing circular
 structures is supported.  Storing references between different
 variables is also supported (see =:inherit= key in
-~org-persist-register~).  
+~org-persist-register~).
 
 The library permits storing buffer-local variables.  Such variables
 are linked to the buffer text, file =inode=, and file path.
@@ -175,6 +175,14 @@ the =compact-itemx= export option, or globally using the
 Items in a description list that begin with =Function:=, =Variable:=
 or certain related prefixes are converted using Texinfo definition
 commands.
+*** New =:noweb-prefix= and =:noweb-trans= babel header arguments
+
+=:noweb-prefix= can be set to =no= to prevent the prefix characters
+from being repeated when expanding a multiline noweb reference.
+
+=:noweb-trans= can be set to =prin1-to-string=. Noweb reference
+therein will be expanded to an elisp string representation of their
+content.
 
 ** New functions and changes in function arguments
 
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 6590eeee7..b5fb68661 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -413,6 +413,8 @@ then run `org-babel-switch-to-session'."
     (noweb	. ((yes no tangle no-export strip-export)))
     (noweb-ref	. :any)
     (noweb-sep  . :any)
+    (noweb-prefix . ((no yes)))
+    (noweb-trans  . ((prin1-to-string)))
     (output-dir . :any)
     (padline	. ((yes no)))
     (post       . :any)
@@ -438,9 +440,10 @@ specific header arguments as well.")
 
 (defconst org-babel-safe-header-args
   '(:cache :colnames :comments :exports :epilogue :hlines :noeval
-	   :noweb :noweb-ref :noweb-sep :padline :prologue :rownames
-	   :sep :session :tangle :wrap
+	   :noweb :noweb-ref :noweb-sep :noweb-prefix :padline
+           :prologue :rownames :sep :session :tangle :wrap
 	   (:eval . ("never" "query"))
+           (:noweb-trans . ("prin1-to-string"))
 	   (:results . (lambda (str) (not (string-match "file" str)))))
   "A list of safe header arguments for babel source blocks.
 
@@ -2827,6 +2830,12 @@ block but are passed literally to the \"example-block\"."
          (lang (nth 0 info))
          (body (nth 1 info))
 	 (comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
+	 (noweb-trans (when (cdr (assq :noweb-trans (nth 2 info)))
+                        (intern (cdr (assq :noweb-trans (nth 2 info))))))
+         (noweb-prefix (let ((v (assq :noweb-prefix (nth 2 info))))
+                         (or (not v)
+                             (and (org-not-nil (cdr v))
+                                  (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
 			     (org-babel-noweb-wrap))))
@@ -2921,11 +2930,16 @@ block but are passed literally to the \"example-block\"."
 			  (let* ((info (org-babel-get-src-block-info t))
 				 (ref (cdr (assq :noweb-ref (nth 2 info)))))
 			    (push info (gethash ref cache))))))
-		     (funcall expand-references id cache)))))
+		     (funcall expand-references id cache))))
+                  (expansion (if (functionp noweb-trans)
+                                 (funcall noweb-trans expansion)
+                               expansion)))
 	     ;; Interpose PREFIX between every line.
-	     (mapconcat #'identity
-			(split-string expansion "[\n\r]")
-			(concat "\n" prefix))))))
+	     (if noweb-prefix
+                 (mapconcat #'identity
+			    (split-string expansion "[\n\r]")
+			    (concat "\n" prefix))
+               expansion)))))
      body t t 2)))
 
 (defun org-babel--script-escape-inner (str)
-- 
2.36.0


[-- Attachment #3: 0001-ob-core.el-noweb-prefix-header-argument-and-nw-synta.patch --]
[-- Type: text/x-patch, Size: 7143 bytes --]

From 8fdd163b3f5c8049c67a6f3eab4587cac4a6d04a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Miquel?= <sebastien.miquel@posteo.eu>
Date: Mon, 6 Sep 2021 18:45:42 +0200
Subject: [PATCH] ob-core.el: `:noweb-prefix` header argument and <<"nw">>
 syntax

* lisp/ob-core.el (org-babel-expand-noweb-references): Add support for
`noweb-prefix' header argument, to not repeat the prefix characters
when expanding a noweb reference. Add support for <<"nw">> noweb
syntax, to insert a lisp string representation of the content.
(org-babel-common-header-args-w-values):
(org-babel-safe-header-args): Add `noweb-prefix' values.
(org-babel-noweb-wrap): Add support for <<"nw">> syntax.
* doc/org-manual.org: Document `noweb-prefix' and <<"nw">> noweb
syntax.
* etc/ORG-NEWS: Document `:noweb-prefix' and <<"nw">> noweb syntax.
---
 doc/org-manual.org | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 etc/ORG-NEWS       | 25 ++++++++++++++++++++++++-
 lisp/ob-core.el    | 34 +++++++++++++++++++++++-----------
 3 files changed, 93 insertions(+), 12 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index 6768ca98d..2e1435279 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -18760,6 +18760,52 @@ else:
     print('do things when false')
 #+end_example
 
+This prefix behavior can be turned off in a block by setting the
+=noweb-prefix= header argument to =no=, as in:
+
+#+begin_example
+,#+BEGIN_SRC elisp :noweb-prefix no
+  (setq example-data "<<example>>")
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+which expands to:
+
+#+begin_example
+(setq example-data "this is the
+multi-line body of example")
+#+end_example
+
+Instead of inserting the content of a block, one may insert a lisp
+string representation of the content using the syntax
+
+: <<"CODE-BLOCK-ID">>
+
+#+texinfo: @noindent
+With:
+
+#+begin_example
+,#+NAME: latex-header
+,#+BEGIN_SRC latex
+  \usepackage{amsmath}
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+this code block:
+
+#+begin_example
+,#+BEGIN_SRC elisp :noweb yes
+  (setq header <<"latex-header">>)
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+expands to:
+
+: (setq header "\\usepackage{amsmath}")
+
 When in doubt about the outcome of a source code block expansion, you
 can preview the results with the following command:
 
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 2b539d305..3a8229d73 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -150,7 +150,7 @@ The entry points are ~org-persist-register~, ~org-persist-unregister~,
 ~org-persist-read~, and ~org-persist-read-all~.  Storing circular
 structures is supported.  Storing references between different
 variables is also supported (see =:inherit= key in
-~org-persist-register~).  
+~org-persist-register~).
 
 The library permits storing buffer-local variables.  Such variables
 are linked to the buffer text, file =inode=, and file path.
@@ -176,6 +176,29 @@ Items in a description list that begin with =Function:=, =Variable:=
 or certain related prefixes are converted using Texinfo definition
 commands.
 
+*** New =:noweb-prefix= babel header argument
+
+=:noweb-prefix= can be set to =no= to prevent the prefix characters
+from being repeated when expanding a multiline noweb reference.
+
+*** New syntax to insert a string representation of a noweb reference
+
+Use =<<"foo">>= to insert a lisp string representing the content of
+the =foo= block. For example:
+
+#+BEGIN_SRC org
+  ,#+BEGIN_SRC LaTeX :noweb-ref foo
+    \usepackage{bar}
+  ,#+END_SRC
+
+  ,#+BEGIN_SRC emacs-lisp :noweb yes
+    (setq latex-header <<"foo">>)
+  ,#+END_SRC
+#+END_SRC
+
+will expand to
+: (setq latex-header "\\usepackage{bar}")
+
 ** New functions and changes in function arguments
 
 *** New function ~org-element-cache-map~ for quick mapping across Org elements
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 6590eeee7..cac1a4162 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -187,7 +187,9 @@ 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]\\)?\\)")
+          "\\(?2:\"?\\)"
+	  (or regexp "\\(?1:[^ \t\n]\\(?:.*?[^ \t\n]\\)?\\)")
+          "\\2"
 	  (regexp-quote org-babel-noweb-wrap-end)))
 
 (defvar org-babel-src-name-regexp
@@ -413,6 +415,7 @@ then run `org-babel-switch-to-session'."
     (noweb	. ((yes no tangle no-export strip-export)))
     (noweb-ref	. :any)
     (noweb-sep  . :any)
+    (noweb-prefix . ((no yes)))
     (output-dir . :any)
     (padline	. ((yes no)))
     (post       . :any)
@@ -438,8 +441,8 @@ specific header arguments as well.")
 
 (defconst org-babel-safe-header-args
   '(:cache :colnames :comments :exports :epilogue :hlines :noeval
-	   :noweb :noweb-ref :noweb-sep :padline :prologue :rownames
-	   :sep :session :tangle :wrap
+	   :noweb :noweb-ref :noweb-sep :noweb-prefix :padline
+           :prologue :rownames :sep :session :tangle :wrap
 	   (:eval . ("never" "query"))
 	   (:results . (lambda (str) (not (string-match "file" str)))))
   "A list of safe header arguments for babel source blocks.
@@ -2827,7 +2830,11 @@ block but are passed literally to the \"example-block\"."
          (lang (nth 0 info))
          (body (nth 1 info))
 	 (comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
-	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
+         (noweb-prefix (let ((v (assq :noweb-prefix (nth 2 info))))
+                         (or (not v)
+                             (and (org-not-nil (cdr v))
+                                  (not (equal (cdr v) "no"))))))
+	 (noweb-re (format "\\(?3:.*?\\)\\(?4:%s\\)"
 			   (with-current-buffer parent-buffer
 			     (org-babel-noweb-wrap))))
 	 (cache nil)
@@ -2878,9 +2885,10 @@ block but are passed literally to the \"example-block\"."
      (lambda (m)
        (with-current-buffer parent-buffer
 	 (save-match-data
-	   (let* ((prefix (match-string 1 m))
-		  (id (match-string 3 m))
+	   (let* ((prefix (match-string 3 m))
+		  (id (match-string 1 m))
 		  (evaluate (string-match-p "(.*)" id))
+                  (print-str (> (length (match-string 2 m)) 0))
 		  (expansion
 		   (cond
 		    (evaluate
@@ -2921,12 +2929,16 @@ block but are passed literally to the \"example-block\"."
 			  (let* ((info (org-babel-get-src-block-info t))
 				 (ref (cdr (assq :noweb-ref (nth 2 info)))))
 			    (push info (gethash ref cache))))))
-		     (funcall expand-references id cache)))))
+		     (funcall expand-references id cache))))
+                  (expansion (if print-str (prin1-to-string expansion)
+                               expansion)))
 	     ;; Interpose PREFIX between every line.
-	     (mapconcat #'identity
-			(split-string expansion "[\n\r]")
-			(concat "\n" prefix))))))
-     body t t 2)))
+	     (if noweb-prefix
+                 (mapconcat #'identity
+			    (split-string expansion "[\n\r]")
+			    (concat "\n" prefix))
+               expansion)))))
+     body t t 4)))
 
 (defun org-babel--script-escape-inner (str)
   (let (in-single in-double backslash out)
-- 
2.36.0


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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-04-29 14:27   ` Sébastien Miquel
@ 2022-04-30  6:05     ` Ihor Radchenko
  2022-04-30  7:35       ` Sébastien Miquel
  2022-05-30 19:51       ` Sébastien Miquel
  0 siblings, 2 replies; 17+ messages in thread
From: Ihor Radchenko @ 2022-04-30  6:05 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

> at least as long as you're tangling to a programming language, that
> can read lisp strings.
>> Consider the following example:
>>
>> #+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no :noweb-trans prin1-to-string
>> <<preamble>>
>> (setq latex-header <<nw>>)
>> #+END_SRC
>>
>> There are two noweb references here. Setting source block-wide
>> :noweb-trans is not helpful because the first reference will be
>> incorrectly filtered through prin1-to-string.
> Indeed. Originally I had thought of adding a new syntax <<"nw">> to
> insert a string representation. I've attached a new patch, that does
> this instead of introducing :noweb-trans. Now that I think of the
> universality of prin1-to-string, I actually like it slightly better
> than :noweb-trans. It would break existing "nw"-like noweb references.

This is too specific, as for me.
Thinking about the whole idea of :noweb-trans more, I see little benefit
compared to something like:

#+name: documentation
This is a sample function documentation.
Because there are "quotes", it must be escaped and cannot be directly
used as noweb-reference.

#+name: doc-escape
#+begin_src emacs-lisp :var str="" :tangle no
(prin1-to-string (string-trim-right str))
#+end_src

#+begin_src emacs-lisp :tangle yes
(defun test ()
<<doc-escape(str=documentation)>>
t)
#+end_src

Maybe we can instead distribute a library ob babel file containing
useful functions together with Org.

>>> [...]
>> This sounds a bit confusing. I would also add an example where it is
>> useful to set :noweb-prefix to no.
>
> I've added such an example in the revised patch attached.

Other than :noweb-trans, the patch looks good for me.

Best,
Ihor


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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-04-30  6:05     ` Ihor Radchenko
@ 2022-04-30  7:35       ` Sébastien Miquel
  2022-04-30  8:41         ` Ihor Radchenko
  2022-05-30 19:51       ` Sébastien Miquel
  1 sibling, 1 reply; 17+ messages in thread
From: Sébastien Miquel @ 2022-04-30  7:35 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

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


Ihor Radchenko writes:
> #+name: documentation
> This is a sample function documentation.
> Because there are "quotes", it must be escaped and cannot be directly
> used as noweb-reference.
>
> #+name: doc-escape
> #+begin_src emacs-lisp :var str="" :tangle no
> (prin1-to-string (string-trim-right str))
> #+end_src
>
> #+begin_src emacs-lisp :tangle yes
> (defun test ()
> <<doc-escape(str=documentation)>>
> t)
> #+end_src

Nice ! Quite obscure and brittle (doesn't work if documentation is a 
text src block) but I can use it nonetheless.

> Other than :noweb-trans, the patch looks good for me. 
Here's a patch with only the :noweb-prefix part. If applied, we can mark 
this thread resolved.

Thanks,

-- 
Sébastien Miquel

[-- Attachment #2: 0001-ob-core.el-Add-noweb-prefix-babel-header-argument.patch --]
[-- Type: text/x-patch, Size: 4626 bytes --]

From 3fc3c3557b27026e2cfdb2a1973921c1baf3758a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Miquel?= <sebastien.miquel@posteo.eu>
Date: Mon, 6 Sep 2021 18:45:42 +0200
Subject: [PATCH] ob-core.el: Add `:noweb-prefix` babel header argument

* lisp/ob-core.el (org-babel-expand-noweb-references): Add support for
`noweb-prefix' header argument, to not repeat the prefix characters
when expanding a noweb reference.
(org-babel-common-header-args-w-values):
(org-babel-safe-header-args): Add `noweb-prefix' value.
* doc/org-manual.org: Document `noweb-prefix' babel header argument.
* etc/ORG-NEWS: Document `:noweb-prefix'.
---
 doc/org-manual.org | 17 +++++++++++++++++
 etc/ORG-NEWS       |  6 +++++-
 lisp/ob-core.el    | 17 ++++++++++++-----
 3 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index 6768ca98d..c9c1c1298 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -18760,6 +18760,23 @@ else:
     print('do things when false')
 #+end_example
 
+This prefix behavior can be turned off in a block by setting the
+=noweb-prefix= header argument to =no=, as in:
+
+#+begin_example
+,#+BEGIN_SRC elisp :noweb-prefix no
+  (setq example-data "<<example>>")
+,#+END_SRC
+#+end_example
+
+#+texinfo: @noindent
+which expands to:
+
+#+begin_example
+(setq example-data "this is the
+multi-line body of example")
+#+end_example
+
 When in doubt about the outcome of a source code block expansion, you
 can preview the results with the following command:
 
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 2b539d305..1e8558c7b 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -150,7 +150,7 @@ The entry points are ~org-persist-register~, ~org-persist-unregister~,
 ~org-persist-read~, and ~org-persist-read-all~.  Storing circular
 structures is supported.  Storing references between different
 variables is also supported (see =:inherit= key in
-~org-persist-register~).  
+~org-persist-register~).
 
 The library permits storing buffer-local variables.  Such variables
 are linked to the buffer text, file =inode=, and file path.
@@ -175,6 +175,10 @@ the =compact-itemx= export option, or globally using the
 Items in a description list that begin with =Function:=, =Variable:=
 or certain related prefixes are converted using Texinfo definition
 commands.
+*** New =:noweb-prefix= babel header argument
+
+=:noweb-prefix= can be set to =no= to prevent the prefix characters
+from being repeated when expanding a multiline noweb reference.
 
 ** New functions and changes in function arguments
 
diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 6590eeee7..09d6adfe0 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -413,6 +413,7 @@ then run `org-babel-switch-to-session'."
     (noweb	. ((yes no tangle no-export strip-export)))
     (noweb-ref	. :any)
     (noweb-sep  . :any)
+    (noweb-prefix . ((no yes)))
     (output-dir . :any)
     (padline	. ((yes no)))
     (post       . :any)
@@ -438,8 +439,8 @@ specific header arguments as well.")
 
 (defconst org-babel-safe-header-args
   '(:cache :colnames :comments :exports :epilogue :hlines :noeval
-	   :noweb :noweb-ref :noweb-sep :padline :prologue :rownames
-	   :sep :session :tangle :wrap
+	   :noweb :noweb-ref :noweb-sep :noweb-prefix :padline
+           :prologue :rownames :sep :session :tangle :wrap
 	   (:eval . ("never" "query"))
 	   (:results . (lambda (str) (not (string-match "file" str)))))
   "A list of safe header arguments for babel source blocks.
@@ -2827,6 +2828,10 @@ block but are passed literally to the \"example-block\"."
          (lang (nth 0 info))
          (body (nth 1 info))
 	 (comment (string= "noweb" (cdr (assq :comments (nth 2 info)))))
+         (noweb-prefix (let ((v (assq :noweb-prefix (nth 2 info))))
+                         (or (not v)
+                             (and (org-not-nil (cdr v))
+                                  (not (equal (cdr v) "no"))))))
 	 (noweb-re (format "\\(.*?\\)\\(%s\\)"
 			   (with-current-buffer parent-buffer
 			     (org-babel-noweb-wrap))))
@@ -2923,9 +2928,11 @@ block but are passed literally to the \"example-block\"."
 			    (push info (gethash ref cache))))))
 		     (funcall expand-references id cache)))))
 	     ;; Interpose PREFIX between every line.
-	     (mapconcat #'identity
-			(split-string expansion "[\n\r]")
-			(concat "\n" prefix))))))
+	     (if noweb-prefix
+                 (mapconcat #'identity
+			    (split-string expansion "[\n\r]")
+			    (concat "\n" prefix))
+               expansion)))))
      body t t 2)))
 
 (defun org-babel--script-escape-inner (str)
-- 
2.36.0


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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-04-30  7:35       ` Sébastien Miquel
@ 2022-04-30  8:41         ` Ihor Radchenko
  0 siblings, 0 replies; 17+ messages in thread
From: Ihor Radchenko @ 2022-04-30  8:41 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

>> Other than :noweb-trans, the patch looks good for me. 
> Here's a patch with only the :noweb-prefix part. If applied, we can mark 
> this thread resolved.

Thanks! Applied on main as 2063596b9.

> Ihor Radchenko writes:
>> #+name: documentation
>> This is a sample function documentation.
>> Because there are "quotes", it must be escaped and cannot be directly
>> used as noweb-reference.
>>
>> #+name: doc-escape
>> #+begin_src emacs-lisp :var str="" :tangle no
>> (prin1-to-string (string-trim-right str))
>> #+end_src
>>
>> #+begin_src emacs-lisp :tangle yes
>> (defun test ()
>> <<doc-escape(str=documentation)>>
>> t)
>> #+end_src
>
> Nice ! Quite obscure and brittle (doesn't work if documentation is a 
> text src block) but I can use it nonetheless.

Well. It looks natural for me. Depends on what you are used to when
working with org babel.

Things are a bit more tricky for latex source blocks, but you can still
do

#+name: nw
#+BEGIN_SRC latex :tangle no
\usepackage{…}
\usepackage{…}
#+END_SRC

#+BEGIN_SRC emacs-lisp :noweb yes :tangle yes :noweb-prefix no
(setq latex-header <<doc-escape(str=nw)>>)
#+END_SRC

Of course, it would only work for source blocks with corresponding
ob-*.el library. But then again, why would you need to wrap things into
text source block when a simple paragraph is enough.

Best,
Ihor

Applied.


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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-04-30  6:05     ` Ihor Radchenko
  2022-04-30  7:35       ` Sébastien Miquel
@ 2022-05-30 19:51       ` Sébastien Miquel
  2022-05-31  5:14         ` Ihor Radchenko
  1 sibling, 1 reply; 17+ messages in thread
From: Sébastien Miquel @ 2022-05-30 19:51 UTC (permalink / raw)
  To: Ihor Radchenko, emacs-orgmode

Hi,

Ihor Radchenko writes:
> Thinking about the whole idea of :noweb-trans more, I see little benefit
> compared to something like:
>
> #+name: documentation
> This is a sample function documentation.
> Because there are "quotes", it must be escaped and cannot be directly
> used as noweb-reference.
>
> #+name: doc-escape
> #+begin_src emacs-lisp :var str="" :tangle no
> (prin1-to-string (string-trim-right str))
> #+end_src
>
> #+begin_src emacs-lisp :tangle yes
> (defun test ()
> <<doc-escape(str=documentation)>>
> t)
> #+end_src
I had converted my uses (tangling code, not text/documentation) to
this but I ended up reverting.

Some drawbacks:
  + doesn't work for all languages (does work for LaTeX)
  + the tangle gets very noisy: not only are the result of execution
    printed in the echo buffer, but emacs visits the tangling buffer
    and moves the point to each block.
    Perhaps this is a bug that can be fixed.
  + src block execution also resets the noweb cache, slowing down
    tangle, though I have not tried to measure the effect.

As stated in the OP, I find it unfortunate that org does not provide
any way to tangle the content of a src block to a string representing
this code. If anyone shows any interest, I've provided two possible
implementations in this thread, that I can rebase.

Regards,

-- 
Sébastien Miquel



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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-05-30 19:51       ` Sébastien Miquel
@ 2022-05-31  5:14         ` Ihor Radchenko
  2022-05-31  6:48           ` Sébastien Miquel
  0 siblings, 1 reply; 17+ messages in thread
From: Ihor Radchenko @ 2022-05-31  5:14 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

>> #+name: documentation
>> This is a sample function documentation.
>> Because there are "quotes", it must be escaped and cannot be directly
>> used as noweb-reference.
>>
>> #+name: doc-escape
>> #+begin_src emacs-lisp :var str="" :tangle no
>> (prin1-to-string (string-trim-right str))
>> #+end_src
>>
>> #+begin_src emacs-lisp :tangle yes
>> (defun test ()
>> <<doc-escape(str=documentation)>>
>> t)
>> #+end_src
> I had converted my uses (tangling code, not text/documentation) to
> this but I ended up reverting.

Can you provide more concrete examples?

> Some drawbacks:
>   + doesn't work for all languages (does work for LaTeX)

Which languages do not work?

>   + the tangle gets very noisy: not only are the result of execution
>     printed in the echo buffer, but emacs visits the tangling buffer
>     and moves the point to each block.
>     Perhaps this is a bug that can be fixed.

Did you try to play with :results header argument to disable messages?
What exactly went unexpected?

>   + src block execution also resets the noweb cache, slowing down
>     tangle, though I have not tried to measure the effect.

I am not sure what you are referring to here. Can you elaborate?

Best,
Ihor



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

* Re: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments
  2022-05-31  5:14         ` Ihor Radchenko
@ 2022-05-31  6:48           ` Sébastien Miquel
  2022-07-16  8:57             ` [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments) Ihor Radchenko
  2022-07-21 11:13             ` [PATCH] org-babel: Do not echo output of resolved noweb references Ihor Radchenko
  0 siblings, 2 replies; 17+ messages in thread
From: Sébastien Miquel @ 2022-05-31  6:48 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

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

Hi,

Ihor Radchenko writes:
> Can you provide more concrete examples?
>
>> Some drawbacks:
>>    + doesn't work for all languages (does work for LaTeX)
> Which languages do not work?
Most languages do not work. Using your proposed solution, what I'm
trying to do is

#+name:javascript-header
#+begin_src javascript :tangle no
some javascript, with \ and " to be escaped
#+end_src

#+name: string-escape
#+begin_src emacs-lisp :var str="" :tangle no
(prin1-to-string (string-trim-right str))
#+end_src

#+begin_src emacs-lisp :noweb yes :tangle yes
(setq javascript-header <<string-escape(str=javascript-header)>>)
#+end_src

If you replace javascript with latex, it happens to work, because when
org executes a latex block, it prints its content.

The goal is to tangle to some lisp code whose purpose is to generate
LaTeX/javascript code. Quite niche admittedly, though as you showed,
it could also be used to string-escape documentation.

>>    + the tangle gets very noisy: not only are the result of execution
>>      printed in the echo buffer, but emacs visits the tangling buffer
>>      and moves the point to each block.
>>      Perhaps this is a bug that can be fixed.
> Did you try to play with :results header argument to disable messages?
> What exactly went unexpected?

I did. I might have missed something, but no combination of :results
argument to both the latex block and the string-escape block silences
the tangle (except for :results none, which doesn't tangle the content
of the block). During tangle, the contents of the latex block are
displayed (shortly) in the echo buffer (check *Messages*), and the
point very briefly moves to the latex block. This isn't very
noticeable with a single block.
>>    + src block execution also resets the noweb cache, slowing down
>>      tangle, though I have not tried to measure the effect.
> I am not sure what you are referring to here. Can you elaborate?

Lines 2892-2893 of (my) ob-core.el, in org-babel-expand-noweb-references:

>              ;; Evaluation can potentially modify the buffer
>              ;; and invalidate the cache: reset it.

Regards,

-- 
Sébastien Miquel

[-- Attachment #2: Type: text/html, Size: 4015 bytes --]

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

* [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments)
  2022-05-31  6:48           ` Sébastien Miquel
@ 2022-07-16  8:57             ` Ihor Radchenko
  2022-07-16 10:17               ` Greg Minshall
  2022-07-21 11:13             ` [PATCH] org-babel: Do not echo output of resolved noweb references Ihor Radchenko
  1 sibling, 1 reply; 17+ messages in thread
From: Ihor Radchenko @ 2022-07-16  8:57 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

> Ihor Radchenko writes:
>> Can you provide more concrete examples?
>>
>>> Some drawbacks:
>>>    + doesn't work for all languages (does work for LaTeX)
>> Which languages do not work?
> Most languages do not work. Using your proposed solution, what I'm
> trying to do is
>
> #+name:javascript-header
> #+begin_src javascript :tangle no
> some javascript, with \ and " to be escaped
> #+end_src
>
> #+name: string-escape
> #+begin_src emacs-lisp :var str="" :tangle no
> (prin1-to-string (string-trim-right str))
> #+end_src
>
> #+begin_src emacs-lisp :noweb yes :tangle yes
> (setq javascript-header <<string-escape(str=javascript-header)>>)
> #+end_src
>
> If you replace javascript with latex, it happens to work, because when
> org executes a latex block, it prints its content.
>
> The goal is to tangle to some lisp code whose purpose is to generate
> LaTeX/javascript code. Quite niche admittedly, though as you showed,
> it could also be used to string-escape documentation.

Thanks for providing an example!

The current behaviour of :var foo=name-of-src-block is assigning result
of evaluation. However, this behaviour is actually not documented.
16.4 Environment of a Code Block section of the manual only documents
uses like
#+BEGIN_SRC emacs-lisp :var length=table-length()
or
#+BEGIN_SRC emacs-lisp :var input=double(input=1)

Currently,
#+BEGIN_SRC emacs-lisp :var length=table-length
is the same with
#+BEGIN_SRC emacs-lisp :var length=table-length()

Given that
#+BEGIN_SRC emacs-lisp :var x=literal-example

inserts the literal contents of the example block, I am voting to change
the current undocumented behaviour for assigning the code block
references.

This will make the discussed example work while not restricting the
existing features.

WDYT?

Best,
Ihor


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

* Re: [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments)
  2022-07-16  8:57             ` [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments) Ihor Radchenko
@ 2022-07-16 10:17               ` Greg Minshall
  2022-07-16 10:45                 ` Ihor Radchenko
  0 siblings, 1 reply; 17+ messages in thread
From: Greg Minshall @ 2022-07-16 10:17 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: sebastien.miquel, emacs-orgmode

Ihor,

> The current behaviour of :var foo=name-of-src-block is assigning result
> of evaluation. However, this behaviour is actually not documented.
> 16.4 Environment of a Code Block section of the manual only documents
> uses like

in fact, the text of the info page (on my system?) says
> code block without arguments
>      A code block name, as assigned by ‘NAME’ keyword from the example
>      above, optionally followed by parentheses.

note the "optionally".

cheers, Greg


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

* Re: [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments)
  2022-07-16 10:17               ` Greg Minshall
@ 2022-07-16 10:45                 ` Ihor Radchenko
  2022-07-16 14:31                   ` Greg Minshall
  2022-07-17 17:39                   ` Sébastien Miquel
  0 siblings, 2 replies; 17+ messages in thread
From: Ihor Radchenko @ 2022-07-16 10:45 UTC (permalink / raw)
  To: Greg Minshall; +Cc: sebastien.miquel, emacs-orgmode

Greg Minshall <minshall@umich.edu> writes:

>> The current behaviour of :var foo=name-of-src-block is assigning result
>> of evaluation. However, this behaviour is actually not documented.
>> 16.4 Environment of a Code Block section of the manual only documents
>> uses like
>
> in fact, the text of the info page (on my system?) says
>> code block without arguments
>>      A code block name, as assigned by ‘NAME’ keyword from the example
>>      above, optionally followed by parentheses.
>
> note the "optionally".

Hmm. You are right. I missed "optionally".

Still, I find this idea as the best solution for people who want to
process the source block text during noweb expansion.

Alternative ideas are welcome though. I'd prefer to avoid breaking
change if we can find an equally simple syntax alternative to assign
source block code to a variable.

Best,
Ihor


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

* Re: [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments)
  2022-07-16 10:45                 ` Ihor Radchenko
@ 2022-07-16 14:31                   ` Greg Minshall
  2022-07-17 17:39                   ` Sébastien Miquel
  1 sibling, 0 replies; 17+ messages in thread
From: Greg Minshall @ 2022-07-16 14:31 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: sebastien.miquel, emacs-orgmode

Ihor,

> Alternative ideas are welcome though. I'd prefer to avoid breaking
> change if we can find an equally simple syntax alternative to assign
> source block code to a variable.

my two cents would be to avoid the breaking change.  (i notice, for
example, that i use this construct in some of my .org files.)

cheers, Greg


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

* Re: [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments)
  2022-07-16 10:45                 ` Ihor Radchenko
  2022-07-16 14:31                   ` Greg Minshall
@ 2022-07-17 17:39                   ` Sébastien Miquel
  2022-07-23  4:52                     ` Ihor Radchenko
  1 sibling, 1 reply; 17+ messages in thread
From: Sébastien Miquel @ 2022-07-17 17:39 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode, Greg Minshall


Hi,

Ihor Radchenko writes:
 > Hmm. You are right. I missed "optionally".
 >
 > Still, I find this idea as the best solution for people who want to
 > process the source block text during noweb expansion.
 >
 > Alternative ideas are welcome though. I'd prefer to avoid breaking
 > change if we can find an equally simple syntax alternative to assign
 > source block code to a variable.

The uses are maybe too niche to warrant the breaking change. A syntax
extension like
  : var=block-id[]
seems possible, even though brackets are already overloaded.

One alternative is to only allow the syntax inside noweb brackets
instead of generic variable arguments. I assume there'd be much less
breakage. It would also makes sense to allow noweb references instead
of block ids. We'd add support for
  : <<babel-fn(var=noweb-ref)>>
and <<babel-fn(var=block-id)>> would also insert the contents as a
by-product.

Do you have any example of use in mind, beyond my original one ?

Regards,

-- 
Sébastien Miquel


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

* [PATCH] org-babel: Do not echo output of resolved noweb references
  2022-05-31  6:48           ` Sébastien Miquel
  2022-07-16  8:57             ` [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments) Ihor Radchenko
@ 2022-07-21 11:13             ` Ihor Radchenko
  2022-07-21 13:41               ` Sébastien Miquel
  1 sibling, 1 reply; 17+ messages in thread
From: Ihor Radchenko @ 2022-07-21 11:13 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode

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

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

>>>    + the tangle gets very noisy: not only are the result of execution
>>>      printed in the echo buffer, but emacs visits the tangling buffer
>>>      and moves the point to each block.
>>>      Perhaps this is a bug that can be fixed.
>> Did you try to play with :results header argument to disable messages?
>> What exactly went unexpected?
>
> I did. I might have missed something, but no combination of :results
> argument to both the latex block and the string-escape block silences
> the tangle (except for :results none, which doesn't tangle the content
> of the block). During tangle, the contents of the latex block are
> displayed (shortly) in the echo buffer (check *Messages*), and the
> point very briefly moves to the latex block. This isn't very
> noticeable with a single block.

Point movement is normal, but usually invisible because it happens
faster than redisplay cycle. As for displaying the resolved noweb
references, I do think that it should not happen.

Currently, every time Org resolves noweb references, the behaviour is
resembling :results silent. That is, the results of evaluation are
displayed, but not inserted after the executed source blocks.

I propose to change this by using :results none that will display
"results silenced" echo instead of messaging the whole result string.

The proposed behaviour makes more sense compared with the default value
because resolved noweb references are usually used to pipe data
(including table data) between source blocks and to include generated
code during noweb expansion. Such data tends to be fairly bulky and
creates a lot of noise during export/tangling. Not to mention that
displaying large messages also gives a considerable slowdown to the
whole export/tangle process.

Note that changing the current behaviour also triggered the way :results
none are being processed. The de facto implementation in ob-core does
not do any kind of return value post-processing on :results none, which
is not consistent with the manual (16.6 Results of Evaluation). In the
manual, "none" option is a part of the option class consisting of
"replace", "silent", "none", "append", and "prepend". All other
alternative options only influence how the results are inserted after
evaluation and processing. The fact that "none" result is not being
processed according to :file, :post, and other arguments is not
consistent. I changed that. Now, :results "none" are being processed
completely, and only the actual insertion is not performed.

The above change affects the return value of
org-babel-execute-src-block. Previously, it always returned nil with
:results none. Now, it returns the actual post-processed result of
evaluation.

Let me know if you see any potential issues with the proposed change.

Best,
Ihor


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-babel-Do-not-echo-output-of-resolved-noweb-refer.patch --]
[-- Type: text/x-patch, Size: 7234 bytes --]

From f01818ef5bce0a557eb119c58c449d75b28a923e Mon Sep 17 00:00:00 2001
Message-Id: <f01818ef5bce0a557eb119c58c449d75b28a923e.1658401224.git.yantar92@gmail.com>
From: Ihor Radchenko <yantar92@gmail.com>
Date: Thu, 21 Jul 2022 18:54:30 +0800
Subject: [PATCH] org-babel: Do not echo output of resolved noweb references

* lisp/ob-core.el (org-babel-execute-src-block): Post-process and
return results even when "none" results parameter is given.  Document
that the result value is returned, as it is assumed by
`org-babel-ref-resolve'.
(org-babel-result-cond): Do return results even when "none" results
parameter is given.

According to the manual ":results none" should only affect how the
results of evaluation are inserted into the buffer.  However, the
results are simply ignored currently.  Fix this.
* lisp/ob-ref.el (org-babel-ref-resolve): Set :results to "none" when
resolving noweb references.  Together with the above changes, this
makes Org not echo the results value yet returning the value
programatically.

Reported in https://orgmode.org/list/7702b511-c289-5688-c64c-fb673324a63a@posteo.eu
---
 lisp/ob-core.el | 118 ++++++++++++++++++++++++------------------------
 lisp/ob-ref.el  |   2 +-
 2 files changed, 59 insertions(+), 61 deletions(-)

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index ac9af5d24..714f70c6a 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -712,7 +712,7 @@ (defvar *this*) ; Dynamically bound in `org-babel-execute-src-block'
 
 ;;;###autoload
 (defun org-babel-execute-src-block (&optional arg info params)
-  "Execute the current source code block.
+  "Execute the current source code block and return the result.
 Insert the results of execution into the buffer.  Source code
 execution and the collection and formatting of results can be
 controlled through a variety of header arguments.
@@ -776,51 +776,50 @@ (defun org-babel-execute-src-block (&optional arg info params)
 		     (capitalize lang)
 		     (let ((name (nth 4 info)))
 		       (if name (format " (%s)" name) "")))
-	    (if (member "none" result-params)
-		(progn (funcall cmd body params)
-		       (message "result silenced"))
-	      (setq result
-		    (let ((r (funcall cmd body params)))
-		      (if (and (eq (cdr (assq :result-type params)) 'value)
-			       (or (member "vector" result-params)
-				   (member "table" result-params))
-			       (not (listp r)))
-			  (list (list r))
-			r)))
-	      (let ((file (and (member "file" result-params)
-			       (cdr (assq :file params)))))
-		;; If non-empty result and :file then write to :file.
-		(when file
-		  ;; If `:results' are special types like `link' or
-		  ;; `graphics', don't write result to `:file'.  Only
-		  ;; insert a link to `:file'.
-		  (when (and result
-			     (not (or (member "link" result-params)
-				      (member "graphics" result-params))))
-		    (with-temp-file file
-		      (insert (org-babel-format-result
-			       result
-			       (cdr (assq :sep params)))))
-		    ;; Set file permissions if header argument
-		    ;; `:file-mode' is provided.
-		    (when (assq :file-mode params)
-		      (set-file-modes file (cdr (assq :file-mode params)))))
-		  (setq result file))
-		;; Possibly perform post process provided its
-		;; appropriate.  Dynamically bind "*this*" to the
-		;; actual results of the block.
-		(let ((post (cdr (assq :post params))))
-		  (when post
-		    (let ((*this* (if (not file) result
-				    (org-babel-result-to-file
-				     file
-				     (org-babel--file-desc params result)
-                                     'attachment))))
-		      (setq result (org-babel-ref-resolve post))
-		      (when file
-			(setq result-params (remove "file" result-params))))))
-		(org-babel-insert-result
-		 result result-params info new-hash lang)))
+	    (setq result
+		  (let ((r (funcall cmd body params)))
+		    (if (and (eq (cdr (assq :result-type params)) 'value)
+			     (or (member "vector" result-params)
+				 (member "table" result-params))
+			     (not (listp r)))
+			(list (list r))
+		      r)))
+	    (let ((file (and (member "file" result-params)
+			     (cdr (assq :file params)))))
+	      ;; If non-empty result and :file then write to :file.
+	      (when file
+		;; If `:results' are special types like `link' or
+		;; `graphics', don't write result to `:file'.  Only
+		;; insert a link to `:file'.
+		(when (and result
+			   (not (or (member "link" result-params)
+				  (member "graphics" result-params))))
+		  (with-temp-file file
+		    (insert (org-babel-format-result
+			     result
+			     (cdr (assq :sep params)))))
+		  ;; Set file permissions if header argument
+		  ;; `:file-mode' is provided.
+		  (when (assq :file-mode params)
+		    (set-file-modes file (cdr (assq :file-mode params)))))
+		(setq result file))
+	      ;; Possibly perform post process provided its
+	      ;; appropriate.  Dynamically bind "*this*" to the
+	      ;; actual results of the block.
+	      (let ((post (cdr (assq :post params))))
+		(when post
+		  (let ((*this* (if (not file) result
+				  (org-babel-result-to-file
+				   file
+				   (org-babel--file-desc params result)
+                                   'attachment))))
+		    (setq result (org-babel-ref-resolve post))
+		    (when file
+		      (setq result-params (remove "file" result-params))))))
+	      (if (member "none" result-params)
+		  (message "result silenced")
+	        (org-babel-insert-result
+	         result result-params info new-hash lang)))
 	    (run-hooks 'org-babel-after-execute-hook)
 	    result)))))))
 
@@ -3199,20 +3198,19 @@ (defmacro org-babel-result-cond (result-params scalar-form &rest table-forms)
   (declare (indent 1) (debug t))
   (org-with-gensyms (params)
     `(let ((,params ,result-params))
-       (unless (member "none" ,params)
-	 (if (or (member "scalar" ,params)
-		 (member "verbatim" ,params)
-		 (member "html" ,params)
-		 (member "code" ,params)
-		 (member "pp" ,params)
-		 (member "file" ,params)
-		 (and (or (member "output" ,params)
-			  (member "raw"    ,params)
-			  (member "org"    ,params)
-			  (member "drawer" ,params))
-		      (not (member "table" ,params))))
-	     ,scalar-form
-	   ,@table-forms)))))
+       (if (or (member "scalar" ,params)
+	       (member "verbatim" ,params)
+	       (member "html" ,params)
+	       (member "code" ,params)
+	       (member "pp" ,params)
+	       (member "file" ,params)
+	       (and (or (member "output" ,params)
+			(member "raw"    ,params)
+			(member "org"    ,params)
+			(member "drawer" ,params))
+		    (not (member "table" ,params))))
+	   ,scalar-form
+	 ,@table-forms))))
 
 (defun org-babel-temp-file (prefix &optional suffix)
   "Create a temporary file in the `org-babel-temporary-directory'.
diff --git a/lisp/ob-ref.el b/lisp/ob-ref.el
index d5356f18c..87a7ccf63 100644
--- a/lisp/ob-ref.el
+++ b/lisp/ob-ref.el
@@ -153,7 +153,7 @@ (defun org-babel-ref-resolve (ref)
 	    (setq ref split-ref))
 	  (org-with-wide-buffer
 	   (goto-char (point-min))
-	   (let* ((params (append args '((:results . "silent"))))
+	   (let* ((params (append args '((:results . "none"))))
 		  (regexp (org-babel-named-data-regexp-for-name ref))
 		  (result
 		   (catch :found
-- 
2.35.1


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

* Re: [PATCH] org-babel: Do not echo output of resolved noweb references
  2022-07-21 11:13             ` [PATCH] org-babel: Do not echo output of resolved noweb references Ihor Radchenko
@ 2022-07-21 13:41               ` Sébastien Miquel
  0 siblings, 0 replies; 17+ messages in thread
From: Sébastien Miquel @ 2022-07-21 13:41 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode


Hi,

Ihor Radchenko writes:
 > Let me know if you see any potential issues with the proposed change.

Thanks for looking into this. I think the change looks right, though I
am no great user of org-babel and its header arguments.

Regards,

-- 
Sébastien Miquel


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

* Re: [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments)
  2022-07-17 17:39                   ` Sébastien Miquel
@ 2022-07-23  4:52                     ` Ihor Radchenko
  0 siblings, 0 replies; 17+ messages in thread
From: Ihor Radchenko @ 2022-07-23  4:52 UTC (permalink / raw)
  To: sebastien.miquel; +Cc: emacs-orgmode, Greg Minshall

Sébastien Miquel <sebastien.miquel@posteo.eu> writes:

> The uses are maybe too niche to warrant the breaking change. A syntax
> extension like
>   : var=block-id[]
> seems possible, even though brackets are already overloaded.

This sounds better. Using brackets will actually make a lot of sense.

Currently, we have roughly the following logic in the :var references:

- :var x=reference(<optional parameters>)
  will execute the reference and assign the returned value

- :var x=reference[<optional parameters>]
  will take the reference text representation, possibly process it
  according to the parameters, and return the processed text

  *this only works for tables*

- :var x=reference
  will perform some "default" action depending on the reference type.
  the action may be "execute" or "get text representation" for source
  blocks and others correspondingly.

Extending reference[...] syntax to all the element types will make
things consistent and allow future extensions if we decide to provide
"index" syntax for non-tables (code lines, function definitions?)

> One alternative is to only allow the syntax inside noweb brackets
> instead of generic variable arguments. I assume there'd be much less
> breakage. It would also makes sense to allow noweb references instead
> of block ids. We'd add support for
>   : <<babel-fn(var=noweb-ref)>>
> and <<babel-fn(var=block-id)>> would also insert the contents as a
> by-product.

This would still be a breaking change. And we will introduce
inconsistency between resolving noweb references and resolving :var
header args.

Moreover, resolving references is currently handled by the same code
inside :vars and noweb references. Changing this will complicate the
source code as well, IMHO increasing the maintenance burden too much.

> Do you have any example of use in mind, beyond my original one ?

For example, one may convert .el file commentary to Readme.org:

#+name: my-library
#+begin_src :tangle my-library.el
;; Commentary:
;; A lot of commentary
#+end_src

#+begin_src :exports results :var commentary=my-library[]
(convert-to-org-headlines commentary)
#+end_src

Best,
Ihor


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

end of thread, other threads:[~2022-07-23  4:52 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-15 10:42 [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments Sébastien Miquel
2022-04-28 13:45 ` Ihor Radchenko
2022-04-29 14:27   ` Sébastien Miquel
2022-04-30  6:05     ` Ihor Radchenko
2022-04-30  7:35       ` Sébastien Miquel
2022-04-30  8:41         ` Ihor Radchenko
2022-05-30 19:51       ` Sébastien Miquel
2022-05-31  5:14         ` Ihor Radchenko
2022-05-31  6:48           ` Sébastien Miquel
2022-07-16  8:57             ` [FR] Make :var foo=name-of-src-block assign the source block code instead of currently assigned result of evaluation (was: [PATCH] Add :noweb-prefix and :noweb-trans babel header arguments) Ihor Radchenko
2022-07-16 10:17               ` Greg Minshall
2022-07-16 10:45                 ` Ihor Radchenko
2022-07-16 14:31                   ` Greg Minshall
2022-07-17 17:39                   ` Sébastien Miquel
2022-07-23  4:52                     ` Ihor Radchenko
2022-07-21 11:13             ` [PATCH] org-babel: Do not echo output of resolved noweb references Ihor Radchenko
2022-07-21 13:41               ` Sébastien Miquel

Code repositories for project(s) associated with this 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).