Developing a “Hello world” directive

The objective of this tutorial is to create a very basic extension that adds a new directive that outputs a paragraph containing hello world.

Only basic information is provided in this tutorial. For more information, refer to the other tutorials that go into more details.

Warning

For this extension, you will need some basic understanding of docutils and Python.

Creating a new extension file

Your extension file could be in any folder of your project. In our case, let’s do the following:

  1. Create an _ext folder in source.

  2. Create a new Python file in the _ext folder called helloworld.py.

    Here is an example of the folder structure you might obtain:

    └── source
        ├── _ext
        │   └── helloworld.py
        ├── _static
        ├── _themes
        ├── conf.py
        ├── somefolder
        ├── somefile.rst
        └── someotherfile.rst
    

Writing the extension

Open helloworld.py and paste the following code in it:

from docutils import nodes
from docutils.parsers.rst import Directive


class HelloWorld(Directive):
    def run(self):
        paragraph_node = nodes.paragraph(text='Hello World!')
        return [paragraph_node]


def setup(app):
    app.add_directive("helloworld", HelloWorld)

Some essential things are happening in this example, and you will see them in all directives:

Directive declaration

Our new directive is declared in the HelloWorld class, it extends docutilsDirective class. All extensions that create directives should extend this class.

run method

This method is a requirement and it is part of every directive. It contains the main logic of the directive and it returns a list of docutils nodes to be processed by Sphinx.

docutils nodes

The run method returns a list of nodes. Nodes are docutils’ way of representing the content of a document. There are many types of nodes available: text, paragraph, reference, table, etc.

The nodes.paragraph class creates a new paragraph node. A paragraph node typically contains some text that we can set during instantiation using the text parameter.

setup function

This function is a requirement. We use it to plug our new directive into Sphinx. The simplest thing you can do it call the app.add_directive method.

Note

The first argument is the name of the directive itself as used in an rST file.

In our case, we would use helloworld:

Some intro text here...

.. helloworld::

Some more text here...

Updating the conf.py file

The extension file has to be declared in your conf.py file to make Sphinx aware of it:

  1. Open conf.py. It is in the source folder by default.

  2. Add sys.path.append(os.path.abspath("./_ext")) before the extensions variable declaration (if it exists).

  3. Update or create the extensions list and add the extension file name to the list:

    extensions.append('helloworld')
    

You can now use the extension.

Example

Some intro text here...

.. helloworld::

Some more text here...

The sample above would generate:

Some intro text here...

Hello World!

Some more text here...

This is the very basic principle of an extension that creates a new directive.

For a more advanced example, refer to Developing a “TODO” extension.

Further reading

You can create your own nodes if needed, refer to the Developing a “TODO” extension for more information.