6
votes

When writing literate Python with Org–Babel, I need to be able to control the indentation level (either explicitly with :indentation-level 3 or implicitly with some clever indication).

Here's an example file that demonstrates the problem.

#+BEGIN_SRC python :tangle "sample.py"
  class Test:
      def __init__(self):
          self.a = 'a test class'
#+END_SRC
#+BEGIN_SRC python :tangle "sample.py"
      def say_hi(self):
          print 'Hi from this Test object!'
          print 'ID: {}'.format(repr(self))
          print 'Data: {}'.format(str(self.__dict__))
#+END_SRC
3
Hm, org-babel respects the indentation of the programming mode. If you edit the code snippet with C-' you can change the indentation with C-c > from python-mode. But, I guess this is not what you want. What is the reason for the wanted option :indentation-level?Tobias
@Tobias When I org-babel-tangle the file, indentation is not respected given a whitespace prefix with the #+begin_src environment. Everything is alright if I keep it all in one source block, but good sense says to split it up and explain each part.Sean Allred
But, this works for me! All indentation is copied verbatim from the org file.Tobias
@Tobias How strange… I will upload a video to prove I'm not crazy XDSean Allred
@Tobias Org version 8.2.4: youtube.com/watch?v=T0gGW3T4zRo (warning: my keyboard is a little loud)Sean Allred

3 Answers

9
votes

Set org-src-preserve-indentation to t.

3
votes

I didn't perfectly like Tobias' answer because when I org-edit-special (C-c ') a code block, my python-mode buffer would yell at me (I have several python minor modes with syntax checkers) because of the unexpected indent for blocks with stand-alone methods (because with org-src-preserve-indentation set, I would have indents in front of all my methods in their individual blocks). So instead, I like this solution using org-mode's :noweb header argument:

#+BEGIN_SRC python :tangle "sample.py" :noweb yes
  class Test:
      <<init_method>> # these are indented
      <<more_methods>> # these are indented
#+END_SRC

#+BEGIN_SRC python :noweb-ref init_method
  def __init__(self):
      self.a = 'a test class'
#+END_SRC

#+BEGIN_SRC python :noweb-ref more_methods
  def say_hi(self):
      print 'Hi from this Test object!'
      print 'ID: {}'.format(repr(self))
      print 'Data: {}'.format(str(self.__dict__))
#+END_SRC

As long as you just indent the Noweb syntax references (the double << >>) in your class definition, the other blocks ("init_method" and "more_methods") will be tangled with respect to your indentation. So, the final output "sample.py" file looks like this:

class Test:
    def __init__(self):
        self.a = 'a test class'
    def say_hi(self):
        print 'Hi from this Test object!'
        print 'ID: {}'.format(repr(self))
        print 'Data: {}'.format(str(self.__dict__))

Nice!

0
votes

I know it is not the desired solution but as a work around you can insert a comment (specific to your programming language) in the source block and make the desired indentation after that comment. This will also preserve the indentation when exiting the edit-buffer

#+BEGIN_SRC python :tangle "sample.py"
  class Test:
      def __init__(self):
          self.a = 'a test class'
#+END_SRC
#+BEGIN_SRC python :tangle "sample.py"
  # This is my dummy python comment to keep the correct indentation 
      def say_hi(self):
          print 'Hi from this Test object!'
          print 'ID: {}'.format(repr(self))
          print 'Data: {}'.format(str(self.__dict__))
#+END_SRC