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?

NickD
  • 27,023
  • 3
  • 23
  • 42
doltes
  • 567
  • 2
  • 11
  • 2
    Does this answer your question? [Backward quote, what does it mean in elisp?](https://emacs.stackexchange.com/questions/27007/backward-quote-what-does-it-mean-in-elisp) – NickD Oct 17 '20 at 01:08
  • 1
    Does this answer your question? [How to evaluate the variables before adding them to a list?](https://emacs.stackexchange.com/questions/7481/how-to-evaluate-the-variables-before-adding-them-to-a-list) – Drew Oct 17 '20 at 17:46
  • Yes, those questions helped. Thanks for the help. I still answered my question just in case anyone have the same problem and doesn't have enough time to read the documentation. – doltes Oct 17 '20 at 20:22

1 Answers1

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"))))
NickD
  • 27,023
  • 3
  • 23
  • 42
doltes
  • 567
  • 2
  • 11