3

In literate programming, I often like to write my code in small snippets and then export them all at once via org-babel-tangle. This works great for non-indentation sensitive code (especially with post-processing), but doesn't work quite well with languages like Haskell or Python as org-babel-tangle removes the initial whitespace:

This is a completely self-contained example of the problem. Copy it into an org-mode buffer and try both =M-x org-export-dispatch= and =M-x org-babel-tangle=. * A simple Python function :PROPERTIES: :header-args:python: :tangle example.py :padline no :END: Here's a small example function in Python: #+begin_src python :shebang "#!/usr/bin/env python" def foo(): #+end_src According to org-mode's documentation[fn:1], we can use `-i' to keep the indentation, so let's do that on the continuation of the aforementioned example: #+begin_src python -i """Says hello!""" print("Hello, world!") #+end_src If we (org-export-dispatch) the file, then everything seems nice. However, if we (org-babel-tangle) the file, then the indentation is gone and thus our Python file invalid. * Footnotes [fn:1] See [[info:org#Literal Examples][info:org#Literal Examples]]. 

The -i switch doesn't seem to work for org-babel-tangle at all. While I could use <<noweb>> to glue the code together in a hidden, non-exported source block, I would rather like to have org-babel-tangle behave correctly.

Is there some hidden option I'm missing? How can I keep the indentation when I tangle files via org-babel-tangle similarly to the -i switch for exporting?

1 Answer 1

5

You can use the variable org-src-preserve-indentation. If you set it to t before tangling like this:

#+begin_src emacs-lisp (setq org-src-preserve-indentation t) #+end_src 

then the tangle will work as you expect.

The variable is defined with a defcustom so it is meant to be customized as you wish. You can either set it in your init file as above or customize it by hitting the customize link in its docstring, which you get with C-h v org-src-preserve-indentation.

EDIT: As a couple of comments point out, Emacs provides a very general mechanism (it can be used in any file, not just Org mode files) for setting the value of a variable as a local, per-file variable. As the documentation of file local variables points out, you can add a section at the very end of the file, like this:

... * File local variables :noexport: # Local Variables: # org-src-preserve-indentation: t # End: 

Tagging the section as noexport prevents it from cluttering up any exported material.

Alternatively, you can add a single line (as a comment, so that Org mode will ignore it) at the top of the file like this:

# -*- org-src-preserve-indentation: t -*- ... 

Local variables are activated when the file is opened, so after adding the local variable, you either have to save and kill the buffer and then reopen the file, or perhaps more conveniently do M-x normal-mode. If you get a question about safe local variables, you might want to add this variable to the list of safe local variables by pressing !.

4
  • Hm. It's unfortunate that a global variable is necessary. I usually like to keep #+OPTIONS or PROPERTIES local. I'll guess I'll use add-file-local-variable and add (org-src-preserver-indentation . t) to the safe values/variables. Commented Jan 6, 2021 at 11:04
  • You might want to suggest that as an RFE on the Org mode mailing list. The thinking goes, I'm guessing, that users prefer it one way or the other and that does not depend on the block or file. Making everything local to a file does have an overhead I imagine. I'm a bit surprised that the default value is nil though. Commented Jan 6, 2021 at 14:46
  • Great answer. I had the same problem. It seems that the author of the document should determine how the code is tangled... but I'm sure there is wisdom in the current setup. Commented Feb 9, 2021 at 17:18
  • Actually variables can be set per-document with a header # -*- org-src-preserve-indentation: t; -*- stackoverflow.com/a/20033865/1013628 Commented Feb 23, 2022 at 7:16

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.