Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade clap from 3.1 to 4.0 #2236

Closed
kalil-pelissier opened this issue Nov 3, 2022 · 11 comments · Fixed by #3209
Closed

Upgrade clap from 3.1 to 4.0 #2236

kalil-pelissier opened this issue Nov 3, 2022 · 11 comments · Fixed by #3209
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@kalil-pelissier
Copy link
Contributor

kalil-pelissier commented Nov 3, 2022

Upgrade clap version from 3.1 to 4.0

Changelog

Sourced from clap changelog.

[4.0.0] - 2022-09-28

Highlights

Arg::num_args(range)

Clap has had several ways for controlling how many values will be captured without always being clear on how they interacted, including

  • Arg::multiple_values(true)
  • Arg::number_of_values(4)
  • Arg::min_values(2)
  • Arg::max_values(20)
  • Arg::takes_value(true)

These have now all been collapsed into Arg::num_args which accepts both
single values and ranges of values. num_args controls how many raw arguments
on the command line will be captured as values per occurrence and independent
of value delimiters.

See Issue 2688 for more background.

Polishing Help

Clap strives to give a polished CLI experience out of the box with little
ceremony. With some feedback that has accumulated over time, we took this
release as an opportunity to re-evaluate our --help output to make sure it is
meeting that goal.

In doing this evaluation, we wanted to keep in mind:

  • Whether other CLIs had ideas that make sense to apply
  • Providing an experience that fits within the rest of applications and works across all shells

Before:

git
A fictional versioning CLI

USAGE:
    git <SUBCOMMAND>

OPTIONS:
    -h, --help    Print help information

SUBCOMMANDS:
    add      adds things
    clone    Clones repos
    help     Print this message or the help of the given subcommand(s)
    push     pushes things
    stash

After:

A fictional versioning CLI

Usage: git <COMMAND>

Commands:
  clone  Clones repos
  push   pushes things
  add    adds things
  stash
  help   Print this message or the help of the given subcommand(s)

Options:
  -h, --help  Print help information
  • name/version header was removed because we couldn't justify the space it occupied when
    • Usage already includes the name
    • --version is available for showing the same thing (if the program has a version set)
  • Usage was dropped to one line to save space
  • Focus is put on the subcommands
  • Headings are now Title case
  • The more general term "command" is used rather than being explicit about being "subcommands"
  • The output is more dense with the expectation that it won't affect legibility but will allow more content
  • We've moved to a more neutral palette for highlighting elements (not highlighted above)

In talking to users, we found some that liked clap's man-like experience.
When deviating from this, we are making the assumption that those are more
power users and that the majority of users wouldn't look as favorably on being
consistent with man.

See Issue 4132 for more background.

More Dynamicism

Clap's API has focused on &str for performance but this can make
dealing with owned data difficult, like #[arg(default_value_t)] generating a
String from the default value.

Additionally, to avoid ArgMatches from borrowing (and for some features we
decided to forgo), clap took the &str argument IDs and hashed them. This
prevented us from providing a usable API for iterating over existing arguments.

Now clap has switched to a string newtype that gives us the flexibility to
decide whether to use &'static str, Cow<'static, str> for fast dynamic behavior, or
Box<str> for dynamic behavior with small binary size.

As an extension of that work, you can now call ArgMatches::ids to iterate
over the arguments and groups that were found when parsing. The newtype Id
was used to prevent some classes of bugs and to make it easier to understand
when opaque Ids are used vs user-visible strings.

Clearing Out Deprecations

Instead of doing all development on clap 4.0.0, we implemented a lot of new features during clap 3's development, deprecating the old API while introducing the new API, including:

  • Replacing the implicit behavior for args when parsing them with ArgAction
  • Replacing various one-off forms of value validation with the ValueParser API
    • Allowing derives to automatically do the right thing for PathBuf (allowing invalid UTF-8)
  • Replacing AppSettings and ArgSettings enums with getters/setters
  • Clarifying terms and making them more consistent

Migrating

Steps:

  1. Upgrade to v3 if you haven't already
  2. Add CLI tests (including example below), -h and --help output at a minimum (recommendation: trycmd for snapshot testing)
  3. If using Builder API: Explicitly set the arg.action(ArgAction::...) on each argument (StoreValue for options and IncOccurrences for flags)
  4. Run cargo check --features clap/deprecated and resolve all deprecation warnings
  5. Upgrade to v4
  6. Update feature flags
  • If default-features = false, run cargo add clap -F help,usage,error-context
  • Run cargo add clap -F wrap_help unless you want to hard code line wraps
  1. Resolve compiler errors
  2. Resolve behavior changes (see "subtle changes" under BREAKING CHANGES)
  3. At your leisure: resolve new deprecation notices

Example test (derive):

#[derive(clap::Parser)]
struct Cli {
    ...
}

#[test]
fn verify_cli() {
    use clap::CommandFactory;
    Cli::command().debug_assert()
}

Example test (builder):

fn cli() -> clap::Command {
    ...
}

#[test]
fn verify_cli() {
    cli().debug_assert();
}

Note: the idiomatic / recommended way of specifying different types of args in the Builder API has changed:

Before

.arg(Arg::new("flag").long("flag"))  # --flag
.arg(Arg::new("option").long("option").takes_value(true))  # --option <option>

After:

.arg(Arg::new("flag").long("flag").action(ArgAction::SetTrue))  # --flag
.arg(Arg::new("option").long("option"))  # --option <option>

In particular, num_args (the replacement for takes_value) will default appropriately
from the ArgAction and generally only needs to be set explicitly for the
other num_args use cases.

Breaking Changes

Subtle changes (i.e. compiler won't catch):

Easier to catch changes:

Compatibility

MSRV is now 1.60.0

Deprecated

Behavior Changes

  • (help) With wrap_help feature, if the terminal size cannot be determined, LINES and COLUMNS variables are used (update tantivy #4186)

Features

Fixes

@kalil-pelissier kalil-pelissier added the enhancement New feature or request label Nov 3, 2022
@evanxg852000 evanxg852000 added good first issue Good for newcomers help wanted Extra attention is needed labels Apr 17, 2023
@0xkelvin
Copy link

@kalil-pelissier i can help this

@fulmicoton
Copy link
Contributor

@0xkelvin awesome! assinign the ticket to you!

@kalil-pelissier
Copy link
Contributor Author

@0xkelvin I have no time to work on it at the moment so it's ok for me!

@EliKalter
Copy link

I am interested in collaborating with someone on their project so I can learn the language while they get a sidekick.
Let me Know if this is something that could work for you.
I Would need you to explain and guide me through my first steps in the language (I already started learning) and set the standard for me in code reviews but after a short while I'm sure I'll become an asset to the project.
(I have some experience in Typescript and Java and have learned C a few years ago).

@0xkelvin
Copy link

0xkelvin commented May 5, 2023

let me see can we pair-working on this, i still working on it, a bit slow because busy with full time job

@EliKalter connect me to discord : 0xqwert#2911

@EliKalter
Copy link

@0xkelvin I think you have a mix up, I am not a code owner nor am I a moderator

@fulmicoton
Copy link
Contributor

@EliKalter I don't think there is any mix up. @0xkelvin is working on this, and you offered your help 2 weeks ago.

@fulmicoton
Copy link
Contributor

It seems like someone sent a PR for this?
#3209

@EliKalter
Copy link

@0xkelvin said "connect me to discord", I can't connect him to anything,
Did he meant to say "contact me on discord"?

@0xkelvin
Copy link

0xkelvin commented May 8, 2023

It seems like someone sent a PR for this? #3209

oh, i was too slow, let me learn from it as well

@fmassot
Copy link
Contributor

fmassot commented May 22, 2023

closed by #3209

@fmassot fmassot closed this as completed May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants