1

I am writing a report in latex, many of which contain code blocks which will be rendered with asymptote.

Since all the scripts will be tangled into the same subdirectory asyscripts, I don't want to have to write code like this

#+BEGIN_SRC asy :tangle asyscripts/test.asy
write("Hello World!");
#+END_SRC

Specifying asyscripts every time is just too tedious. Any way I can specify globally which directory all the code blocks must be tangled into? (Each code block will be in general tangled into a different script. )

0

I could not find any header args to do this (I thought that :dir would be the one, but it does not make any difference in tangling). But you can use the post-tangle hook, org-babel-post-tangle-hook, to manipulate the tangled files after they are produced. Here is a test file:

#+PROPERTY: dest ./tangled/

* Link

* TODO foo

#+BEGIN_SRC asy :tangle test.asy
write("Hello World!");
#+END_SRC


#+BEGIN_SRC asy :tangle test2.asy
write("Good-bye World!");
#+END_SRC


* Code                                                                                                        :noexport:

#+begin_src emacs-lisp
  (setq ndk/tangle-dir (org-entry-get nil "dest" t))

  (defun ndk/org-babel-tangle-rename ()
    (let ((tangledir ndk/tangle-dir)
          (tanglefile (buffer-file-name)))
        (rename-file tanglefile tangledir t)))

  (add-hook 'org-babel-post-tangle-hook #'ndk/org-babel-tangle-rename)
#+end_src

The code consists of three things:

  • the setting of a global variable ndk/tangle-dir to the directory path where you want the tangled files to end up. You could hardwire this into the function, but I made it a bit more flexible by defining a global #_PROPERTY called dest whose value is the path (N.B. The path MUST end with a slash). We retrieve the value of the dest property with org-entry-get and set ndk/tangle-dir to that value.

  • a function that will be called through the hook on every file that is tangled. The function is run in a buffer that contains the tangled output. We retrieve the file name from the buffer, and then we call rename-file to move that file to the destination directory. The t argument means it's OK to move it there even if a file with the same name exists in that directory already.

  • adding the function above to the org-babel-post-tangle-hook.

If you create an Org mode file with the contents above, and create the destination directory, you should be able to open the Org mode file, C-c C-c on the source code block, C-c C-v C-t to tangle the two blocks in the foo section and then check out the contents of the destination directory: the two tangled files should be there.

You probably want to remove the function from the hook afterwards, otherwise all files you tangle will end up in that directory:

(remove-hook 'org-babel-post-tangle-hook #'ndk/org-babel-tangle-rename)

For another example of the use of this hook, see this recent question. As you can see, it's pretty flexible!

0

Have you tried adding in this Header property at the top of your org file? This is what I add to most of my org files that I want tangled to a specific directory.

#+PROPERTY: header-args:emacs-lisp :noweb yes :tangle emacs.d/init.el

just replace the emacs.d/init.el with the location of where you want your tangle files to be located. You can drop the ":emacs-lisp" and the ":noweb yes" if you don't need them. So to just recap, you can try just adding this to the top of your file:

#+PROPERTY: header-args  :tangle "asyscripts/test.asy"

and it should tangle your source blocks to that location. (I'm using emacs 25.3.1 and Org mode version 9.2.3 (9.2.3-13-g727c3f-elpa if that helps, I've been using this tag back from org mode version 9.1.10)

1
  • They are to be tangled to the same subdirectory, but (as I read the question) NOT to the same file. – NickD Oct 23 '20 at 16:56

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.