Skip to content

Commit 1c15fe1

Browse files
TomerGodingerstephenfin
authored andcommitted
Add anchors to options, arguments and envvars
Add anchors to all the Click components (i.e. groups and commands), along with another general one for options so that now using the full path of the component with separating dashes is always a valid reference. E.g. for a group "mygroup", command "mycommand" and option "-myoption", all of the following work: :ref:`My Group <mygroup>` :ref:`My Command <mygroup-mycommand>` :ref:`My Option <mygroup-mycommand-myoption>` :option:`My Option <mygroup-mycommand -myoption>`
1 parent dc11fe1 commit 1c15fe1

File tree

2 files changed

+109
-11
lines changed

2 files changed

+109
-11
lines changed

sphinx_click/ext.py

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,25 @@ def _format_usage(ctx: click.Context) -> ty.Generator[str, None, None]:
171171
yield ''
172172

173173

174+
def _format_command_name(ctx: click.Context) -> str:
175+
command_name: str = ctx.command_path.replace(' ', '-')
176+
return command_name
177+
178+
174179
def _format_option(
175180
ctx: click.Context, opt: click.core.Option
176181
) -> ty.Generator[str, None, None]:
177182
"""Format the output for a `click.core.Option`."""
183+
184+
# Add an anchor for each form of option name
185+
# For click.option('--flag', '-f', ...) it'll create anchors for "flag" and "f"
186+
option_names = list(set([option_name.lstrip('-') for option_name in opt.opts]))
187+
for option_name in option_names:
188+
yield '.. _{command_name}-{param}:'.format(
189+
command_name=_format_command_name(ctx), param=option_name
190+
)
191+
yield ''
192+
178193
opt_help = _get_help_record(ctx, opt)
179194

180195
yield '.. option:: {}'.format(opt_help[0])
@@ -209,8 +224,16 @@ def _format_options(ctx: click.Context) -> ty.Generator[str, None, None]:
209224
yield ''
210225

211226

212-
def _format_argument(arg: click.Argument) -> ty.Generator[str, None, None]:
227+
def _format_argument(
228+
ctx: click.Context,
229+
arg: click.Argument,
230+
) -> ty.Generator[str, None, None]:
213231
"""Format the output of a `click.Argument`."""
232+
yield '.. _{command_name}-{param}:'.format(
233+
command_name=_format_command_name(ctx), param=arg.human_readable_name
234+
)
235+
yield ''
236+
214237
yield '.. option:: {}'.format(arg.human_readable_name)
215238
yield ''
216239
yield _indent(
@@ -233,15 +256,36 @@ def _format_arguments(ctx: click.Context) -> ty.Generator[str, None, None]:
233256
params = [x for x in ctx.command.params if isinstance(x, click.Argument)]
234257

235258
for param in params:
236-
for line in _format_argument(param):
259+
for line in _format_argument(ctx, param):
237260
yield line
238261
yield ''
239262

240263

241264
def _format_envvar(
265+
ctx: click.Context,
242266
param: ty.Union[click.core.Option, click.Argument],
243267
) -> ty.Generator[str, None, None]:
244268
"""Format the envvars of a `click.Option` or `click.Argument`."""
269+
command_name = _format_command_name(ctx)
270+
271+
# Add an anchor for each form of parameter name
272+
# For click.option('--flag', '-f', ...) it'll create anchors for "flag" and "f"
273+
param_names = sorted(set(param_name.lstrip('-') for param_name in param.opts))
274+
275+
# Only add the parameter's own name if it's not already present, in whatever case
276+
if param.name.upper() not in (
277+
name.upper() for name in param_names
278+
): # Case-insensitive "in" test
279+
param_names.append(param.name)
280+
281+
for param_name in param_names:
282+
yield '.. _{command_name}-{param_name}-{envvar}:'.format(
283+
command_name=command_name,
284+
param_name=param_name,
285+
envvar=param.envvar,
286+
)
287+
yield ''
288+
245289
yield '.. envvar:: {}'.format(param.envvar)
246290
yield ' :noindex:'
247291
yield ''
@@ -270,13 +314,7 @@ def _format_envvars(ctx: click.Context) -> ty.Generator[str, None, None]:
270314
params = [x for x in ctx.command.params if x.envvar]
271315

272316
for param in params:
273-
yield '.. _{command_name}-{param_name}-{envvar}:'.format(
274-
command_name=ctx.command_path.replace(' ', '-'),
275-
param_name=param.name,
276-
envvar=param.envvar,
277-
)
278-
yield ''
279-
for line in _format_envvar(param):
317+
for line in _format_envvar(ctx, param):
280318
yield line
281319
yield ''
282320

tests/test_formatter.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,32 +87,44 @@ def foobar(bar):
8787
8888
.. rubric:: Options
8989
90+
.. _foobar-param:
91+
9092
.. option:: --param <param>
9193
9294
A sample option
9395
96+
.. _foobar-another:
97+
9498
.. option:: --another <FOO>
9599
96100
Another option
97101
102+
.. _foobar-choice:
103+
98104
.. option:: --choice <choice>
99105
100106
A sample option with choices
101107
102108
:options: Option1 | Option2
103109
110+
.. _foobar-numeric-choice:
111+
104112
.. option:: --numeric-choice <choice>
105113
106114
A sample option with numeric choices
107115
108116
:options: 1 | 2 | 3
109117
118+
.. _foobar-flag:
119+
110120
.. option:: --flag
111121
112122
A boolean flag
113123
114124
.. rubric:: Arguments
115125
126+
.. _foobar-ARG:
127+
116128
.. option:: ARG
117129
118130
Required argument
@@ -126,7 +138,7 @@ def foobar(bar):
126138
127139
Provide a default for :option:`--param`
128140
129-
.. _foobar-arg-ARG:
141+
.. _foobar-ARG-ARG:
130142
131143
.. envvar:: ARG
132144
:noindex:
@@ -160,6 +172,8 @@ def foobar(bar):
160172
161173
.. rubric:: Options
162174
175+
.. _foobar-param:
176+
163177
.. option:: --param <param>
164178
165179
A sample option
@@ -205,19 +219,25 @@ def foobar(bar):
205219
206220
.. rubric:: Options
207221
222+
.. _foobar-option:
223+
208224
.. option:: --option <option>
209225
210226
A sample option
211227
212228
.. rubric:: Arguments
213229
230+
.. _foobar-ARG:
231+
214232
.. option:: ARG
215233
216234
Required argument
217235
218236
A sample argument
219237
220238
239+
.. _foobar-ARG_NO_HELP:
240+
221241
.. option:: ARG_NO_HELP
222242
223243
Required argument
@@ -269,26 +289,38 @@ def foobar(bar):
269289
270290
.. rubric:: Options
271291
292+
.. _foobar-num-param:
293+
272294
.. option:: --num-param <num_param>
273295
274296
:default: ``42``
275297
298+
.. _foobar-param:
299+
276300
.. option:: --param <param>
277301
278302
:default: ``'Something computed at runtime'``
279303
304+
.. _foobar-group:
305+
280306
.. option:: --group <group>
281307
282308
:default: ``('foo', 'bar')``
283309
310+
.. _foobar-only-show-default:
311+
284312
.. option:: --only-show-default <only_show_default>
285313
286314
:default: ``'Some default computed at runtime!'``
287315
316+
.. _foobar-string-default:
317+
288318
.. option:: --string-default <string_default>
289319
290320
:default: ``'abc'``
291321
322+
.. _foobar-empty-string-default:
323+
292324
.. option:: --empty-string-default <empty_string_default>
293325
294326
:default: ``''``
@@ -321,10 +353,14 @@ def foobar():
321353
322354
.. rubric:: Options
323355
356+
.. _foobar-no-set:
357+
324358
.. option:: --no-set <no_set>
325359
326360
:default: ``0``
327361
362+
.. _foobar-set-false:
363+
328364
.. option:: --set-false <set_false>
329365
"""
330366
).lstrip(),
@@ -382,6 +418,8 @@ def hello(name):
382418
383419
.. rubric:: Options
384420
421+
.. _hello-name:
422+
385423
.. option:: --name <name>
386424
387425
**Required** Name to say hello to.
@@ -436,16 +474,22 @@ def foobar():
436474
437475
.. rubric:: Options
438476
477+
.. _foobar-name:
478+
439479
.. option:: --name <name>
440480
441481
**Required** Name to say hello to.
442482
483+
.. _foobar-choice:
484+
443485
.. option:: --choice <choice>
444486
445487
A sample option with choices
446488
447489
:options: Option1 | Option2
448490
491+
.. _foobar-param:
492+
449493
.. option:: --param <param>
450494
451495
:default: ``'Something computed at runtime'``
@@ -572,6 +616,8 @@ def cli():
572616
573617
.. rubric:: Options
574618
619+
.. _cli-param:
620+
575621
.. option:: --param <param>
576622
577623
An option containing pre-wrapped text.
@@ -660,12 +706,16 @@ def cli():
660706
661707
.. rubric:: Options
662708
709+
.. _cli-param:
710+
663711
.. option:: --param <param>
664712
665713
A sample option
666714
667715
.. rubric:: Arguments
668716
717+
.. _cli-ARG:
718+
669719
.. option:: ARG
670720
671721
Required argument
@@ -679,7 +729,7 @@ def cli():
679729
680730
Provide a default for :option:`--param`
681731
682-
.. _cli-arg-ARG:
732+
.. _cli-ARG-ARG:
683733
684734
.. envvar:: ARG
685735
:noindex:
@@ -1089,14 +1139,20 @@ def cli_with_auto_envvars():
10891139
10901140
.. rubric:: Options
10911141
1142+
.. _cli-param:
1143+
10921144
.. option:: --param <param>
10931145
10941146
Help for param
10951147
1148+
.. _cli-other-param:
1149+
10961150
.. option:: --other-param <other_param>
10971151
10981152
Help for other-param
10991153
1154+
.. _cli-param-with-explicit-envvar:
1155+
11001156
.. option:: --param-with-explicit-envvar <param_with_explicit_envvar>
11011157
11021158
Help for param-with-explicit-envvar
@@ -1110,13 +1166,17 @@ def cli_with_auto_envvars():
11101166
11111167
Provide a default for :option:`--param`
11121168
1169+
.. _cli-other-param-PREFIX_OTHER_PARAM:
1170+
11131171
.. _cli-other_param-PREFIX_OTHER_PARAM:
11141172
11151173
.. envvar:: PREFIX_OTHER_PARAM
11161174
:noindex:
11171175
11181176
Provide a default for :option:`--other-param`
11191177
1178+
.. _cli-param-with-explicit-envvar-EXPLICIT_ENVVAR:
1179+
11201180
.. _cli-param_with_explicit_envvar-EXPLICIT_ENVVAR:
11211181
11221182
.. envvar:: EXPLICIT_ENVVAR

0 commit comments

Comments
 (0)