Skip to content

Instantly share code, notes, and snippets.

@zondo
Last active September 17, 2024 02:30
Show Gist options
  • Save zondo/01e09b68e1d763389b6f19d289959178 to your computer and use it in GitHub Desktop.
Save zondo/01e09b68e1d763389b6f19d289959178 to your computer and use it in GitHub Desktop.
Conditional tangling in org mode based on tags

Conditional Tangling based on Tags

I recently came across a little-known (to me, anyway) feature of org mode, thanks to this mailing list reply: conditional tangling. In the :tangle argument, as well as the standard values (yes, no or a filename string), you can also set it dynamically, by specifying an elisp expression which evaluates to the tangle setting.

This is quite useful together with tags. Here’s a function which sets the argument based on which tags are currently set in the file:

(defun if-tags (tags &optional filename)
  "Return tangle setting based on tags.

This function is intended to be used as a :tangle argument.
TAGS is a colon-separated list of tags.  If all the tags are set, the tangle setting
is \"yes\" (or FILENAME, if defined).  Otherwise it is \"no\"."
  (let ((tags (split-string tags ":")))
    (if (equal (seq-intersection (org-get-tags) tags) tags)
        (or filename "yes") "no")))

With this function defined, things like this become possible:

#+begin_src toml :tangle (if-tags "foo")
  foo = "I am only tangled if 'foo' is set"
#+end_src

#+begin_src toml :tangle (if-tags "bar")
  bar = "I am only tangled if 'bar' is set"
#+end_src

#+begin_src toml :tangle (if-tags "foo:bar")
  foobar = "I am only tangled if both 'foo' and 'bar' are set"
#+end_src

I’m using this to define feature tags set by #+filetags: in a literate project config file, and it’s working pretty well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment