emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Noweb Function's body without evaluation
@ 2023-03-15 22:54 suarezmiguelc
  2023-03-16  4:16 ` Ken Mankoff
  2023-04-02 10:06 ` Ihor Radchenko
  0 siblings, 2 replies; 6+ messages in thread
From: suarezmiguelc @ 2023-03-15 22:54 UTC (permalink / raw)
  To: emacs-orgmode


Hello Org-mode community. I’m using Emacs Doom Framework, specifically:

Emacs 28.2 (build 1, aarch64-apple-darwin22.3.0, Carbon Version 169 AppKit 2299.4) of 2023-02-23.

I use heavily org-mode for Literate DevOps, so I have a lot of shell commands that connect through SSH and do some things later, for example:

#+name: initSSH
#+begin_src shell :var connection=“admin@somehost"
ssh -t miguel@host "sudo -u someuser ssh -t $connection 'sudo su'"
#+end_src

So then I can call:

#+call: initSSH(connection=“admin@anotherhost”)

With any other header parameters or session, the above works correctly. I cannot use tramp due to network latency issues, so this is the most performance way for me, since I also have to do some multi-hops which are indeed supported in tramp, but it is too slow for me, so I rather only commands.

The thing is that, I then would like to call these not with a #+call function, but add them into a bigger script, let’s say that I define another command:

#+name: getStorage
#+begin_src shell
df
#+end_src

Which has to be run in a remote server, could be any remote server as I have to connect to several. So I would like to be able to:

#+begin_src shell
<<initSSH(connection=“admin@anotherhost”)>>
<<getStorage>>
#+end_src

The first doesn’t work as org-mode runs the code and passes the resulting string to bash, which isn’t a command. The latter works normally. So the issue here are the parameters.

So I made another simple example for this:

#+name: greeting
#+begin_src sh :var name="world" :results output :session testing
echo "hello, $name\!"
#+end_src

#+results: greeting
#+begin_src sh
hello, world\!
#+end_src

#+begin_src shell
<<greeting(name="ss")>>
#+end_src

This results in sh: hello,: command not found, as it is executing the function. I see in the documentation that I can:
- Call a function’s body with <<namedcodeblock>>
- Execute a function and return its results with <<namedcodeblock()>>
- Execute a function and return its results even with different params with <<namedcodeblock(param=“sds”)>>

So right now, the one that’s missing is, call a function’s body with different parameters. So the function <<namedcodeblock>> is not evaluated.

After searching a lot, I came across:

#+begin_src shell :session testing
<<greeting[:body](name="Testingggg")>>
#+end_src

Which results in:

sh-3.2$ PS1="org_babel_sh_prompt> "
org_babel_sh_prompt> name='Testingggg'
org_babel_sh_prompt> echo "hello, $name\!"
hello, Testingggg\!
org_babel_sh_prompt> echo 'org_babel_sh_eoe'
org_babel_sh_eoe
org_babel_sh_prompt> hello, Testingggg\!
sh: hello,: command not found
org_babel_sh_prompt> echo 'org_babel_sh_eoe'
org_babel_sh_eoe
org_babel_sh_prompt> 

Which is somewhat what I need since at least the variable is changed, but the result of this execution is also passed to shell so, same error.

I can’t find much documentation about this, what is the correct syntax here?,

Thank you!

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

* Re: Noweb Function's body without evaluation
  2023-03-15 22:54 Noweb Function's body without evaluation suarezmiguelc
@ 2023-03-16  4:16 ` Ken Mankoff
  2023-03-16  7:56   ` suarezmiguelc
  2023-04-02 10:06 ` Ihor Radchenko
  1 sibling, 1 reply; 6+ messages in thread
From: Ken Mankoff @ 2023-03-16  4:16 UTC (permalink / raw)
  To: suarezmiguelc; +Cc: emacs-orgmode

Hi,

I'm not sure that I understand your issue or needs from the provided examples, but I wonder if the example I provide here would be helpful. It bypasses :var an lets you inject a PROPERTY value anywhere. It is also language agnostic. You can use it to execute commands (that are set as PROPERTY values) or set variables to values.

https://lists.gnu.org/archive/html/emacs-orgmode/2023-03/msg00251.html

  -k.

On 2023-03-15 at 18:54 -04, suarezmiguelc@icloud.com wrote...
> Hello Org-mode community. I’m using Emacs Doom Framework, specifically:
>
> Emacs 28.2 (build 1, aarch64-apple-darwin22.3.0, Carbon Version 169
> AppKit 2299.4) of 2023-02-23.
>
> I use heavily org-mode for Literate DevOps, so I have a lot of shell
> commands that connect through SSH and do some things later, for
> example:
>
> #+name: initSSH
> #+begin_src shell :var connection=“admin@somehost"
>
> ssh -t miguel@host "sudo -u someuser ssh -t $connection 'sudo su'"
> #+end_src
>
> So then I can call:
>
> #+call: initSSH(connection=“admin@anotherhost”)
>
> With any other header parameters or session, the above works
> correctly. I cannot use tramp due to network latency issues, so this
> is the most performance way for me, since I also have to do some
> multi-hops which are indeed supported in tramp, but it is too slow for
> me, so I rather only commands.
>
> The thing is that, I then would like to call these not with a #+call
> function, but add them into a bigger script, let’s say that I define
> another command:
>
> #+name: getStorage
> #+begin_src shell
>
> df
> #+end_src
>
> Which has to be run in a remote server, could be any remote server as
> I have to connect to several. So I would like to be able to:
>
> #+begin_src shell
> <<initSSH(connection=“admin@anotherhost”)>>
> <<getStorage>>
> #+end_src
>
>
> The first doesn’t work as org-mode runs the code and passes the
> resulting string to bash, which isn’t a command. The latter works
> normally. So the issue here are the parameters.
>
> So I made another simple example for this:
>
> #+name: greeting
> #+begin_src sh :var name="world" :results output :session testing
>
> echo "hello, $name\!"
> #+end_src
>
> #+results: greeting
> #+begin_src sh
>
> hello, world\!
> #+end_src
>
> #+begin_src shell
> <<greeting(name="ss")>>
> #+end_src
>
>
> This results in sh: hello,: command not found, as it is executing the function. I see in the documentation that I can:
> - Call a function’s body with <<namedcodeblock>>
> - Execute a function and return its results with <<namedcodeblock()>>
> - Execute a function and return its results even with different params with <<namedcodeblock(param=“sds”)>>
>
> So right now, the one that’s missing is, call a function’s body with different parameters. So the
> function <<namedcodeblock>> is not evaluated.
>
> After searching a lot, I came across:
>
> #+begin_src shell :session testing
> <<greeting[:body](name="Testingggg")>>
> #+end_src
>
> Which results in:
>
> sh-3.2$ PS1="org_babel_sh_prompt> "
> org_babel_sh_prompt> name='Testingggg'
> org_babel_sh_prompt> echo "hello, $name\!"
> hello, Testingggg\!
> org_babel_sh_prompt> echo 'org_babel_sh_eoe'
> org_babel_sh_eoe
> org_babel_sh_prompt> hello, Testingggg\!
> sh: hello,: command not found
> org_babel_sh_prompt> echo 'org_babel_sh_eoe'
> org_babel_sh_eoe
> org_babel_sh_prompt> 
>
> Which is somewhat what I need since at least the variable is changed,
> but the result of this execution is also passed to shell so, same
> error.
>
> I can’t find much documentation about this, what is the correct syntax
> here?,
>
> Thank you!



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

* Re: Noweb Function's body without evaluation
  2023-03-16  4:16 ` Ken Mankoff
@ 2023-03-16  7:56   ` suarezmiguelc
  0 siblings, 0 replies; 6+ messages in thread
From: suarezmiguelc @ 2023-03-16  7:56 UTC (permalink / raw)
  To: Ken Mankoff; +Cc: emacs-orgmode

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

Hello Ken, thank you for your message,

After reading the very interesting get_property function, I found that even though I will probably use it for some cases, it doesn’t apply directly, to my case.

For more examples, if I have 1 source code block:

>> #+name: greeting
>> #+begin_src sh :var name="world" :results output :session testing
>> 
>> echo "hello, $name\!"
>> #+end_src


I have three options in noweb to use this:
- Use its body into another begin_src source code block with <<greeting>>
- Use its result “hello, world!” Into another code block, which results in babel trying to execute the hello, command, which doesn’t exist, this with <<greeting()>>
- Use its result, the same as above, but with another parameter, results in the same but the variable name is different, so <<greeting(name=“another name”)>>

I’m trying to do the first, but with another parameter, so Use its body into another begin_src source code block with, get the resulting body after changing the variable without it being evaluated, so that I get a valid command to get to bash, like with <<greeting>>, but I can specify a different name variable.

I found the [:body] param but, even though it lets me change the variable as I want, it then tries to evaluate it, so I get a different value but the same hello, command doesn’t exist. Even though what I would want is to get echo “hello, $name\!” but, $name is different.

Thank you for your response Ken, I hope I gave a clearer example with the above.


> 16/3/23 5:16、Ken Mankoff <mankoff@gmail.com>のメール:
> 
> Hi,
> 
> I'm not sure that I understand your issue or needs from the provided examples, but I wonder if the example I provide here would be helpful. It bypasses :var an lets you inject a PROPERTY value anywhere. It is also language agnostic. You can use it to execute commands (that are set as PROPERTY values) or set variables to values.
> 
> https://lists.gnu.org/archive/html/emacs-orgmode/2023-03/msg00251.html
> 
>  -k.
> 
> On 2023-03-15 at 18:54 -04, suarezmiguelc@icloud.com wrote...
>> Hello Org-mode community. I’m using Emacs Doom Framework, specifically:
>> 
>> Emacs 28.2 (build 1, aarch64-apple-darwin22.3.0, Carbon Version 169
>> AppKit 2299.4) of 2023-02-23.
>> 
>> I use heavily org-mode for Literate DevOps, so I have a lot of shell
>> commands that connect through SSH and do some things later, for
>> example:
>> 
>> #+name: initSSH
>> #+begin_src shell :var connection=“admin@somehost"
>> 
>> ssh -t miguel@host "sudo -u someuser ssh -t $connection 'sudo su'"
>> #+end_src
>> 
>> So then I can call:
>> 
>> #+call: initSSH(connection=“admin@anotherhost”)
>> 
>> With any other header parameters or session, the above works
>> correctly. I cannot use tramp due to network latency issues, so this
>> is the most performance way for me, since I also have to do some
>> multi-hops which are indeed supported in tramp, but it is too slow for
>> me, so I rather only commands.
>> 
>> The thing is that, I then would like to call these not with a #+call
>> function, but add them into a bigger script, let’s say that I define
>> another command:
>> 
>> #+name: getStorage
>> #+begin_src shell
>> 
>> df
>> #+end_src
>> 
>> Which has to be run in a remote server, could be any remote server as
>> I have to connect to several. So I would like to be able to:
>> 
>> #+begin_src shell
>> <<initSSH(connection=“admin@anotherhost”)>>
>> <<getStorage>>
>> #+end_src
>> 
>> 
>> The first doesn’t work as org-mode runs the code and passes the
>> resulting string to bash, which isn’t a command. The latter works
>> normally. So the issue here are the parameters.
>> 
>> So I made another simple example for this:
>> 
>> #+name: greeting
>> #+begin_src sh :var name="world" :results output :session testing
>> 
>> echo "hello, $name\!"
>> #+end_src
>> 
>> #+results: greeting
>> #+begin_src sh
>> 
>> hello, world\!
>> #+end_src
>> 
>> #+begin_src shell
>> <<greeting(name="ss")>>
>> #+end_src
>> 
>> 
>> This results in sh: hello,: command not found, as it is executing the function. I see in the documentation that I can:
>> - Call a function’s body with <<namedcodeblock>>
>> - Execute a function and return its results with <<namedcodeblock()>>
>> - Execute a function and return its results even with different params with <<namedcodeblock(param=“sds”)>>
>> 
>> So right now, the one that’s missing is, call a function’s body with different parameters. So the
>> function <<namedcodeblock>> is not evaluated.
>> 
>> After searching a lot, I came across:
>> 
>> #+begin_src shell :session testing
>> <<greeting[:body](name="Testingggg")>>
>> #+end_src
>> 
>> Which results in:
>> 
>> sh-3.2$ PS1="org_babel_sh_prompt> "
>> org_babel_sh_prompt> name='Testingggg'
>> org_babel_sh_prompt> echo "hello, $name\!"
>> hello, Testingggg\!
>> org_babel_sh_prompt> echo 'org_babel_sh_eoe'
>> org_babel_sh_eoe
>> org_babel_sh_prompt> hello, Testingggg\!
>> sh: hello,: command not found
>> org_babel_sh_prompt> echo 'org_babel_sh_eoe'
>> org_babel_sh_eoe
>> org_babel_sh_prompt> 
>> 
>> Which is somewhat what I need since at least the variable is changed,
>> but the result of this execution is also passed to shell so, same
>> error.
>> 
>> I can’t find much documentation about this, what is the correct syntax
>> here?,
>> 
>> Thank you!
> 


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

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

* Re: Noweb Function's body without evaluation
  2023-03-15 22:54 Noweb Function's body without evaluation suarezmiguelc
  2023-03-16  4:16 ` Ken Mankoff
@ 2023-04-02 10:06 ` Ihor Radchenko
  2023-04-03 13:03   ` suarezmiguelc
  1 sibling, 1 reply; 6+ messages in thread
From: Ihor Radchenko @ 2023-04-02 10:06 UTC (permalink / raw)
  To: suarezmiguelc; +Cc: emacs-orgmode

suarezmiguelc@icloud.com writes:

> I use heavily org-mode for Literate DevOps, so I have a lot of shell commands that connect through SSH and do some things later, for example:
>
> #+name: initSSH
> #+begin_src shell :var connection=“admin@somehost"
> ssh -t miguel@host "sudo -u someuser ssh -t $connection 'sudo su'"
> #+end_src
>
p ...>
> #+name: getStorage
> #+begin_src shell
> df
> #+end_src
>
> Which has to be run in a remote server, could be any remote server as I have to connect to several. So I would like to be able to:
>
> #+begin_src shell
> <<initSSH(connection=“admin@anotherhost”)>>
> <<getStorage>>
> #+end_src

You can just

#+begin_src shell :var connection "admin@anotherhost"
<<initSSH>>
<getStorage>>
#+end_src

-- 
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] 6+ messages in thread

* Re: Noweb Function's body without evaluation
  2023-04-02 10:06 ` Ihor Radchenko
@ 2023-04-03 13:03   ` suarezmiguelc
  2023-04-04 12:14     ` Ihor Radchenko
  0 siblings, 1 reply; 6+ messages in thread
From: suarezmiguelc @ 2023-04-03 13:03 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode

Wow, works!, thank you very much.

Now, I have a more specific example.

#+name: initSSH
#+begin_src shell :var connection=“admin@10.0.3.200" :noweb yes
ssh -t miguel@172.28.3.249 "sudo -u admin ssh -t $connection 'sudo su'"
#+end_src

#+name: getClientInstanceNameNew
#+begin_src shell :session something :var connection="admin@10.0.3.149" :var client="example_client" :var apacheDir="/etc/apache/vhosts"
<<initSSH>>
client=$client
apacheDir=$apacheDir
grep $client $apacheDir/*
#+end_src

So, the initSSH call works successfully, so that concludes my first question, being that I can now affect the $connection variable. Thank you again!

However, since the SSH call changes the environment, the $client and $apacheDir variables are not defined in the new environment. I did try setting it again like above, but this doesn’t help as the variables do not exist.

 99% of the commands I run are remote so, I will keep investigating this. It would make more sense to use :dir and tramp, but as the connections are slow, I can only connect with this call which works pretty fast.

> 2/4/23 12:06、Ihor Radchenko <yantar92@posteo.net>のメール:
> 
> suarezmiguelc@icloud.com writes:
> 
>> I use heavily org-mode for Literate DevOps, so I have a lot of shell commands that connect through SSH and do some things later, for example:
>> 
>> #+name: initSSH
>> #+begin_src shell :var connection=“admin@somehost"
>> ssh -t miguel@host "sudo -u someuser ssh -t $connection 'sudo su'"
>> #+end_src
>> 
> p ...>
>> #+name: getStorage
>> #+begin_src shell
>> df
>> #+end_src
>> 
>> Which has to be run in a remote server, could be any remote server as I have to connect to several. So I would like to be able to:
>> 
>> #+begin_src shell
>> <<initSSH(connection=“admin@anotherhost”)>>
>> <<getStorage>>
>> #+end_src
> 
> You can just
> 
> #+begin_src shell :var connection "admin@anotherhost"
> <<initSSH>>
> <getStorage>>
> #+end_src
> 
> -- 
> 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] 6+ messages in thread

* Re: Noweb Function's body without evaluation
  2023-04-03 13:03   ` suarezmiguelc
@ 2023-04-04 12:14     ` Ihor Radchenko
  0 siblings, 0 replies; 6+ messages in thread
From: Ihor Radchenko @ 2023-04-04 12:14 UTC (permalink / raw)
  To: suarezmiguelc; +Cc: emacs-orgmode

suarezmiguelc@icloud.com writes:

> #+name: getClientInstanceNameNew
> #+begin_src shell :session something :var connection="admin@10.0.3.149" :var client="example_client" :var apacheDir="/etc/apache/vhosts"
> <<initSSH>>
> client=$client
> apacheDir=$apacheDir
> grep $client $apacheDir/*
> #+end_src
>
> So, the initSSH call works successfully, so that concludes my first question, being that I can now affect the $connection variable. Thank you again!
>
> However, since the SSH call changes the environment, the $client and $apacheDir variables are not defined in the new environment. I did try setting it again like above, but this doesn’t help as the variables do not exist.

Org babel knows not if the environment changes along the way.
Of course, you can break the variable in bash by calling "bash" as one of
the commands in src block. Or you can do more crazy staff and call
"python" (or, say, "ghci") interpreter. There is no sane way to handle
such weird scenarios programmatically.

I suggest you to write some kind of wrapper like

#+name: obl-identity
#+begin_src emacs-lisp :var x=""
x
#+end_src

#+begin_src bash :noweb yes
<<initSSH>>
client=<<obl-identity(x="example_client")>>
#+end_src

This will not rely on language-specific way to define variables and
instead generate the code you want to execute fully, on Elisp side.

-- 
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] 6+ messages in thread

end of thread, other threads:[~2023-04-04 12:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-15 22:54 Noweb Function's body without evaluation suarezmiguelc
2023-03-16  4:16 ` Ken Mankoff
2023-03-16  7:56   ` suarezmiguelc
2023-04-02 10:06 ` Ihor Radchenko
2023-04-03 13:03   ` suarezmiguelc
2023-04-04 12:14     ` Ihor Radchenko

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).