|
| 1 | +# ************************************** |
| 2 | +# |docname| - A for loop for Sphinx/reST |
| 3 | +# ************************************** |
| 4 | +# This provides a simple for loop for Sphinx/reST. |
| 5 | +# |
| 6 | +# Imports |
| 7 | +# ======= |
| 8 | +# These are listed in the order prescribed by `PEP 8 |
| 9 | +# <http://www.python.org/dev/peps/pep-0008/#imports>`_. |
| 10 | +# |
| 11 | +# Standard library |
| 12 | +# ---------------- |
| 13 | +# None. |
| 14 | +# |
| 15 | +# Third-party imports |
| 16 | +# ------------------- |
| 17 | +from docutils.parsers.rst import directives |
| 18 | +from docutils.parsers.rst import Directive |
| 19 | +from docutils import nodes |
| 20 | +from docutils.statemachine import StringList |
| 21 | + |
| 22 | +# Local application imports |
| 23 | +# ------------------------- |
| 24 | +# None. |
| 25 | + |
| 26 | + |
| 27 | +class ForLoop(Directive): |
| 28 | + # The required argument is the first parameter to ``range``. |
| 29 | + required_arguments = 1 |
| 30 | + # The optional arguments are the second and third parameter to ``range``. |
| 31 | + optional_arguments = 2 |
| 32 | + # Per http://docutils.sourceforge.net/docs/howto/rst-directives.html, True if content is allowed. However, this isn't checked or enforced. |
| 33 | + has_content = True |
| 34 | + |
| 35 | + def __init__(self, *args, **kwargs): |
| 36 | + super(ForLoop, self).__init__(*args, **kwargs) |
| 37 | + |
| 38 | + def run(self): |
| 39 | + # Create and error-check the range. |
| 40 | + try: |
| 41 | + _range = range(*[int(arg) for arg in self.arguments]) |
| 42 | + except Exception as e: |
| 43 | + raise self.error("Invalid arguments to range: {}".format(e)) |
| 44 | + |
| 45 | + # Run the for loop over all this directive's content. Docutils expects a StringList, so use that. |
| 46 | + loop_content = StringList() |
| 47 | + for loop_index in _range: |
| 48 | + # Loop over each line of the content, only replacing lines in the content of this directive. |
| 49 | + for source, offset, value in self.content.xitems(): |
| 50 | + loop_content.append( |
| 51 | + value.format(loop_index, *self.arguments), source, offset |
| 52 | + ) |
| 53 | + |
| 54 | + # Add an additional newline between loop iterations. |
| 55 | + loop_content.append("\n", "for-loop", 0) |
| 56 | + |
| 57 | + # Parse the resulting content and return it. |
| 58 | + node = nodes.container() |
| 59 | + self.state.nested_parse(loop_content, self.content_offset, node) |
| 60 | + return [node] |
| 61 | + |
| 62 | + |
| 63 | +directives.register_directive("for-loop", ForLoop) |
0 commit comments