python-sphinxrestructuredtextdocutils

Clarification on reStructuredText directive indentation rules


I'm working with Sphinx to transform reStructuredText (rst) documents to HTML.

I've read documentation (primarily Sphinx's rST primer and Docutils rST documentation) and need clarification on the indentation rules around directives.

An rst "directive" comprises:

  1. the directive marker (comprised of an explicit markup start (.. ) followed by the directive type, two colons, and whitespace),
  2. the directive arguments,
  3. the directive options, and
  4. the directive content.

I'd like to clarify my understanding about the indentation expectations of directive arguments, options, and content. My understanding is as follows:

  1. The directive marker must be given on one line

  2. Directive arguments may be given space-separated on the same line as the marker.

    • Arguments may be given (or continued) on the line immediately following the marker.
    • If the first argument is given on the same line as the marker, it sets the indentation precedent for any arguments given on subsequent lines.
    • If the first argument is given on the line following the marker, it has no indentation requirement (other than being nonzero), and sets the indentation precedent for subsequent arguments.
  3. Directive options must be given on the line immediately following the marker or the last argument.

    • The first option has no indentation requirement (other than being nonzero), and sets the precedent of subsequent options.
  4. Directive content must be given on the line following a blank line that follows the last option or the last argument or the marker (whichever applies).

    • If the directive has options, the option indentation sets the precedent for content indentation.
    • If the directive has no options, the first line of directive content has no indentation requirement (other than being nonzero), and sets the indentation precedent for subsequent lines of content.

Is that correct?

Examples that would illustrate my understanding:

.. my_markup:: arg1
               arg2_must_go_here_because_of_arg1_indentation
               arg3_must_go_here_etc
     :option_whose_indentation_does_not_matter: val1
     :option2_must_go_here_because_of_option1_indentation: val2
     :option3_must_go_here_etc: val3

     I think this line of directive content must be indented the same as the options.
     I think this and subsequent lines of directive content must be indented the ...
     same as the first line of directive content
.. my_markup:: arg1 arg2
               arg3_must_go_here_because_of_arg1_indentation
    :option_whose_indentation_does_not_matter: val1
    :option2_must_go_here_because_of_option1_indentation: val2
    :option3_must_go_here_etc: val3

    I think this line of directive content must be indented the same as the options.
    I think this and subsequent lines of directive content must be indented the ...
    same as the first line of directive content.
.. my_markup:: arg1 arg2
               arg3_must_go_here_because_of_arg1_indentation

          I think this line of directive content can be indented any nonzero amount.
          I think this and subsequent lines of directive content must be indented ...
          the same as the first line of directive content.

Solution

  • The authoritative, explicit documentation is the reStructuredText Markup Specification by David Goodger. Unfortunately, the indentation rules regarding directives are scattered over several places.

    It helps to recapitulate how a directive is parsed:

    1. After recognising a directive marker, the parser isolates the directive block (any text following the directive marker that is more indented than the line with the directive marker). The maximum common indentation is removed from the second and subsequent lines of the directive block.

      For example in this "parsed-literal" directive:

      .. parsed-literal::
         This is
      
       the directive
           block.
      
      It ends above this line.
      

      the isolated directive block is:

        This is
      
      the directive
          block.
      

      Text after the directive marker, like in

      .. parsed-literal::   First line
          and subsequent
       lines.
      

      becomes the first line of the directive block (leading whitespace is stripped):

      First line
         and subsequent
      lines.
      
    2. The isolated directive block is parsed for three logical parts: arguments, options, and content (details).

      Directives define individually, which parts they accept or require, their interpretation, and their internal syntax (see the reStructuredText Directives documentation).

    Conclusions

    Based on these considerations and a series of experiments, my understanding is that:

    1. The directive marker must be given on one line.

      • Text following the marker and all subsequent lines that are empty or more indented than the directive marker form the directive block.

      • The least indented line of the directive block lines following the directive marker sets the indentation precedent ("maximum common indentation"). Text on the same line as the marker has no influence on the expected indentation.

    2. Directive arguments may be given on the same line as the marker and/or the following line(s).

      • The indentation of argument lines does not matter (except for determining the "maximum common indentation" of the directive block), if arguments are parsed as URI ("image", "figure"), whitespace separated list ("class", "raw"), or reStructuredText inline markup ("rubric", "sidebar", "table", "topic", ...).
    3. Directive options are specified as a field-list.

      • The option list must start on the line immediately following the marker or the last argument. (If there is no argument, options may also start on the same line as the marker.)

      • The option list must not be more indented than the "maximum common indentation" of the directive block.

      • Option values may start on the same line as the marker or subsequent, indented lines. Directives may specify special syntax requirements for option values.

      • A blank line ends the option list.

    4. Directive content is the part of the directive block after the first blank line.

      • The content of directives that do not accept arguments (e.g. the specific admonitions, may start directly after or below the directive marker.

      • The content block is usually interpreted as reStructuredText body elements and indentation must follow the restrictions of rST syntax (exceptions include "code", "parsed-literal", "math", and "raw").

    Examples

    All examples are valid rST markup. They show what is possible (but not always recommended). You are invited to play with them.

    .. admonition:: admonition
             example
                one
       :name: example 1
       :class: option fields must be
           the least indented
                 lines of the block
       
       Content follows the "normal" rST indentation rules.
       
       This
         is a definition list.
    
    And this a paragraph following the directive.
    

    Directive options are optional.

    .. admonition:: example
        without options
    
     This content line can be indented to any nonzero amount.
    
     So can this (the parsing result will vary, of course).
    

    Directive options may not be more indented than any other line of the directive block:

    .. admonition:: caution
         :name: no option
         :class: but arguments
    
       This line sets the indentation precedent.
    

    Valid but not recommended:

    .. admonition::        weird 
                 indentation
            example
       :name: 
           weird 
                indentation
       :class:
                    option values may start
          on the next line
    
              The first content line may be more indented
              than the option list.
    
       Subsequent lines may be less or more indented than
       the first. However, not less than the option list.
    

    The indentation of the first line does not affect the indentation precedent:

    .. admonition:: cool
    
                      This content line is even more indented
                      than the argument!
    
                      It still sets the indentation precedent.
    

    Since specific admonitons don't take arguments, the content can be given without preceding blank line:

    .. important:: 
       * Wash behind your ears.
       * Back up your data.
    

    On the same line as the directive marker:

    .. warning:: Mind the step!
    

    Optionally followed by an option list:

    .. warning:: Mind the step!
       :class: urgent
    

    Hower, mixing content and options is not recommended:

    .. tip:: Don't use
       **this**
       :class: problematic
    
       in production!
    

    Block-quotes are indicated by indentation relative to their context.

    .. note::
    
           Readability counts.
    
       This line sets the indentation precedent.
    

    Some results may be unexpected:

    .. hint:: This is a
         definition list
    
       Because this line sets the indentation precedent.