Control indentation with Org–Babel
Asked Answered
J

3

7

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
Jot answered 3/1, 2014 at 0:54 Comment(7)
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?Axinomancy
@Axinomancy 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.Jot
But, this works for me! All indentation is copied verbatim from the org file.Axinomancy
@Axinomancy How strange… I will upload a video to prove I'm not crazy XDJot
@Axinomancy Org version 8.2.4: youtube.com/watch?v=T0gGW3T4zRo (warning: my keyboard is a little loud)Jot
Sorry that you had to go through this. After your video I re-started emacs with -q and recognized what you mean. The solution is in the answer.Axinomancy
@Axinomancy I just updated emacs for a new machine so I'll re-test your answer. Just as a record for what I did in the meantime, using noweb references solves the issue in practice.Jot
A
9

Set org-src-preserve-indentation to t.

Axinomancy answered 3/1, 2014 at 11:50 Comment(3)
It seems that, even with this set, the first line is still indented poorly: i.sstatic.net/0EwwH.pngJot
Well, this does work, but an annoying side-effect is that all the code blocks (not only python) become left justified. Is there a way to avoid this, or at least to restrict this option only to python source blocks? Thanks.Alarise
@Alarise this is my favorite answer emacs.stackexchange.com/a/62613/39420Dennet
H
4

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!

Hephzibah answered 31/3, 2018 at 15:14 Comment(0)
F
1

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
Festination answered 28/6, 2016 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.