summaryrefslogtreecommitdiff
path: root/doc/ext
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2014-01-20 17:21:44 +0100
committerGeorg Brandl <georg@python.org>2014-01-20 17:21:44 +0100
commit57f7239fc8a5dc0867da07e5c7b1dc023227deb6 (patch)
tree3c719fca66c0bb1b98027f69aa0226d44dad6faa /doc/ext
parent2ce06ad6912442129e03910ffb1e4dd8fe89acfe (diff)
downloadsphinx-57f7239fc8a5dc0867da07e5c7b1dc023227deb6.tar.gz
Doc: move API docs in their own chapter and add more of it.
Diffstat (limited to 'doc/ext')
-rw-r--r--doc/ext/appapi.rst505
-rw-r--r--doc/ext/builderapi.rst30
-rw-r--r--doc/ext/tutorial.rst344
3 files changed, 0 insertions, 879 deletions
diff --git a/doc/ext/appapi.rst b/doc/ext/appapi.rst
deleted file mode 100644
index a6393d40..00000000
--- a/doc/ext/appapi.rst
+++ /dev/null
@@ -1,505 +0,0 @@
-.. highlight:: rest
-
-Extension API
-=============
-
-.. currentmodule:: sphinx.application
-
-Each Sphinx extension is a Python module with at least a :func:`setup` function.
-This function is called at initialization time with one argument, the
-application object representing the Sphinx process. This application object has
-the following public API:
-
-.. method:: Sphinx.setup_extension(name)
-
- Load the extension given by the module *name*. Use this if your extension
- needs the features provided by another extension.
-
-.. method:: Sphinx.add_builder(builder)
-
- Register a new builder. *builder* must be a class that inherits from
- :class:`~sphinx.builders.Builder`.
-
-.. method:: Sphinx.add_config_value(name, default, rebuild)
-
- Register a configuration value. This is necessary for Sphinx to recognize
- new values and set default values accordingly. The *name* should be prefixed
- with the extension name, to avoid clashes. The *default* value can be any
- Python object. The string value *rebuild* must be one of those values:
-
- * ``'env'`` if a change in the setting only takes effect when a document is
- parsed -- this means that the whole environment must be rebuilt.
- * ``'html'`` if a change in the setting needs a full rebuild of HTML
- documents.
- * ``''`` if a change in the setting will not need any special rebuild.
-
- .. versionchanged:: 0.4
- If the *default* value is a callable, it will be called with the config
- object as its argument in order to get the default value. This can be
- used to implement config values whose default depends on other values.
-
- .. versionchanged:: 0.6
- Changed *rebuild* from a simple boolean (equivalent to ``''`` or
- ``'env'``) to a string. However, booleans are still accepted and
- converted internally.
-
-.. method:: Sphinx.add_domain(domain)
-
- Make the given *domain* (which must be a class; more precisely, a subclass of
- :class:`~sphinx.domains.Domain`) known to Sphinx.
-
- .. versionadded:: 1.0
-
-.. method:: Sphinx.override_domain(domain)
-
- Make the given *domain* class known to Sphinx, assuming that there is already
- a domain with its ``.name``. The new domain must be a subclass of the
- existing one.
-
- .. versionadded:: 1.0
-
-.. method:: Sphinx.add_index_to_domain(domain, index)
-
- Add a custom *index* class to the domain named *domain*. *index* must be a
- subclass of :class:`~sphinx.domains.Index`.
-
- .. versionadded:: 1.0
-
-.. method:: Sphinx.add_event(name)
-
- Register an event called *name*. This is needed to be able to emit it.
-
-.. method:: Sphinx.add_node(node, **kwds)
-
- Register a Docutils node class. This is necessary for Docutils internals.
- It may also be used in the future to validate nodes in the parsed documents.
-
- Node visitor functions for the Sphinx HTML, LaTeX, text and manpage writers
- can be given as keyword arguments: the keyword must be one or more of
- ``'html'``, ``'latex'``, ``'text'``, ``'man'``, ``'texinfo'``, the value a
- 2-tuple of ``(visit, depart)`` methods. ``depart`` can be ``None`` if the
- ``visit`` function raises :exc:`docutils.nodes.SkipNode`. Example:
-
- .. code-block:: python
-
- class math(docutils.nodes.Element): pass
-
- def visit_math_html(self, node):
- self.body.append(self.starttag(node, 'math'))
- def depart_math_html(self, node):
- self.body.append('</math>')
-
- app.add_node(math, html=(visit_math_html, depart_math_html))
-
- Obviously, translators for which you don't specify visitor methods will choke
- on the node when encountered in a document to translate.
-
- .. versionchanged:: 0.5
- Added the support for keyword arguments giving visit functions.
-
-.. method:: Sphinx.add_directive(name, func, content, arguments, **options)
- Sphinx.add_directive(name, directiveclass)
-
- Register a Docutils directive. *name* must be the prospective directive
- name. There are two possible ways to write a directive:
-
- * In the docutils 0.4 style, *obj* is the directive function. *content*,
- *arguments* and *options* are set as attributes on the function and
- determine whether the directive has content, arguments and options,
- respectively. **This style is deprecated.**
-
- * In the docutils 0.5 style, *directiveclass* is the directive class. It
- must already have attributes named *has_content*, *required_arguments*,
- *optional_arguments*, *final_argument_whitespace* and *option_spec* that
- correspond to the options for the function way. See `the Docutils docs
- <http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_ for
- details.
-
- The directive class must inherit from the class
- ``docutils.parsers.rst.Directive``.
-
- For example, the (already existing) :rst:dir:`literalinclude` directive would be
- added like this:
-
- .. code-block:: python
-
- from docutils.parsers.rst import directives
- add_directive('literalinclude', literalinclude_directive,
- content = 0, arguments = (1, 0, 0),
- linenos = directives.flag,
- language = direcitves.unchanged,
- encoding = directives.encoding)
-
- .. versionchanged:: 0.6
- Docutils 0.5-style directive classes are now supported.
-
-.. method:: Sphinx.add_directive_to_domain(domain, name, func, content, arguments, **options)
- Sphinx.add_directive_to_domain(domain, name, directiveclass)
-
- Like :meth:`add_directive`, but the directive is added to the domain named
- *domain*.
-
- .. versionadded:: 1.0
-
-.. method:: Sphinx.add_role(name, role)
-
- Register a Docutils role. *name* must be the role name that occurs in the
- source, *role* the role function (see the `Docutils documentation
- <http://docutils.sourceforge.net/docs/howto/rst-roles.html>`_ on details).
-
-.. method:: Sphinx.add_role_to_domain(domain, name, role)
-
- Like :meth:`add_role`, but the role is added to the domain named *domain*.
-
- .. versionadded:: 1.0
-
-.. method:: Sphinx.add_generic_role(name, nodeclass)
-
- Register a Docutils role that does nothing but wrap its contents in the
- node given by *nodeclass*.
-
- .. versionadded:: 0.6
-
-.. method:: Sphinx.add_object_type(directivename, rolename, indextemplate='', parse_node=None, \
- ref_nodeclass=None, objname='', doc_field_types=[])
-
- This method is a very convenient way to add a new :term:`object` type that
- can be cross-referenced. It will do this:
-
- * Create a new directive (called *directivename*) for documenting an object.
- It will automatically add index entries if *indextemplate* is nonempty; if
- given, it must contain exactly one instance of ``%s``. See the example
- below for how the template will be interpreted.
- * Create a new role (called *rolename*) to cross-reference to these
- object descriptions.
- * If you provide *parse_node*, it must be a function that takes a string and
- a docutils node, and it must populate the node with children parsed from
- the string. It must then return the name of the item to be used in
- cross-referencing and index entries. See the :file:`conf.py` file in the
- source for this documentation for an example.
- * The *objname* (if not given, will default to *directivename*) names the
- type of object. It is used when listing objects, e.g. in search results.
-
- For example, if you have this call in a custom Sphinx extension::
-
- app.add_object_type('directive', 'dir', 'pair: %s; directive')
-
- you can use this markup in your documents::
-
- .. rst:directive:: function
-
- Document a function.
-
- <...>
-
- See also the :rst:dir:`function` directive.
-
- For the directive, an index entry will be generated as if you had prepended ::
-
- .. index:: pair: function; directive
-
- The reference node will be of class ``literal`` (so it will be rendered in a
- proportional font, as appropriate for code) unless you give the *ref_nodeclass*
- argument, which must be a docutils node class (most useful are
- ``docutils.nodes.emphasis`` or ``docutils.nodes.strong`` -- you can also use
- ``docutils.nodes.generated`` if you want no further text decoration).
-
- For the role content, you have the same syntactical possibilities as for
- standard Sphinx roles (see :ref:`xref-syntax`).
-
- This method is also available under the deprecated alias
- ``add_description_unit``.
-
-.. method:: Sphinx.add_crossref_type(directivename, rolename, indextemplate='', ref_nodeclass=None, objname='')
-
- This method is very similar to :meth:`add_object_type` except that the
- directive it generates must be empty, and will produce no output.
-
- That means that you can add semantic targets to your sources, and refer to
- them using custom roles instead of generic ones (like :rst:role:`ref`). Example
- call::
-
- app.add_crossref_type('topic', 'topic', 'single: %s', docutils.nodes.emphasis)
-
- Example usage::
-
- .. topic:: application API
-
- The application API
- -------------------
-
- <...>
-
- See also :topic:`this section <application API>`.
-
- (Of course, the element following the ``topic`` directive needn't be a
- section.)
-
-.. method:: Sphinx.add_transform(transform)
-
- Add the standard docutils :class:`Transform` subclass *transform* to the list
- of transforms that are applied after Sphinx parses a reST document.
-
-.. method:: Sphinx.add_javascript(filename)
-
- Add *filename* to the list of JavaScript files that the default HTML template
- will include. The filename must be relative to the HTML static path, see
- :confval:`the docs for the config value <html_static_path>`. A full URI with
- scheme, like ``http://example.org/foo.js``, is also supported.
-
- .. versionadded:: 0.5
-
-.. method:: Sphinx.add_stylesheet(filename)
-
- Add *filename* to the list of CSS files that the default HTML template will
- include. Like for :meth:`add_javascript`, the filename must be relative to
- the HTML static path, or a full URI with scheme.
-
- .. versionadded:: 1.0
-
-.. method:: Sphinx.add_lexer(alias, lexer)
-
- Use *lexer*, which must be an instance of a Pygments lexer class, to
- highlight code blocks with the given language *alias*.
-
- .. versionadded:: 0.6
-
-.. method:: Sphinx.add_autodocumenter(cls)
-
- Add *cls* as a new documenter class for the :mod:`sphinx.ext.autodoc`
- extension. It must be a subclass of :class:`sphinx.ext.autodoc.Documenter`.
- This allows to auto-document new types of objects. See the source of the
- autodoc module for examples on how to subclass :class:`Documenter`.
-
- .. XXX add real docs for Documenter and subclassing
-
- .. versionadded:: 0.6
-
-.. method:: Sphinx.add_autodoc_attrgetter(type, getter)
-
- Add *getter*, which must be a function with an interface compatible to the
- :func:`getattr` builtin, as the autodoc attribute getter for objects that are
- instances of *type*. All cases where autodoc needs to get an attribute of a
- type are then handled by this function instead of :func:`getattr`.
-
- .. versionadded:: 0.6
-
-.. method:: Sphinx.add_search_language(cls)
-
- Add *cls*, which must be a subclass of :class:`sphinx.search.SearchLanguage`,
- as a support language for building the HTML full-text search index. The
- class must have a *lang* attribute that indicates the language it should be
- used for. See :confval:`html_search_language`.
-
- .. versionadded:: 1.1
-
-.. method:: Sphinx.connect(event, callback)
-
- Register *callback* to be called when *event* is emitted. For details on
- available core events and the arguments of callback functions, please see
- :ref:`events`.
-
- The method returns a "listener ID" that can be used as an argument to
- :meth:`disconnect`.
-
-.. method:: Sphinx.disconnect(listener_id)
-
- Unregister callback *listener_id*.
-
-.. method:: Sphinx.emit(event, *arguments)
-
- Emit *event* and pass *arguments* to the callback functions. Return the
- return values of all callbacks as a list. Do not emit core Sphinx events
- in extensions!
-
-.. method:: Sphinx.emit_firstresult(event, *arguments)
-
- Emit *event* and pass *arguments* to the callback functions. Return the
- result of the first callback that doesn't return ``None``.
-
- .. versionadded:: 0.5
-
-.. method:: Sphinx.require_sphinx(version)
-
- Compare *version* (which must be a ``major.minor`` version string,
- e.g. ``'1.1'``) with the version of the running Sphinx, and abort the build
- when it is too old.
-
- .. versionadded:: 1.0
-
-
-.. exception:: ExtensionError
-
- All these functions raise this exception if something went wrong with the
- extension API.
-
-Examples of using the Sphinx extension API can be seen in the :mod:`sphinx.ext`
-package.
-
-
-.. _events:
-
-Sphinx core events
-------------------
-
-These events are known to the core. The arguments shown are given to the
-registered event handlers.
-
-.. event:: builder-inited (app)
-
- Emitted when the builder object has been created. It is available as
- ``app.builder``.
-
-.. event:: env-get-outdated (app, env, added, changed, removed)
-
- Emitted when the environment determines which source files have changed and
- should be re-read. *added*, *changed* and *removed* are sets of docnames
- that the environment has determined. You can return a list of docnames to
- re-read in addition to these.
-
- .. versionadded:: 1.1
-
-.. event:: env-purge-doc (app, env, docname)
-
- Emitted when all traces of a source file should be cleaned from the
- environment, that is, if the source file is removed or before it is freshly
- read. This is for extensions that keep their own caches in attributes of the
- environment.
-
- For example, there is a cache of all modules on the environment. When a
- source file has been changed, the cache's entries for the file are cleared,
- since the module declarations could have been removed from the file.
-
- .. versionadded:: 0.5
-
-.. event:: source-read (app, docname, source)
-
- Emitted when a source file has been read. The *source* argument is a list
- whose single element is the contents of the source file. You can process the
- contents and replace this item to implement source-level transformations.
-
- For example, if you want to use ``$`` signs to delimit inline math, like in
- LaTeX, you can use a regular expression to replace ``$...$`` by
- ``:math:`...```.
-
- .. versionadded:: 0.5
-
-.. event:: doctree-read (app, doctree)
-
- Emitted when a doctree has been parsed and read by the environment, and is
- about to be pickled. The *doctree* can be modified in-place.
-
-.. event:: missing-reference (app, env, node, contnode)
-
- Emitted when a cross-reference to a Python module or object cannot be
- resolved. If the event handler can resolve the reference, it should return a
- new docutils node to be inserted in the document tree in place of the node
- *node*. Usually this node is a :class:`reference` node containing *contnode*
- as a child.
-
- :param env: The build environment (``app.builder.env``).
- :param node: The :class:`pending_xref` node to be resolved. Its attributes
- ``reftype``, ``reftarget``, ``modname`` and ``classname`` attributes
- determine the type and target of the reference.
- :param contnode: The node that carries the text and formatting inside the
- future reference and should be a child of the returned reference node.
-
- .. versionadded:: 0.5
-
-.. event:: doctree-resolved (app, doctree, docname)
-
- Emitted when a doctree has been "resolved" by the environment, that is, all
- references have been resolved and TOCs have been inserted. The *doctree* can
- be modified in place.
-
- Here is the place to replace custom nodes that don't have visitor methods in
- the writers, so that they don't cause errors when the writers encounter them.
-
-.. event:: env-updated (app, env)
-
- Emitted when the :meth:`update` method of the build environment has
- completed, that is, the environment and all doctrees are now up-to-date.
-
- .. versionadded:: 0.5
-
-.. event:: html-collect-pages (app)
-
- Emitted when the HTML builder is starting to write non-document pages. You
- can add pages to write by returning an iterable from this event consisting of
- ``(pagename, context, templatename)``.
-
- .. versionadded:: 1.0
-
-.. event:: html-page-context (app, pagename, templatename, context, doctree)
-
- Emitted when the HTML builder has created a context dictionary to render a
- template with -- this can be used to add custom elements to the context.
-
- The *pagename* argument is the canonical name of the page being rendered,
- that is, without ``.html`` suffix and using slashes as path separators. The
- *templatename* is the name of the template to render, this will be
- ``'page.html'`` for all pages from reST documents.
-
- The *context* argument is a dictionary of values that are given to the
- template engine to render the page and can be modified to include custom
- values. Keys must be strings.
-
- The *doctree* argument will be a doctree when the page is created from a reST
- documents; it will be ``None`` when the page is created from an HTML template
- alone.
-
- .. versionadded:: 0.4
-
-.. event:: build-finished (app, exception)
-
- Emitted when a build has finished, before Sphinx exits, usually used for
- cleanup. This event is emitted even when the build process raised an
- exception, given as the *exception* argument. The exception is reraised in
- the application after the event handlers have run. If the build process
- raised no exception, *exception* will be ``None``. This allows to customize
- cleanup actions depending on the exception status.
-
- .. versionadded:: 0.5
-
-
-Checking the Sphinx version
----------------------------
-
-.. currentmodule:: sphinx
-
-Use this to adapt your extension to API changes in Sphinx.
-
-.. data:: version_info
-
- A tuple of five elements; for Sphinx version 1.2.1 beta 3 this would be
- ``(1, 2, 1, 'beta', 3)``.
-
- .. versionadded:: 1.2
- Before version 1.2, check the string ``sphinx.__version__``.
-
-
-.. _template-bridge:
-
-The template bridge
--------------------
-
-.. currentmodule:: sphinx.application
-
-.. autoclass:: TemplateBridge
- :members:
-
-
-.. _domain-api:
-
-Domain API
-----------
-
-.. module:: sphinx.domains
-
-.. autoclass:: Domain
- :members:
-
-.. autoclass:: ObjType
-
-.. autoclass:: Index
- :members:
diff --git a/doc/ext/builderapi.rst b/doc/ext/builderapi.rst
deleted file mode 100644
index 3ace2687..00000000
--- a/doc/ext/builderapi.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-.. _writing-builders:
-
-Writing new builders
-====================
-
-.. todo:: Expand this.
-
-.. currentmodule:: sphinx.builders
-
-.. class:: Builder
-
- This is the base class for all builders.
-
- These methods are predefined and will be called from the application:
-
- .. automethod:: get_relative_uri
- .. automethod:: build_all
- .. automethod:: build_specific
- .. automethod:: build_update
- .. automethod:: build
-
- These methods can be overridden in concrete builder classes:
-
- .. automethod:: init
- .. automethod:: get_outdated_docs
- .. automethod:: get_target_uri
- .. automethod:: prepare_writing
- .. automethod:: write_doc
- .. automethod:: finish
-
diff --git a/doc/ext/tutorial.rst b/doc/ext/tutorial.rst
deleted file mode 100644
index c09be29a..00000000
--- a/doc/ext/tutorial.rst
+++ /dev/null
@@ -1,344 +0,0 @@
-.. _exttut:
-
-Tutorial: Writing a simple extension
-====================================
-
-This section is intended as a walkthrough for the creation of custom extensions.
-It covers the basics of writing and activating an extensions, as well as
-commonly used features of extensions.
-
-As an example, we will cover a "todo" extension that adds capabilities to
-include todo entries in the documentation, and collecting these in a central
-place. (A similar "todo" extension is distributed with Sphinx.)
-
-
-Build Phases
-------------
-
-One thing that is vital in order to understand extension mechanisms is the way
-in which a Sphinx project is built: this works in several phases.
-
-**Phase 0: Initialization**
-
- In this phase, almost nothing interesting for us happens. The source
- directory is searched for source files, and extensions are initialized.
- Should a stored build environment exist, it is loaded, otherwise a new one is
- created.
-
-**Phase 1: Reading**
-
- In Phase 1, all source files (and on subsequent builds, those that are new or
- changed) are read and parsed. This is the phase where directives and roles
- are encountered by the docutils, and the corresponding functions are called.
- The output of this phase is a *doctree* for each source files, that is a tree
- of docutils nodes. For document elements that aren't fully known until all
- existing files are read, temporary nodes are created.
-
- During reading, the build environment is updated with all meta- and cross
- reference data of the read documents, such as labels, the names of headings,
- described Python objects and index entries. This will later be used to
- replace the temporary nodes.
-
- The parsed doctrees are stored on the disk, because it is not possible to
- hold all of them in memory.
-
-**Phase 2: Consistency checks**
-
- Some checking is done to ensure no surprises in the built documents.
-
-**Phase 3: Resolving**
-
- Now that the metadata and cross-reference data of all existing documents is
- known, all temporary nodes are replaced by nodes that can be converted into
- output. For example, links are created for object references that exist, and
- simple literal nodes are created for those that don't.
-
-**Phase 4: Writing**
-
- This phase converts the resolved doctrees to the desired output format, such
- as HTML or LaTeX. This happens via a so-called docutils writer that visits
- the individual nodes of each doctree and produces some output in the process.
-
-.. note::
-
- Some builders deviate from this general build plan, for example, the builder
- that checks external links does not need anything more than the parsed
- doctrees and therefore does not have phases 2--4.
-
-
-Extension Design
-----------------
-
-We want the extension to add the following to Sphinx:
-
-* A "todo" directive, containing some content that is marked with "TODO", and
- only shown in the output if a new config value is set. (Todo entries should
- not be in the output by default.)
-
-* A "todolist" directive that creates a list of all todo entries throughout the
- documentation.
-
-For that, we will need to add the following elements to Sphinx:
-
-* New directives, called ``todo`` and ``todolist``.
-* New document tree nodes to represent these directives, conventionally also
- called ``todo`` and ``todolist``. We wouldn't need new nodes if the new
- directives only produced some content representable by existing nodes.
-* A new config value ``todo_include_todos`` (config value names should start
- with the extension name, in order to stay unique) that controls whether todo
- entries make it into the output.
-* New event handlers: one for the :event:`doctree-resolved` event, to replace
- the todo and todolist nodes, and one for :event:`env-purge-doc` (the reason
- for that will be covered later).
-
-
-The Setup Function
-------------------
-
-.. currentmodule:: sphinx.application
-
-The new elements are added in the extension's setup function. Let us create a
-new Python module called :file:`todo.py` and add the setup function::
-
- def setup(app):
- app.add_config_value('todo_include_todos', False, False)
-
- app.add_node(todolist)
- app.add_node(todo,
- html=(visit_todo_node, depart_todo_node),
- latex=(visit_todo_node, depart_todo_node),
- text=(visit_todo_node, depart_todo_node))
-
- app.add_directive('todo', TodoDirective)
- app.add_directive('todolist', TodolistDirective)
- app.connect('doctree-resolved', process_todo_nodes)
- app.connect('env-purge-doc', purge_todos)
-
-The calls in this function refer to classes and functions not yet written. What
-the individual calls do is the following:
-
-* :meth:`~Sphinx.add_config_value` lets Sphinx know that it should recognize the
- new *config value* ``todo_include_todos``, whose default value should be
- ``False`` (this also tells Sphinx that it is a boolean value).
-
- If the third argument was ``True``, all documents would be re-read if the
- config value changed its value. This is needed for config values that
- influence reading (build phase 1).
-
-* :meth:`~Sphinx.add_node` adds a new *node class* to the build system. It also
- can specify visitor functions for each supported output format. These visitor
- functions are needed when the new nodes stay until phase 4 -- since the
- ``todolist`` node is always replaced in phase 3, it doesn't need any.
-
- We need to create the two node classes ``todo`` and ``todolist`` later.
-
-* :meth:`~Sphinx.add_directive` adds a new *directive*, given by name and class.
-
- The handler functions are created later.
-
-* Finally, :meth:`~Sphinx.connect` adds an *event handler* to the event whose
- name is given by the first argument. The event handler function is called
- with several arguments which are documented with the event.
-
-
-The Node Classes
-----------------
-
-Let's start with the node classes::
-
- from docutils import nodes
-
- class todo(nodes.Admonition, nodes.Element):
- pass
-
- class todolist(nodes.General, nodes.Element):
- pass
-
- def visit_todo_node(self, node):
- self.visit_admonition(node)
-
- def depart_todo_node(self, node):
- self.depart_admonition(node)
-
-Node classes usually don't have to do anything except inherit from the standard
-docutils classes defined in :mod:`docutils.nodes`. ``todo`` inherits from
-``Admonition`` because it should be handled like a note or warning, ``todolist``
-is just a "general" node.
-
-
-The Directive Classes
----------------------
-
-A directive class is a class deriving usually from
-``docutils.parsers.rst.Directive``. Since the class-based directive interface
-doesn't exist yet in Docutils 0.4, Sphinx has another base class called
-``sphinx.util.compat.Directive`` that you can derive your directive from, and it
-will work with both Docutils 0.4 and 0.5 upwards. The directive interface is
-covered in detail in the `docutils documentation`_; the important thing is that the
-class has a method ``run`` that returns a list of nodes.
-
-The ``todolist`` directive is quite simple::
-
- from sphinx.util.compat import Directive
-
- class TodolistDirective(Directive):
-
- def run(self):
- return [todolist('')]
-
-An instance of our ``todolist`` node class is created and returned. The
-todolist directive has neither content nor arguments that need to be handled.
-
-The ``todo`` directive function looks like this::
-
- from sphinx.util.compat import make_admonition
-
- class TodoDirective(Directive):
-
- # this enables content in the directive
- has_content = True
-
- def run(self):
- env = self.state.document.settings.env
-
- targetid = "todo-%d" % env.new_serialno('todo')
- targetnode = nodes.target('', '', ids=[targetid])
-
- ad = make_admonition(todo, self.name, [_('Todo')], self.options,
- self.content, self.lineno, self.content_offset,
- self.block_text, self.state, self.state_machine)
-
- if not hasattr(env, 'todo_all_todos'):
- env.todo_all_todos = []
- env.todo_all_todos.append({
- 'docname': env.docname,
- 'lineno': self.lineno,
- 'todo': ad[0].deepcopy(),
- 'target': targetnode,
- })
-
- return [targetnode] + ad
-
-Several important things are covered here. First, as you can see, you can refer
-to the build environment instance using ``self.state.document.settings.env``.
-
-Then, to act as a link target (from the todolist), the todo directive needs to
-return a target node in addition to the todo node. The target ID (in HTML, this
-will be the anchor name) is generated by using ``env.new_serialno`` which is
-returns a new integer directive on each call and therefore leads to unique
-target names. The target node is instantiated without any text (the first two
-arguments).
-
-An admonition is created using a standard docutils function (wrapped in Sphinx
-for docutils cross-version compatibility). The first argument gives the node
-class, in our case ``todo``. The third argument gives the admonition title (use
-``arguments`` here to let the user specify the title). A list of nodes is
-returned from ``make_admonition``.
-
-Then, the todo node is added to the environment. This is needed to be able to
-create a list of all todo entries throughout the documentation, in the place
-where the author puts a ``todolist`` directive. For this case, the environment
-attribute ``todo_all_todos`` is used (again, the name should be unique, so it is
-prefixed by the extension name). It does not exist when a new environment is
-created, so the directive must check and create it if necessary. Various
-information about the todo entry's location are stored along with a copy of the
-node.
-
-In the last line, the nodes that should be put into the doctree are returned:
-the target node and the admonition node.
-
-The node structure that the directive returns looks like this::
-
- +--------------------+
- | target node |
- +--------------------+
- +--------------------+
- | todo node |
- +--------------------+
- \__+--------------------+
- | admonition title |
- +--------------------+
- | paragraph |
- +--------------------+
- | ... |
- +--------------------+
-
-
-The Event Handlers
-------------------
-
-Finally, let's look at the event handlers. First, the one for the
-:event:`env-purge-doc` event::
-
- def purge_todos(app, env, docname):
- if not hasattr(env, 'todo_all_todos'):
- return
- env.todo_all_todos = [todo for todo in env.todo_all_todos
- if todo['docname'] != docname]
-
-Since we store information from source files in the environment, which is
-persistent, it may become out of date when the source file changes. Therefore,
-before each source file is read, the environment's records of it are cleared,
-and the :event:`env-purge-doc` event gives extensions a chance to do the same.
-Here we clear out all todos whose docname matches the given one from the
-``todo_all_todos`` list. If there are todos left in the document, they will be
-added again during parsing.
-
-The other handler belongs to the :event:`doctree-resolved` event. This event is
-emitted at the end of phase 3 and allows custom resolving to be done::
-
- def process_todo_nodes(app, doctree, fromdocname):
- if not app.config.todo_include_todos:
- for node in doctree.traverse(todo):
- node.parent.remove(node)
-
- # Replace all todolist nodes with a list of the collected todos.
- # Augment each todo with a backlink to the original location.
- env = app.builder.env
-
- for node in doctree.traverse(todolist):
- if not app.config.todo_include_todos:
- node.replace_self([])
- continue
-
- content = []
-
- for todo_info in env.todo_all_todos:
- para = nodes.paragraph()
- filename = env.doc2path(todo_info['docname'], base=None)
- description = (
- _('(The original entry is located in %s, line %d and can be found ') %
- (filename, todo_info['lineno']))
- para += nodes.Text(description, description)
-
- # Create a reference
- newnode = nodes.reference('', '')
- innernode = nodes.emphasis(_('here'), _('here'))
- newnode['refdocname'] = todo_info['docname']
- newnode['refuri'] = app.builder.get_relative_uri(
- fromdocname, todo_info['docname'])
- newnode['refuri'] += '#' + todo_info['target']['refid']
- newnode.append(innernode)
- para += newnode
- para += nodes.Text('.)', '.)')
-
- # Insert into the todolist
- content.append(todo_info['todo'])
- content.append(para)
-
- node.replace_self(content)
-
-It is a bit more involved. If our new "todo_include_todos" config value is
-false, all todo and todolist nodes are removed from the documents.
-
-If not, todo nodes just stay where and how they are. Todolist nodes are
-replaced by a list of todo entries, complete with backlinks to the location
-where they come from. The list items are composed of the nodes from the todo
-entry and docutils nodes created on the fly: a paragraph for each entry,
-containing text that gives the location, and a link (reference node containing
-an italic node) with the backreference. The reference URI is built by
-``app.builder.get_relative_uri`` which creates a suitable URI depending on the
-used builder, and appending the todo node's (the target's) ID as the anchor
-name.
-
-.. _docutils documentation: http://docutils.sourceforge.net/docs/ref/rst/directives.html