11

In RST, we use some whitespaces in front of a block to say this is a code block. Because Python also uses whitespace to indent a code block, I would like my RST code block to preserve those whitespaces if I were writing Python code. How can I do that?

Let's say we have a class:

class Test(object):

And we want to write a method called __init__ that is a member of this class. This method belongs to another code block but we want to have some visual clue so that readers know that this second block is a continuation of the previous one. At the moment, I use # to mark the vertical guide line of a code block like this:

    def __init__(self):
        pass
#

Without the #, def __init__(self) would be printed at the same indentation level as class Test(object). There's gotta be more elegant way.

Nam Nguyen
  • 1,765
  • 9
  • 13
  • can you indicate what doesn't work? maybe i'm being stupid, but i have written rst docs like this http://code.google.com/p/pytyp/source/browse/pytyp.rst#685 with python code and don't need to do anything special. – andrew cooke Aug 12 '11 at 02:02
  • Andrew, I added more clarification. – Nam Nguyen Aug 12 '11 at 02:07
  • but that's not true. for example http://code.google.com/p/pytyp/source/browse/pytyp.rst#750 works fine (the doc is at http://acooke.org/pytyp.pdf and that class is on p7). maybe i am still misunderstanding. why are you calling the end of code the beginning of a code block? – andrew cooke Aug 12 '11 at 02:09
  • 1
    Andrew, the `def...` is in another code block, not the same block as `class...` but I would like to make it indented one level so that readers know it is a continuation from the previous block. I am sorry that my wording is confusing. By "beginning" I meant "vertical guide line". – Nam Nguyen Aug 12 '11 at 02:26
  • oh, sorry! so this is code across multiple code blocks. now i see. sorry... – andrew cooke Aug 12 '11 at 02:44

3 Answers3

1

You need to define your own directive (it's true that the standard .. code:: directive gobbles spaces but you can make your own directive that doesn't):

import re
from docutils.parsers.rst import directives

INDENTATION_RE = re.compile("^ *")

def measure_indentation(line):
    return INDENTATION_RE.match(line).end()

class MyCodeBlock(directives.body.CodeBlock):
    EXPECTED_INDENTATION = 3

    def run(self):
        block_lines = self.block_text.splitlines()
        block_header_len = self.content_offset - self.lineno + 1
        block_indentation = measure_indentation(self.block_text)
        code_indentation = block_indentation + MyCodeBlock.EXPECTED_INDENTATION
        self.content = [ln[code_indentation:] for ln in block_lines[block_header_len:]]
        return super(MyCodeBlock, self).run()

directives.register_directive("my-code", MyCodeBlock)

You could of course overwrite the standard .. code:: directive with this, too.

Clément
  • 12,299
  • 15
  • 75
  • 115
0

Ah... I've run into this before ;). The # trick is usually what I use, alas. If you read the spec it sounds like it will always take away the leading indent. [1]

You could also use an alternate syntax:

::

>     def foo(x):
>         pass

With the leading ">" that will preserve leading space.

[1] : http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#indented-literal-blocks

EDIT

Just dug through the docutils code (this has been bugging me a lot too) and can confirm that it will always strip out the common indent, no questions asked. It would be easy to modify to change this behavior but that would make the resulting restructured text non-standard.

Owen
  • 38,836
  • 14
  • 95
  • 125
  • 2
    The leading ">" is also preserved in the text. Not only does it need an extra character per line, but it may confuse readers also. – Nam Nguyen Aug 12 '11 at 03:41
  • @Nam Yeah, sorry I don't know a better way. You could make your own directive that strips out the fudge "#", but that may be more work than this is worth. – Owen Aug 12 '11 at 04:00
0

You can also try Line Blocks which look like this:

|     def foo(x):
|         pass

though they aren't specific to code examples.

Kevin Horn
  • 4,167
  • 28
  • 30