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

ENH: enable multiline signatures when too long. #11011

Merged
merged 110 commits into from May 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
82f1b98
ENH: enable multiline signatures when too long.
TLouf Dec 3, 2022
8d6dfba
Make parameter nodes inherit from sig classes
TLouf Dec 17, 2022
581433b
Fix permalink for multiline Python signatures
TLouf Dec 17, 2022
d3ec233
Enable multiline sig for C and C++
TLouf Dec 17, 2022
1229b66
Simplify `desc_parameterlist` into single class
TLouf Dec 26, 2022
ec713e9
Fix flake8 errors
TLouf Dec 26, 2022
85ff493
Pass multiline as `desc_parameterlist` attribute
TLouf Dec 26, 2022
8ca560d
Add type annotation
TLouf Dec 26, 2022
9ec4698
Use new desc_parameterline instead of desc_content
TLouf Dec 28, 2022
b93ecf0
Support HTML writer
TLouf Dec 28, 2022
3b110ce
Support text writer
TLouf Dec 28, 2022
234acd6
Increment environment versions
TLouf Dec 29, 2022
7c016c9
Better variable names
TLouf Dec 30, 2022
5b8735d
Expand docstrings of new nodes' classes
TLouf Dec 30, 2022
1ca68b0
Fix oversight of param line name change in C++
TLouf Jan 3, 2023
8e198f3
Add newlines to make param list HTML prettier
TLouf Jan 3, 2023
25ae353
Tweak EPUB's CSS to match HTML's
TLouf Jan 3, 2023
d6b2dac
Add tests for python domain
TLouf Jan 3, 2023
af77cad
Add tests for C domain
TLouf Jan 3, 2023
ea89180
Add tests for C++ domain
TLouf Jan 3, 2023
5cc07d6
Add minimal implementation for man and texinfo
TLouf Jan 3, 2023
caff655
Python domain test cleanup
TLouf Jan 3, 2023
b71b06d
Make flake8 happy
TLouf Jan 3, 2023
88c2e09
Make isort happy
TLouf Jan 3, 2023
4258fd5
Add doc
TLouf Jan 3, 2023
6e6261c
Make docslint happy
TLouf Jan 3, 2023
9c52eae
Add types for `maximum_signature_line_length`
TLouf Jan 8, 2023
2d9ad80
Fix typo
TLouf Jan 8, 2023
0bc3b68
Add global `maximum_signature_line_length` config
TLouf Jan 8, 2023
2c0da6a
Add tentative LaTeX implementation
TLouf Jan 20, 2023
bba2b51
Merge branch 'master' into signature-linebreaks
TLouf Jan 20, 2023
d8df099
Make docslint happy
TLouf Jan 20, 2023
d18f973
Merge branch 'master' into signature-linebreaks
jfbu Jan 23, 2023
d803e68
Cleanup latex style
TLouf Jan 23, 2023
3753e7e
Rename new latex command for clarity
TLouf Jan 23, 2023
eb63da6
Force zero margins for dl tag
TLouf Jan 23, 2023
53e882f
latex: avoid page break above first function argument
TLouf Jan 24, 2023
d7508a0
latex: match coding style of LaTeX macro files in for loop
TLouf Jan 24, 2023
b665647
latex: rename command to `pysigwithonelineperarg`
TLouf Jan 24, 2023
ada9d00
latex: avoid page break before dedented closing brace
TLouf Jan 24, 2023
ed7fac8
Update versionadded
TLouf Jan 24, 2023
1475f5f
docs: fix linking to `single-line-signature`
TLouf Jan 24, 2023
9b9e694
docs: better linking to `single-line-signature`
TLouf Jan 25, 2023
691a780
Merge branch 'master' into signature-linebreaks
TLouf Apr 7, 2023
4deb58c
Add trailing commas for ruff
TLouf Apr 7, 2023
48d2ccb
Add trailing commas in tests
TLouf Apr 7, 2023
b065ab7
Add `desc_parameter_line` to doc
TLouf Apr 7, 2023
8d42ac1
Merge branch 'master' into signature-linebreaks
AA-Turner Apr 7, 2023
2b864fe
Update config docs
AA-Turner Apr 8, 2023
fa97a15
Update option docs
AA-Turner Apr 7, 2023
d787002
Move options to end
AA-Turner Apr 8, 2023
707650f
Revert changes to the frozen HTML 4 writer
AA-Turner Apr 7, 2023
b1cb1b3
Revert ``is_multiline`` -> ```is_multi_line`` rename for ``desc_signa…
AA-Turner Apr 7, 2023
8308742
``maximum_signature_line_length`` type to be int | None
AA-Turner Apr 7, 2023
e6ef3c2
Rename ``single-line-signature`` to ``single-line-{parameter,argument…
AA-Turner Apr 8, 2023
dfd0075
Refactor tests
AA-Turner Apr 8, 2023
bfab7ea
Set and use ``multi_line_parameter_list`` on node
AA-Turner Apr 7, 2023
26551bc
Remove ``desc_parameter_line``
AA-Turner Apr 8, 2023
9d03de0
options docs typo (macro -> function)
AA-Turner Apr 8, 2023
b3e5662
CHANGES entry
AA-Turner Apr 8, 2023
592c86c
fixup! Remove ``desc_parameter_line``
AA-Turner Apr 8, 2023
1af1a2e
Restore stripped whitespace
AA-Turner Apr 8, 2023
69dba4b
fixup! (round 2) Remove ``desc_parameter_line``
AA-Turner Apr 8, 2023
2918995
Remove unneeded py domain permalink logic
AA-Turner Apr 8, 2023
d58b63c
Restore cross-reference to single line option
TLouf Apr 8, 2023
b866b88
Add JS domain implentation
TLouf Apr 8, 2023
c6cf460
Mention @jfbu in CHANGES
TLouf Apr 9, 2023
b18c481
Unify directive option to `single-line-parameter-list`
TLouf Apr 9, 2023
4b47e79
Fix directive hyperlink in CHANGES
TLouf Apr 9, 2023
a652d3e
Pass multiline bool to `_pseudo_parse_arglist`
TLouf Apr 10, 2023
bcba5f6
Handle bracket notation for optional params in HTML
TLouf Apr 10, 2023
3243f9d
Rename `on_single_line` to `on_separate_line`
TLouf Apr 10, 2023
93bdb8d
Fix latex for sigs starting with optional param
TLouf Apr 10, 2023
417db1f
Cleanup of HTML
TLouf Apr 11, 2023
c4e9c62
Update LaTeX to handle optional parameters in one line per param context
jfbu Apr 11, 2023
57004e3
Use some LaTeX hack to handle comma placement vs bracket
jfbu Apr 11, 2023
88cfe5a
Mark latex strings as raw to ignore backslashes
TLouf Apr 11, 2023
9ce3e34
Add trailing comma in expected HTML of tests
TLouf Apr 11, 2023
3379337
Merge branch 'master' into signature-linebreaks
jfbu Apr 11, 2023
98f1803
Move `and` operator to line start
TLouf Apr 16, 2023
ef7adde
Handle optionals in text writer
TLouf Apr 16, 2023
1ad0981
Add `single-line-parameter-list` as JS object option
TLouf Apr 16, 2023
e36c811
Add essential JS tests
TLouf Apr 16, 2023
ea30441
Actually test for `multi_line_parameter_list` bool
TLouf Apr 16, 2023
2d604b9
Add JS tests with `maximum_signature_line_length`
TLouf Apr 16, 2023
71f5a8a
Remove (probably) forgotten c test template
TLouf Apr 16, 2023
e948563
Make test names consistent
TLouf Apr 16, 2023
d2b3459
Add newline after dd tags to make more readable HTML
TLouf Apr 16, 2023
bfc353e
Test for optional syntax in js and py domains
TLouf Apr 16, 2023
0c54703
latex: handle comma placement in writer
TLouf Apr 16, 2023
a1b031f
latex: follow-up refactoring after TeX black magic removal
jfbu Apr 16, 2023
a0f5d9b
latex: tidy-up some comment in sphinxlatexstyletext.sty
jfbu Apr 16, 2023
a8a9be9
Fix comma placement when `required_params_left`
TLouf Apr 16, 2023
3b34e30
Fix case of multiple params at same optional level
TLouf Apr 16, 2023
2c1f83a
lint: remove extra line between method defs
TLouf Apr 16, 2023
9c625f1
Conform test to new syntax
TLouf Apr 16, 2023
5866fe6
Test for multiple params in optional level
TLouf Apr 17, 2023
3bef7e4
Make HTML asserts more modular to ease debugging
TLouf Apr 18, 2023
30041a6
Test xelatex PDF build
TLouf Apr 21, 2023
8037a5b
Actually override xelatex' build conf
TLouf Apr 21, 2023
2a85b9e
Merge branch 'master' into signature-linebreaks
jfbu Apr 21, 2023
35424ea
Document the added \sphinxparam, \sphinxparamcomma...
jfbu Apr 21, 2023
db91327
Add a specific latex unit test
jfbu Apr 21, 2023
1a44553
Remove blank line in latex.rst
jfbu Apr 21, 2023
0c4fdb8
Simplify parametrize of latex build test
TLouf Apr 22, 2023
36183f5
Add tests for text output
TLouf Apr 22, 2023
f2d1574
Bump versionadded in doc/latex.rst to match expected release number
jfbu Apr 24, 2023
370cd0e
Bump again versionadded in doc/latex.rst to match expected release
jfbu Apr 30, 2023
50ac9a6
Merge branch 'master' into signature-linebreaks
AA-Turner May 11, 2023
585b2b9
misc updates (inc version bump)
AA-Turner May 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES
Expand Up @@ -26,6 +26,13 @@ Features added
generated HTML, using the CRC32 algorithm.
* :meth:`~sphinx.application.Sphinx.require_sphinx` now allows the version
requirement to be specified as ``(major, minor)``.
* #11011: Allow configuring a line-length limit for object signatures, via
:confval:`maximum_signature_line_length` and the domain-specific variants.
If the length of the signature (in characters) is greater than the configured
limit, each parameter in the signature will be split to its own logical line.
This behaviour may also be controlled by options on object description
directives, for example :rst:dir:`py:function:single-line-parameter-list`.
Patch by Thomas Louf, Adam Turner, and Jean-François Burnol.

Bugs fixed
----------
Expand Down
6 changes: 6 additions & 0 deletions doc/latex.rst
Expand Up @@ -1479,6 +1479,12 @@ Macros
.. versionadded:: 6.2.0
``\sphinxparam``, ``\sphinxsamedocref``

jfbu marked this conversation as resolved.
Show resolved Hide resolved
.. versionadded:: 7.1.0
``\sphinxparamcomma`` which defaults to a comma followed by a space and
``\sphinxparamcommaoneperline`` which is used for one-parameter-per-line
signatures (see :confval:`maximum_signature_line_length`). It defaults
to ``\texttt{,}`` to make these end-of-line separators more distinctive.

- More text styling:

.. csv-table::
Expand Down
54 changes: 54 additions & 0 deletions doc/usage/configuration.rst
Expand Up @@ -675,6 +675,25 @@ General configuration
If the value is a fully-qualified name of a custom Pygments style class,
this is then used as custom style.

.. confval:: maximum_signature_line_length

If a signature's length in characters exceeds the number set, each
parameter within the signature will be displayed on an individual logical
line.

When ``None`` (the default), there is no maximum length and the entire
signature will be displayed on a single logical line.

A 'logical line' is similar to a hard line break---builders or themes may
choose to 'soft wrap' a single logical line, and this setting does not affect
that behaviour.

Domains may provide options to suppress any hard wrapping on an individual
object directive, such as seen in the C, C++, and Python domains (e.g.
:rst:dir:`py:function:single-line-parameter-list`).

.. versionadded:: 7.1

.. confval:: add_function_parentheses

A boolean that decides whether parentheses are appended to function and
Expand Down Expand Up @@ -2912,6 +2931,14 @@ Options for the C domain

.. versionadded:: 4.0.3

.. confval:: c_maximum_signature_line_length
TLouf marked this conversation as resolved.
Show resolved Hide resolved

If a signature's length in characters exceeds the number set, each
parameter will be displayed on an individual logical line. This is a
domain-specific setting, overriding :confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. _cpp-config:

Options for the C++ domain
Expand Down Expand Up @@ -2942,6 +2969,14 @@ Options for the C++ domain

.. versionadded:: 1.5

.. confval:: cpp_maximum_signature_line_length

If a signature's length in characters exceeds the number set, each
parameter will be displayed on an individual logical line. This is a
domain-specific setting, overriding :confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

Options for the Python domain
-----------------------------

Expand Down Expand Up @@ -2984,6 +3019,25 @@ Options for the Python domain

.. note:: This configuration is still in experimental

.. confval:: python_maximum_signature_line_length

If a signature's length in characters exceeds the number set, each
argument will be displayed on an individual logical line. This is a
domain-specific setting, overriding :confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

Options for the Javascript domain
---------------------------------

.. confval:: javascript_maximum_signature_line_length

If a signature's length in characters exceeds the number set, each
parameter will be displayed on an individual logical line. This is a
domain-specific setting, overriding :confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

Example of configuration file
-----------------------------

Expand Down
91 changes: 91 additions & 0 deletions doc/usage/restructuredtext/domains.rst
Expand Up @@ -231,6 +231,16 @@ The following directives are provided for module and class contents:
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the function's arguments will be emitted on a single logical
line, overriding :confval:`python_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1


.. rst:directive:: .. py:data:: name

Describes global data in a module, including both variables and values used
Expand Down Expand Up @@ -329,6 +339,15 @@ The following directives are provided for module and class contents:
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the class constructor's arguments will be emitted on a single
logical line, overriding :confval:`python_maximum_signature_line_length`
and :confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. py:attribute:: name

Describes an object data attribute. The description should include
Expand Down Expand Up @@ -441,6 +460,15 @@ The following directives are provided for module and class contents:
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the method's arguments will be emitted on a single logical
line, overriding :confval:`python_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:option:: staticmethod
:type: no value

Expand Down Expand Up @@ -494,6 +522,15 @@ The following directives are provided for module and class contents:
There is no ``py:deco`` role to link to a decorator that is marked up with
this directive; rather, use the :rst:role:`py:func` role.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the decorator's arguments will be emitted on a single logical
line, overriding :confval:`python_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. py:decoratormethod:: name
.. py:decoratormethod:: name(signature)

Expand Down Expand Up @@ -763,6 +800,15 @@ The C domain (name **c**) is suited for documentation of C API.
:retval NULL: under some conditions.
:retval NULL: under some other conditions as well.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the function's parameters will be emitted on a single logical
line, overriding :confval:`c_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1


.. rst:directive:: .. c:macro:: name
.. c:macro:: name(arg list)
Expand All @@ -776,6 +822,15 @@ The C domain (name **c**) is suited for documentation of C API.
.. versionadded:: 3.0
The function style variant.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the macro's parameters will be emitted on a single logical
line, overriding :confval:`c_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. c:struct:: name

Describes a C struct.
Expand Down Expand Up @@ -1126,6 +1181,15 @@ visibility statement (``public``, ``private`` or ``protected``).
.. cpp:function:: template<> \
void print(int i)

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the function's parameters will be emitted on a single logical
line, overriding :confval:`cpp_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. cpp:member:: (member) variable declaration
.. cpp:var:: (member) variable declaration

Expand Down Expand Up @@ -1908,13 +1972,31 @@ The JavaScript domain (name **js**) provides the following directives:
:throws SomeError: For whatever reason in that case.
:returns: Something.

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the function's parameters will be emitted on a single logical
line, overriding :confval:`javascript_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. js:method:: name(signature)

This directive is an alias for :rst:dir:`js:function`, however it describes
a function that is implemented as a method on a class object.

.. versionadded:: 1.6

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the function's parameters will be emitted on a single logical
line, overriding :confval:`javascript_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. js:class:: name

Describes a constructor that creates an object. This is basically like a
Expand All @@ -1933,6 +2015,15 @@ The JavaScript domain (name **js**) provides the following directives:
:param string name: The name of the animal
:param number age: an optional age for the animal

.. rst:directive:option:: single-line-parameter-list
:type: no value

Ensures that the function's parameters will be emitted on a single logical
line, overriding :confval:`javascript_maximum_signature_line_length` and
:confval:`maximum_signature_line_length`.

.. versionadded:: 7.1

.. rst:directive:: .. js:data:: name

Describes a global variable or constant.
Expand Down
7 changes: 6 additions & 1 deletion sphinx/addnodes.py
Expand Up @@ -246,7 +246,12 @@ def astext(self) -> str:


class desc_parameterlist(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a general parameter list."""
"""Node for a general parameter list.

As default the parameter list is written in line with the rest of the signature.
Set ``multi_line_parameter_list = True`` to describe a multi-line parameter list.
In that case each parameter will then be written on its own, indented line.
"""
child_text_separator = ', '

def astext(self):
Expand Down
2 changes: 1 addition & 1 deletion sphinx/config.py
Expand Up @@ -137,7 +137,7 @@ class Config:
'numfig': (False, 'env', []),
'numfig_secnum_depth': (1, 'env', []),
'numfig_format': ({}, 'env', []), # will be initialized in init_numfig_format()

'maximum_signature_line_length': (None, 'env', {int, None}),
'math_number_all': (False, 'env', []),
'math_eqref_format': (None, 'env', [str]),
'math_numfig': (True, 'env', []),
Expand Down
22 changes: 21 additions & 1 deletion sphinx/domains/c.py
Expand Up @@ -727,9 +727,19 @@ def _stringify(self, transform: StringifyTransform) -> str:
def describe_signature(self, signode: TextElement, mode: str,
env: BuildEnvironment, symbol: Symbol) -> None:
verify_description_mode(mode)
multi_line_parameter_list = False
test_node: Element = signode
while test_node.parent:
if not isinstance(test_node, addnodes.desc_signature):
test_node = test_node.parent
continue
multi_line_parameter_list = test_node.get('multi_line_parameter_list', False)
break

# only use the desc_parameterlist for the outer list, not for inner lists
if mode == 'lastIsName':
paramlist = addnodes.desc_parameterlist()
paramlist['multi_line_parameter_list'] = multi_line_parameter_list
for arg in self.args:
param = addnodes.desc_parameter('', '', noemph=True)
arg.describe_signature(param, 'param', env, symbol=symbol)
Expand Down Expand Up @@ -3153,6 +3163,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
option_spec: OptionSpec = {
'noindexentry': directives.flag,
'nocontentsentry': directives.flag,
'single-line-parameter-list': directives.flag,
}

def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None:
Expand Down Expand Up @@ -3258,6 +3269,14 @@ def run(self) -> list[Node]:
def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration:
parentSymbol: Symbol = self.env.temp_data['c:parent_symbol']

max_len = (self.env.config.c_maximum_signature_line_length
or self.env.config.maximum_signature_line_length
or 0)
signode['multi_line_parameter_list'] = (
'single-line-parameter-list' not in self.options
and (len(sig) > max_len > 0)
)

parser = DefinitionParser(sig, location=signode, config=self.env.config)
try:
ast = self.parse_definition(parser)
Expand Down Expand Up @@ -3866,11 +3885,12 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_config_value("c_id_attributes", [], 'env')
app.add_config_value("c_paren_attributes", [], 'env')
app.add_config_value("c_extra_keywords", _macroKeywords, 'env')
app.add_config_value("c_maximum_signature_line_length", None, 'env', types={int, None})
app.add_post_transform(AliasTransform)

return {
'version': 'builtin',
'env_version': 2,
'env_version': 3,
'parallel_read_safe': True,
'parallel_write_safe': True,
}