Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 225
Nam Nguyen Avatar asked Aug 12 '11 01:08

Nam Nguyen


People also ask

How do you use a sphinx code block?

Literal code blocks (ref) are introduced by ending a paragraph with the special marker :: . The literal block must be indented (and, like all paragraphs, separated from the surrounding ones by blank lines): This is a normal text paragraph.

How do I add a new line to an RST file?

To get a new line immediately following a few long lines I have to a) start a new (empty) line and b) THEN (on the next line) follow it with | <my new line> .

How do I comment in RST file?

For comments, add 2 periods .. followed by a newline and then your comment indented.


1 Answers

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.

like image 53
Clément Avatar answered Oct 27 '22 01:10

Clément