cappa icon indicating copy to clipboard operation
cappa copied to clipboard

More compact help text for boolean flags

Open liblaf opened this issue 2 months ago • 2 comments

Thanks for creating cappa! It's a fantastic library that I enjoy using.

I'd like to propose a small improvement to the generated help text for boolean flags that use the long=["--flag", "--no-flag"] style.

Currently, with this code:

@cappa.command
class Args:
    flag: Annotated[bool, cappa.Arg(long=["--flag", "--no-flag"])] = False

The generated help looks like this:

Usage: args [--flag] [--no-flag] [-h] [--completion COMPLETION]
                                                                                                                                       
  Options                                                                                                                              
    [--flag]                                                                                                                           
    [--no-flag]                (Default: False)                                                                                        
                                                                                                                                       
  Help                                                                                                                                 
    [-h, --help]               Show this message and exit.                                                                             
    [--completion COMPLETION]  Use --completion generate to print shell-specific completion source. Valid options: generate, complete.                                                                                     

While this is clear, it could be more compact. I find that having two separate lines for the same flag can be a bit harder to read at a glance.

Would it be possible to consolidate these into a single line? Here are a couple of ideas for the format:

  • --flag / --no-flag (Default: False)
  • Or, even more compactly: --(no-)flag (Default: False)

I believe a change like this would make the help output cleaner and easier for users to parse.

Thank you for your time and for all your work on this great project

liblaf avatar Oct 01 '25 08:10 liblaf

mmm indeed. I think this was how they used to be displayed, when support for this was hardcoded into the parser. nowadays, each variant is a standalone Arg (because they have inverse actions).

Not to say that it's not possible, the current impl is just the one that falls out of them being different args. Arguably, you'd probably wan the same behavior for any set of args that reference the same field_name, such as

@cappa.command
class Args:
    flag: Annotated[
        str,
        cappa.Arg(long="--blue", action=lambda: "blue", num_args=0),
        cappa.Arg(long="--red", action=lambda: "red", num_args=0),
        cappa.Arg(long="--green", action=lambda: "green", num_args=0),
    ]

DanCardin avatar Oct 01 '25 12:10 DanCardin

update, tl;dr it's not trivially simple to arrive at the solution i'd like.

i'm working on this in the background a bit. currently the bool parsing doesn't make the options mutually exclusive, and mutual exclusivity is currently based on the name of the group which (currently) forces the items in that group to display in their own helptext group; which i wouldnt want by default.

Also num_args becomes relevant. flags end up being the trivial case: [--foo/--no-foo] (Default: True) (although perhaps this should be (Default: --foo), i wonder?). things with args probably need to end up being [--foo FOO, --no-foo FOO] and repeating the value_name because i feel like it gets confusing/ambiguous if you have mutually exclusive args with different numbers of num_args. And I have tests already for a situation like this.

Either all of that, or some alternate setting like Group(inline=False) (which bools happen to default to True) which causes the args to be displayed together or not.

so i think it's doable, i'm just ironing out the details.

DanCardin avatar Oct 14 '25 16:10 DanCardin