2

Is it possible to use the result of one source code block not within another code block but actually within another source blocks header argument? I know this piece of functionality works

#+name: block-1
#+BEGIN_SRC emacs-lisp
(current-time-string)
#+END_SRC

#+BEGIN_SRC emacs-lisp :var input=block-1
(format "We got %S in block-1" input)
#+END_SRC

but what I want is something like this, i.e. to reuse the result to e.g. form a path for the dir header argument

#+name: block-1
#+BEGIN_SRC emacs-lisp
(current-time-string)
#+END_SRC

#+BEGIN_SRC emacs-lisp :var input=block-1 :dir path/input
(format "We got %S in block-1" input)
#+END_SRC

so what I want to achieve is to have a variable path for the :dir header argument.

maybe there is a way to concatenate the argument to :dir in a dynamic way depending on what the first source block resulted in?

Drew
  • 75,699
  • 9
  • 109
  • 225
CD86
  • 543
  • 2
  • 9

3 Answers3

2

Looks like it might be possible to achieve it by creating a helper lisp function:

#+name: block-1
#+BEGIN_SRC sh
  echo '/bin'
#+END_SRC

#+RESULTS: block-1
: /bin

#+begin_src emacs-lisp :results silent
  (defun result1 ()
    (save-excursion
      (org-babel-goto-named-result "block-1")
      (setq value (org-babel-read-result))
      )
    (print value)
    )
#+end_src

#+BEGIN_SRC sh :dir (result1) :results scalar
  pwd
#+END_SRC

#+RESULTS:
: /bin

In second code block we define a function result1 which prints contents of block-1 result (those with better lisp knowledge can make this function accept an argument), and in last code block we use output of this function as current directory (:dir (result1)). Apparently, it's a documented feature.

Lex-2008
  • 21
  • 1
2

Use org-sbe in :dir header to fetch the result from a named block.

Tip: Create dirB directory in same directory as the org-mode example file otherwise the pwd command will throw an error.

#+NAME: block-a
#+BEGIN_SRC elisp 
(format "%sdirB" (file-name-directory (buffer-file-name)))
#+END_SRC

#+RESULTS: block-a
: /tmp/sx/org-mode/dirB

#+NAME: block-b
#+BEGIN_SRC bash :dir (org-sbe block-a)
  pwd
#+END_SRC 

#+RESULTS: block-b
: /tmp/sx/org-mode/dirB


This answer was tested using:
emacs version: GNU Emacs 25.2.1 (x86_64-unknown-cygwin, GTK+ Version 3.22.10) org-mode version: 9.1.2

Melioratus
  • 4,504
  • 1
  • 25
  • 43
  • 3
    As two of the answers here point out, you can give a value to e.g. `:dir` by evaluating a lisp form. As this answer points out, `org-sbe` can be used to get the result of another source block (as a string). But you cannot write `:dir foo/(org-sbe "something")` trying to interpolate the result of a lisp call in a string: you have to do something like this instead: `:dir (concat "foo/" (org-sbe "something"))`. – NickD Apr 15 '20 at 01:58
  • thanks a lot guys for the help. I stuck with the sbe option. The background is, that I want to assemble a path to attach to docker container dynamically via docker-tramp https://github.com/emacs-pe/docker-tramp.el by generating container names in a shell script during execution – CD86 Apr 15 '20 at 07:46
  • 1
    in the sbe case, is the first code block automatically run when the second one is executed? – CD86 Apr 15 '20 at 10:06
  • @CD86 - Correct, the first block is executed automatically when the second block is executed because the headers on the second block are evaluated before the code in the second block is evaluated. The `org-sbe` macro can be very useful to fetch results from code blocks. – Melioratus Apr 15 '20 at 14:30
  • @CD86 - I use org-mode for Literate DevOps everyday and have been looking for a way to add docker in my CI/CD pipelines. I hope you’ll write up a tutorial and/or add your answer when you get this working. – Melioratus Apr 15 '20 at 14:36
  • I will try to. Still figuring it out myself xD – CD86 Apr 15 '20 at 15:07
  • +1 to Melioratus's request for a write-up @CD86. I hope if you succeed(ed) you get around to linking here and tagging both of us please please :) – Reed Spool Jul 24 '20 at 05:38
1

You can use org-babel-execute:org from that answer. Just put it in your init file. I think a (require 'cl-lib) in front of it should make the code run in your init file.

Therewith executing an org source block will duplicate it with the header variables replaced by their values.

See the following example:

Before Execution:

#+NAME: block-1
#+BEGIN_SRC emacs-lisp 
"2020-04-14"
#+END_SRC

#+BEGIN_SRC org :var mydir=block-1 :noweb yes :results raw
,#+BEGIN_SRC emacs-lisp :dir mydir
default-directory
,#+END_SRC
#+END_SRC

After Execution With C-c C-v b:

#+NAME: block-1
#+BEGIN_SRC emacs-lisp 
"2020-04-14"
#+END_SRC

#+RESULTS: block-1
: 2020-04-14

#+BEGIN_SRC org :var mydir=block-1 :noweb yes :results raw
,#+BEGIN_SRC emacs-lisp :dir mydir
default-directory
,#+END_SRC
#+END_SRC

#+RESULTS:
#+BEGIN_SRC emacs-lisp :dir 2020-04-14
default-directory
#+END_SRC

#+RESULTS:
: /home/Tobias/Work/2020-04-14/
Tobias
  • 32,569
  • 1
  • 34
  • 75
  • this doesnt work for me for some reason. let alone, that the escaping of source code block is maeh... – CD86 Apr 15 '20 at 15:50