0

The context

I always experiment with commands in the following path $HOME/trash/experimental. For this reason, I wanted to make all shell code blocks to use that directory as the default directory. I've already accomplished that by setting the following in my configuration

$ cat ~/.emacs.d/init.el
(org-babel-do-load-languages
 'org-babel-load-languages '((shell . t)))

(setq org-babel-default-header-args:shell '((:dir . "~/trash/experimental")))

Sometimes I also play with the zsh and the dash shell so I would also make the previous mentioned directory as the default one for code blocks whose language is any of those shells. Similarly, I can accomplish that by setting the following in my init.el file.

$ cat ~/.emacs.d/init.el
(org-babel-do-load-languages
 'org-babel-load-languages '((shell . t)))

(setq org-babel-default-header-args:shell '((:dir . "~/trash/experimental")))
(setq org-babel-default-header-args:dash '((:dir . "~/trash/experimental")))
(setq org-babel-default-header-args:zsh '((:dir . "~/trash/experimental")))

As seen above, the path is repeated three times. In order to avoid that I defined a variable that stores the path where I experiment with commands (i.e. ~/trash/experimental). Thus, my configration file looks like

$ cat ~/.emacs.d/init.el
(org-babel-do-load-languages
 'org-babel-load-languages '((shell . t)))

(setf path/experiments "~/trash/experimental")

(setq org-babel-default-header-args:shell '((:dir . path/experiments)))
(setq org-babel-default-header-args:dash '((:dir . path/experiments)))
(setq org-babel-default-header-args:zsh '((:dir . path/experiments)))

This is where the problem comes.

The problem

When evaluating code blocks whose language is shell, dash or zsh, I get the following error

Wrong type argument: stringp, path/experiments

The question

How can I use the value of a variable so that it affects all code blocks whose language is zsh, dash or shell?

0

You can accomplish this by using the concept of backquoting. Consider the following minimal configuration. Note the usage of `(...) and , within `(...)

$ cat ~/.emacs.d/init.el
(org-babel-do-load-languages
 'org-babel-load-languages '((python . t) (shell . t)))

(setq my/path/experiments "~/trash/experimental")

(defun path/experiments (&optional file)
  (if file
      (concat my/path/experiments "/" file) my/path/experiments))

(setq org-babel-default-header-args:sh
  `((:dir . ,(path/experiments)) 
    (:tangle . ,(path/experiments "sh.sh"))))
$

This would cause the following behavior in an Org file

* My heading

** My subheading

#+begin_src sh
pwd
#+end_src

#+RESULTS:
: /home/myname/trash/experimental

#+begin_src python :results output
import os
print(os.getcwd())
#+end_src

#+RESULTS:
: /home/myname/location/of/this/file

Note that this configuration file would evaluate the expression once Emacs reaches the setq statements. This implies that if you change the value of the variable my/path/experiments, then that value will not be evaluated when obtaining the header arguments for sh code blocks. What I state can also be proved because of the fact that the value of org-babel-defaul-header-args:sh stores strings instead of expressions. As far as I know, those strings are set once Emacs reaches that statement in your configuration file or when you evaluate it.

org-babel-default-header-args:sh is a variable defined in ‘ob-shell.el’.
Its value is
((:dir . "~/trash/experimental")
 (:tangle . "~/trash/experimental/sh.sh"))

If you want to change the value of the variable, you would need to evaluate the expression that sets the header arguments again

(setq org-babel-default-header-args:sh
  `((:dir . ,(path/experiments)) 
    (:tangle . ,(path/experiments "sh.sh"))))
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.