Search code examples
python-3.xrestructuredtextdocutils

How to assemble a tool that parses reStructuredText with additional directives


Let's say I want to add a singe new directive to the reStructuredText standard directives.

There is a how-to for creating reStructuredText directives which outlines how each directive is essentially derived from the Directive class or its subclasses. It also suggests that the interested reader should check how the standard directives are implemented and use that as a starting point.

So far, so good, but the tutorial actually stops at that point. How can that new directive be incorporated into a new tool; how am I supposed to actually use it?

The "Hacker's Guide", which outlines how the front-end tools are assembled out of a Reader, a Parser, a Transformer and a Writer, seems incomplete and contains absolutely no code.

So, how am I supposed to assemble a new tool out of the standard reader + my extended Parser which recognizes the new directive + possibly a new Writer which appropriately handles the new directive in the output it produces?

I would very much appreciate a nudge in the right direction.


Solution

  • The docutils.core.Publisher class is "A facade encapsulating the high-level logic of a Docutils system." According to its documentation:

    Calling the publish_* convenience functions (or instantiating a Publisher object) with component names will result in default behavior. For custom behavior (setting component options), create custom component objects first, and pass them to publish_*/Publisher.

    So, in order to build a tool which, for example, parses an .rst file and outputs html5 to the standard output, using standard components, one can write:

    import sys
    import docutils.core
    import docutils.parsers.rst
    import docutils.writers.html5_polyglot
    
    public = docutils.core.publish_file(
                source=open("filename.rst", 'r'),
                parser=docutils.parsers.rst.Parser(),
                writer=docutils.writers.html5_polyglot.Writer())
    

    Replace the standard components for the parser or the writer with your own, extended, classes and you 're done.