Opinion: Arguments should be used in a limited way
From the docs:
- Parameters: arguments are recommended to use for subcommands, urls, or files.
- Help pages: click.argument() does not take a help parameter. This is to follow the general convention of Unix tools of using arguments for only the most necessary things, and to document them in the command help text by referring to them by name.
Reasoning: Unclear to me.
Features unlocked:
- help text for support for arguments
I generally agree with the currently documented opinion that arguments should be used sparingly, should typically not be optional, and should be documented as part of the command. However, I don't think it's useful to reference the POSIX standard or backwards compatibility as the reason for those decisions.
- The more positional arguments there are, the more confusing the CLI invocation becomes to read. (This is true of Python too.)
- Making some arguments optional, or arbitrary length, can make it even harder to reason about. The parser handles this consistently by filling left to right, with an error if there is a non-optional unfilled after that. But that's not obvious to a user just looking at a command line.
- A command should be doing one thing, and the arguments should be related directly to that.
- A group, where the argument is the sub-command name.
- A command acts on some files.
- A command looks at a source and acts on a destination.
- The arguments should be so obviously related to the purpose of the command that it should be impossible to document what the command does without referring to the arguments. And in that case, it would be redundant/repetitive to also have
help="..."to document each argument separately.
That said, I'm fine adding a help param to Argument. It comes up regularly, and while I have consistently closed and pointed to this documentation, I agree it's not particularly convincing. Cloup handles it: https://cloup.readthedocs.io/en/stable/pages/arguments.html
I agree with all of @davidism bulleted points, and just want to add that the expectation that the positional argument be documented in the general docstring, and that optional parameters get their own help lines is very jarring. Even if I do just use one positional argument and could theoretically document it in the general docs, it often feels odd to put parameter-level documentation in two different places. I would like the doc string to describe at a high level what the CLI tool is for, and not necessarily document one of the parameters.
For example, I'm working on a CLI tool to upload firmware to multiple STM32 devices over the CAN bus. By necessity, the minimum argument that is required is a CAN channel. I think it is perfectly reasonable to not have that documented in the overall docstring, and specify more details about the parameter in the argument section.
usage: main.py [-h] [-b BINARY] [-sa 0x08008000] [-ba 0x08000000] [-p 0x2000] [-c None] [-l 20] can_channel
Upload a program to STM32H523 over FDCAN using OpenBootloader
positional arguments:
can_channel CAN channel the MCU is attached to. If the channel is down, this tool will try to bring up the channel.
options:
-h, --help show this help message and exit
-b BINARY, --binary BINARY
Binary file to write
This is exactly what I was hoping to gather. I am interested in being able to understand the behavior we adopt for parsing reasons from the the behavior which is adopted for design taste.
- The more positional arguments there are, the more confusing the CLI invocation becomes to read. (This is true of Python too.)
I agree with this but I don't think it become a problem until you have 4 + arguments. So we should let the CLI designer decide mostly.
- Making some arguments optional, or arbitrary length, can make it even harder to reason about. The parser handles this consistently by filling left to right, with an error if there is a non-optional unfilled after that. But that's not obvious to a user just looking at a command line.
I can document this.
- The arguments should be so obviously related to the purpose of the command that it should be impossible to document what the command does without referring to the arguments. And in that case, it would be redundant/repetitive to also have.
This I think is flexible based on your context. I can already see edges case where forcing this on CLI creators leads to less good usability outcomes.
Closed by #3127