Nam Nguyen
Nam Nguyen

Reputation: 1793

How to force whitespace in code block in reStructuredText

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.

Upvotes: 11

Views: 4581

Answers (3)

Clément
Clément

Reputation: 12937

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.

Upvotes: 1

Kevin Horn
Kevin Horn

Reputation: 4295

You can also try Line Blocks which look like this:

|     def foo(x):
|         pass

though they aren't specific to code examples.

Upvotes: 0

Owen
Owen

Reputation: 39366

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.

Upvotes: 0

Related Questions