21

If I have a code snippet that I tangle to a file, but I expect the file name to change over time, Is there a cleaner way to change the filename than Query-replace?

For example, say I tangle code to ~/dir/my-file.el:

#+BEGIN_SRC emacs-lisp :tangle ~/dir/my-file.el
(setq myvar1 "value1")
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle ~/dir/my-file.el
(defun foo (bar) ... )
#+END_SRC

etc.

Then later on I realize that the file would be better placed in another location:

#+BEGIN_SRC emacs-lisp :tangle ~/dir/my/file.el
(setq myvar1 "value1")
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle ~/dir/my/file.el
(defun foo (bar) ... )
#+END_SRC

etc.

Is there a way to change the argument to :tangle dynamically.

I have investigated and discovered that I can feed elisp into the :tangle argument. If I evaluate (setq myfile "~/dir/file.el) and then tangle the following:

#+BEGIN_SRC emacs-lisp :tangle (print myfile)
(setq myvar1 "value1")
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle (print myfile)
(defun foo (bar) ... )
#+END_SRC

I get the desired result I am looking for. I could then execute an elisp snippet to set the variable using org-babel, but I was wondering if there is a cleaner way to do so.

The docs on the :tangle header do not stipulate a native way.

2 Answers 2

19

You should not repeat such things, but define them in one place. For example you can define output file in a drawer as header args for whole tree and subtrees:

* Header
:PROPERTIES:
:tangle: ~/dir/my/testfile.el
:END:

or for :dir

* Header
:PROPERTIES:
:header-args: :dir ~/dir/my/dir/
:END:

As described in docs you can have:

  • System-wide header arguments
  • Language-specific header arguments
  • Header arguments in Org mode properties
  • Language-specific header arguments in Org mode properties
  • Code block specific header arguments
  • Header arguments in function calls
7

You can use a property of the org heading instead of a setq

* Header
:PROPERTIES:
:PRJ-DIR: ~/prj/dir/
:END:

#+BEGIN_SRC emacs-lisp :tangle (concat (org-entry-get nil "PRJ-DIR" t) "file.el")
(setq myvar1 "value1")
#+END_SRC

#+BEGIN_SRC emacs-lisp :tangle (concat (org-entry-get nil "PRJ-DIR" t) "file.el")
(defun foo (bar) ... )
#+END_SRC

etc.

This way you can set different file names for each source block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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