clap-rs / clap

A full featured, fast Command Line Argument Parser for Rust
docs.rs/clap
Apache License 2.0
13.64k stars 1.02k forks source link

DisplayVersion "errors" don't really allow to distinguish between -V and --version #5543

Open glandium opened 1 week ago

glandium commented 1 week ago

Please complete the following tasks

Clap Version

4.5.7

Describe your use case

-V and --version come with a message that is essentially "{name} {version}\n", where version is version for -V and long_version for --version. On top of this difference in output, one might want to print out some license text on --version but not -V, or do some other things.

It's technically possible to distinguish by parsing the output for format!("{}", error.render()), but that's not super nice.

Describe the solution you'd like

A breaking change would be to have DisplayVersion and DisplayLongVersion. I guess since ErrorKind is non_exhaustive, adding DisplayLongVersion wouldn't be breaking as long as it's not emitted by default. (meaning it would require some flag to enable)

Alternatives, if applicable

No response

Additional Context

No response

epage commented 1 week ago

Is there a reason you are attempting to detect this vs specifying a long-version?

glandium commented 1 week ago

Because I want to actually do something different after displaying the version. Specifically, I want to make -V show the version and --version show the long version and check for updates. Well, I already did, by checking format!("{}", error.render()). Also, in the hypothetical case of showing licensing terms, that somehow feels wrong to put in long_version.

epage commented 1 week ago

Also, in the hypothetical case of showing licensing terms, that somehow feels wrong to put in long_version.

long_version exists to control what is shown for --version, so it fits.

--version show the long version and check for updates

That is an interesting case. Besides splitting up the ErrorKind, I am wondering what other options are. Some I could think of

Can't think of too much else.

glandium commented 1 week ago

Manually implement the flags separately

I actually rejected that one for my use-case, because I'm deriving Parser on an enum (with subcommand_required=true), which doesn't leave space for that, except if I add another layer to handle --help and --version.

Allow providing custom ArgActions so a user can implement a custom "version" within clap

That's a variant of "Manually implement the flags separately" isn't it?

epage commented 1 week ago

I actually rejected that one for my use-case, because I'm deriving Parser on an enum (with subcommand_required=true), which doesn't leave space for that, except if I add another layer to handle --help and --version.

Not too sure which part is the blocker here

Allow providing custom ArgActions so a user can implement a custom "version" within clap

That's a variant of "Manually implement the flags separately" isn't it?

In the ideal case, the interface would allow for all existing actions to be implemented as if they were third party. This would allow you to put all of that logic (license and update checks) in the call and then ask for the program to exit.

glandium commented 1 week ago

Not too sure which part is the blocker here

I didn't mean it was a blocker, but it's unappealing in the amount of boilerplate it requires for something that the gross hack I came up with dealt with in 2 lines of code.