Skip to content

Commit 86b07d4

Browse files
TLoufAA-Turnerjfbu
authored
Allow multi-line object description signatures (#11011)
Co-authored-by: Adam Turner <[email protected]> Co-authored-by: Jean-François B <[email protected]> Co-authored-by: TLouf <[email protected]>
1 parent c73628d commit 86b07d4

File tree

30 files changed

+1635
-43
lines changed

30 files changed

+1635
-43
lines changed

CHANGES

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ Features added
2626
generated HTML, using the CRC32 algorithm.
2727
* :meth:`~sphinx.application.Sphinx.require_sphinx` now allows the version
2828
requirement to be specified as ``(major, minor)``.
29+
* #11011: Allow configuring a line-length limit for object signatures, via
30+
:confval:`maximum_signature_line_length` and the domain-specific variants.
31+
If the length of the signature (in characters) is greater than the configured
32+
limit, each parameter in the signature will be split to its own logical line.
33+
This behaviour may also be controlled by options on object description
34+
directives, for example :rst:dir:`py:function:single-line-parameter-list`.
35+
Patch by Thomas Louf, Adam Turner, and Jean-François Burnol.
2936

3037
Bugs fixed
3138
----------

doc/latex.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,12 @@ Macros
14791479
.. versionadded:: 6.2.0
14801480
``\sphinxparam``, ``\sphinxsamedocref``
14811481

1482+
.. versionadded:: 7.1.0
1483+
``\sphinxparamcomma`` which defaults to a comma followed by a space and
1484+
``\sphinxparamcommaoneperline`` which is used for one-parameter-per-line
1485+
signatures (see :confval:`maximum_signature_line_length`). It defaults
1486+
to ``\texttt{,}`` to make these end-of-line separators more distinctive.
1487+
14821488
- More text styling:
14831489

14841490
.. csv-table::

doc/usage/configuration.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,25 @@ General configuration
675675
If the value is a fully-qualified name of a custom Pygments style class,
676676
this is then used as custom style.
677677

678+
.. confval:: maximum_signature_line_length
679+
680+
If a signature's length in characters exceeds the number set, each
681+
parameter within the signature will be displayed on an individual logical
682+
line.
683+
684+
When ``None`` (the default), there is no maximum length and the entire
685+
signature will be displayed on a single logical line.
686+
687+
A 'logical line' is similar to a hard line break---builders or themes may
688+
choose to 'soft wrap' a single logical line, and this setting does not affect
689+
that behaviour.
690+
691+
Domains may provide options to suppress any hard wrapping on an individual
692+
object directive, such as seen in the C, C++, and Python domains (e.g.
693+
:rst:dir:`py:function:single-line-parameter-list`).
694+
695+
.. versionadded:: 7.1
696+
678697
.. confval:: add_function_parentheses
679698

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

29132932
.. versionadded:: 4.0.3
29142933

2934+
.. confval:: c_maximum_signature_line_length
2935+
2936+
If a signature's length in characters exceeds the number set, each
2937+
parameter will be displayed on an individual logical line. This is a
2938+
domain-specific setting, overriding :confval:`maximum_signature_line_length`.
2939+
2940+
.. versionadded:: 7.1
2941+
29152942
.. _cpp-config:
29162943

29172944
Options for the C++ domain
@@ -2942,6 +2969,14 @@ Options for the C++ domain
29422969

29432970
.. versionadded:: 1.5
29442971

2972+
.. confval:: cpp_maximum_signature_line_length
2973+
2974+
If a signature's length in characters exceeds the number set, each
2975+
parameter will be displayed on an individual logical line. This is a
2976+
domain-specific setting, overriding :confval:`maximum_signature_line_length`.
2977+
2978+
.. versionadded:: 7.1
2979+
29452980
Options for the Python domain
29462981
-----------------------------
29472982

@@ -2984,6 +3019,25 @@ Options for the Python domain
29843019

29853020
.. note:: This configuration is still in experimental
29863021

3022+
.. confval:: python_maximum_signature_line_length
3023+
3024+
If a signature's length in characters exceeds the number set, each
3025+
argument will be displayed on an individual logical line. This is a
3026+
domain-specific setting, overriding :confval:`maximum_signature_line_length`.
3027+
3028+
.. versionadded:: 7.1
3029+
3030+
Options for the Javascript domain
3031+
---------------------------------
3032+
3033+
.. confval:: javascript_maximum_signature_line_length
3034+
3035+
If a signature's length in characters exceeds the number set, each
3036+
parameter will be displayed on an individual logical line. This is a
3037+
domain-specific setting, overriding :confval:`maximum_signature_line_length`.
3038+
3039+
.. versionadded:: 7.1
3040+
29873041
Example of configuration file
29883042
-----------------------------
29893043

doc/usage/restructuredtext/domains.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,16 @@ The following directives are provided for module and class contents:
231231
Describe the location where the object is defined. The default value is
232232
the module specified by :rst:dir:`py:currentmodule`.
233233
234+
.. rst:directive:option:: single-line-parameter-list
235+
:type: no value
236+
237+
Ensures that the function's arguments will be emitted on a single logical
238+
line, overriding :confval:`python_maximum_signature_line_length` and
239+
:confval:`maximum_signature_line_length`.
240+
241+
.. versionadded:: 7.1
242+
243+
234244
.. rst:directive:: .. py:data:: name
235245
236246
Describes global data in a module, including both variables and values used
@@ -329,6 +339,15 @@ The following directives are provided for module and class contents:
329339
Describe the location where the object is defined. The default value is
330340
the module specified by :rst:dir:`py:currentmodule`.
331341
342+
.. rst:directive:option:: single-line-parameter-list
343+
:type: no value
344+
345+
Ensures that the class constructor's arguments will be emitted on a single
346+
logical line, overriding :confval:`python_maximum_signature_line_length`
347+
and :confval:`maximum_signature_line_length`.
348+
349+
.. versionadded:: 7.1
350+
332351
.. rst:directive:: .. py:attribute:: name
333352
334353
Describes an object data attribute. The description should include
@@ -441,6 +460,15 @@ The following directives are provided for module and class contents:
441460
Describe the location where the object is defined. The default value is
442461
the module specified by :rst:dir:`py:currentmodule`.
443462
463+
.. rst:directive:option:: single-line-parameter-list
464+
:type: no value
465+
466+
Ensures that the method's arguments will be emitted on a single logical
467+
line, overriding :confval:`python_maximum_signature_line_length` and
468+
:confval:`maximum_signature_line_length`.
469+
470+
.. versionadded:: 7.1
471+
444472
.. rst:directive:option:: staticmethod
445473
:type: no value
446474
@@ -494,6 +522,15 @@ The following directives are provided for module and class contents:
494522
There is no ``py:deco`` role to link to a decorator that is marked up with
495523
this directive; rather, use the :rst:role:`py:func` role.
496524

525+
.. rst:directive:option:: single-line-parameter-list
526+
:type: no value
527+
528+
Ensures that the decorator's arguments will be emitted on a single logical
529+
line, overriding :confval:`python_maximum_signature_line_length` and
530+
:confval:`maximum_signature_line_length`.
531+
532+
.. versionadded:: 7.1
533+
497534
.. rst:directive:: .. py:decoratormethod:: name
498535
.. py:decoratormethod:: name(signature)
499536
@@ -763,6 +800,15 @@ The C domain (name **c**) is suited for documentation of C API.
763800
:retval NULL: under some conditions.
764801
:retval NULL: under some other conditions as well.
765802
803+
.. rst:directive:option:: single-line-parameter-list
804+
:type: no value
805+
806+
Ensures that the function's parameters will be emitted on a single logical
807+
line, overriding :confval:`c_maximum_signature_line_length` and
808+
:confval:`maximum_signature_line_length`.
809+
810+
.. versionadded:: 7.1
811+
766812
767813
.. rst:directive:: .. c:macro:: name
768814
.. c:macro:: name(arg list)
@@ -776,6 +822,15 @@ The C domain (name **c**) is suited for documentation of C API.
776822
.. versionadded:: 3.0
777823
The function style variant.
778824
825+
.. rst:directive:option:: single-line-parameter-list
826+
:type: no value
827+
828+
Ensures that the macro's parameters will be emitted on a single logical
829+
line, overriding :confval:`c_maximum_signature_line_length` and
830+
:confval:`maximum_signature_line_length`.
831+
832+
.. versionadded:: 7.1
833+
779834
.. rst:directive:: .. c:struct:: name
780835
781836
Describes a C struct.
@@ -1126,6 +1181,15 @@ visibility statement (``public``, ``private`` or ``protected``).
11261181
.. cpp:function:: template<> \
11271182
void print(int i)
11281183
1184+
.. rst:directive:option:: single-line-parameter-list
1185+
:type: no value
1186+
1187+
Ensures that the function's parameters will be emitted on a single logical
1188+
line, overriding :confval:`cpp_maximum_signature_line_length` and
1189+
:confval:`maximum_signature_line_length`.
1190+
1191+
.. versionadded:: 7.1
1192+
11291193
.. rst:directive:: .. cpp:member:: (member) variable declaration
11301194
.. cpp:var:: (member) variable declaration
11311195
@@ -1908,13 +1972,31 @@ The JavaScript domain (name **js**) provides the following directives:
19081972
:throws SomeError: For whatever reason in that case.
19091973
:returns: Something.
19101974

1975+
.. rst:directive:option:: single-line-parameter-list
1976+
:type: no value
1977+
1978+
Ensures that the function's parameters will be emitted on a single logical
1979+
line, overriding :confval:`javascript_maximum_signature_line_length` and
1980+
:confval:`maximum_signature_line_length`.
1981+
1982+
.. versionadded:: 7.1
1983+
19111984
.. rst:directive:: .. js:method:: name(signature)
19121985
19131986
This directive is an alias for :rst:dir:`js:function`, however it describes
19141987
a function that is implemented as a method on a class object.
19151988

19161989
.. versionadded:: 1.6
19171990

1991+
.. rst:directive:option:: single-line-parameter-list
1992+
:type: no value
1993+
1994+
Ensures that the function's parameters will be emitted on a single logical
1995+
line, overriding :confval:`javascript_maximum_signature_line_length` and
1996+
:confval:`maximum_signature_line_length`.
1997+
1998+
.. versionadded:: 7.1
1999+
19182000
.. rst:directive:: .. js:class:: name
19192001
19202002
Describes a constructor that creates an object. This is basically like a
@@ -1933,6 +2015,15 @@ The JavaScript domain (name **js**) provides the following directives:
19332015
:param string name: The name of the animal
19342016
:param number age: an optional age for the animal
19352017

2018+
.. rst:directive:option:: single-line-parameter-list
2019+
:type: no value
2020+
2021+
Ensures that the function's parameters will be emitted on a single logical
2022+
line, overriding :confval:`javascript_maximum_signature_line_length` and
2023+
:confval:`maximum_signature_line_length`.
2024+
2025+
.. versionadded:: 7.1
2026+
19362027
.. rst:directive:: .. js:data:: name
19372028
19382029
Describes a global variable or constant.

sphinx/addnodes.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,12 @@ def astext(self) -> str:
246246

247247

248248
class desc_parameterlist(nodes.Part, nodes.Inline, nodes.FixedTextElement):
249-
"""Node for a general parameter list."""
249+
"""Node for a general parameter list.
250+
251+
As default the parameter list is written in line with the rest of the signature.
252+
Set ``multi_line_parameter_list = True`` to describe a multi-line parameter list.
253+
In that case each parameter will then be written on its own, indented line.
254+
"""
250255
child_text_separator = ', '
251256

252257
def astext(self):

sphinx/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class Config:
137137
'numfig': (False, 'env', []),
138138
'numfig_secnum_depth': (1, 'env', []),
139139
'numfig_format': ({}, 'env', []), # will be initialized in init_numfig_format()
140-
140+
'maximum_signature_line_length': (None, 'env', {int, None}),
141141
'math_number_all': (False, 'env', []),
142142
'math_eqref_format': (None, 'env', [str]),
143143
'math_numfig': (True, 'env', []),

sphinx/domains/c.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,19 @@ def _stringify(self, transform: StringifyTransform) -> str:
727727
def describe_signature(self, signode: TextElement, mode: str,
728728
env: BuildEnvironment, symbol: Symbol) -> None:
729729
verify_description_mode(mode)
730+
multi_line_parameter_list = False
731+
test_node: Element = signode
732+
while test_node.parent:
733+
if not isinstance(test_node, addnodes.desc_signature):
734+
test_node = test_node.parent
735+
continue
736+
multi_line_parameter_list = test_node.get('multi_line_parameter_list', False)
737+
break
738+
730739
# only use the desc_parameterlist for the outer list, not for inner lists
731740
if mode == 'lastIsName':
732741
paramlist = addnodes.desc_parameterlist()
742+
paramlist['multi_line_parameter_list'] = multi_line_parameter_list
733743
for arg in self.args:
734744
param = addnodes.desc_parameter('', '', noemph=True)
735745
arg.describe_signature(param, 'param', env, symbol=symbol)
@@ -3153,6 +3163,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
31533163
option_spec: OptionSpec = {
31543164
'noindexentry': directives.flag,
31553165
'nocontentsentry': directives.flag,
3166+
'single-line-parameter-list': directives.flag,
31563167
}
31573168

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

3272+
max_len = (self.env.config.c_maximum_signature_line_length
3273+
or self.env.config.maximum_signature_line_length
3274+
or 0)
3275+
signode['multi_line_parameter_list'] = (
3276+
'single-line-parameter-list' not in self.options
3277+
and (len(sig) > max_len > 0)
3278+
)
3279+
32613280
parser = DefinitionParser(sig, location=signode, config=self.env.config)
32623281
try:
32633282
ast = self.parse_definition(parser)
@@ -3866,11 +3885,12 @@ def setup(app: Sphinx) -> dict[str, Any]:
38663885
app.add_config_value("c_id_attributes", [], 'env')
38673886
app.add_config_value("c_paren_attributes", [], 'env')
38683887
app.add_config_value("c_extra_keywords", _macroKeywords, 'env')
3888+
app.add_config_value("c_maximum_signature_line_length", None, 'env', types={int, None})
38693889
app.add_post_transform(AliasTransform)
38703890

38713891
return {
38723892
'version': 'builtin',
3873-
'env_version': 2,
3893+
'env_version': 3,
38743894
'parallel_read_safe': True,
38753895
'parallel_write_safe': True,
38763896
}

0 commit comments

Comments
 (0)