From 1c15fe1e4f0d26a9ae52b5f75fc27070af600ab6 Mon Sep 17 00:00:00 2001 From: Tomer Godinger Date: Thu, 14 Apr 2022 13:26:15 +0300 Subject: [PATCH 1/5] 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 ` :ref:`My Command ` :ref:`My Option ` :option:`My Option ` --- sphinx_click/ext.py | 56 ++++++++++++++++++++++++++++++------ tests/test_formatter.py | 64 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 11 deletions(-) diff --git a/sphinx_click/ext.py b/sphinx_click/ext.py index 9876069..939c9c5 100644 --- a/sphinx_click/ext.py +++ b/sphinx_click/ext.py @@ -171,10 +171,25 @@ def _format_usage(ctx: click.Context) -> ty.Generator[str, None, None]: yield '' +def _format_command_name(ctx: click.Context) -> str: + command_name: str = ctx.command_path.replace(' ', '-') + return command_name + + def _format_option( ctx: click.Context, opt: click.core.Option ) -> ty.Generator[str, None, None]: """Format the output for a `click.core.Option`.""" + + # Add an anchor for each form of option name + # For click.option('--flag', '-f', ...) it'll create anchors for "flag" and "f" + option_names = list(set([option_name.lstrip('-') for option_name in opt.opts])) + for option_name in option_names: + yield '.. _{command_name}-{param}:'.format( + command_name=_format_command_name(ctx), param=option_name + ) + yield '' + opt_help = _get_help_record(ctx, opt) yield '.. option:: {}'.format(opt_help[0]) @@ -209,8 +224,16 @@ def _format_options(ctx: click.Context) -> ty.Generator[str, None, None]: yield '' -def _format_argument(arg: click.Argument) -> ty.Generator[str, None, None]: +def _format_argument( + ctx: click.Context, + arg: click.Argument, +) -> ty.Generator[str, None, None]: """Format the output of a `click.Argument`.""" + yield '.. _{command_name}-{param}:'.format( + command_name=_format_command_name(ctx), param=arg.human_readable_name + ) + yield '' + yield '.. option:: {}'.format(arg.human_readable_name) yield '' yield _indent( @@ -233,15 +256,36 @@ def _format_arguments(ctx: click.Context) -> ty.Generator[str, None, None]: params = [x for x in ctx.command.params if isinstance(x, click.Argument)] for param in params: - for line in _format_argument(param): + for line in _format_argument(ctx, param): yield line yield '' def _format_envvar( + ctx: click.Context, param: ty.Union[click.core.Option, click.Argument], ) -> ty.Generator[str, None, None]: """Format the envvars of a `click.Option` or `click.Argument`.""" + command_name = _format_command_name(ctx) + + # Add an anchor for each form of parameter name + # For click.option('--flag', '-f', ...) it'll create anchors for "flag" and "f" + param_names = sorted(set(param_name.lstrip('-') for param_name in param.opts)) + + # Only add the parameter's own name if it's not already present, in whatever case + if param.name.upper() not in ( + name.upper() for name in param_names + ): # Case-insensitive "in" test + param_names.append(param.name) + + for param_name in param_names: + yield '.. _{command_name}-{param_name}-{envvar}:'.format( + command_name=command_name, + param_name=param_name, + envvar=param.envvar, + ) + yield '' + yield '.. envvar:: {}'.format(param.envvar) yield ' :noindex:' yield '' @@ -270,13 +314,7 @@ def _format_envvars(ctx: click.Context) -> ty.Generator[str, None, None]: params = [x for x in ctx.command.params if x.envvar] for param in params: - yield '.. _{command_name}-{param_name}-{envvar}:'.format( - command_name=ctx.command_path.replace(' ', '-'), - param_name=param.name, - envvar=param.envvar, - ) - yield '' - for line in _format_envvar(param): + for line in _format_envvar(ctx, param): yield line yield '' diff --git a/tests/test_formatter.py b/tests/test_formatter.py index e688f2d..d977539 100644 --- a/tests/test_formatter.py +++ b/tests/test_formatter.py @@ -87,32 +87,44 @@ def foobar(bar): .. rubric:: Options + .. _foobar-param: + .. option:: --param A sample option + .. _foobar-another: + .. option:: --another Another option + .. _foobar-choice: + .. option:: --choice A sample option with choices :options: Option1 | Option2 + .. _foobar-numeric-choice: + .. option:: --numeric-choice A sample option with numeric choices :options: 1 | 2 | 3 + .. _foobar-flag: + .. option:: --flag A boolean flag .. rubric:: Arguments + .. _foobar-ARG: + .. option:: ARG Required argument @@ -126,7 +138,7 @@ def foobar(bar): Provide a default for :option:`--param` - .. _foobar-arg-ARG: + .. _foobar-ARG-ARG: .. envvar:: ARG :noindex: @@ -160,6 +172,8 @@ def foobar(bar): .. rubric:: Options + .. _foobar-param: + .. option:: --param A sample option @@ -205,12 +219,16 @@ def foobar(bar): .. rubric:: Options + .. _foobar-option: + .. option:: --option