Merge pull request #6314 from tk0miya/refactor_rst_domain3

Add rst:directive:option directive
This commit is contained in:
Takeshi KOMIYA 2019-05-13 14:29:32 +09:00 committed by GitHub
commit 8df362154e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 175 additions and 4 deletions

View File

@ -90,6 +90,9 @@ Features added
- ``:classmethod:``
- ``:property:``
- ``:staticmethod:``
* rst domain: Add :rst:dir:`directive:option` directive to describe the option
for directive
* #6306: html: Add a label to search form for accessability purposes
Bugs fixed

View File

@ -1423,6 +1423,43 @@ The reStructuredText domain (name **rst**) provides the following directives:
Bar description.
.. rst:directive:: .. rst:directive:option:: name
Describes an option for reST directive. The *name* can be a single option
name or option name with arguments which separated with colon (``:``).
For example::
.. rst:directive:: toctree
.. rst:directive:option:: caption: caption of ToC
.. rst:directive:option:: glob
will be rendered as:
.. rst:directive:: toctree
:noindex:
.. rst:directive:option:: caption: caption of ToC
.. rst:directive:option:: glob
.. rubric:: options
.. rst:directive:option:: type
:type: description for the option of directive
Describe the type of option value.
For example::
.. rst:directive:: toctree
.. rst:directive:option:: maxdepth
:type: integer or no value
.. versionadded:: 2.1
.. rst:directive:: .. rst:role:: name
Describes a reST role. For example::

View File

@ -11,6 +11,8 @@
import re
from typing import cast
from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType
@ -98,6 +100,74 @@ class ReSTDirective(ReSTMarkup):
# type: (str, str) -> str
return _('%s (directive)') % name
def before_content(self):
# type: () -> None
if self.names:
directives = self.env.ref_context.setdefault('rst:directives', [])
directives.append(self.names[0])
def after_content(self):
# type: () -> None
directives = self.env.ref_context.setdefault('rst:directives', [])
if directives:
directives.pop()
class ReSTDirectiveOption(ReSTMarkup):
"""
Description of an option for reST directive.
"""
option_spec = ReSTMarkup.option_spec.copy()
option_spec.update({
'type': directives.unchanged,
})
def handle_signature(self, sig, signode):
# type: (str, addnodes.desc_signature) -> str
try:
name, argument = re.split(r'\s*:\s+', sig.strip(), 1)
except ValueError:
name, argument = sig, None
signode += addnodes.desc_name(':%s:' % name, ':%s:' % name)
if argument:
signode += addnodes.desc_annotation(' ' + argument, ' ' + argument)
if self.options.get('type'):
text = ' (%s)' % self.options['type']
signode += addnodes.desc_annotation(text, text)
return name
def add_target_and_index(self, name, sig, signode):
# type: (str, str, addnodes.desc_signature) -> None
targetname = '-'.join([self.objtype, self.current_directive, name])
if targetname not in self.state.document.ids:
signode['names'].append(targetname)
signode['ids'].append(targetname)
signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode)
domain = cast(ReSTDomain, self.env.get_domain('rst'))
domain.note_object(self.objtype, name, location=(self.env.docname, self.lineno))
if self.current_directive:
key = name[0].upper()
pair = [_('%s (directive)') % self.current_directive,
_(':%s: (directive option)') % name]
self.indexnode['entries'].append(('pair', '; '.join(pair), targetname, '', key))
else:
key = name[0].upper()
text = _(':%s: (directive option)') % name
self.indexnode['entries'].append(('single', text, targetname, '', key))
@property
def current_directive(self):
# type: () -> str
directives = self.env.ref_context.get('rst:directives')
if directives:
return directives[-1]
else:
return ''
class ReSTRole(ReSTMarkup):
"""
@ -119,11 +189,13 @@ class ReSTDomain(Domain):
label = 'reStructuredText'
object_types = {
'directive': ObjType(_('directive'), 'dir'),
'role': ObjType(_('role'), 'role'),
'directive': ObjType(_('directive'), 'dir'),
'directive:option': ObjType(_('directive-option'), 'dir'),
'role': ObjType(_('role'), 'role'),
}
directives = {
'directive': ReSTDirective,
'directive:option': ReSTDirectiveOption,
'role': ReSTRole,
}
roles = {

View File

@ -10,8 +10,7 @@
from sphinx import addnodes
from sphinx.addnodes import (
desc, desc_addname, desc_content, desc_name, desc_optional, desc_parameter,
desc_parameterlist, desc_returns, desc_signature
desc, desc_addname, desc_annotation, desc_content, desc_name, desc_signature
)
from sphinx.domains.rst import parse_directive
from sphinx.testing import restructuredtext
@ -69,6 +68,66 @@ def test_rst_directive_with_argument(app):
domain="rst", objtype="directive", noindex=False)
def test_rst_directive_option(app):
text = ".. rst:directive:option:: foo"
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, desc_name, ":foo:"],
[desc_content, ()])]))
assert_node(doctree[0],
entries=[("single", ":foo: (directive option)",
"directive:option--foo", "", "F")])
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
def test_rst_directive_option_with_argument(app):
text = ".. rst:directive:option:: foo: bar baz"
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_name, ":foo:"],
[desc_annotation, " bar baz"])],
[desc_content, ()])]))
assert_node(doctree[0],
entries=[("single", ":foo: (directive option)",
"directive:option--foo", "", "F")])
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
def test_rst_directive_option_type(app):
text = (".. rst:directive:option:: foo\n"
" :type: directives.flags\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, ([desc_name, ":foo:"],
[desc_annotation, " (directives.flags)"])],
[desc_content, ()])]))
assert_node(doctree[0],
entries=[("single", ":foo: (directive option)",
"directive:option--foo", "", "F")])
assert_node(doctree[1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
def test_rst_directive_and_directive_option(app):
text = (".. rst:directive:: foo\n"
"\n"
" .. rst:directive:option:: bar\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index,
[desc, ([desc_signature, desc_name, ".. foo::"],
[desc_content, (addnodes.index,
desc)])]))
assert_node(doctree[1][1][0],
entries=[("pair", "foo (directive); :bar: (directive option)",
"directive:option-foo-bar", "", "B")])
assert_node(doctree[1][1][1], ([desc_signature, desc_name, ":bar:"],
[desc_content, ()]))
assert_node(doctree[1][1][1], addnodes.desc, desctype="directive:option",
domain="rst", objtype="directive:option", noindex=False)
def test_rst_role(app):
text = ".. rst:role:: ref"
doctree = restructuredtext.parse(app, text)