clap icon indicating copy to clipboard operation
clap copied to clipboard

Add support for arg stability attributes (unstable/deprecated)

Open yaahc opened this issue 3 years ago • 5 comments

Please complete the following tasks

  • [X] I have searched the discussions
  • [X] I have searched the existing issues

Clap Version

3.0.10

Describe your use case

I had this idea while I was reviewing @sunshowers's CLI recommendations on versioning: https://rust-cli-recommendations.sunshowers.io/versioning.html. In their book they recommend having a stability flag or environment variable for gating new experimental features being exposed in your CLI. This made me think it would be nice if clap provided some support out of the box for managing the stability of various subsets of an App's CLI.

Describe the solution you'd like

I'm imagining two new methods being added to Arg

impl Arg {
    /// Specifies that an argument is unstable.
    ///
    /// **Note**: Unstable arguments cannot be used except when the `--unstable-options` flag is also enabled
    fn unstable(self, yes: bool) -> Self;

    /// Specifies that an argument is deprecated.
    ///
    /// **Note**: Using a deprecated argument will produce a warning unless the `--allow-deprecated` flag is also enabled
    fn deprecated(self, yes: bool) -> Self;
}

I'd expect these flags to also affect the generated help text to somehow deprioritize unstable/deprecated arguments in the generated output and to make it clear that they are not intended for general use.

Alternatives, if applicable

@epage and @sunshowers have both also suggested adding general support for custom settings / attributes so that a feature like this could be experimented with out of tree rather than needing to bake it into clap directly.

Additional Context

No response

yaahc avatar Jan 20 '22 01:01 yaahc

This entails a lot of policy (flag names, whether they should be global or not, user messages, etc). This would both lock us in to specific behavior but also leave a lot of room for it not quite meeting people needs and wanting customization of it.

My proposal is we start an example that covers these cases. We then use this to explore how we could improve clap.

For example, "require an argument to be present with a value" would go a long way towards a general solution to unstable(yes) but we don't have this. We instead have "when value is set, require another argument" (as both requires_if and required_if_eq, depending on which side you want to express this relationship).

My hope is we can move clap from a closed-form API to an open-form API where we don't need to bake all of the validation options directly into clap but allow users to create their own (https://github.com/clap-rs/clap/issues/3008). This means we can add this new form of requires in a way that the compiler can trivially remove if unused, unlike the current validation logic.

As another example of this open-form API design, yaahc mentioned in a PM wanting this relationship included in a hint in the help, like defaults, envs, and possible values. I had two idea for this

  • We expose a general hint mechanism (this would help with https://github.com/clap-rs/clap/issues/1695)
  • Have a hint(&self, app &App) -> Option<String> as part of the validation interface. The "require when other arg has value" struct could then have a show(self, yes: bool) -> Self function which will cause hint to report a "[requires -- ]` to be added to the help
    • This could still help us with #1695 if we are able to make custom defaulting logic into a trait as well

epage avatar Jan 20 '22 15:01 epage

experimented with out of tree rather than needing to bake it into clap directly.

As a small clarification on my vague statements, we are looking at not having everything baked directly into clap::App::get_matches but allow passing in logic through trait objects. These trait impls can be defined in-tree or out-of-tree. General ones, like what I talked about above, could be in the clap crate. If someone wanted to customize things, like optimizing for this specific feature request, that would probably be kept out-of-tree.

epage avatar Jan 20 '22 15:01 epage

Now that #[deprecated] is available to 3rd-party crates, would it be possible for for clap to pick up the presence of that attribute for displaying this kind thing?

Fishrock123 avatar Nov 27 '24 19:11 Fishrock123

That is an interesting idea to leverage #[deprecated]. We'd have to work out how it affects the CLI (ie what builder calls does it make or how it changes existing builder calls)

epage avatar Dec 13 '24 20:12 epage

Now that #[deprecated] is available to 3rd-party crates, would it be possible for for clap to pick up the presence of that attribute for displaying this kind thing?

I was just searching for something similar in issues: my idea was that items marked with the #[deprecated] attribute should be hidden by default, or, when using the --allow-deprecated flag, shown to the user, but have some kind of note that the item was deprecated. I recently wrote a plugin for Cargo that parses the entire source code and finds #[deprecated] attributes, looks at their versions and matches them with the version from Cargo.toml of its crate to issue a warning that the item is deprecated and can be removed, if 1+ major version(-s) has passed since its removal. In my case, specifying the "deprecated" attribute would be very useful.

fidelicura avatar Aug 04 '25 16:08 fidelicura