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

Flexible declaration styling #9023

Merged
merged 22 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
14f7d24
Decl styling, more nodes and C++ conversion
jakobandersen Mar 16, 2021
3c9a74c
Decl styling, docs and restructuring
jakobandersen Mar 20, 2021
d131ec7
Decl styling, move desc dynamic classes to domain base class
jakobandersen Mar 20, 2021
e012c93
Decl styling, move static classes to addnodes from HTML5 writer
jakobandersen Mar 20, 2021
98800be
Decl styling, make desc_inline node
jakobandersen Mar 20, 2021
b0a2e5c
Decl styling, consistent monospace
jakobandersen Mar 20, 2021
86eeee5
Fix flake8 and mypy violations
jakobandersen Mar 20, 2021
c1da955
Decl styling, use a post-transform to get the domain name in the desc…
jakobandersen Mar 20, 2021
70708e4
Decl styling, add CSS for the C++ domain
jakobandersen Mar 20, 2021
87414fa
Decl styling, fix cpp tests
jakobandersen Mar 20, 2021
3fdc9bc
Fix desc_sig_space
jakobandersen Mar 20, 2021
f769dde
Decl styling, fix html test
jakobandersen Mar 20, 2021
c0ef6a9
Fix isort violation
jakobandersen Mar 20, 2021
7126503
Decl styling, update writers
jakobandersen Mar 25, 2021
a1ac0fd
Decl styling, C++, fix alternate spellings of operators
jakobandersen Mar 30, 2021
9cd9e12
Decl styling, convert C
jakobandersen Mar 30, 2021
f1d9d0a
Decl styling, C styling and C++ char literal styling
jakobandersen Mar 30, 2021
a840b9e
C, C++, fix unary op
jakobandersen Mar 30, 2021
da5b8e4
Decl styling, fixes from review
jakobandersen Apr 7, 2021
cb21eb2
Decl styling, handle desc_inline in manpage and texinfo
jakobandersen Apr 11, 2021
9b3b8a4
Decl styling, fix font size in basic
jakobandersen Apr 12, 2021
709339e
Decl styling, disable smart quoting in sigs
jakobandersen Apr 12, 2021
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
5 changes: 5 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ Dependencies
Incompatible changes
--------------------

* #9023: Change the CSS classes on :rst:role:`cpp:expr` and
:rst:role:`cpp:texpr`.

Deprecated
----------

Features added
--------------

* #9023: More CSS classes on domain descriptions, see :ref:`nodes` for details.

Bugs fixed
----------

Expand Down
18 changes: 16 additions & 2 deletions doc/extdev/nodes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,32 @@ Doctree node classes added by Sphinx
Nodes for domain-specific object descriptions
---------------------------------------------

Top-level nodes
...............

These nodes form the top-most levels of object descriptions.

.. autoclass:: desc
.. autoclass:: desc_signature
.. autoclass:: desc_signature_line
.. autoclass:: desc_content
.. autoclass:: desc_inline

Nodes for high-level structure in signatures
............................................

These nodes occur in in non-multiline :py:class:`desc_signature` nodes
and in :py:class:`desc_signature_line` nodes.

.. autoclass:: desc_name
.. autoclass:: desc_addname

.. autoclass:: desc_type
.. autoclass:: desc_returns
.. autoclass:: desc_name
.. autoclass:: desc_parameterlist
.. autoclass:: desc_parameter
.. autoclass:: desc_optional
.. autoclass:: desc_annotation
.. autoclass:: desc_content

New admonition-like constructs
------------------------------
Expand Down
183 changes: 152 additions & 31 deletions sphinx/addnodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,25 +115,53 @@ def extract_original_messages(self) -> List[str]:
return messages


# domain-specific object descriptions (class, function etc.)
#############################################################
# Domain-specific object descriptions (class, function etc.)
#############################################################

class _desc_classes_injector(nodes.Element, not_smartquotable):
"""Helper base class for injecting a fixes list of classes.

Use as the first base class.
"""

classes: List[str] = []

def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self['classes'].extend(self.classes)


# Top-level nodes
#################

class desc(nodes.Admonition, nodes.Element):
"""Node for object descriptions.
"""Node for a list of object signatures and a common description of them.

This node is similar to a "definition list" with one definition. It
contains one or more ``desc_signature`` and a ``desc_content``.
Contains one or more :py:class:`desc_signature` nodes
and then a single :py:class:`desc_content` node.

This node always has two classes:

- The name of the domain it belongs to, e.g., ``py`` or ``cpp``.
- The name of the object type in the domain, e.g., ``function``.
"""

# TODO: can we introduce a constructor
# that forces the specification of the domain and objtyp?

class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for object signatures.

The "term" part of the custom Sphinx definition list.
class desc_signature(_desc_classes_injector, nodes.Part, nodes.Inline, nodes.TextElement):
"""Node for a single object signature.

As default the signature is a single line signature,
but set ``is_multiline = True`` to describe a multi-line signature.
In that case all child nodes must be ``desc_signature_line`` nodes.
As default the signature is a single-line signature.
Set ``is_multiline = True`` to describe a multi-line signature.
In that case all child nodes must be :py:class:`desc_signature_line` nodes.

This node always has the classes ``sig``, ``sig-object``, and the domain it belongs to.
"""
# Note: the domain name is being added through a post-transform DescSigAddDomainAsClass
classes = ['sig', 'sig-object']

@property
def child_text_separator(self):
Expand All @@ -144,18 +172,63 @@ def child_text_separator(self):


class desc_signature_line(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a line in a multi-line object signatures.
"""Node for a line in a multi-line object signature.

It should only be used in a ``desc_signature`` with ``is_multiline`` set.
It should only be used as a child of a :py:class:`desc_signature`
with ``is_multiline`` set to ``True``.
Set ``add_permalink = True`` for the line that should get the permalink.
"""
sphinx_line_type = ''


class desc_content(nodes.General, nodes.Element):
"""Node for object description content.

Must be the last child node in a :py:class:`desc` node.
"""


class desc_inline(_desc_classes_injector, nodes.Inline, nodes.TextElement):
"""Node for a signature fragment in inline text.

This is for example used for roles like :rst:role:`cpp:expr`.

This node always has the classes ``sig``, ``sig-inline``,
and the name of the domain it belongs to.
"""
classes = ['sig', 'sig-inline']

def __init__(self, domain: str, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self['classes'].append(domain)


# Nodes for high-level structure in signatures
##############################################

# nodes to use within a desc_signature or desc_signature_line

class desc_addname(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for additional name parts (module name, class name)."""
class desc_name(_desc_classes_injector, nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for the main object name.

For example, in the declaration of a Python class ``MyModule.MyClass``,
the main name is ``MyClass``.

This node always has the class ``sig-name``.
"""
classes = ['sig-name', 'descname'] # 'descname' is for backwards compatibility


class desc_addname(_desc_classes_injector, nodes.Part, nodes.Inline, nodes.FixedTextElement):
jakobandersen marked this conversation as resolved.
Show resolved Hide resolved
"""Node for additional name parts for an object.

For example, in the declaration of a Python class ``MyModule.MyClass``,
the additional name part is ``MyModule.``.

This node always has the class ``sig-prename``.
"""
# 'descclassname' is for backwards compatibility
classes = ['sig-prename', 'descclassname']


# compatibility alias
Expand All @@ -168,14 +241,11 @@ class desc_type(nodes.Part, nodes.Inline, nodes.FixedTextElement):

class desc_returns(desc_type):
"""Node for a "returns" annotation (a la -> in Python)."""

def astext(self) -> str:
return ' -> ' + super().astext()


class desc_name(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for the main object name."""


class desc_parameterlist(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a general parameter list."""
child_text_separator = ', '
Expand All @@ -200,14 +270,14 @@ class desc_annotation(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for signature annotations (not Python 3-style annotations)."""


class desc_content(nodes.General, nodes.Element):
"""Node for object description content.

This is the "definition" part of the custom Sphinx definition list.
"""
# Leaf nodes for markup of text fragments
#########################################

# Signature text elements, generally translated to node.inline
# in SigElementFallbackTransform.
# When adding a new one, add it to SIG_ELEMENTS.

class desc_sig_element(nodes.inline):
class desc_sig_element(nodes.inline, _desc_classes_injector):
"""Common parent class of nodes for inline text of a signature."""
classes: List[str] = []

Expand All @@ -217,8 +287,20 @@ def __init__(self, rawsource: str = '', text: str = '',
self['classes'].extend(self.classes)


# to not reinvent the wheel, the classes in the following desc_sig classes
# are based on those used in Pygments

class desc_sig_space(desc_sig_element):
"""Node for a space in a signature."""
classes = ["w"]

def __init__(self, rawsource: str = '', text: str = ' ',
*children: Element, **attributes: Any) -> None:
super().__init__(rawsource, text, *children, **attributes)


class desc_sig_name(desc_sig_element):
"""Node for a name in a signature."""
"""Node for an identifier in a signature."""
classes = ["n"]


Expand All @@ -228,10 +310,44 @@ class desc_sig_operator(desc_sig_element):


class desc_sig_punctuation(desc_sig_element):
"""Node for a punctuation in a signature."""
"""Node for punctuation in a signature."""
classes = ["p"]


class desc_sig_keyword(desc_sig_element):
"""Node for a general keyword in a signature."""
classes = ["k"]


class desc_sig_keyword_type(desc_sig_element):
"""Node for a keyword which is a built-in type in a signature."""
classes = ["kt"]


class desc_sig_literal_number(desc_sig_element):
"""Node for a numeric literal in a signature."""
classes = ["m"]


class desc_sig_literal_string(desc_sig_element):
"""Node for a string literal in a signature."""
classes = ["s"]


class desc_sig_literal_char(desc_sig_element):
"""Node for a character literal in a signature."""
classes = ["sc"]


SIG_ELEMENTS = [desc_sig_space,
desc_sig_name,
desc_sig_operator,
desc_sig_punctuation,
desc_sig_keyword, desc_sig_keyword_type,
desc_sig_literal_number, desc_sig_literal_string, desc_sig_literal_char]


###############################################################
# new admonition-like constructs

class versionmodified(nodes.Admonition, nodes.TextElement):
Expand Down Expand Up @@ -336,6 +452,7 @@ class pending_xref(nodes.Inline, nodes.Element):
These nodes are resolved before writing output, in
BuildEnvironment.resolve_references.
"""
child_text_separator = ''
tk0miya marked this conversation as resolved.
Show resolved Hide resolved


class pending_xref_condition(nodes.Inline, nodes.TextElement):
Expand Down Expand Up @@ -412,21 +529,25 @@ class manpage(nodes.Inline, nodes.FixedTextElement):

def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_node(toctree)

app.add_node(desc)
app.add_node(desc_signature)
app.add_node(desc_signature_line)
app.add_node(desc_content)
app.add_node(desc_inline)

app.add_node(desc_name)
app.add_node(desc_addname)
app.add_node(desc_type)
app.add_node(desc_returns)
app.add_node(desc_name)
app.add_node(desc_parameterlist)
app.add_node(desc_parameter)
app.add_node(desc_optional)
app.add_node(desc_annotation)
app.add_node(desc_content)
app.add_node(desc_sig_name)
app.add_node(desc_sig_operator)
app.add_node(desc_sig_punctuation)

for n in SIG_ELEMENTS:
app.add_node(n)

app.add_node(versionmodified)
app.add_node(seealso)
app.add_node(productionlist)
Expand Down
1 change: 1 addition & 0 deletions sphinx/directives/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ def run(self) -> List[Node]:
node['noindex'] = noindex = ('noindex' in self.options)
if self.domain:
node['classes'].append(self.domain)
node['classes'].append(node['objtype'])

self.names: List[T] = []
signatures = self.get_signatures()
Expand Down
Loading