diff --git a/doc/develop.rst b/doc/develop.rst index f0ef9cec6..94f747714 100644 --- a/doc/develop.rst +++ b/doc/develop.rst @@ -100,7 +100,7 @@ This is the current list of contributed extensions in that repository: - zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_ -See the :ref:`extension tutorial ` on getting started with writing your +See the :ref:`extension tutorial ` on getting started with writing your own extensions. diff --git a/doc/extdev/tutorials/helloworld_ext.rst b/doc/extdev/tutorials/helloworld_ext.rst new file mode 100644 index 000000000..62a50bd19 --- /dev/null +++ b/doc/extdev/tutorials/helloworld_ext.rst @@ -0,0 +1,150 @@ +.. _exttuto-helloworld: + +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 :ref:`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: + +#. Create an :file:`_ext` folder in :file:`source`. +#. Create a new Python file in the :file:`_ext` folder called + :file:`helloworld.py`. + + Here is an example of the folder structure you might obtain: + + .. code-block:: text + + └── source +    ├── _ext + │   └── helloworld.py +    ├── _static +    ├── _themes +    ├── conf.py +    ├── somefolder +    ├── somefile.rst +    └── someotherfile.rst + +Writing the extension +--------------------- + +Open :file:`helloworld.py` and paste the following code in it: + +.. code-block:: python + + 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: + +.. rubric:: Directive declaration + +Our new directive is declared in the :code:`HelloWorld` class, it extends +docutils_' code:`Directive` class. All extensions that create directives +should extend this class. + +.. rubric:: `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. + +Read more on this topic in :ref:`exttuto-todo`. + +.. rubric:: 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. + +Read more about `docutils nodes`_. + +You can also create your own nodes if needed, refer to the +:ref:`exttuto-todo` for more information. + +The :code:`nodes.paragraph` method creates a new paragraph node. A paragraph +node typically contains some text that we can set during instantiation using +the ``text`` parameter. + +.. rubric:: `setup` method + +This method is a requirement. We use it to plug our new directive into +Sphinx. The first argument is the name of the directive itself. In our case: + +.. code-block:: rst + + Some intro text here... + + .. helloworld:: + + Some more text here... + + +Updating the conf.py file +------------------------- + +The extension file has to be declared in your :file:`conf.py` file to make +Sphinx aware of it: + +#. Open :file:`conf.py`. It is in the :file:`source` folder by default. +#. Add :code:`sys.path.append(os.path.abspath("./_ext"))` before + the ``extensions`` variable declaration (if it exists). +#. Update of create the ``extensions`` list and add the + extension file name to the list: + + .. code-block:: python + + extensions.append('helloworld') + +You can now use the extension. + +.. admonition:: Example + + .. code-block:: rst + + Some intro text here... + + .. helloworld:: + + Some more text here... + + The sample above would generate: + + .. code-block:: text + + 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 :ref:`exttuto-todo` + +.. _docutils: http://docutils.sourceforge.net/ +.. _`docutils nodes`: http://docutils.sourceforge.net/docs/ref/doctree.html \ No newline at end of file diff --git a/doc/extdev/tutorials/index.rst b/doc/extdev/tutorials/index.rst index fbcc0e001..5a9e9d89e 100644 --- a/doc/extdev/tutorials/index.rst +++ b/doc/extdev/tutorials/index.rst @@ -1,4 +1,4 @@ -.. _exttuttodoorials: +.. _extensiontutos: Extension tutorials =================== @@ -6,5 +6,8 @@ Extension tutorials Refer to the following tutorials to get started with extension development. .. toctree:: + :caption: Directive tutorials + :maxdepth: 1 - todo_ext \ No newline at end of file + helloworld_ext + todo_ext diff --git a/doc/extdev/tutorials/todo_ext.rst b/doc/extdev/tutorials/todo_ext.rst index bff369e29..ec5081dc5 100644 --- a/doc/extdev/tutorials/todo_ext.rst +++ b/doc/extdev/tutorials/todo_ext.rst @@ -1,6 +1,6 @@ -.. _exttuttodo: +.. _exttuto-todo: -Developing a `TODO` extension +Developing a "TODO" extension ============================= This section is intended as a walkthrough for the creation of custom extensions. diff --git a/doc/faq.rst b/doc/faq.rst index 4711b7973..d57f56530 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -33,7 +33,7 @@ How do I... ``sidebartoc`` block. ... write my own extension? - See the :ref:`extension tutorial `. + See the :ref:`extension tutorial `. ... convert from my existing docs using MoinMoin markup? The easiest way is to convert to xhtml, then convert `xhtml to reST`_.