Add a new `confval` directive to document settings and configuration values (#12536)

This commit is contained in:
Adam Turner
2024-07-10 20:44:16 +01:00
committed by GitHub
parent 05d1d8aeb2
commit a4de250b5a
5 changed files with 120 additions and 6 deletions

View File

@@ -58,6 +58,8 @@ Features added
Patch by Bénédikt Tran and Adam Turner. Patch by Bénédikt Tran and Adam Turner.
* #12524: Add a ``class`` option to the :rst:dir:`toctree` directive. * #12524: Add a ``class`` option to the :rst:dir:`toctree` directive.
Patch by Tim Hoffmann. Patch by Tim Hoffmann.
* #12536: Add the :rst:dir:`confval` directive.
Patch by Adam Turner.
Bugs fixed Bugs fixed
---------- ----------

View File

@@ -328,12 +328,6 @@ def setup(app: Sphinx) -> None:
app.connect('autodoc-process-docstring', cut_lines(4, what=['module'])) app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
app.connect('source-read', linkify_issues_in_changelog) app.connect('source-read', linkify_issues_in_changelog)
app.connect('build-finished', build_redirects) app.connect('build-finished', build_redirects)
app.add_object_type(
'confval',
'confval',
objname='configuration value',
indextemplate='pair: %s; configuration value',
)
fdesc = GroupedField('parameter', label='Parameters', names=['param'], can_collapse=True) fdesc = GroupedField('parameter', label='Parameters', names=['param'], can_collapse=True)
app.add_object_type( app.add_object_type(
'event', 'event', 'pair: %s; event', parse_event, doc_field_types=[fdesc] 'event', 'event', 'pair: %s; event', parse_event, doc_field_types=[fdesc]

View File

@@ -42,6 +42,44 @@ There is a set of directives allowing documenting command-line programs:
``cmdoption`` directive is a deprecated alias for the ``option`` directive. ``cmdoption`` directive is a deprecated alias for the ``option`` directive.
.. rst:directive:: .. confval:: name
Describes a configuration value or setting that the documented
code or program uses or defines.
Referenceable by :rst:role:`confval`.
.. rst:directive:option:: type
:type: text
Describes the type of the configuration value.
This is optional, and if specified will be interpreted as reStructuredText.
.. rst:directive:option:: default
:type: text
Describes the default value of the configuration value.
This is optional, and if specified will be interpreted as reStructuredText.
Example:
.. code-block:: rst
.. confval:: the_answer
:type: ``int`` (a *number*)
:default: **42**
This is a setting that controls the value of the answer.
will be rendered as follows:
.. confval:: the_answer
:no-contents-entry:
:no-index-entry:
:type: ``int`` (a *number*)
:default: **42**
This is a setting that controls the value of the answer.
.. rst:directive:: .. envvar:: name .. rst:directive:: .. envvar:: name
Describes an environment variable that the documented code or program uses Describes an environment variable that the documented code or program uses

View File

@@ -222,6 +222,13 @@ Cross-referencing other items of interest
The following roles do possibly create a cross-reference, but do not refer to The following roles do possibly create a cross-reference, but do not refer to
objects: objects:
.. rst:role:: confval
A configuration value or setting.
Index entries are generated.
Also generates a link to the matching :rst:dir:`confval` directive,
if it exists.
.. rst:role:: envvar .. rst:role:: envvar
An environment variable. Index entries are generated. Also generates a link An environment variable. Index entries are generated. Also generates a link

View File

@@ -102,6 +102,76 @@ class EnvVarXRefRole(XRefRole):
return [indexnode, targetnode, node], [] return [indexnode, targetnode, node], []
class ConfigurationValue(ObjectDescription[str]):
index_template: str = _('%s; configuration value')
option_spec: ClassVar[OptionSpec] = {
'no-index': directives.flag,
'no-index-entry': directives.flag,
'no-contents-entry': directives.flag,
'no-typesetting': directives.flag,
'type': directives.unchanged_required,
'default': directives.unchanged_required,
}
def handle_signature(self, sig: str, sig_node: desc_signature) -> str:
sig_node.clear()
sig_node += addnodes.desc_name(sig, sig)
name = ws_re.sub(' ', sig)
sig_node['fullname'] = name
return name
def _object_hierarchy_parts(self, sig_node: desc_signature) -> tuple[str, ...]:
return (sig_node['fullname'],)
def _toc_entry_name(self, sig_node: desc_signature) -> str:
if not sig_node.get('_toc_parts'):
return ''
name, = sig_node['_toc_parts']
return name
def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
node_id = make_id(self.env, self.state.document, self.objtype, name)
signode['ids'].append(node_id)
self.state.document.note_explicit_target(signode)
index_entry = self.index_template % name
self.indexnode['entries'].append(('pair', index_entry, node_id, '', None))
self.env.domains['std'].note_object(self.objtype, name, node_id, location=signode)
def transform_content(self, content_node: addnodes.desc_content) -> None:
"""Insert *type* and *default* as a field list."""
field_list = nodes.field_list()
if 'type' in self.options:
field, msgs = self.format_type(self.options['type'])
field_list.append(field)
field_list += msgs
if 'default' in self.options:
field, msgs = self.format_default(self.options['default'])
field_list.append(field)
field_list += msgs
if len(field_list.children) > 0:
content_node.insert(0, field_list)
def format_type(self, type_: str) -> tuple[nodes.field, list[system_message]]:
"""Formats the ``:type:`` option."""
parsed, msgs = self.parse_inline(type_, lineno=self.lineno)
field = nodes.field(
'',
nodes.field_name('', _('Type')),
nodes.field_body('', *parsed),
)
return field, msgs
def format_default(self, default: str) -> tuple[nodes.field, list[system_message]]:
"""Formats the ``:default:`` option."""
parsed, msgs = self.parse_inline(default, lineno=self.lineno)
field = nodes.field(
'',
nodes.field_name('', _('Default')),
nodes.field_body('', *parsed),
)
return field, msgs
class Target(SphinxDirective): class Target(SphinxDirective):
""" """
Generic target for user-defined cross-reference types. Generic target for user-defined cross-reference types.
@@ -527,6 +597,7 @@ class StandardDomain(Domain):
'token': ObjType(_('grammar token'), 'token', searchprio=-1), 'token': ObjType(_('grammar token'), 'token', searchprio=-1),
'label': ObjType(_('reference label'), 'ref', 'keyword', 'label': ObjType(_('reference label'), 'ref', 'keyword',
searchprio=-1), searchprio=-1),
'confval': ObjType('configuration value', 'confval'),
'envvar': ObjType(_('environment variable'), 'envvar'), 'envvar': ObjType(_('environment variable'), 'envvar'),
'cmdoption': ObjType(_('program option'), 'option'), 'cmdoption': ObjType(_('program option'), 'option'),
'doc': ObjType(_('document'), 'doc', searchprio=-1), 'doc': ObjType(_('document'), 'doc', searchprio=-1),
@@ -536,12 +607,14 @@ class StandardDomain(Domain):
'program': Program, 'program': Program,
'cmdoption': Cmdoption, # old name for backwards compatibility 'cmdoption': Cmdoption, # old name for backwards compatibility
'option': Cmdoption, 'option': Cmdoption,
'confval': ConfigurationValue,
'envvar': EnvVar, 'envvar': EnvVar,
'glossary': Glossary, 'glossary': Glossary,
'productionlist': ProductionList, 'productionlist': ProductionList,
} }
roles: dict[str, RoleFunction | XRefRole] = { roles: dict[str, RoleFunction | XRefRole] = {
'option': OptionXRefRole(warn_dangling=True), 'option': OptionXRefRole(warn_dangling=True),
'confval': XRefRole(warn_dangling=True),
'envvar': EnvVarXRefRole(), 'envvar': EnvVarXRefRole(),
# links to tokens in grammar productions # links to tokens in grammar productions
'token': TokenXRefRole(), 'token': TokenXRefRole(),