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
  • 29,717
  • 3
  • 27
  • 44
doltes
  • 587
  • 2
  • 11

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
  • 29,717
  • 3
  • 27
  • 44
doltes
  • 587
  • 2
  • 11