I'd like to create a custom Directive
that uses the an existing Directive (code-block
in this example) in it's implementation.
The manual equivalent of this in reStructuredText would be:
.. mydirective:: py
.. code-block: py
print("Hello world")
However, I would like the code-block
to be created within my-directive
's definition. I found an example that hard-codes the appropriate reStructuredText
for the existing Directive (below), but this depends on the parser using rST
.
class MyDirective(Directive):
has_content = True
def run(self):
# Do custom stuff...
# Use code-block Directive
new_content = [
'.. tab:: {}'.format(json.dumps(tab_args)),
' {}'.format(tab_name),
'',
' .. code-block:: {}'.format(lang),
]
if 'linenos' in self.options:
new_content.append(' :linenos:')
new_content.append('')
for idx, line in enumerate(new_content):
self.content.data.insert(idx, line)
self.content.items.insert(idx, (None, idx))
node = nodes.container()
self.state.nested_parse(self.content, self.content_offset, node)
return node.children
How could I implement this in a parser-independent fashion?
In the end, my solution was:
from sphinx.directives.code import CodeBlock
class CodeTabDirective(CodeBlock):
""" Tab directive with a codeblock as its content"""
def run(self):
self.assert_has_content()
code_block = super().run()[0]
# Set anything required by OtherDirective
node = OtherDirective.run(self)[0] # Generates container
node.append(code_block) # Put code block inside container
return [node]
Where OtherDirective
was another existing directive.
I wasn't able to subclass both directives and use their functionality via super
, as I needed to call a method named run
from both.
You can see the final solution in place in the CodeTabDirective of sphinx-tabs
.