Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add object description options mechanism #75

Merged
merged 2 commits into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 174 additions & 11 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,23 +1,186 @@
General API customization
=========================

.. confval:: include_object_description_fields_in_toc
This theme supports a number of options that can be customized for each
domain/object type pair.

:python:`bool` indicating whether to include domain object description
fields, like "Parameters", "Returns", "Raises", etc. in the table of
contents. Defaults to :python:`True`.
.. confval:: object_description_options

:python:`list` of :python:`(pattern, options)` pairs, where :python:`pattern`
is a regular expression matching strings of the form
:python:`"domain:objtype"` and :python:`options` is a dictionary of supported
`object-description-options`.

We need something `object_description_options`.

The actual options for a given object type are determined by first
initializing each option to its default value, and then applying as overrides
the options associated with each matching pattern in order.

.. _object-description-options:

Object description options
--------------------------

The following options can be customized for each object type using
:confval:`object_description_options`.

.. objconf:: include_in_toc

Indicates whether to include the object description in the table of contents.

.. admonition:: Example
:class: example

To prevent C++ parameter descriptions from appearing in the TOC, add the
following to :file:`conf.py`:

.. code-block:: python

object_description_options = [
("cpp:.*Param": dict(include_in_toc=False)),
]

.. objconf:: generate_synopses

Indicates whether to generate a *synopsis* from the object description. The
synopsis is shown as a tooltip when hovering over a cross-reference link, and
is also shown in the search results list. Supported values are:

:python:`None`
Disables synopsis generation.

:python:`"first_paragraph"`
Uses the first paragraph of the description as the synopsis.

:python:`"first_sentence"`
Uses the first sentence of the first paragraph of the description as the synopsis.

The default is :python:`"first_paragraph"` except for :regexp:`c(pp)?:.*Param`
where the default is :python:`"first_sentence"`.

.. note::

Synopsis generation is currently supported only for the following domains:

- ``std`` (including object types added using :py:obj:`sphinx.application.Sphinx.add_object_type`)
- ``c`` and ``cpp``

.. admonition:: Example
:class: example

To use the first sentence rather than the first paragraph as the synopsis
for C++ class descriptions, add the following to :file:`conf.py`:

.. code-block:: python

object_description_options = [
("cpp:class", dict(generate_synopses="first_sentence")),
]

.. objconf:: include_object_type_in_xref_tooltip

Indicates whether to include the object type in cross-reference and TOC
tooltips.

.. note::

For TOC entries, this is supported for all domains. For regular cross
references, this is supported only for the following domains:

- ``std`` (including object types added using :py:obj:`sphinx.application.Sphinx.add_object_type`)
- ``c`` and ``cpp``

.. admonition:: Example
:class: example

To exclude the object type from all ``py`` domain xrefs, add the following
to :file:`conf.py`:

.. code-block:: python

object_description_options = [
("py:.*", dict(include_object_type_in_xref_tooltip=False)),
]

.. objconf:: include_fields_in_toc

Indicates whether to include fields, like "Parameters", "Returns", "Raises",
etc. in the table of contents.

For an example, see: :cpp:expr:`synopses_ex::Foo` and note the ``Template
Parameters``, ``Parameters``, and ``Returns`` headings shown in the
right-side table of contents.

.. note::

This option does not control whether there are separate TOC entries for
individual parameters, such as for :cpp:expr:`synopses_ex::Foo::T`,
To control whether there are separate TOC entries for individual
parameters, such as for :cpp:expr:`synopses_ex::Foo::T`,
:cpp:expr:`synopses_ex::Foo::N`, :cpp:expr:`synopses_ex::Foo::param`, and
:cpp:expr:`synopses_ex::Foo::arr`. Currently, for the C and C++ domains,
any parameter documented by a :rst:``:param x:`` field will always result
in a TOC entry, regardless of the value of
:confval:`include_object_description_fields_in_toc`. Other domains are
not yet supported.
:cpp:expr:`synopses_ex::Foo::arr`, use the :objconf:`include_in_toc`
option.


.. admonition:: Example
:class: example

To exclude object description fields from the table of contents for all
``py`` domain objects, add the following to :file:`conf.py`:

.. code-block:: python

object_description_options = [
("py:.*", dict(include_fields_in_toc=False)),
]

Other options described elsewhere include:

- :objconf:`wrap_signatures_with_css`
- :objconf:`wrap_signatures_column_limit`
- :objconf:`clang_format_style`

Table of contents icons
^^^^^^^^^^^^^^^^^^^^^^^

For object descriptions included in the table of contents (when
:objconf:`include_in_toc` is :python:`True`), a text-based "icon" can optionally
be included to indicate the object type.

Default icons are specified for a number of object types, but they can be
overridden using the following options:

.. objconf:: toc_icon_class

Indicates the icon class, or :python:`None` to disable the icon. The class
must be one of:

- :python:`"alias"`
- :python:`"procedure"`
- :python:`"data"`
- :python:`"sub-data"`

.. objconf:: toc_icon_text

Indicates the text content of the icon, or :python:`None` to disable the
icon. This should normally be a single character, such as :python:`"C"` to
indicate a class or :python:`"F"` to indicate a function.

.. admonition:: Example
:class: example

To define a custom object type and specify an icon for it, add the following to
:file:`conf.py`:

.. code-block:: python

object_description_options = [
("std:confval", dict(toc_icon_class="data", toc_icon_text="C")),
]

def setup(app):
app.add_object_type(
"confval",
"confval",
objname="configuration value",
indextemplate="pair: %s; configuration value",
)
84 changes: 77 additions & 7 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@

sys.path.insert(0, os.path.abspath("."))

import docutils
import sphinx
import sphinx.domains.python
import sphinx.environment
import sphinx.util.logging
import sphinx.util.typing

from sphinx_immaterial import apidoc_formatting

logger = sphinx.util.logging.getLogger(__name__)

# -- Project information -----------------------------------------------------

project = "Sphinx-Immaterial"
Expand Down Expand Up @@ -161,16 +172,15 @@
"dudir": ("http://docutils.sourceforge.net/docs/ref/rst/directives.html#%s", ""),
}

object_description_options = []

# BEGIN: sphinx_immaterial.format_signatures extension options
2bndy5 marked this conversation as resolved.
Show resolved Hide resolved
clang_format_signatures_domain_styles = {
"cpp": """{
BasedOnStyle: LLVM,
ColumnLimit: 68,
}""",
}
object_description_options.append(
("cpp:.*", dict(clang_format_style={"BasedOnStyle": "LLVM"}))
)
# END: sphinx_immaterial.format_signatures extension options

html_wrap_signatures_with_css = ["py"]
object_description_options.append(("py:.*", dict(wrap_signatures_with_css=True)))

# BEGIN: sphinx_immaterial.external_cpp_references extension options
external_cpp_references = {
Expand Down Expand Up @@ -210,10 +220,70 @@
"""


object_description_options.append(
(
"std:confval",
dict(
toc_icon_class="data", toc_icon_text="C", generate_synopses="first_sentence"
),
)
)

object_description_options.append(
(
"std:objconf",
dict(
toc_icon_class="data", toc_icon_text="O", generate_synopses=None,
),
)
)


def _validate_parallel_build(app):
# Verifies that all of the extensions defined by this theme support parallel
# building.
assert app.is_parallel_allowed("read")
assert app.is_parallel_allowed("write")
2bndy5 marked this conversation as resolved.
Show resolved Hide resolved


def _parse_object_description_signature(
env: sphinx.environment.BuildEnvironment, signature: str, node: docutils.nodes.Node
) -> str:
registry = apidoc_formatting.get_object_description_option_registry(env.app)
registry_option = registry.get(signature)
node += sphinx.addnodes.desc_name(signature, signature)
if registry_option is None:
logger.error("Invalid object description option: %r", signature)
else:
node += sphinx.addnodes.desc_sig_punctuation(" : ", " : ")
annotations = sphinx.domains.python._parse_annotation(
sphinx.util.typing.stringify(registry_option.type_constraint), env
)
node += sphinx.addnodes.desc_type("", "", *annotations)
node += sphinx.addnodes.desc_sig_punctuation(" = ", " = ")
default_repr = repr(registry_option.default)
node += docutils.nodes.literal(
default_repr,
default_repr,
language="python",
classes=["python", "code", "highlight"],
)
return signature


def setup(app):
app.add_object_type(
"confval",
"confval",
objname="configuration value",
indextemplate="pair: %s; configuration value",
)

app.add_object_type(
"objconf",
"objconf",
objname="object description option",
indextemplate="pair: %s; object description option",
parse_node=_parse_object_description_signature,
)
app.connect("builder-inited", _validate_parallel_build)
53 changes: 0 additions & 53 deletions docs/cpp.rst
Original file line number Diff line number Diff line change
@@ -1,59 +1,6 @@
C++ domain customization
========================

.. confval:: cpp_generate_synopses

:python:`bool` specifying whether to generate a *synopsis* for C++ domain
objects based on the first paragraph of their content (first sentence for
parameters). The synopsis is shown as a tooltip when hovering over a
cross-reference link, and is also shown in the search results list.

Defaults to :python:`True`.

.. rst-example:: C++ synopses

.. cpp:type:: synopses_ex::SomeType

Description will be shown as a tooltip when hovering over
cross-references to :cpp:expr:`SomeType` in other signatures as well as
in the TOC.

Additional description not shown in tooltip. This is the return type
for :cpp:expr:`Foo`.

.. cpp:function:: template <typename T, int N> \
synopses_ex::SomeType synopses_ex::Foo(\
T param, \
const int (&arr)[N]\
);

Synopsis for this function, shown when hovering over cross references
as well as in the TOC.

:tparam T: Tooltip shown when hovering over cross-references to this
template parameter. Additional description not included in
tooltip.
:tparam N: Tooltip shown for N.
:param param: Tooltip shown for cross-references to this function
parameter param.
:param arr: Tooltip shown for cross-references to this function
parameter arr. To cross reference another parameter, use the
:rst:role:`cpp:expr` role, e.g.: :cpp:expr:`N`. Parameters can
also be referenced via their fake qualified name,
e.g. :cpp:expr:`synopses_ex::Foo::N`.
:returns: Something or other.


.. rst-example::

.. cpp:class:: synopses_ex::Class

.. cpp:function:: Class(uint16_t _cepin, uint16_t _cspin, uint32_t _spi_speed=RF24_SPI_SPEED)

:param _cepin: The pin attached to Chip Enable on the RF module
:param _cspin: The pin attached to Chip Select (often labeled CSN) on the radio module.
:param _spi_speed: The SPI speed in Hz ie: 1000000 == 1Mhz

.. confval:: cpp_strip_namespaces_from_signatures

:python:`list[str]` specifying namespaces to strip from signatures. This
Expand Down
Loading