Upgrade clap to 4.1.8 am: f0f5837f59 am: be31cd74d2
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/clap/+/2465998
Change-Id: I06ff39c77527d5063eb0d0fbeb843083987a2e07
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3582b8c..382d047 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
{
"git": {
- "sha1": "ad4726378b2ee0320bbab5569acd8869a402e9fd"
+ "sha1": "f931de694a5478d7e4bd424613e6699f7d4f4e9f"
},
"path_in_vcs": ""
}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index b925e74..1ef7b16 100644
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,7 @@
host_supported: true,
crate_name: "clap",
cargo_env_compat: true,
- cargo_pkg_version: "4.0.29",
+ cargo_pkg_version: "4.1.8",
srcs: ["src/lib.rs"],
edition: "2021",
features: [
@@ -67,7 +67,7 @@
host_supported: true,
crate_name: "stdio_fixture",
cargo_env_compat: true,
- cargo_pkg_version: "4.0.29",
+ cargo_pkg_version: "4.1.8",
srcs: ["src/bin/stdio-fixture.rs"],
edition: "2021",
features: [
diff --git a/Cargo.toml b/Cargo.toml
index a40a3e2..fc59af3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.60.0"
+rust-version = "1.64.0"
name = "clap"
-version = "4.0.29"
+version = "4.1.8"
include = [
"build.rs",
"src/**/*",
@@ -363,7 +363,7 @@
version = "1.2"
[dependencies.clap_derive]
-version = "=4.0.21"
+version = "=4.1.8"
optional = true
[dependencies.clap_lex]
@@ -413,10 +413,10 @@
version = "1.1.0"
[dev-dependencies.trybuild]
-version = "1.0.71"
+version = "1.0.73"
[dev-dependencies.trycmd]
-version = "0.14.3"
+version = "0.14.9"
features = [
"color-auto",
"diff",
@@ -471,7 +471,6 @@
"unicode",
"string",
"unstable-replace",
- "unstable-grouped",
]
unstable-grouped = []
unstable-replace = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 7660ea5..fac36f6 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -8,9 +8,23 @@
"clap_mangen",
]
+[workspace.package]
+license = "MIT OR Apache-2.0"
+edition = "2021"
+rust-version = "1.64.0" # MSRV
+include = [
+ "build.rs",
+ "src/**/*",
+ "Cargo.toml",
+ "LICENSE*",
+ "README.md",
+ "benches/**/*",
+ "examples/**/*"
+]
+
[package]
name = "clap"
-version = "4.0.29"
+version = "4.1.8"
description = "A simple to use, efficient, and full-featured Command Line Argument Parser"
repository = "https://github.com/clap-rs/clap"
categories = ["command-line-interface"]
@@ -21,18 +35,10 @@
"parser",
"parse"
]
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.60.0" # MSRV
-include = [
- "build.rs",
- "src/**/*",
- "Cargo.toml",
- "LICENSE*",
- "README.md",
- "benches/**/*",
- "examples/**/*"
-]
+license.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+include.workspace = true
[package.metadata.docs.rs]
features = ["unstable-doc"]
@@ -63,7 +69,7 @@
"suggestions",
]
debug = ["clap_derive?/debug", "dep:backtrace"] # Enables debug messages
-unstable-doc = ["derive", "cargo", "wrap_help", "env", "unicode", "string", "unstable-replace", "unstable-grouped"] # for docs.rs
+unstable-doc = ["derive", "cargo", "wrap_help", "env", "unicode", "string", "unstable-replace"] # for docs.rs
# Used in default
std = [] # support for no_std in a backwards-compatible way
@@ -91,7 +97,7 @@
bench = false
[dependencies]
-clap_derive = { path = "./clap_derive", version = "=4.0.21", optional = true }
+clap_derive = { path = "./clap_derive", version = "=4.1.8", optional = true }
clap_lex = { path = "./clap_lex", version = "0.3.0" }
bitflags = "1.2"
unicase = { version = "2.6", optional = true }
@@ -104,10 +110,10 @@
once_cell = { version = "1.12.0", optional = true }
[dev-dependencies]
-trybuild = "1.0.71"
+trybuild = "1.0.73"
rustversion = "1"
# Cutting out `filesystem` feature
-trycmd = { version = "0.14.3", default-features = false, features = ["color-auto", "diff", "examples"] }
+trycmd = { version = "0.14.9", default-features = false, features = ["color-auto", "diff", "examples"] }
humantime = "2"
snapbox = "0.4"
shlex = "1.1.0"
diff --git a/METADATA b/METADATA
index fc7fe6c..ac42e03 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/clap/clap-4.0.29.crate"
+ value: "https://static.crates.io/crates/clap/clap-4.1.8.crate"
}
- version: "4.0.29"
+ version: "4.1.8"
license_type: NOTICE
last_upgrade_date {
- year: 2022
- month: 11
- day: 30
+ year: 2023
+ month: 3
+ day: 2
}
}
diff --git a/README.md b/README.md
index eea6ba6..b1298f8 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
[![Crates.io](https://img.shields.io/crates/d/clap?style=flat-square)](https://crates.io/crates/clap)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](LICENSE-APACHE)
[![License](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE-MIT)
-[![Build Status](https://img.shields.io/github/workflow/status/clap-rs/clap/CI/staging?style=flat-square)](https://github.com/clap-rs/clap/actions/workflows/ci.yml?query=branch%3Astaging)
+[![Build Status](https://img.shields.io/github/actions/workflow/status/clap-rs/clap/ci.yml?branch=master&style=flat-square)](https://github.com/clap-rs/clap/actions/workflows/ci.yml?query=branch%3Amaster)
[![Coverage Status](https://img.shields.io/coveralls/github/clap-rs/clap/master?style=flat-square)](https://coveralls.io/github/clap-rs/clap?branch=master)
[![Contributors](https://img.shields.io/github/contributors/clap-rs/clap?style=flat-square)](https://github.com/clap-rs/clap/graphs/contributors)
diff --git a/examples/cargo-example-derive.md b/examples/cargo-example-derive.md
index 99cbb2f..a3dcef3 100644
--- a/examples/cargo-example-derive.md
+++ b/examples/cargo-example-derive.md
@@ -13,7 +13,7 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
+ -h, --help Print help
$ cargo-example-derive example-derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
@@ -22,8 +22,8 @@
Options:
--manifest-path <MANIFEST_PATH>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
diff --git a/examples/cargo-example-derive.rs b/examples/cargo-example-derive.rs
index d9603db..dfdd799 100644
--- a/examples/cargo-example-derive.rs
+++ b/examples/cargo-example-derive.rs
@@ -3,18 +3,18 @@
#[derive(Parser)] // requires `derive` feature
#[command(name = "cargo")]
#[command(bin_name = "cargo")]
-enum Cargo {
- ExampleDerive(ExampleDerive),
+enum CargoCli {
+ ExampleDerive(ExampleDeriveArgs),
}
#[derive(clap::Args)]
#[command(author, version, about, long_about = None)]
-struct ExampleDerive {
+struct ExampleDeriveArgs {
#[arg(long)]
manifest_path: Option<std::path::PathBuf>,
}
fn main() {
- let Cargo::ExampleDerive(args) = Cargo::parse();
+ let CargoCli::ExampleDerive(args) = CargoCli::parse();
println!("{:?}", args.manifest_path);
}
diff --git a/examples/cargo-example.md b/examples/cargo-example.md
index caafbad..edf8ee1 100644
--- a/examples/cargo-example.md
+++ b/examples/cargo-example.md
@@ -13,7 +13,7 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
+ -h, --help Print help
$ cargo-example example --help
A simple to use, efficient, and full-featured Command Line Argument Parser
@@ -22,8 +22,8 @@
Options:
--manifest-path <PATH>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
diff --git a/examples/demo.md b/examples/demo.md
index 2a9ed94..772d98d 100644
--- a/examples/demo.md
+++ b/examples/demo.md
@@ -7,8 +7,8 @@
Options:
-n, --name <NAME> Name of the person to greet
-c, --count <COUNT> Number of times to greet [default: 1]
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ demo --name Me
Hello Me!
diff --git a/examples/derive_ref/augment_args.rs b/examples/derive_ref/augment_args.rs
index 458beb4..39d837c 100644
--- a/examples/derive_ref/augment_args.rs
+++ b/examples/derive_ref/augment_args.rs
@@ -23,5 +23,5 @@
let derived_matches = DerivedArgs::from_arg_matches(&matches)
.map_err(|err| err.exit())
.unwrap();
- println!("Value of derived: {:#?}", derived_matches);
+ println!("Value of derived: {derived_matches:#?}");
}
diff --git a/examples/derive_ref/augment_subcommands.rs b/examples/derive_ref/augment_subcommands.rs
index 5775275..51cbe75 100644
--- a/examples/derive_ref/augment_subcommands.rs
+++ b/examples/derive_ref/augment_subcommands.rs
@@ -17,5 +17,5 @@
let derived_subcommands = Subcommands::from_arg_matches(&matches)
.map_err(|err| err.exit())
.unwrap();
- println!("Derived subcommands: {:#?}", derived_subcommands);
+ println!("Derived subcommands: {derived_subcommands:#?}");
}
diff --git a/examples/derive_ref/flatten_hand_args.rs b/examples/derive_ref/flatten_hand_args.rs
index 2ceeb7c..36aac09 100644
--- a/examples/derive_ref/flatten_hand_args.rs
+++ b/examples/derive_ref/flatten_hand_args.rs
@@ -87,5 +87,5 @@
fn main() {
let args = Cli::parse();
- println!("{:#?}", args);
+ println!("{args:#?}");
}
diff --git a/examples/derive_ref/hand_subcommand.rs b/examples/derive_ref/hand_subcommand.rs
index 5ea169c..ebaa60d 100644
--- a/examples/derive_ref/hand_subcommand.rs
+++ b/examples/derive_ref/hand_subcommand.rs
@@ -69,11 +69,11 @@
struct Cli {
#[arg(short, long)]
top_level: bool,
- #[clap(subcommand)]
+ #[command(subcommand)]
subcommand: CliSub,
}
fn main() {
let args = Cli::parse();
- println!("{:#?}", args);
+ println!("{args:#?}");
}
diff --git a/examples/derive_ref/interop_tests.md b/examples/derive_ref/interop_tests.md
index b013b0c..a7bcc7e 100644
--- a/examples/derive_ref/interop_tests.md
+++ b/examples/derive_ref/interop_tests.md
@@ -35,11 +35,11 @@
```console
$ interop_augment_args --unknown
? failed
-error: Found argument '--unknown' which wasn't expected, or isn't valid in this context
+error: unexpected argument '--unknown' found
Usage: interop_augment_args[EXE] [OPTIONS]
-For more information try '--help'
+For more information, try '--help'.
```
@@ -70,22 +70,22 @@
```console
$ interop_augment_subcommands derived --unknown
? failed
-error: Found argument '--unknown' which wasn't expected, or isn't valid in this context
+error: unexpected argument '--unknown' found
Usage: interop_augment_subcommands[EXE] derived [OPTIONS]
-For more information try '--help'
+For more information, try '--help'.
```
```console
$ interop_augment_subcommands unknown
? failed
-error: The subcommand 'unknown' wasn't recognized
+error: unrecognized subcommand 'unknown'
Usage: interop_augment_subcommands[EXE] [COMMAND]
-For more information try '--help'
+For more information, try '--help'.
```
@@ -103,7 +103,7 @@
Options:
-t, --top-level
- -h, --help Print help information
+ -h, --help Print help
```
@@ -140,13 +140,13 @@
```console
$ interop_hand_subcommand add --unknown
? failed
-error: Found argument '--unknown' which wasn't expected, or isn't valid in this context
+error: unexpected argument '--unknown' found
- If you tried to supply '--unknown' as a value rather than a flag, use '-- --unknown'
+ note: to pass '--unknown' as a value, use '-- --unknown'
Usage: interop_hand_subcommand[EXE] add [NAME]...
-For more information try '--help'
+For more information, try '--help'.
```
@@ -185,11 +185,11 @@
```console
$ interop_hand_subcommand unknown
? failed
-error: The subcommand 'unknown' wasn't recognized
+error: unrecognized subcommand 'unknown'
Usage: interop_hand_subcommand[EXE] [OPTIONS] <COMMAND>
-For more information try '--help'
+For more information, try '--help'.
```
@@ -239,10 +239,10 @@
```console
$ interop_flatten_hand_args --unknown
? failed
-error: Found argument '--unknown' which wasn't expected, or isn't valid in this context
+error: unexpected argument '--unknown' found
Usage: interop_flatten_hand_args[EXE] [OPTIONS]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/escaped-positional-derive.md b/examples/escaped-positional-derive.md
index cd52add..82990b5 100644
--- a/examples/escaped-positional-derive.md
+++ b/examples/escaped-positional-derive.md
@@ -15,8 +15,8 @@
Options:
-f
-p <PEAR>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
@@ -33,11 +33,11 @@
```console
$ escaped-positional-derive foo bar
? failed
-error: Found argument 'foo' which wasn't expected, or isn't valid in this context
+error: unexpected argument 'foo' found
Usage: escaped-positional-derive[EXE] [OPTIONS] [-- <SLOP>...]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/escaped-positional.md b/examples/escaped-positional.md
index 6015cc3..d94e399 100644
--- a/examples/escaped-positional.md
+++ b/examples/escaped-positional.md
@@ -15,8 +15,8 @@
Options:
-f
-p <PEAR>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
@@ -33,11 +33,11 @@
```console
$ escaped-positional foo bar
? failed
-error: Found argument 'foo' which wasn't expected, or isn't valid in this context
+error: unexpected argument 'foo' found
Usage: escaped-positional[EXE] [OPTIONS] [-- <SLOP>...]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/find.md b/examples/find.md
index 6388d47..e9b1a86 100644
--- a/examples/find.md
+++ b/examples/find.md
@@ -7,8 +7,8 @@
Usage: find[EXE] [OPTIONS]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
TESTS:
--empty File is empty and is either a regular file or a directory
diff --git a/examples/git-derive.md b/examples/git-derive.md
index a4769de..57edb61 100644
--- a/examples/git-derive.md
+++ b/examples/git-derive.md
@@ -19,7 +19,7 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git-derive help
A fictional versioning CLI
@@ -35,7 +35,7 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git-derive help add
adds things
@@ -46,7 +46,7 @@
<PATH>... Stuff to add
Options:
- -h, --help Print help information
+ -h, --help Print help
```
@@ -62,7 +62,7 @@
<PATH>... Stuff to add
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git-derive add Cargo.toml Cargo.lock
Adding ["Cargo.toml", "Cargo.lock"]
@@ -83,14 +83,14 @@
Options:
-m, --message <MESSAGE>
- -h, --help Print help information
+ -h, --help Print help
$ git-derive stash push -h
Usage: git-derive[EXE] stash push [OPTIONS]
Options:
-m, --message <MESSAGE>
- -h, --help Print help information
+ -h, --help Print help
$ git-derive stash pop -h
Usage: git-derive[EXE] stash pop [STASH]
@@ -99,16 +99,16 @@
[STASH]
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git-derive stash -m "Prototype"
-Pushing StashPush { message: Some("Prototype") }
+Pushing StashPushArgs { message: Some("Prototype") }
$ git-derive stash pop
Popping None
$ git-derive stash push -m "Prototype"
-Pushing StashPush { message: Some("Prototype") }
+Pushing StashPushArgs { message: Some("Prototype") }
$ git-derive stash pop
Popping None
@@ -136,7 +136,7 @@
Options:
--color[=<WHEN>] [default: auto] [possible values: always, auto, never]
- -h, --help Print help information
+ -h, --help Print help
$ git-derive diff
Diffing stage..worktree (color=auto)
diff --git a/examples/git-derive.rs b/examples/git-derive.rs
index 519982d..ad82e0c 100644
--- a/examples/git-derive.rs
+++ b/examples/git-derive.rs
@@ -53,7 +53,7 @@
#[arg(required = true)]
path: Vec<PathBuf>,
},
- Stash(Stash),
+ Stash(StashArgs),
#[command(external_subcommand)]
External(Vec<OsString>),
}
@@ -76,23 +76,23 @@
#[derive(Debug, Args)]
#[command(args_conflicts_with_subcommands = true)]
-struct Stash {
+struct StashArgs {
#[command(subcommand)]
command: Option<StashCommands>,
#[command(flatten)]
- push: StashPush,
+ push: StashPushArgs,
}
#[derive(Debug, Subcommand)]
enum StashCommands {
- Push(StashPush),
+ Push(StashPushArgs),
Pop { stash: Option<String> },
Apply { stash: Option<String> },
}
#[derive(Debug, Args)]
-struct StashPush {
+struct StashPushArgs {
#[arg(short, long)]
message: Option<String>,
}
@@ -102,7 +102,7 @@
match args.command {
Commands::Clone { remote } => {
- println!("Cloning {}", remote);
+ println!("Cloning {remote}");
}
Commands::Diff {
mut base,
@@ -136,22 +136,22 @@
);
}
Commands::Push { remote } => {
- println!("Pushing to {}", remote);
+ println!("Pushing to {remote}");
}
Commands::Add { path } => {
- println!("Adding {:?}", path);
+ println!("Adding {path:?}");
}
Commands::Stash(stash) => {
let stash_cmd = stash.command.unwrap_or(StashCommands::Push(stash.push));
match stash_cmd {
StashCommands::Push(push) => {
- println!("Pushing {:?}", push);
+ println!("Pushing {push:?}");
}
StashCommands::Pop { stash } => {
- println!("Popping {:?}", stash);
+ println!("Popping {stash:?}");
}
StashCommands::Apply { stash } => {
- println!("Applying {:?}", stash);
+ println!("Applying {stash:?}");
}
}
}
diff --git a/examples/git.md b/examples/git.md
index de01a44..d90b2e8 100644
--- a/examples/git.md
+++ b/examples/git.md
@@ -17,7 +17,7 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git help
A fictional versioning CLI
@@ -33,7 +33,7 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git help add
adds things
@@ -44,7 +44,7 @@
<PATH>... Stuff to add
Options:
- -h, --help Print help information
+ -h, --help Print help
```
@@ -60,7 +60,7 @@
<PATH>... Stuff to add
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git add Cargo.toml Cargo.lock
Adding ["Cargo.toml", "Cargo.lock"]
@@ -81,14 +81,14 @@
Options:
-m, --message <MESSAGE>
- -h, --help Print help information
+ -h, --help Print help
$ git stash push -h
Usage: git[EXE] stash push [OPTIONS]
Options:
-m, --message <MESSAGE>
- -h, --help Print help information
+ -h, --help Print help
$ git stash pop -h
Usage: git[EXE] stash pop [STASH]
@@ -97,7 +97,7 @@
[STASH]
Options:
- -h, --help Print help information
+ -h, --help Print help
$ git stash -m "Prototype"
Pushing Some("Prototype")
@@ -134,7 +134,7 @@
Options:
--color[=<WHEN>] [default: auto] [possible values: always, auto, never]
- -h, --help Print help information
+ -h, --help Print help
$ git diff
Diffing stage..worktree (color=auto)
diff --git a/examples/git.rs b/examples/git.rs
index 8a2fcc7..bd05e53 100644
--- a/examples/git.rs
+++ b/examples/git.rs
@@ -86,7 +86,7 @@
let base = base.unwrap_or("stage");
let head = head.unwrap_or("worktree");
let path = path.unwrap_or("");
- println!("Diffing {}..{} {} (color={})", base, head, path, color);
+ println!("Diffing {base}..{head} {path} (color={color})");
}
Some(("push", sub_matches)) => {
println!(
@@ -100,22 +100,22 @@
.into_iter()
.flatten()
.collect::<Vec<_>>();
- println!("Adding {:?}", paths);
+ println!("Adding {paths:?}");
}
Some(("stash", sub_matches)) => {
let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches));
match stash_command {
("apply", sub_matches) => {
let stash = sub_matches.get_one::<String>("STASH");
- println!("Applying {:?}", stash);
+ println!("Applying {stash:?}");
}
("pop", sub_matches) => {
let stash = sub_matches.get_one::<String>("STASH");
- println!("Popping {:?}", stash);
+ println!("Popping {stash:?}");
}
("push", sub_matches) => {
let message = sub_matches.get_one::<String>("message");
- println!("Pushing {:?}", message);
+ println!("Pushing {message:?}");
}
(name, _) => {
unreachable!("Unsupported subcommand `{}`", name)
@@ -128,9 +128,9 @@
.into_iter()
.flatten()
.collect::<Vec<_>>();
- println!("Calling out to {:?} with {:?}", ext, args);
+ println!("Calling out to {ext:?} with {args:?}");
}
- _ => unreachable!(), // If all subcommands are defined above, anything else is unreachabe!()
+ _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable!()
}
// Continued program logic goes here...
diff --git a/examples/multicall-busybox.md b/examples/multicall-busybox.md
index 8ee93cc..e84b263 100644
--- a/examples/multicall-busybox.md
+++ b/examples/multicall-busybox.md
@@ -34,6 +34,6 @@
Options:
--install <install> Install hardlinks for all subcommands in path
- -h, --help Print help information
+ -h, --help Print help
```
diff --git a/examples/pacman.md b/examples/pacman.md
index 73ec86f..b02cf8f 100644
--- a/examples/pacman.md
+++ b/examples/pacman.md
@@ -45,8 +45,8 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ pacman -S -h
Synchronize packages.
@@ -59,7 +59,7 @@
Options:
-s, --search <search>... search remote repositories for matching strings
-i, --info view package information
- -h, --help Print help information
+ -h, --help Print help
```
@@ -67,11 +67,11 @@
```console
$ pacman -S -s foo -i bar
? failed
-error: The argument '--search <search>...' cannot be used with '--info'
+error: the argument '--search <search>...' cannot be used with '--info'
Usage: pacman[EXE] {sync|--sync|-S} --search <search>... <package>...
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/pacman.rs b/examples/pacman.rs
index 12e7ffa..7ab30db 100644
--- a/examples/pacman.rs
+++ b/examples/pacman.rs
@@ -78,7 +78,7 @@
.map(|s| s.as_str())
.collect();
let values = packages.join(", ");
- println!("Searching for {}...", values);
+ println!("Searching for {values}...");
return;
}
@@ -90,18 +90,18 @@
let values = packages.join(", ");
if sync_matches.get_flag("info") {
- println!("Retrieving info for {}...", values);
+ println!("Retrieving info for {values}...");
} else {
- println!("Installing {}...", values);
+ println!("Installing {values}...");
}
}
Some(("query", query_matches)) => {
if let Some(packages) = query_matches.get_many::<String>("info") {
let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
- println!("Retrieving info for {}...", comma_sep);
+ println!("Retrieving info for {comma_sep}...");
} else if let Some(queries) = query_matches.get_many::<String>("search") {
let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
- println!("Searching Locally for {}...", comma_sep);
+ println!("Searching Locally for {comma_sep}...");
} else {
println!("Displaying all locally installed packages...");
}
diff --git a/examples/repl.rs b/examples/repl.rs
index e18fbbd..2806ac8 100644
--- a/examples/repl.rs
+++ b/examples/repl.rs
@@ -17,7 +17,7 @@
}
}
Err(err) => {
- write!(std::io::stdout(), "{}", err).map_err(|e| e.to_string())?;
+ write!(std::io::stdout(), "{err}").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
}
}
@@ -29,7 +29,7 @@
fn respond(line: &str) -> Result<bool, String> {
let args = shlex::split(line).ok_or("error: Invalid quoting")?;
let matches = cli()
- .try_get_matches_from(&args)
+ .try_get_matches_from(args)
.map_err(|e| e.to_string())?;
match matches.subcommand() {
Some(("ping", _matches)) => {
diff --git a/examples/tutorial_builder/01_quick.md b/examples/tutorial_builder/01_quick.md
index b963151..bdba15c 100644
--- a/examples/tutorial_builder/01_quick.md
+++ b/examples/tutorial_builder/01_quick.md
@@ -14,8 +14,8 @@
Options:
-c, --config <FILE> Sets a custom config file
-d, --debug... Turn debugging information on
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
diff --git a/examples/tutorial_builder/01_quick.rs b/examples/tutorial_builder/01_quick.rs
index 7e53fc6..8126e33 100644
--- a/examples/tutorial_builder/01_quick.rs
+++ b/examples/tutorial_builder/01_quick.rs
@@ -48,7 +48,7 @@
// matches just as you would the top level cmd
if let Some(matches) = matches.subcommand_matches("test") {
// "$ myapp test" was run
- if *matches.get_one::<bool>("list").expect("defaulted by clap") {
+ if matches.get_flag("list") {
// "$ myapp test -l" was run
println!("Printing testing lists...");
} else {
diff --git a/examples/tutorial_builder/02_app_settings.md b/examples/tutorial_builder/02_app_settings.md
index 47fa61b..3ac9a95 100644
--- a/examples/tutorial_builder/02_app_settings.md
+++ b/examples/tutorial_builder/02_app_settings.md
@@ -10,8 +10,8 @@
--one <VALUE>
-h, --help
- Print help information
+ Print help
-V, --version
- Print version information
+ Print version
```
diff --git a/examples/tutorial_builder/02_apps.md b/examples/tutorial_builder/02_apps.md
index 47379ce..1f8b071 100644
--- a/examples/tutorial_builder/02_apps.md
+++ b/examples/tutorial_builder/02_apps.md
@@ -7,8 +7,8 @@
Options:
--two <VALUE>
--one <VALUE>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 02_apps --version
MyApp 1.0
diff --git a/examples/tutorial_builder/02_crate.md b/examples/tutorial_builder/02_crate.md
index 832f7f7..a0d21b3 100644
--- a/examples/tutorial_builder/02_crate.md
+++ b/examples/tutorial_builder/02_crate.md
@@ -7,8 +7,8 @@
Options:
--two <VALUE>
--one <VALUE>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 02_crate --version
clap [..]
diff --git a/examples/tutorial_builder/03_01_flag_bool.md b/examples/tutorial_builder/03_01_flag_bool.md
index 71f6f90..feec8e0 100644
--- a/examples/tutorial_builder/03_01_flag_bool.md
+++ b/examples/tutorial_builder/03_01_flag_bool.md
@@ -6,8 +6,8 @@
Options:
-v, --verbose
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_01_flag_bool
verbose: false
@@ -17,10 +17,10 @@
$ 03_01_flag_bool --verbose --verbose
? failed
-error: The argument '--verbose' was provided more than once, but cannot be used multiple times
+error: the argument '--verbose' cannot be used multiple times
Usage: 03_01_flag_bool[EXE] [OPTIONS]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_builder/03_01_flag_count.md b/examples/tutorial_builder/03_01_flag_count.md
index 95610a1..5e964b6 100644
--- a/examples/tutorial_builder/03_01_flag_count.md
+++ b/examples/tutorial_builder/03_01_flag_count.md
@@ -6,8 +6,8 @@
Options:
-v, --verbose...
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_01_flag_count
verbose: 0
diff --git a/examples/tutorial_builder/03_02_option.md b/examples/tutorial_builder/03_02_option.md
index 68dc25e..42b81fd 100644
--- a/examples/tutorial_builder/03_02_option.md
+++ b/examples/tutorial_builder/03_02_option.md
@@ -6,8 +6,8 @@
Options:
-n, --name <name>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_02_option
name: None
diff --git a/examples/tutorial_builder/03_02_option_mult.md b/examples/tutorial_builder/03_02_option_mult.md
index 21af579..659748e 100644
--- a/examples/tutorial_builder/03_02_option_mult.md
+++ b/examples/tutorial_builder/03_02_option_mult.md
@@ -6,8 +6,8 @@
Options:
-n, --name <name>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_02_option_mult
name: None
diff --git a/examples/tutorial_builder/03_03_positional.md b/examples/tutorial_builder/03_03_positional.md
index df54b02..d8d49f3 100644
--- a/examples/tutorial_builder/03_03_positional.md
+++ b/examples/tutorial_builder/03_03_positional.md
@@ -8,8 +8,8 @@
[name]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_03_positional
name: None
diff --git a/examples/tutorial_builder/03_03_positional_mult.md b/examples/tutorial_builder/03_03_positional_mult.md
index d31acdf..174ddd9 100644
--- a/examples/tutorial_builder/03_03_positional_mult.md
+++ b/examples/tutorial_builder/03_03_positional_mult.md
@@ -8,8 +8,8 @@
[name]...
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_03_positional_mult
names: []
diff --git a/examples/tutorial_builder/03_04_subcommands.md b/examples/tutorial_builder/03_04_subcommands.md
index 91a4a05..7c73add 100644
--- a/examples/tutorial_builder/03_04_subcommands.md
+++ b/examples/tutorial_builder/03_04_subcommands.md
@@ -9,8 +9,8 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_04_subcommands help add
Adds files to myapp
@@ -21,8 +21,8 @@
[NAME]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_04_subcommands add bob
'myapp add' was used, name is: Some("bob")
@@ -42,8 +42,8 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
diff --git a/examples/tutorial_builder/03_05_default_values.md b/examples/tutorial_builder/03_05_default_values.md
index 96880f1..b62a415 100644
--- a/examples/tutorial_builder/03_05_default_values.md
+++ b/examples/tutorial_builder/03_05_default_values.md
@@ -8,8 +8,8 @@
[PORT] [default: 2020]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_05_default_values
port: 2020
diff --git a/examples/tutorial_builder/04_01_enum.md b/examples/tutorial_builder/04_01_enum.md
index 7f1a0d1..ec4c0ae 100644
--- a/examples/tutorial_builder/04_01_enum.md
+++ b/examples/tutorial_builder/04_01_enum.md
@@ -14,10 +14,10 @@
Options:
-h, --help
- Print help information (use `-h` for a summary)
+ Print help (see a summary with '-h')
-V, --version
- Print version information
+ Print version
$ 04_01_enum -h
A simple to use, efficient, and full-featured Command Line Argument Parser
@@ -28,8 +28,8 @@
<MODE> What mode to run the program in [possible values: fast, slow]
Options:
- -h, --help Print help information (use `--help` for more detail)
- -V, --version Print version information
+ -h, --help Print help (see more with '--help')
+ -V, --version Print version
$ 04_01_enum fast
Hare
@@ -39,9 +39,9 @@
$ 04_01_enum medium
? failed
-error: 'medium' isn't a valid value for '<MODE>'
+error: invalid value 'medium' for '<MODE>'
[possible values: fast, slow]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_builder/04_01_enum.rs b/examples/tutorial_builder/04_01_enum.rs
index a8b0e68..1afa018 100644
--- a/examples/tutorial_builder/04_01_enum.rs
+++ b/examples/tutorial_builder/04_01_enum.rs
@@ -38,7 +38,7 @@
return Ok(*variant);
}
}
- Err(format!("Invalid variant: {}", s))
+ Err(format!("invalid variant: {}", s))
}
}
diff --git a/examples/tutorial_builder/04_01_possible.md b/examples/tutorial_builder/04_01_possible.md
index 22a81fe..fa2c835 100644
--- a/examples/tutorial_builder/04_01_possible.md
+++ b/examples/tutorial_builder/04_01_possible.md
@@ -8,8 +8,8 @@
<MODE> What mode to run the program in [possible values: fast, slow]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_01_possible fast
Hare
@@ -19,9 +19,9 @@
$ 04_01_possible medium
? failed
-error: 'medium' isn't a valid value for '<MODE>'
+error: invalid value 'medium' for '<MODE>'
[possible values: fast, slow]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_builder/04_02_parse.md b/examples/tutorial_builder/04_02_parse.md
index e91f5dd..af03e95 100644
--- a/examples/tutorial_builder/04_02_parse.md
+++ b/examples/tutorial_builder/04_02_parse.md
@@ -8,22 +8,22 @@
<PORT> Network port to use
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_02_parse 22
PORT = 22
$ 04_02_parse foobar
? failed
-error: Invalid value 'foobar' for '<PORT>': invalid digit found in string
+error: invalid value 'foobar' for '<PORT>': invalid digit found in string
-For more information try '--help'
+For more information, try '--help'.
$ 04_02_parse_derive 0
? failed
-error: Invalid value '0' for '<PORT>': 0 is not in 1..=65535
+error: invalid value '0' for '<PORT>': 0 is not in 1..=65535
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_builder/04_02_validate.md b/examples/tutorial_builder/04_02_validate.md
index b62328e..949072b 100644
--- a/examples/tutorial_builder/04_02_validate.md
+++ b/examples/tutorial_builder/04_02_validate.md
@@ -8,22 +8,22 @@
<PORT> Network port to use
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_02_validate 22
PORT = 22
$ 04_02_validate foobar
? failed
-error: Invalid value 'foobar' for '<PORT>': `foobar` isn't a port number
+error: invalid value 'foobar' for '<PORT>': `foobar` isn't a port number
-For more information try '--help'
+For more information, try '--help'.
$ 04_02_validate 0
? failed
-error: Invalid value '0' for '<PORT>': Port not in range 1-65535
+error: invalid value '0' for '<PORT>': port not in range 1-65535
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_builder/04_02_validate.rs b/examples/tutorial_builder/04_02_validate.rs
index ea2f32e..4690e8e 100644
--- a/examples/tutorial_builder/04_02_validate.rs
+++ b/examples/tutorial_builder/04_02_validate.rs
@@ -28,7 +28,7 @@
Ok(port as u16)
} else {
Err(format!(
- "Port not in range {}-{}",
+ "port not in range {}-{}",
PORT_RANGE.start(),
PORT_RANGE.end()
))
diff --git a/examples/tutorial_builder/04_03_relations.md b/examples/tutorial_builder/04_03_relations.md
index cdca193..dd0c35a 100644
--- a/examples/tutorial_builder/04_03_relations.md
+++ b/examples/tutorial_builder/04_03_relations.md
@@ -14,37 +14,37 @@
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_03_relations
? failed
-error: The following required arguments were not provided:
+error: the following required arguments were not provided:
<--set-ver <VER>|--major|--minor|--patch>
Usage: 04_03_relations[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_03_relations --major
Version: 2.2.3
$ 04_03_relations --major --minor
? failed
-error: The argument '--major' cannot be used with '--minor'
+error: the argument '--major' cannot be used with '--minor'
Usage: 04_03_relations[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_03_relations --major -c config.toml
? failed
-error: The following required arguments were not provided:
+error: the following required arguments were not provided:
<INPUT_FILE|--spec-in <SPEC_IN>>
Usage: 04_03_relations[EXE] -c <CONFIG> <--set-ver <VER>|--major|--minor|--patch> <INPUT_FILE|--spec-in <SPEC_IN>>
-For more information try '--help'
+For more information, try '--help'.
$ 04_03_relations --major -c config.toml --spec-in input.txt
Version: 2.2.3
diff --git a/examples/tutorial_builder/04_04_custom.md b/examples/tutorial_builder/04_04_custom.md
index 64e38b5..0a83eb9 100644
--- a/examples/tutorial_builder/04_04_custom.md
+++ b/examples/tutorial_builder/04_04_custom.md
@@ -14,8 +14,8 @@
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_04_custom
? failed
@@ -23,7 +23,7 @@
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_04_custom --major
Version: 2.2.3
@@ -34,7 +34,7 @@
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_04_custom --major -c config.toml
? failed
@@ -43,7 +43,7 @@
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_04_custom --major -c config.toml --spec-in input.txt
Version: 2.2.3
diff --git a/examples/tutorial_derive/01_quick.md b/examples/tutorial_derive/01_quick.md
index 1d97584..21bbfe1 100644
--- a/examples/tutorial_derive/01_quick.md
+++ b/examples/tutorial_derive/01_quick.md
@@ -14,8 +14,8 @@
Options:
-c, --config <FILE> Sets a custom config file
-d, --debug... Turn debugging information on
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
diff --git a/examples/tutorial_derive/01_quick.rs b/examples/tutorial_derive/01_quick.rs
index 960e7ea..0edcd25 100644
--- a/examples/tutorial_derive/01_quick.rs
+++ b/examples/tutorial_derive/01_quick.rs
@@ -35,7 +35,7 @@
// You can check the value provided by positional arguments, or option arguments
if let Some(name) = cli.name.as_deref() {
- println!("Value for name: {}", name);
+ println!("Value for name: {name}");
}
if let Some(config_path) = cli.config.as_deref() {
diff --git a/examples/tutorial_derive/02_app_settings.md b/examples/tutorial_derive/02_app_settings.md
index fa21fda..90da3ae 100644
--- a/examples/tutorial_derive/02_app_settings.md
+++ b/examples/tutorial_derive/02_app_settings.md
@@ -10,8 +10,8 @@
--one <ONE>
-h, --help
- Print help information
+ Print help
-V, --version
- Print version information
+ Print version
```
diff --git a/examples/tutorial_derive/02_apps.md b/examples/tutorial_derive/02_apps.md
index 373d6a5..b5ae114 100644
--- a/examples/tutorial_derive/02_apps.md
+++ b/examples/tutorial_derive/02_apps.md
@@ -7,8 +7,8 @@
Options:
--two <TWO>
--one <ONE>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 02_apps_derive --version
MyApp 1.0
diff --git a/examples/tutorial_derive/02_crate.md b/examples/tutorial_derive/02_crate.md
index 001ccad..3f64460 100644
--- a/examples/tutorial_derive/02_crate.md
+++ b/examples/tutorial_derive/02_crate.md
@@ -7,8 +7,8 @@
Options:
--two <TWO>
--one <ONE>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 02_crate_derive --version
clap [..]
diff --git a/examples/tutorial_derive/03_01_flag_bool.md b/examples/tutorial_derive/03_01_flag_bool.md
index 83f57fa..9762260 100644
--- a/examples/tutorial_derive/03_01_flag_bool.md
+++ b/examples/tutorial_derive/03_01_flag_bool.md
@@ -6,8 +6,8 @@
Options:
-v, --verbose
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_01_flag_bool_derive
verbose: false
@@ -17,10 +17,10 @@
$ 03_01_flag_bool_derive --verbose --verbose
? failed
-error: The argument '--verbose' was provided more than once, but cannot be used multiple times
+error: the argument '--verbose' cannot be used multiple times
Usage: 03_01_flag_bool_derive[EXE] [OPTIONS]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_derive/03_01_flag_count.md b/examples/tutorial_derive/03_01_flag_count.md
index 53834ee..56ef9ca 100644
--- a/examples/tutorial_derive/03_01_flag_count.md
+++ b/examples/tutorial_derive/03_01_flag_count.md
@@ -6,8 +6,8 @@
Options:
-v, --verbose...
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_01_flag_count_derive
verbose: 0
diff --git a/examples/tutorial_derive/03_02_option.md b/examples/tutorial_derive/03_02_option.md
index d1acf39..24e272a 100644
--- a/examples/tutorial_derive/03_02_option.md
+++ b/examples/tutorial_derive/03_02_option.md
@@ -6,8 +6,8 @@
Options:
-n, --name <NAME>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_02_option_derive
name: None
diff --git a/examples/tutorial_derive/03_02_option_mult.md b/examples/tutorial_derive/03_02_option_mult.md
index b1969e7..cd2fe13 100644
--- a/examples/tutorial_derive/03_02_option_mult.md
+++ b/examples/tutorial_derive/03_02_option_mult.md
@@ -6,8 +6,8 @@
Options:
-n, --name <NAME>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_02_option_mult_derive
name: []
diff --git a/examples/tutorial_derive/03_03_positional.md b/examples/tutorial_derive/03_03_positional.md
index 6ca99ae..9437c24 100644
--- a/examples/tutorial_derive/03_03_positional.md
+++ b/examples/tutorial_derive/03_03_positional.md
@@ -8,8 +8,8 @@
[NAME]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_03_positional_derive
name: None
diff --git a/examples/tutorial_derive/03_03_positional_mult.md b/examples/tutorial_derive/03_03_positional_mult.md
index deec722..8f295e0 100644
--- a/examples/tutorial_derive/03_03_positional_mult.md
+++ b/examples/tutorial_derive/03_03_positional_mult.md
@@ -8,8 +8,8 @@
[NAME]...
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_03_positional_mult_derive
name: []
diff --git a/examples/tutorial_derive/03_04_subcommands.md b/examples/tutorial_derive/03_04_subcommands.md
index 3e95a68..1fbac8f 100644
--- a/examples/tutorial_derive/03_04_subcommands.md
+++ b/examples/tutorial_derive/03_04_subcommands.md
@@ -9,8 +9,8 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_04_subcommands_derive help add
Adds files to myapp
@@ -21,8 +21,8 @@
[NAME]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_04_subcommands_derive add bob
'myapp add' was used, name is: Some("bob")
@@ -42,8 +42,8 @@
help Print this message or the help of the given subcommand(s)
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
```
diff --git a/examples/tutorial_derive/03_04_subcommands.rs b/examples/tutorial_derive/03_04_subcommands.rs
index 279a5ff..da7c644 100644
--- a/examples/tutorial_derive/03_04_subcommands.rs
+++ b/examples/tutorial_derive/03_04_subcommands.rs
@@ -21,7 +21,7 @@
// matches just as you would the top level cmd
match &cli.command {
Commands::Add { name } => {
- println!("'myapp add' was used, name is: {:?}", name)
+ println!("'myapp add' was used, name is: {name:?}")
}
}
}
diff --git a/examples/tutorial_derive/03_04_subcommands_alt.rs b/examples/tutorial_derive/03_04_subcommands_alt.rs
index 8b70dba..80b0ec6 100644
--- a/examples/tutorial_derive/03_04_subcommands_alt.rs
+++ b/examples/tutorial_derive/03_04_subcommands_alt.rs
@@ -11,11 +11,11 @@
#[derive(Subcommand)]
enum Commands {
/// Adds files to myapp
- Add(Add),
+ Add(AddArgs),
}
#[derive(Args)]
-struct Add {
+struct AddArgs {
name: Option<String>,
}
diff --git a/examples/tutorial_derive/03_05_default_values.md b/examples/tutorial_derive/03_05_default_values.md
index 194f54f..994cb33 100644
--- a/examples/tutorial_derive/03_05_default_values.md
+++ b/examples/tutorial_derive/03_05_default_values.md
@@ -8,8 +8,8 @@
[PORT] [default: 2020]
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 03_05_default_values_derive
port: 2020
diff --git a/examples/tutorial_derive/04_01_enum.md b/examples/tutorial_derive/04_01_enum.md
index d208c8f..89db08c 100644
--- a/examples/tutorial_derive/04_01_enum.md
+++ b/examples/tutorial_derive/04_01_enum.md
@@ -14,10 +14,10 @@
Options:
-h, --help
- Print help information (use `-h` for a summary)
+ Print help (see a summary with '-h')
-V, --version
- Print version information
+ Print version
$ 04_01_enum_derive -h
A simple to use, efficient, and full-featured Command Line Argument Parser
@@ -28,8 +28,8 @@
<MODE> What mode to run the program in [possible values: fast, slow]
Options:
- -h, --help Print help information (use `--help` for more detail)
- -V, --version Print version information
+ -h, --help Print help (see more with '--help')
+ -V, --version Print version
$ 04_01_enum_derive fast
Hare
@@ -39,9 +39,9 @@
$ 04_01_enum_derive medium
? failed
-error: 'medium' isn't a valid value for '<MODE>'
+error: invalid value 'medium' for '<MODE>'
[possible values: fast, slow]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_derive/04_02_parse.md b/examples/tutorial_derive/04_02_parse.md
index df7537a..573b43c 100644
--- a/examples/tutorial_derive/04_02_parse.md
+++ b/examples/tutorial_derive/04_02_parse.md
@@ -8,22 +8,22 @@
<PORT> Network port to use
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_02_parse_derive 22
PORT = 22
$ 04_02_parse_derive foobar
? failed
-error: Invalid value 'foobar' for '<PORT>': invalid digit found in string
+error: invalid value 'foobar' for '<PORT>': invalid digit found in string
-For more information try '--help'
+For more information, try '--help'.
$ 04_02_parse_derive 0
? failed
-error: Invalid value '0' for '<PORT>': 0 is not in 1..=65535
+error: invalid value '0' for '<PORT>': 0 is not in 1..=65535
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_derive/04_02_validate.md b/examples/tutorial_derive/04_02_validate.md
index 87bf265..f8835fd 100644
--- a/examples/tutorial_derive/04_02_validate.md
+++ b/examples/tutorial_derive/04_02_validate.md
@@ -8,22 +8,22 @@
<PORT> Network port to use
Options:
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_02_validate_derive 22
PORT = 22
$ 04_02_validate_derive foobar
? failed
-error: Invalid value 'foobar' for '<PORT>': `foobar` isn't a port number
+error: invalid value 'foobar' for '<PORT>': `foobar` isn't a port number
-For more information try '--help'
+For more information, try '--help'.
$ 04_02_validate_derive 0
? failed
-error: Invalid value '0' for '<PORT>': Port not in range 1-65535
+error: invalid value '0' for '<PORT>': port not in range 1-65535
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/tutorial_derive/04_02_validate.rs b/examples/tutorial_derive/04_02_validate.rs
index 2b81ef2..3391d5b 100644
--- a/examples/tutorial_derive/04_02_validate.rs
+++ b/examples/tutorial_derive/04_02_validate.rs
@@ -21,12 +21,12 @@
fn port_in_range(s: &str) -> Result<u16, String> {
let port: usize = s
.parse()
- .map_err(|_| format!("`{}` isn't a port number", s))?;
+ .map_err(|_| format!("`{s}` isn't a port number"))?;
if PORT_RANGE.contains(&port) {
Ok(port as u16)
} else {
Err(format!(
- "Port not in range {}-{}",
+ "port not in range {}-{}",
PORT_RANGE.start(),
PORT_RANGE.end()
))
diff --git a/examples/tutorial_derive/04_03_relations.md b/examples/tutorial_derive/04_03_relations.md
index 4770334..6eafb9f 100644
--- a/examples/tutorial_derive/04_03_relations.md
+++ b/examples/tutorial_derive/04_03_relations.md
@@ -14,37 +14,37 @@
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_03_relations_derive
? failed
-error: The following required arguments were not provided:
+error: the following required arguments were not provided:
<--set-ver <VER>|--major|--minor|--patch>
Usage: 04_03_relations_derive[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_03_relations_derive --major
Version: 2.2.3
$ 04_03_relations_derive --major --minor
? failed
-error: The argument '--major' cannot be used with '--minor'
+error: the argument '--major' cannot be used with '--minor'
Usage: 04_03_relations_derive[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_03_relations_derive --major -c config.toml
? failed
-error: The following required arguments were not provided:
+error: the following required arguments were not provided:
<INPUT_FILE|--spec-in <SPEC_IN>>
Usage: 04_03_relations_derive[EXE] -c <CONFIG> <--set-ver <VER>|--major|--minor|--patch> <INPUT_FILE|--spec-in <SPEC_IN>>
-For more information try '--help'
+For more information, try '--help'.
$ 04_03_relations_derive --major -c config.toml --spec-in input.txt
Version: 2.2.3
diff --git a/examples/tutorial_derive/04_03_relations.rs b/examples/tutorial_derive/04_03_relations.rs
index e366095..cbe491d 100644
--- a/examples/tutorial_derive/04_03_relations.rs
+++ b/examples/tutorial_derive/04_03_relations.rs
@@ -56,10 +56,10 @@
(_, _, true) => patch += 1,
_ => unreachable!(),
};
- format!("{}.{}.{}", major, minor, patch)
+ format!("{major}.{minor}.{patch}")
};
- println!("Version: {}", version);
+ println!("Version: {version}");
// Check for usage of -c
if let Some(config) = cli.config.as_deref() {
@@ -67,6 +67,6 @@
.input_file
.as_deref()
.unwrap_or_else(|| cli.spec_in.as_deref().unwrap());
- println!("Doing work using input {} and config {}", input, config);
+ println!("Doing work using input {input} and config {config}");
}
}
diff --git a/examples/tutorial_derive/04_04_custom.md b/examples/tutorial_derive/04_04_custom.md
index a68a914..c601e9f 100644
--- a/examples/tutorial_derive/04_04_custom.md
+++ b/examples/tutorial_derive/04_04_custom.md
@@ -14,8 +14,8 @@
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
- -h, --help Print help information
- -V, --version Print version information
+ -h, --help Print help
+ -V, --version Print version
$ 04_04_custom_derive
? failed
@@ -23,7 +23,7 @@
Usage: clap [OPTIONS] [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_04_custom_derive --major
Version: 2.2.3
@@ -34,7 +34,7 @@
Usage: clap [OPTIONS] [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_04_custom_derive --major -c config.toml
? failed
@@ -43,7 +43,7 @@
Usage: clap [OPTIONS] [INPUT_FILE]
-For more information try '--help'
+For more information, try '--help'.
$ 04_04_custom_derive --major -c config.toml --spec-in input.txt
Version: 2.2.3
diff --git a/examples/tutorial_derive/04_04_custom.rs b/examples/tutorial_derive/04_04_custom.rs
index cbc460f..a84b5ed 100644
--- a/examples/tutorial_derive/04_04_custom.rs
+++ b/examples/tutorial_derive/04_04_custom.rs
@@ -66,10 +66,10 @@
.exit();
}
};
- format!("{}.{}.{}", major, minor, patch)
+ format!("{major}.{minor}.{patch}")
};
- println!("Version: {}", version);
+ println!("Version: {version}");
// Check for usage of -c
if let Some(config) = cli.config.as_deref() {
@@ -86,6 +86,6 @@
)
.exit()
});
- println!("Doing work using input {} and config {}", input, config);
+ println!("Doing work using input {input} and config {config}");
}
}
diff --git a/examples/typed-derive.md b/examples/typed-derive.md
index 713594d..bf7a56a 100644
--- a/examples/typed-derive.md
+++ b/examples/typed-derive.md
@@ -13,7 +13,7 @@
-D <DEFINES> Hand-written parser for tuples
--port <PORT> Support for discrete numbers [default: 22] [possible values: 22, 80]
--log-level <LOG_LEVEL> Support enums from a foreign crate that don't implement `ValueEnum` [default: info] [possible values: info, debug, info, warn, error]
- -h, --help Print help information
+ -h, --help Print help
```
@@ -24,9 +24,9 @@
$ typed-derive -O plaid
? failed
-error: Invalid value 'plaid' for '-O <OPTIMIZATION>': invalid digit found in string
+error: invalid value 'plaid' for '-O <OPTIMIZATION>': invalid digit found in string
-For more information try '--help'
+For more information, try '--help'.
```
@@ -44,9 +44,9 @@
$ typed-derive --bind localhost
? failed
-error: Invalid value 'localhost' for '--bind <BIND>': invalid IP address syntax
+error: invalid value 'localhost' for '--bind <BIND>': invalid IP address syntax
-For more information try '--help'
+For more information, try '--help'.
```
@@ -57,9 +57,9 @@
$ typed-derive --sleep forever
? failed
-error: Invalid value 'forever' for '--sleep <SLEEP>': expected number at 0
+error: invalid value 'forever' for '--sleep <SLEEP>': expected number at 0
-For more information try '--help'
+For more information, try '--help'.
```
@@ -70,15 +70,15 @@
$ typed-derive -D Foo
? failed
-error: Invalid value 'Foo' for '-D <DEFINES>': invalid KEY=value: no `=` found in `Foo`
+error: invalid value 'Foo' for '-D <DEFINES>': invalid KEY=value: no `=` found in `Foo`
-For more information try '--help'
+For more information, try '--help'.
$ typed-derive -D Foo=Bar
? failed
-error: Invalid value 'Foo=Bar' for '-D <DEFINES>': invalid digit found in string
+error: invalid value 'Foo=Bar' for '-D <DEFINES>': invalid digit found in string
-For more information try '--help'
+For more information, try '--help'.
```
@@ -92,17 +92,17 @@
$ typed-derive --port
? failed
-error: The argument '--port <PORT>' requires a value but none was supplied
+error: a value is required for '--port <PORT>' but none was supplied
[possible values: 22, 80]
-For more information try '--help'
+For more information, try '--help'.
$ typed-derive --port 3000
? failed
-error: '3000' isn't a valid value for '--port <PORT>'
+error: invalid value '3000' for '--port <PORT>'
[possible values: 22, 80]
-For more information try '--help'
+For more information, try '--help'.
```
@@ -116,16 +116,16 @@
$ typed-derive --log-level
? failed
-error: The argument '--log-level <LOG_LEVEL>' requires a value but none was supplied
+error: a value is required for '--log-level <LOG_LEVEL>' but none was supplied
[possible values: info, debug, info, warn, error]
-For more information try '--help'
+For more information, try '--help'.
$ typed-derive --log-level critical
? failed
-error: 'critical' isn't a valid value for '--log-level <LOG_LEVEL>'
+error: invalid value 'critical' for '--log-level <LOG_LEVEL>'
[possible values: info, debug, info, warn, error]
-For more information try '--help'
+For more information, try '--help'.
```
diff --git a/examples/typed-derive.rs b/examples/typed-derive.rs
index bdf8a58..8d7a84e 100644
--- a/examples/typed-derive.rs
+++ b/examples/typed-derive.rs
@@ -54,7 +54,7 @@
{
let pos = s
.find('=')
- .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{}`", s))?;
+ .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?;
Ok((s[..pos].parse()?, s[pos + 1..].parse()?))
}
@@ -98,5 +98,5 @@
fn main() {
let args = Args::parse();
- println!("{:?}", args);
+ println!("{args:?}");
}
diff --git a/src/_derive/_tutorial.rs b/src/_derive/_tutorial.rs
index eb95c87..f3f55c3 100644
--- a/src/_derive/_tutorial.rs
+++ b/src/_derive/_tutorial.rs
@@ -75,7 +75,7 @@
#![doc = include_str!("../../examples/tutorial_derive/03_03_positional.md")]
//!
//! Note that the default [`ArgAction`][crate::ArgAction] is [`Set`][crate::ArgAction::Set]. To
-//! accept multiple values, use [`Append`][crate::ArgAction::Append]:
+//! accept multiple values, use [`Append`][crate::ArgAction::Append] via `Vec`:
//! ```rust
#![doc = include_str!("../../examples/tutorial_derive/03_03_positional_mult.rs")]
//! ```
@@ -98,7 +98,7 @@
#![doc = include_str!("../../examples/tutorial_derive/03_02_option.md")]
//!
//! Note that the default [`ArgAction`][crate::ArgAction] is [`Set`][crate::ArgAction::Set]. To
-//! accept multiple occurrences, use [`Append`][crate::ArgAction::Append]:
+//! accept multiple occurrences, use [`Append`][crate::ArgAction::Append] via `Vec`:
//! ```rust
#![doc = include_str!("../../examples/tutorial_derive/03_02_option_mult.rs")]
//! ```
diff --git a/src/_derive/mod.rs b/src/_derive/mod.rs
index b09cdf6..a92b7c8 100644
--- a/src/_derive/mod.rs
+++ b/src/_derive/mod.rs
@@ -232,7 +232,8 @@
//! - Without `<expr>`: fills the field with `Default::default()`
//! - `default_value = <str>`: [`Arg::default_value`][crate::Arg::default_value] and [`Arg::required(false)`][crate::Arg::required]
//! - `default_value_t [= <expr>]`: [`Arg::default_value`][crate::Arg::default_value] and [`Arg::required(false)`][crate::Arg::required]
-//! - Requires `std::fmt::Display` or `#[arg(value_enum)]`
+//! - Requires `std::fmt::Display` that roundtrips correctly with the
+//! [`Arg::value_parser`][crate::Arg::value_parser] or `#[arg(value_enum)]`
//! - Without `<expr>`, relies on `Default::default()`
//! - `default_values_t = <expr>`: [`Arg::default_values`][crate::Arg::default_values] and [`Arg::required(false)`][crate::Arg::required]
//! - Requires field arg to be of type `Vec<T>` and `T` to implement `std::fmt::Display` or `#[arg(value_enum)]`
diff --git a/src/_features.rs b/src/_features.rs
index 10d6163..2f551e7 100644
--- a/src/_features.rs
+++ b/src/_features.rs
@@ -26,5 +26,4 @@
//! **Warning:** These may contain breaking changes between minor releases.
//!
//! * **unstable-replace**: Enable [`Command::replace`](https://github.com/clap-rs/clap/issues/2836)
-//! * **unstable-grouped**: Enable [`ArgMatches::grouped_values_of`](https://github.com/clap-rs/clap/issues/2924)
//! * **unstable-v5**: Preview features which will be stable on the v5.0 release
diff --git a/src/_tutorial.rs b/src/_tutorial.rs
index 3f0a833..4605ec9 100644
--- a/src/_tutorial.rs
+++ b/src/_tutorial.rs
@@ -75,7 +75,7 @@
//! ```
#![doc = include_str!("../examples/tutorial_builder/03_03_positional.md")]
//!
-//! Note that the default [`ArgAction`][crate::ArgAction]` is [`Set`][crate::ArgAction::Set]. To
+//! Note that the default [`ArgAction`][crate::ArgAction] is [`Set`][crate::ArgAction::Set]. To
//! accept multiple values, use [`Append`][crate::ArgAction::Append]:
//! ```rust
#![doc = include_str!("../examples/tutorial_builder/03_03_positional_mult.rs")]
@@ -94,7 +94,7 @@
//! ```
#![doc = include_str!("../examples/tutorial_builder/03_02_option.md")]
//!
-//! Note that the default [`ArgAction`][crate::ArgAction]` is [`Set`][crate::ArgAction::Set]. To
+//! Note that the default [`ArgAction`][crate::ArgAction] is [`Set`][crate::ArgAction::Set]. To
//! accept multiple occurrences, use [`Append`][crate::ArgAction::Append]:
//! ```rust
#![doc = include_str!("../examples/tutorial_builder/03_02_option_mult.rs")]
diff --git a/src/builder/action.rs b/src/builder/action.rs
index 01d1f07..9739f88 100644
--- a/src/builder/action.rs
+++ b/src/builder/action.rs
@@ -99,15 +99,15 @@
/// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap();
/// assert!(matches.contains_id("flag"));
/// assert_eq!(
- /// matches.get_one::<bool>("flag").copied(),
- /// Some(true)
+ /// matches.get_flag("flag"),
+ /// true
/// );
///
/// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
/// assert!(matches.contains_id("flag"));
/// assert_eq!(
- /// matches.get_one::<bool>("flag").copied(),
- /// Some(false)
+ /// matches.get_flag("flag"),
+ /// false
/// );
/// ```
///
@@ -172,15 +172,15 @@
/// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag"]).unwrap();
/// assert!(matches.contains_id("flag"));
/// assert_eq!(
- /// matches.get_one::<bool>("flag").copied(),
- /// Some(false)
+ /// matches.get_flag("flag"),
+ /// false
/// );
///
/// let matches = cmd.try_get_matches_from(["mycmd"]).unwrap();
/// assert!(matches.contains_id("flag"));
/// assert_eq!(
- /// matches.get_one::<bool>("flag").copied(),
- /// Some(true)
+ /// matches.get_flag("flag"),
+ /// true
/// );
/// ```
SetFalse,
diff --git a/src/builder/arg.rs b/src/builder/arg.rs
index 17db059..bf898cb 100644
--- a/src/builder/arg.rs
+++ b/src/builder/arg.rs
@@ -286,7 +286,7 @@
/// .get_matches_from(vec![
/// "prog", "--do-tests"
/// ]);
- /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+ /// assert_eq!(m.get_flag("test"), true);
/// ```
#[must_use]
pub fn aliases(mut self, names: impl IntoIterator<Item = impl Into<Str>>) -> Self {
@@ -314,7 +314,7 @@
/// .get_matches_from(vec![
/// "prog", "-s"
/// ]);
- /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+ /// assert_eq!(m.get_flag("test"), true);
/// ```
#[must_use]
pub fn short_aliases(mut self, names: impl IntoIterator<Item = char>) -> Self {
@@ -399,7 +399,7 @@
/// .get_matches_from(vec![
/// "prog", "--awesome"
/// ]);
- /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+ /// assert_eq!(m.get_flag("test"), true);
/// ```
/// [`Command::aliases`]: Arg::aliases()
#[must_use]
@@ -425,7 +425,7 @@
/// .get_matches_from(vec![
/// "prog", "-t"
/// ]);
- /// assert_eq!(*m.get_one::<bool>("test").expect("defaulted by clap"), true);
+ /// assert_eq!(m.get_flag("test"), true);
/// ```
#[must_use]
pub fn visible_short_aliases(mut self, names: impl IntoIterator<Item = char>) -> Self {
@@ -807,7 +807,7 @@
///
/// assert_eq!(m.subcommand_name(), Some("do-stuff"));
/// let sub_m = m.subcommand_matches("do-stuff").unwrap();
- /// assert_eq!(*sub_m.get_one::<bool>("verb").expect("defaulted by clap"), true);
+ /// assert_eq!(sub_m.get_flag("verb"), true);
/// ```
///
/// [`Subcommand`]: crate::Subcommand
@@ -1900,9 +1900,9 @@
/// "prog"
/// ]);
///
- /// assert!(*m.get_one::<bool>("true_flag").unwrap());
- /// assert!(!*m.get_one::<bool>("false_flag").unwrap());
- /// assert!(!*m.get_one::<bool>("absent_flag").unwrap());
+ /// assert!(m.get_flag("true_flag"));
+ /// assert!(!m.get_flag("false_flag"));
+ /// assert!(!m.get_flag("absent_flag"));
/// ```
///
/// In this example, we show the variable coming from an option on the CLI:
@@ -2111,7 +2111,8 @@
///
/// Args with a lower value will be displayed first in the help message. This is helpful when
/// one would like to emphasise frequently used args, or prioritize those towards the top of
- /// the list. Args with duplicate display orders will be displayed in alphabetical order.
+ /// the list. Args with duplicate display orders will be displayed in the order they are
+ /// defined.
///
/// **NOTE:** The default is 999 for all arguments.
///
@@ -3639,10 +3640,10 @@
/// "prog", "-f", "-d", "-c"]);
/// // ^~~~~~~~~~~~^~~~~ flag is overridden by color
///
- /// assert!(*m.get_one::<bool>("color").unwrap());
- /// assert!(*m.get_one::<bool>("debug").unwrap()); // even though flag conflicts with debug, it's as if flag
+ /// assert!(m.get_flag("color"));
+ /// assert!(m.get_flag("debug")); // even though flag conflicts with debug, it's as if flag
/// // was never used because it was overridden with color
- /// assert!(!*m.get_one::<bool>("flag").unwrap());
+ /// assert!(!m.get_flag("flag"));
/// ```
#[must_use]
pub fn overrides_with(mut self, arg_id: impl IntoResettable<Id>) -> Self {
@@ -3678,11 +3679,11 @@
/// "prog", "-f", "-d", "-c"]);
/// // ^~~~~~^~~~~~~~~ flag and debug are overridden by color
///
- /// assert!(*m.get_one::<bool>("color").unwrap()); // even though flag conflicts with color, it's as if flag
+ /// assert!(m.get_flag("color")); // even though flag conflicts with color, it's as if flag
/// // and debug were never used because they were overridden
/// // with color
- /// assert!(!*m.get_one::<bool>("debug").unwrap());
- /// assert!(!*m.get_one::<bool>("flag").unwrap());
+ /// assert!(!m.get_flag("debug"));
+ /// assert!(!m.get_flag("flag"));
/// ```
#[must_use]
pub fn overrides_with_all(mut self, names: impl IntoIterator<Item = impl Into<Id>>) -> Self {
@@ -3858,6 +3859,13 @@
self.val_delim
}
+ /// Get the value terminator for this argument. The value_terminator is a value
+ /// that terminates parsing of multi-valued arguments.
+ #[inline]
+ pub fn get_value_terminator(&self) -> Option<&Str> {
+ self.terminator.as_ref()
+ }
+
/// Get the index of this argument, if any
#[inline]
pub fn get_index(&self) -> Option<usize> {
@@ -4115,7 +4123,7 @@
if self.val_names.len() > 1 {
self.val_names
.iter()
- .map(|n| format!("<{}>", n))
+ .map(|n| format!("<{n}>"))
.collect::<Vec<_>>()
.join(delim)
} else {
@@ -4179,7 +4187,7 @@
styled
}
- /// Write the values such as <name1> <name2>
+ /// Write the values such as `<name1> <name2>`
fn render_arg_val(&self, required: bool) -> String {
let mut rendered = String::new();
@@ -4199,9 +4207,9 @@
debug_assert!(self.is_takes_value_set());
for (n, val_name) in val_names.iter().enumerate() {
let arg_name = if self.is_positional() && (num_vals.min_values() == 0 || !required) {
- format!("[{}]", val_name)
+ format!("[{val_name}]")
} else {
- format!("<{}>", val_name)
+ format!("<{val_name}>")
};
if n != 0 {
diff --git a/src/builder/arg_settings.rs b/src/builder/arg_settings.rs
index 0f63e43..b8bc069 100644
--- a/src/builder/arg_settings.rs
+++ b/src/builder/arg_settings.rs
@@ -113,7 +113,7 @@
assert!(m.is_required_set());
let m = m.unset_setting(ArgSettings::Required);
- assert!(!m.is_required_set(), "{:#?}", m);
+ assert!(!m.is_required_set(), "{m:#?}");
}
#[test]
@@ -138,8 +138,8 @@
assert!(m.is_last_set());
let m = m.unset_setting(ArgSettings::Required | ArgSettings::Hidden | ArgSettings::Last);
- assert!(!m.is_required_set(), "{:#?}", m);
- assert!(!m.is_hide_set(), "{:#?}", m);
- assert!(!m.is_last_set(), "{:#?}", m);
+ assert!(!m.is_required_set(), "{m:#?}");
+ assert!(!m.is_hide_set(), "{m:#?}");
+ assert!(!m.is_last_set(), "{m:#?}");
}
}
diff --git a/src/builder/command.rs b/src/builder/command.rs
index 203e677..72a68dc 100644
--- a/src/builder/command.rs
+++ b/src/builder/command.rs
@@ -243,7 +243,7 @@
let a = self
.args
.remove_by_name(id)
- .unwrap_or_else(|| panic!("Argument `{}` is undefined", id));
+ .unwrap_or_else(|| panic!("Argument `{id}` is undefined"));
self.args.push(f(a));
self
@@ -287,7 +287,7 @@
let subcmd = if let Some(idx) = pos {
self.subcommands.remove(idx)
} else {
- panic!("Command `{}` is undefined", name)
+ panic!("Command `{name}` is undefined")
};
self.subcommands.push(f(subcmd));
@@ -449,7 +449,7 @@
///
/// fn main() {
/// let m = cmd().get_matches_from(vec!["foo", "-b"]);
- /// println!("{}", *m.get_one::<bool>("bar").expect("defaulted by clap"));
+ /// println!("{}", m.get_flag("bar"));
/// }
/// ```
pub fn debug_assert(mut self) {
@@ -487,7 +487,7 @@
/// [`Command::try_get_matches_from_mut`]: Command::try_get_matches_from_mut()
#[inline]
pub fn get_matches(self) -> ArgMatches {
- self.get_matches_from(&mut env::args_os())
+ self.get_matches_from(env::args_os())
}
/// Parse [`env::args_os`], exiting on failure.
@@ -545,7 +545,7 @@
#[inline]
pub fn try_get_matches(self) -> ClapResult<ArgMatches> {
// Start the parsing
- self.try_get_matches_from(&mut env::args_os())
+ self.try_get_matches_from(env::args_os())
}
/// Parse the specified arguments, exiting on failure.
@@ -822,7 +822,7 @@
let mut styled = StyledStr::new();
let usage = Usage::new(self);
write_help(&mut styled, self, &usage, false);
- ok!(write!(w, "{}", styled));
+ ok!(write!(w, "{styled}"));
w.flush()
}
@@ -837,7 +837,7 @@
let mut styled = StyledStr::new();
let usage = Usage::new(self);
write_help(&mut styled, self, &usage, true);
- ok!(write!(w, "{}", styled));
+ ok!(write!(w, "{styled}"));
w.flush()
}
@@ -963,7 +963,7 @@
/// assert!(r.is_ok(), "unexpected error: {:?}", r);
/// let m = r.unwrap();
/// assert_eq!(m.get_one::<String>("config").unwrap(), "file");
- /// assert!(*m.get_one::<bool>("f").expect("defaulted"));
+ /// assert!(m.get_flag("f"));
/// assert_eq!(m.get_one::<String>("stuff"), None);
/// ```
#[inline]
@@ -1744,7 +1744,7 @@
/// Valid tags are:
///
/// * `{name}` - Display name for the (sub-)command.
- /// * `{bin}` - Binary name.
+ /// * `{bin}` - Binary name.(deprecated)
/// * `{version}` - Version number.
/// * `{author}` - Author information.
/// * `{author-with-newline}` - Author followed by `\n`.
@@ -1760,7 +1760,7 @@
/// * `{options}` - Help for options.
/// * `{positionals}` - Help for positional arguments.
/// * `{subcommands}` - Help for subcommands.
- /// * `{tag}` - Standard tab sized used within clap
+ /// * `{tab}` - Standard tab sized used within clap
/// * `{after-help}` - Help from [`Command::after_help`] or [`Command::after_long_help`].
/// * `{before-help}` - Help from [`Command::before_help`] or [`Command::before_long_help`].
///
@@ -1772,7 +1772,7 @@
/// # use clap::Command;
/// Command::new("myprog")
/// .version("1.0")
- /// .help_template("{bin} ({version}) - {usage}")
+ /// .help_template("{name} ({version}) - {usage}")
/// # ;
/// ```
///
@@ -1943,8 +1943,8 @@
/// .replace("--save-all", &["--save-context", "--save-runtime"])
/// .get_matches_from(vec!["cmd", "--save-all"]);
///
- /// assert!(*m.get_one::<bool>("save-context").expect("defaulted by clap"));
- /// assert!(*m.get_one::<bool>("save-runtime").expect("defaulted by clap"));
+ /// assert!(m.get_flag("save-context"));
+ /// assert!(m.get_flag("save-runtime"));
/// ```
///
/// This can also be used with options, for example if our application with
@@ -1969,8 +1969,8 @@
/// .replace("--save-all", &["--save-context", "--save-runtime", "--format=json"])
/// .get_matches_from(vec!["cmd", "--save-all"]);
///
- /// assert!(*m.get_one::<bool>("save-context").expect("defaulted by clap"));
- /// assert!(*m.get_one::<bool>("save-runtime").expect("defaulted by clap"));
+ /// assert!(m.get_flag("save-context"));
+ /// assert!(m.get_flag("save-runtime"));
/// assert_eq!(m.get_one::<String>("format").unwrap(), "json");
/// ```
///
@@ -2191,7 +2191,7 @@
///
/// assert_eq!(matches.subcommand_name().unwrap(), "sync");
/// let sync_matches = matches.subcommand_matches("sync").unwrap();
- /// assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
+ /// assert!(sync_matches.get_flag("search"));
/// ```
/// [`Arg::short`]: Arg::short()
#[must_use]
@@ -2228,7 +2228,7 @@
///
/// assert_eq!(matches.subcommand_name().unwrap(), "sync");
/// let sync_matches = matches.subcommand_matches("sync").unwrap();
- /// assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
+ /// assert!(sync_matches.get_flag("search"));
/// ```
///
/// [`Arg::long`]: Arg::long()
@@ -2599,7 +2599,7 @@
/// Set the placement of this subcommand within the help.
///
/// Subcommands with a lower value will be displayed first in the help message. Subcommands
- /// with duplicate display orders will be displayed in alphabetical order.
+ /// with duplicate display orders will be displayed in order they are defined.
///
/// This is helpful when one would like to emphasize frequently used subcommands, or prioritize
/// those towards the top of the list.
@@ -2641,8 +2641,8 @@
/// alpha Some help and text
///
/// Options:
- /// -h, --help Print help information
- /// -V, --version Print version information
+ /// -h, --help Print help
+ /// -V, --version Print version
/// ```
#[inline]
#[must_use]
@@ -3105,8 +3105,8 @@
/// sub1
///
/// Options:
- /// -h, --help Print help information
- /// -V, --version Print version information
+ /// -h, --help Print help
+ /// -V, --version Print version
/// ```
///
/// but usage of `subcommand_value_name`
@@ -3132,8 +3132,8 @@
/// sub1
///
/// Options:
- /// -h, --help Print help information
- /// -V, --version Print version information
+ /// -h, --help Print help
+ /// -V, --version Print version
/// ```
#[must_use]
pub fn subcommand_value_name(mut self, value_name: impl IntoResettable<Str>) -> Self {
@@ -3169,8 +3169,8 @@
/// sub1
///
/// Options:
- /// -h, --help Print help information
- /// -V, --version Print version information
+ /// -h, --help Print help
+ /// -V, --version Print version
/// ```
///
/// but usage of `subcommand_help_heading`
@@ -3196,8 +3196,8 @@
/// sub1
///
/// Options:
- /// -h, --help Print help information
- /// -V, --version Print version information
+ /// -h, --help Print help
+ /// -V, --version Print version
/// ```
#[must_use]
pub fn subcommand_help_heading(mut self, heading: impl IntoResettable<Str>) -> Self {
@@ -3947,22 +3947,22 @@
sc_names.push_str(sc.name.as_str());
let mut flag_subcmd = false;
if let Some(l) = sc.get_long_flag() {
- write!(sc_names, "|--{}", l).unwrap();
+ write!(sc_names, "|--{l}").unwrap();
flag_subcmd = true;
}
if let Some(s) = sc.get_short_flag() {
- write!(sc_names, "|-{}", s).unwrap();
+ write!(sc_names, "|-{s}").unwrap();
flag_subcmd = true;
}
if flag_subcmd {
- sc_names = format!("{{{}}}", sc_names);
+ sc_names = format!("{{{sc_names}}}");
}
let usage_name = self
.bin_name
.as_ref()
- .map(|bin_name| format!("{}{}{}", bin_name, mid_string, sc_names))
+ .map(|bin_name| format!("{bin_name}{mid_string}{sc_names}"))
.unwrap_or(sc_names);
sc.usage_name = Some(usage_name);
@@ -4044,19 +4044,19 @@
sc_names.push_str(sc.name.as_str());
let mut flag_subcmd = false;
if let Some(l) = sc.get_long_flag() {
- write!(sc_names, "|--{}", l).unwrap();
+ write!(sc_names, "|--{l}").unwrap();
flag_subcmd = true;
}
if let Some(s) = sc.get_short_flag() {
- write!(sc_names, "|-{}", s).unwrap();
+ write!(sc_names, "|-{s}").unwrap();
flag_subcmd = true;
}
if flag_subcmd {
- sc_names = format!("{{{}}}", sc_names);
+ sc_names = format!("{{{sc_names}}}");
}
- let usage_name = format!("{}{}{}", self_bin_name, mid_string, sc_names);
+ let usage_name = format!("{self_bin_name}{mid_string}{sc_names}");
debug!(
"Command::_build_bin_names:iter: Setting usage_name of {} to {:?}",
sc.name, usage_name
@@ -4243,10 +4243,10 @@
.action(ArgAction::Help);
if self.long_help_exists {
arg = arg
- .help("Print help information (use `--help` for more detail)")
- .long_help("Print help information (use `-h` for a summary)");
+ .help("Print help (see more with '--help')")
+ .long_help("Print help (see a summary with '-h')");
} else {
- arg = arg.help("Print help information");
+ arg = arg.help("Print help");
}
// Avoiding `arg_internal` to not be sensitive to `next_help_heading` /
// `next_display_order`
@@ -4258,7 +4258,7 @@
.short('V')
.long("version")
.action(ArgAction::Version)
- .help("Print version information");
+ .help("Print version");
// Avoiding `arg_internal` to not be sensitive to `next_help_heading` /
// `next_display_order`
self.args.push(arg);
@@ -4334,7 +4334,7 @@
.unwrap_or_default()
};
let display_name = self.get_display_name().unwrap_or_else(|| self.get_name());
- format!("{} {}\n", display_name, ver)
+ format!("{display_name} {ver}\n")
}
pub(crate) fn format_group(&self, g: &Id) -> StyledStr {
@@ -4593,12 +4593,14 @@
// specified by the user is sent through. If hide_short_help is not included,
// then items specified with hidden_short_help will also be hidden.
let should_long = |v: &Arg| {
- v.get_long_help().is_some()
- || v.is_hide_long_help_set()
- || v.is_hide_short_help_set()
- || v.get_possible_values()
- .iter()
- .any(PossibleValue::should_show_help)
+ !v.is_hide_set()
+ && (v.get_long_help().is_some()
+ || v.is_hide_long_help_set()
+ || v.is_hide_short_help_set()
+ || (!v.is_hide_possible_values_set()
+ && v.get_possible_values()
+ .iter()
+ .any(PossibleValue::should_show_help)))
};
// Subcommands aren't checked because we prefer short help for them, deferring to
diff --git a/src/builder/debug_asserts.rs b/src/builder/debug_asserts.rs
index dff70e3..86e3677 100644
--- a/src/builder/debug_asserts.rs
+++ b/src/builder/debug_asserts.rs
@@ -40,20 +40,20 @@
for sc in cmd.get_subcommands() {
if let Some(s) = sc.get_short_flag().as_ref() {
- short_flags.push(Flag::Command(format!("-{}", s), sc.get_name()));
+ short_flags.push(Flag::Command(format!("-{s}"), sc.get_name()));
}
for short_alias in sc.get_all_short_flag_aliases() {
- short_flags.push(Flag::Command(format!("-{}", short_alias), sc.get_name()));
+ short_flags.push(Flag::Command(format!("-{short_alias}"), sc.get_name()));
}
if let Some(l) = sc.get_long_flag().as_ref() {
assert!(!l.starts_with('-'), "Command {}: long_flag {:?} must not start with a `-`, that will be handled by the parser", sc.get_name(), l);
- long_flags.push(Flag::Command(format!("--{}", l), sc.get_name()));
+ long_flags.push(Flag::Command(format!("--{l}"), sc.get_name()));
}
for long_alias in sc.get_all_long_flag_aliases() {
- long_flags.push(Flag::Command(format!("--{}", long_alias), sc.get_name()));
+ long_flags.push(Flag::Command(format!("--{long_alias}"), sc.get_name()));
}
}
@@ -68,26 +68,20 @@
);
if let Some(s) = arg.get_short() {
- short_flags.push(Flag::Arg(format!("-{}", s), arg.get_id().as_str()));
+ short_flags.push(Flag::Arg(format!("-{s}"), arg.get_id().as_str()));
}
for (short_alias, _) in &arg.short_aliases {
- short_flags.push(Flag::Arg(
- format!("-{}", short_alias),
- arg.get_id().as_str(),
- ));
+ short_flags.push(Flag::Arg(format!("-{short_alias}"), arg.get_id().as_str()));
}
if let Some(l) = arg.get_long() {
assert!(!l.starts_with('-'), "Argument {}: long {:?} must not start with a `-`, that will be handled by the parser", arg.get_id(), l);
- long_flags.push(Flag::Arg(format!("--{}", l), arg.get_id().as_str()));
+ long_flags.push(Flag::Arg(format!("--{l}"), arg.get_id().as_str()));
}
for (long_alias, _) in &arg.aliases {
- long_flags.push(Flag::Arg(
- format!("--{}", long_alias),
- arg.get_id().as_str(),
- ));
+ long_flags.push(Flag::Arg(format!("--{long_alias}"), arg.get_id().as_str()));
}
// Name conflicts
@@ -359,6 +353,13 @@
cmd.get_name(),
"`{unified}` template variable was removed in clap3, use `{options}` instead"
);
+ #[cfg(feature = "unstable-v5")]
+ assert!(
+ !help_template.to_string().contains("{bin}"),
+ "Command {}: {}",
+ cmd.get_name(),
+ "`{bin}` template variable was removed in clap5, use `{name}` instead"
+ )
}
cmd._panic_on_missing_help(cmd.is_help_expected_set());
@@ -422,19 +423,16 @@
for (one, two) in find_duplicates(flags) {
match (one, two) {
(Command(flag, one), Command(_, another)) if one != another => panic!(
- "the '{}' {} flag is specified for both '{}' and '{}' subcommands",
- flag, short_or_long, one, another
+ "the '{flag}' {short_or_long} flag is specified for both '{one}' and '{another}' subcommands"
),
(Arg(flag, one), Arg(_, another)) if one != another => panic!(
- "{} option names must be unique, but '{}' is in use by both '{}' and '{}'",
- short_or_long, flag, one, another
+ "{short_or_long} option names must be unique, but '{flag}' is in use by both '{one}' and '{another}'"
),
(Arg(flag, arg), Command(_, sub)) | (Command(flag, sub), Arg(_, arg)) => panic!(
- "the '{}' {} flag for the '{}' argument conflicts with the short flag \
- for '{}' subcommand",
- flag, short_or_long, arg, sub
+ "the '{flag}' {short_or_long} flag for the '{arg}' argument conflicts with the short flag \
+ for '{sub}' subcommand"
),
_ => {}
@@ -522,10 +520,8 @@
assert!(
highest_idx == num_p,
- "Found positional argument whose index is {} but there \
- are only {} positional arguments defined",
- highest_idx,
- num_p
+ "Found positional argument whose index is {highest_idx} but there \
+ are only {num_p} positional arguments defined",
);
for arg in cmd.get_arguments() {
diff --git a/src/builder/range.rs b/src/builder/range.rs
index cc2890b..6ecf053 100644
--- a/src/builder/range.rs
+++ b/src/builder/range.rs
@@ -92,7 +92,7 @@
}
pub(crate) fn num_values(&self) -> Option<usize> {
- self.is_fixed().then(|| self.start_inclusive)
+ self.is_fixed().then_some(self.start_inclusive)
}
pub(crate) fn accepts_more(&self, current: usize) -> bool {
@@ -183,7 +183,7 @@
impl std::fmt::Debug for ValueRange {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- write!(f, "{}", self)
+ write!(f, "{self}")
}
}
diff --git a/src/builder/resettable.rs b/src/builder/resettable.rs
index 0176d39..e0b82b1 100644
--- a/src/builder/resettable.rs
+++ b/src/builder/resettable.rs
@@ -10,6 +10,24 @@
use crate::builder::ValueRange;
/// Clearable builder value
+///
+/// This allows a builder function to both accept any value that can [`Into::into`] `T` (like
+/// `&str` into `OsStr`) as well as `None` to reset it to the default. This is needed to
+/// workaround a limitation where you can't have a function argument that is `impl Into<Option<T>>`
+/// where `T` is `impl Into<S>` accept `None` as its type is ambiguous.
+///
+/// # Example
+///
+/// ```rust
+/// # use clap::Command;
+/// # use clap::Arg;
+/// fn common() -> Command {
+/// Command::new("cli")
+/// .arg(Arg::new("input").short('i').long("input"))
+/// }
+/// let mut command = common();
+/// command.mut_arg("input", |arg| arg.short(None));
+/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Resettable<T> {
/// Overwrite builder value
diff --git a/src/builder/str.rs b/src/builder/str.rs
index c6689d3..be69c3f 100644
--- a/src/builder/str.rs
+++ b/src/builder/str.rs
@@ -246,7 +246,10 @@
}
pub(crate) fn into_string(self) -> String {
- self.as_str().to_owned()
+ match self {
+ Self::Static(s) => s.to_owned(),
+ Self::Owned(s) => s.into(),
+ }
}
}
}
diff --git a/src/builder/styled_str.rs b/src/builder/styled_str.rs
index ecd05a3..d36329d 100644
--- a/src/builder/styled_str.rs
+++ b/src/builder/styled_str.rs
@@ -1,4 +1,7 @@
/// Terminal-styling container
+///
+/// For now, this is the same as a [`Str`][crate::builder::Str]. This exists to reserve space in
+/// the API for exposing terminal styling.
#[derive(Clone, Default, Debug, PartialEq, Eq)]
pub struct StyledStr {
#[cfg(feature = "color")]
diff --git a/src/builder/value_hint.rs b/src/builder/value_hint.rs
index 812d5d8..ee286b1 100644
--- a/src/builder/value_hint.rs
+++ b/src/builder/value_hint.rs
@@ -89,7 +89,7 @@
"hostname" => ValueHint::Hostname,
"url" => ValueHint::Url,
"emailaddress" => ValueHint::EmailAddress,
- _ => return Err(format!("unknown ValueHint: `{}`", s)),
+ _ => return Err(format!("unknown ValueHint: `{s}`")),
})
}
}
diff --git a/src/builder/value_parser.rs b/src/builder/value_parser.rs
index 4681857..191e8ae 100644
--- a/src/builder/value_parser.rs
+++ b/src/builder/value_parser.rs
@@ -2351,18 +2351,15 @@
/// assert_eq!(format!("{:?}", parser), "ValueParser::os_string");
/// let parser = clap::value_parser!(std::path::PathBuf);
/// assert_eq!(format!("{:?}", parser), "ValueParser::path_buf");
-/// let parser = clap::value_parser!(u16).range(3000..);
-/// assert_eq!(format!("{:?}", parser), "RangedI64ValueParser { bounds: (Included(3000), Included(65535)), target: PhantomData }");
-/// let parser = clap::value_parser!(u64).range(3000..);
-/// assert_eq!(format!("{:?}", parser), "RangedU64ValueParser { bounds: (Included(3000), Unbounded), target: PhantomData }");
+/// clap::value_parser!(u16).range(3000..);
+/// clap::value_parser!(u64).range(3000..);
///
/// // FromStr types
/// let parser = clap::value_parser!(usize);
/// assert_eq!(format!("{:?}", parser), "_AnonymousValueParser(ValueParser::other(usize))");
///
/// // ValueEnum types
-/// let parser = clap::value_parser!(ColorChoice);
-/// assert_eq!(format!("{:?}", parser), "EnumValueParser(PhantomData)");
+/// clap::value_parser!(ColorChoice);
/// ```
#[macro_export]
macro_rules! value_parser {
diff --git a/src/derive.rs b/src/derive.rs
index a5df2ed..98bb012 100644
--- a/src/derive.rs
+++ b/src/derive.rs
@@ -69,7 +69,7 @@
/// impl From<ArgMatches> for Context {
/// fn from(m: ArgMatches) -> Self {
/// Context {
-/// verbose: *m.get_one::<bool>("verbose").expect("defaulted_by_clap"),
+/// verbose: m.get_flag("verbose"),
/// name: m.get_one::<String>("name").cloned(),
/// }
/// }
@@ -201,7 +201,7 @@
/// fn from(m: ArgMatches) -> Self {
/// Context {
/// name: m.get_one::<String>("name").unwrap().clone(),
- /// debug: *m.get_one::<bool>("debug").expect("defaulted by clap"),
+ /// debug: m.get_flag("debug"),
/// }
/// }
/// }
@@ -235,7 +235,7 @@
/// fn from(m: ArgMatches) -> Self {
/// Context {
/// name: m.get_one::<String>("name").unwrap().to_string(),
- /// debug: *m.get_one::<bool>("debug").expect("defaulted by clap"),
+ /// debug: m.get_flag("debug"),
/// }
/// }
/// }
@@ -278,7 +278,7 @@
/// #[derive(clap::Args)]
/// struct LogArgs {
/// #[arg(long, short = 'v', action = clap::ArgAction::Count)]
-/// verbose: i8,
+/// verbose: u8,
/// }
/// ```
pub trait Args: FromArgMatches + Sized {
@@ -385,7 +385,7 @@
.matches(input, ignore_case)
})
.cloned()
- .ok_or_else(|| format!("Invalid variant: {}", input))
+ .ok_or_else(|| format!("invalid variant: {input}"))
}
/// The canonical argument value.
diff --git a/src/error/format.rs b/src/error/format.rs
index 1714943..d3ce6c6 100644
--- a/src/error/format.rs
+++ b/src/error/format.rs
@@ -36,7 +36,7 @@
} else if let Some(source) = error.inner.source.as_ref() {
styled.none(source.to_string());
} else {
- styled.none("Unknown cause");
+ styled.none("unknown cause");
}
styled.none("\n");
styled
@@ -44,6 +44,8 @@
}
/// Richly formatted error context
+///
+/// This follows the [rustc diagnostic style guide](https://rustc-dev-guide.rust-lang.org/diagnostics.html#suggestion-style-guide).
#[non_exhaustive]
#[cfg(feature = "error-context")]
pub struct RichFormatter;
@@ -60,27 +62,44 @@
} else if let Some(source) = error.inner.source.as_ref() {
styled.none(source.to_string());
} else {
- styled.none("Unknown cause");
+ styled.none("unknown cause");
}
}
+ let mut suggested = false;
if let Some(valid) = error.get(ContextKind::SuggestedSubcommand) {
- styled.none("\n\n");
- did_you_mean(&mut styled, valid);
+ styled.none("\n");
+ if !suggested {
+ styled.none("\n");
+ suggested = true;
+ }
+ did_you_mean(&mut styled, "subcommand", valid);
}
if let Some(valid) = error.get(ContextKind::SuggestedArg) {
- styled.none("\n\n");
- did_you_mean(&mut styled, valid);
+ styled.none("\n");
+ if !suggested {
+ styled.none("\n");
+ suggested = true;
+ }
+ did_you_mean(&mut styled, "argument", valid);
}
if let Some(valid) = error.get(ContextKind::SuggestedValue) {
- styled.none("\n\n");
- did_you_mean(&mut styled, valid);
+ styled.none("\n");
+ if !suggested {
+ styled.none("\n");
+ suggested = true;
+ }
+ did_you_mean(&mut styled, "value", valid);
}
let suggestions = error.get(ContextKind::Suggested);
if let Some(ContextValue::StyledStrs(suggestions)) = suggestions {
+ if !suggested {
+ styled.none("\n");
+ }
for suggestion in suggestions {
- styled.none("\n\n");
+ styled.none("\n");
styled.none(TAB);
+ styled.good("note: ");
styled.extend(suggestion.iter());
}
}
@@ -112,11 +131,11 @@
(invalid_arg, prior_arg)
{
if ContextValue::String(invalid_arg.clone()) == *prior_arg {
- styled.none("The argument '");
+ styled.none("the argument '");
styled.warning(invalid_arg);
- styled.none("' was provided more than once, but cannot be used multiple times");
+ styled.none("' cannot be used multiple times");
} else {
- styled.none("The argument '");
+ styled.none("the argument '");
styled.warning(invalid_arg);
styled.none("' cannot be used with");
@@ -147,7 +166,7 @@
ErrorKind::NoEquals => {
let invalid_arg = error.get(ContextKind::InvalidArg);
if let Some(ContextValue::String(invalid_arg)) = invalid_arg {
- styled.none("Equal sign is needed when assigning values to '");
+ styled.none("equal sign is needed when assigning values to '");
styled.warning(invalid_arg);
styled.none("'");
true
@@ -164,13 +183,13 @@
) = (invalid_arg, invalid_value)
{
if invalid_value.is_empty() {
- styled.none("The argument '");
+ styled.none("a value is required for '");
styled.warning(invalid_arg);
- styled.none("' requires a value but none was supplied");
+ styled.none("' but none was supplied");
} else {
- styled.none("'");
+ styled.none("invalid value '");
styled.none(invalid_value);
- styled.none("' isn't a valid value for '");
+ styled.none("' for '");
styled.warning(invalid_arg);
styled.none("'");
}
@@ -199,9 +218,9 @@
ErrorKind::InvalidSubcommand => {
let invalid_sub = error.get(ContextKind::InvalidSubcommand);
if let Some(ContextValue::String(invalid_sub)) = invalid_sub {
- styled.none("The subcommand '");
+ styled.none("unrecognized subcommand '");
styled.warning(invalid_sub);
- styled.none("' wasn't recognized");
+ styled.none("'");
true
} else {
false
@@ -210,7 +229,7 @@
ErrorKind::MissingRequiredArgument => {
let invalid_arg = error.get(ContextKind::InvalidArg);
if let Some(ContextValue::Strings(invalid_arg)) = invalid_arg {
- styled.none("The following required arguments were not provided:");
+ styled.none("the following required arguments were not provided:");
for v in invalid_arg {
styled.none("\n");
styled.none(TAB);
@@ -259,11 +278,11 @@
Some(ContextValue::String(invalid_value)),
) = (invalid_arg, invalid_value)
{
- styled.none("The value '");
+ styled.none("unexpected value '");
styled.warning(invalid_value);
- styled.none("' was provided to '");
+ styled.none("' for '");
styled.warning(invalid_arg);
- styled.none("' but it wasn't expecting any more values");
+ styled.none("' found; no more were expected");
true
} else {
false
@@ -280,11 +299,10 @@
) = (invalid_arg, actual_num_values, min_values)
{
let were_provided = singular_or_plural(*actual_num_values as usize);
- styled.none("The argument '");
- styled.warning(invalid_arg);
- styled.none("' requires at least ");
styled.warning(min_values.to_string());
- styled.none(" values but only ");
+ styled.none(" more values required by '");
+ styled.warning(invalid_arg);
+ styled.none("'; only ");
styled.warning(actual_num_values.to_string());
styled.none(were_provided);
true
@@ -300,7 +318,7 @@
Some(ContextValue::String(invalid_value)),
) = (invalid_arg, invalid_value)
{
- styled.none("Invalid value '");
+ styled.none("invalid value '");
styled.warning(invalid_value);
styled.none("' for '");
styled.warning(invalid_arg);
@@ -326,11 +344,10 @@
) = (invalid_arg, actual_num_values, num_values)
{
let were_provided = singular_or_plural(*actual_num_values as usize);
- styled.none("The argument '");
- styled.warning(invalid_arg);
- styled.none("' requires ");
styled.warning(num_values.to_string());
- styled.none(" values, but ");
+ styled.none(" values required for '");
+ styled.warning(invalid_arg);
+ styled.none("' but ");
styled.warning(actual_num_values.to_string());
styled.none(were_provided);
true
@@ -341,9 +358,9 @@
ErrorKind::UnknownArgument => {
let invalid_arg = error.get(ContextKind::InvalidArg);
if let Some(ContextValue::String(invalid_arg)) = invalid_arg {
- styled.none("Found argument '");
+ styled.none("unexpected argument '");
styled.warning(invalid_arg.to_string());
- styled.none("' which wasn't expected, or isn't valid in this context");
+ styled.none("' found");
true
} else {
false
@@ -400,24 +417,31 @@
fn try_help(styled: &mut StyledStr, help: Option<&str>) {
if let Some(help) = help {
- styled.none("\n\nFor more information try '");
+ styled.none("\n\nFor more information, try '");
styled.literal(help.to_owned());
- styled.none("'\n");
+ styled.none("'.\n");
} else {
styled.none("\n");
}
}
#[cfg(feature = "error-context")]
-fn did_you_mean(styled: &mut StyledStr, valid: &ContextValue) {
+fn did_you_mean(styled: &mut StyledStr, context: &str, valid: &ContextValue) {
if let ContextValue::String(valid) = valid {
styled.none(TAB);
- styled.none("Did you mean '");
+ styled.good("note: ");
+ styled.none(context);
+ styled.none(" '");
styled.good(valid);
- styled.none("'?");
+ styled.none("' exists");
} else if let ContextValue::Strings(valid) = valid {
styled.none(TAB);
- styled.none("Did you mean ");
+ styled.good("note: ");
+ styled.none(context);
+ if valid.len() > 1 {
+ styled.none("s");
+ }
+ styled.none(" ");
for (i, valid) in valid.iter().enumerate() {
if i != 0 {
styled.none(", ");
@@ -426,14 +450,18 @@
styled.good(valid);
styled.none("'");
}
- styled.none("?");
+ if valid.len() == 1 {
+ styled.none(" exists");
+ } else {
+ styled.none(" exist");
+ }
}
}
fn escape(s: impl AsRef<str>) -> String {
let s = s.as_ref();
if s.contains(char::is_whitespace) {
- format!("{:?}", s)
+ format!("{s:?}")
} else {
s.to_owned()
}
diff --git a/src/error/kind.rs b/src/error/kind.rs
index aa316ef..1859237 100644
--- a/src/error/kind.rs
+++ b/src/error/kind.rs
@@ -82,7 +82,7 @@
/// fn is_numeric(val: &str) -> Result<(), String> {
/// match val.parse::<i64>() {
/// Ok(..) => Ok(()),
- /// Err(..) => Err(String::from("Value wasn't a number!")),
+ /// Err(..) => Err(String::from("value wasn't a number!")),
/// }
/// }
///
@@ -316,24 +316,22 @@
/// End-user description of the error case, where relevant
pub fn as_str(self) -> Option<&'static str> {
match self {
- Self::InvalidValue => Some("One of the values isn't valid for an argument"),
- Self::UnknownArgument => {
- Some("Found an argument which wasn't expected or isn't valid in this context")
- }
- Self::InvalidSubcommand => Some("A subcommand wasn't recognized"),
- Self::NoEquals => Some("Equal is needed when assigning values to one of the arguments"),
- Self::ValueValidation => Some("Invalid value for one of the arguments"),
- Self::TooManyValues => Some("An argument received an unexpected value"),
- Self::TooFewValues => Some("An argument requires more values"),
- Self::WrongNumberOfValues => Some("An argument received too many or too few values"),
+ Self::InvalidValue => Some("one of the values isn't valid for an argument"),
+ Self::UnknownArgument => Some("unexpected argument found"),
+ Self::InvalidSubcommand => Some("unrecognized subcommand"),
+ Self::NoEquals => Some("equal is needed when assigning values to one of the arguments"),
+ Self::ValueValidation => Some("invalid value for one of the arguments"),
+ Self::TooManyValues => Some("unexpected value for an argument found"),
+ Self::TooFewValues => Some("more values required for an argument"),
+ Self::WrongNumberOfValues => Some("too many or too few values for an argument"),
Self::ArgumentConflict => {
- Some("An argument cannot be used with one or more of the other specified arguments")
+ Some("an argument cannot be used with one or more of the other specified arguments")
}
Self::MissingRequiredArgument => {
- Some("One or more required arguments were not provided")
+ Some("one or more required arguments were not provided")
}
- Self::MissingSubcommand => Some("A subcommand is required but one was not provided"),
- Self::InvalidUtf8 => Some("Invalid UTF-8 was detected in one or more arguments"),
+ Self::MissingSubcommand => Some("a subcommand is required but one was not provided"),
+ Self::InvalidUtf8 => Some("invalid UTF-8 was detected in one or more arguments"),
Self::DisplayHelp => None,
Self::DisplayHelpOnMissingArgumentOrSubcommand => None,
Self::DisplayVersion => None,
diff --git a/src/error/mod.rs b/src/error/mod.rs
index d88df46..2d8bf62 100644
--- a/src/error/mod.rs
+++ b/src/error/mod.rs
@@ -242,7 +242,10 @@
/// ```
pub fn print(&self) -> io::Result<()> {
let style = self.formatted();
- let color_when = if self.kind() == ErrorKind::DisplayHelp {
+ let color_when = if matches!(
+ self.kind(),
+ ErrorKind::DisplayHelp | ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand,
+ ) {
self.inner.color_help_when
} else {
self.inner.color_when
@@ -431,8 +434,9 @@
#[cfg(feature = "error-context")]
{
let mut styled_suggestion = StyledStr::new();
- styled_suggestion
- .none("If you believe you received this message in error, try re-running with '");
+ styled_suggestion.none("to pass '");
+ styled_suggestion.warning(&subcmd);
+ styled_suggestion.none("' as a value, use '");
styled_suggestion.good(name);
styled_suggestion.good(" -- ");
styled_suggestion.good(&subcmd);
@@ -659,9 +663,9 @@
let mut suggestions = vec![];
if suggested_trailing_arg {
let mut styled_suggestion = StyledStr::new();
- styled_suggestion.none("If you tried to supply '");
+ styled_suggestion.none("to pass '");
styled_suggestion.warning(&arg);
- styled_suggestion.none("' as a value rather than a flag, use '");
+ styled_suggestion.none("' as a value, use '");
styled_suggestion.good("-- ");
styled_suggestion.good(&arg);
styled_suggestion.none("'");
@@ -677,18 +681,18 @@
match did_you_mean {
Some((flag, Some(sub))) => {
let mut styled_suggestion = StyledStr::new();
- styled_suggestion.none("Did you mean to put '");
+ styled_suggestion.none("'");
+ styled_suggestion.good(sub);
+ styled_suggestion.none(" ");
styled_suggestion.good("--");
styled_suggestion.good(flag);
- styled_suggestion.none("' after the subcommand '");
- styled_suggestion.good(sub);
- styled_suggestion.none("'?");
+ styled_suggestion.none("' exists");
suggestions.push(styled_suggestion);
}
Some((flag, None)) => {
err = err.insert_context_unchecked(
ContextKind::SuggestedArg,
- ContextValue::String(format!("--{}", flag)),
+ ContextValue::String(format!("--{flag}")),
);
}
None => {}
@@ -714,11 +718,11 @@
#[cfg(feature = "error-context")]
{
let mut styled_suggestion = StyledStr::new();
- styled_suggestion.none("If you tried to supply '");
- styled_suggestion.warning(&arg);
- styled_suggestion.none("' as a subcommand, remove the '");
+ styled_suggestion.none("subcommand '");
+ styled_suggestion.good(&arg);
+ styled_suggestion.none("' exists; to use it, remove the '");
styled_suggestion.warning("--");
- styled_suggestion.none("' before it.");
+ styled_suggestion.none("' before it");
err = err.extend_context_unchecked([
(ContextKind::InvalidArg, ContextValue::String(arg)),
@@ -778,7 +782,7 @@
if let Some(backtrace) = self.inner.backtrace.as_ref() {
ok!(writeln!(f));
ok!(writeln!(f, "Backtrace:"));
- ok!(writeln!(f, "{}", backtrace));
+ ok!(writeln!(f, "{backtrace}"));
}
Ok(())
}
diff --git a/src/lib.rs b/src/lib.rs
index 393e1f0..ab2d9d4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,7 +24,7 @@
//! - Leverage feature flags to keep to one active branch
//! - Being under [WG-CLI](https://github.com/rust-cli/team/) to increase the bus factor
//! - We follow semver and will wait about 6-9 months between major breaking changes
-//! - We will support the last two minor Rust releases (MSRV, currently 1.60.0)
+//! - We will support the last two minor Rust releases (MSRV, currently 1.64.0)
//!
//! While these aspirations can be at odds with fast build times and low binary
//! size, we will still strive to keep these reasonable for the flexibility you
diff --git a/src/macros.rs b/src/macros.rs
index e5e5a71..8addab3 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -17,7 +17,7 @@
#[macro_export]
macro_rules! crate_version {
() => {
- "4.0.29"
+ "4.1.8"
};
}
@@ -85,6 +85,12 @@
/// Allows you to pull the name from your Cargo.toml at compile time.
///
+/// **NOTE:** This macro extracts the name from an environment variable `CARGO_PKG_NAME`.
+/// When the crate name is set to something different from the package name,
+/// use environment variables `CARGO_CRATE_NAME` or `CARGO_BIN_NAME`.
+/// See [the Cargo Book](https://doc.rust-lang.org/cargo/reference/environment-variables.html)
+/// for more information.
+///
/// # Examples
///
/// ```no_run
@@ -197,256 +203,238 @@
($arg:expr)
--$long:ident
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ ) => {{
+ debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- let mut arg = $arg;
- let long = $crate::arg_impl! { @string $long };
- if arg.get_id() == "" {
- arg = arg.id(long);
- }
- let action = $crate::ArgAction::SetTrue;
- arg
- .long(long)
- .action(action)
- })
- $($tail)*
+ let mut arg = $arg;
+ let long = $crate::arg_impl! { @string $long };
+ if arg.get_id() == "" {
+ arg = arg.id(long);
}
- };
+ let action = $crate::ArgAction::SetTrue;
+ let arg = arg
+ .long(long)
+ .action(action);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
--$long:literal
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ ) => {{
+ debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- let mut arg = $arg;
- let long = $crate::arg_impl! { @string $long };
- if arg.get_id() == "" {
- arg = arg.id(long);
- }
- let action = $crate::ArgAction::SetTrue;
- arg
- .long(long)
- .action(action)
- })
- $($tail)*
+ let mut arg = $arg;
+ let long = $crate::arg_impl! { @string $long };
+ if arg.get_id() == "" {
+ arg = arg.id(long);
}
- };
+ let action = $crate::ArgAction::SetTrue;
+ let arg = arg
+ .long(long)
+ .action(action);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
-$short:ident
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
- debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ ) => {{
+ debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
+ debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- let action = $crate::ArgAction::SetTrue;
- $arg
- .short($crate::arg_impl! { @char $short })
- .action(action)
- })
- $($tail)*
- }
- };
+ let action = $crate::ArgAction::SetTrue;
+ let arg = $arg
+ .short($crate::arg_impl! { @char $short })
+ .action(action);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
-$short:literal
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
- debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ ) => {{
+ debug_assert_eq!($arg.get_long(), None, "Short flags should precede long flags");
+ debug_assert_eq!($arg.get_value_names(), None, "Flags should precede values");
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- let action = $crate::ArgAction::SetTrue;
- $arg
- .short($crate::arg_impl! { @char $short })
- .action(action)
- })
- $($tail)*
- }
- };
+ let action = $crate::ArgAction::SetTrue;
+ let arg = $arg
+ .short($crate::arg_impl! { @char $short })
+ .action(action);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
<$value_name:ident>
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
+ ) => {{
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
- let mut arg = $arg;
+ let mut arg = $arg;
- if arg.get_long().is_none() && arg.get_short().is_none() {
- arg = arg.required(true);
- }
-
- let value_name = $crate::arg_impl! { @string $value_name };
- if arg.get_id() == "" {
- arg = arg.id(value_name);
- }
- arg
- .value_name(value_name)
- .action($crate::ArgAction::Set)
- })
- $($tail)*
+ if arg.get_long().is_none() && arg.get_short().is_none() {
+ arg = arg.required(true);
}
- };
+
+ let value_name = $crate::arg_impl! { @string $value_name };
+ if arg.get_id() == "" {
+ arg = arg.id(value_name);
+ }
+ let arg = arg
+ .value_name(value_name)
+ .action($crate::ArgAction::Set);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
<$value_name:literal>
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
+ ) => {{
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
- let mut arg = $arg;
+ let mut arg = $arg;
- if arg.get_long().is_none() && arg.get_short().is_none() {
- arg = arg.required(true);
- }
-
- let value_name = $crate::arg_impl! { @string $value_name };
- if arg.get_id() == "" {
- arg = arg.id(value_name);
- }
- arg
- .value_name(value_name)
- .action($crate::ArgAction::Set)
- })
- $($tail)*
+ if arg.get_long().is_none() && arg.get_short().is_none() {
+ arg = arg.required(true);
}
- };
+
+ let value_name = $crate::arg_impl! { @string $value_name };
+ if arg.get_id() == "" {
+ arg = arg.id(value_name);
+ }
+ let arg = arg
+ .value_name(value_name)
+ .action($crate::ArgAction::Set);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
[$value_name:ident]
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
+ ) => {{
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
- let mut arg = $arg;
+ let mut arg = $arg;
- if arg.get_long().is_none() && arg.get_short().is_none() {
- arg = arg.required(false);
- } else {
- arg = arg.num_args(0..=1);
- }
-
- let value_name = $crate::arg_impl! { @string $value_name };
- if arg.get_id() == "" {
- arg = arg.id(value_name);
- }
- arg
- .value_name(value_name)
- .action($crate::ArgAction::Set)
- })
- $($tail)*
+ if arg.get_long().is_none() && arg.get_short().is_none() {
+ arg = arg.required(false);
+ } else {
+ arg = arg.num_args(0..=1);
}
- };
+
+ let value_name = $crate::arg_impl! { @string $value_name };
+ if arg.get_id() == "" {
+ arg = arg.id(value_name);
+ }
+ let arg = arg
+ .value_name(value_name)
+ .action($crate::ArgAction::Set);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
[$value_name:literal]
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
- debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
+ ) => {{
+ debug_assert!(!matches!($arg.get_action(), $crate::ArgAction::Append), "Flags should precede `...`");
+ debug_assert_eq!($arg.get_value_names(), None, "Multiple values not yet supported");
- let mut arg = $arg;
+ let mut arg = $arg;
- if arg.get_long().is_none() && arg.get_short().is_none() {
- arg = arg.required(false);
- } else {
- arg = arg.num_args(0..=1);
- }
-
- let value_name = $crate::arg_impl! { @string $value_name };
- if arg.get_id() == "" {
- arg = arg.id(value_name);
- }
- arg
- .value_name(value_name)
- .action($crate::ArgAction::Set)
- })
- $($tail)*
+ if arg.get_long().is_none() && arg.get_short().is_none() {
+ arg = arg.required(false);
+ } else {
+ arg = arg.num_args(0..=1);
}
- };
+
+ let value_name = $crate::arg_impl! { @string $value_name };
+ if arg.get_id() == "" {
+ arg = arg.id(value_name);
+ }
+ let arg = arg
+ .value_name(value_name)
+ .action($crate::ArgAction::Set);
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
...
$($tail:tt)*
- ) => {
- $crate::arg_impl! {
- @arg
- ({
- match $arg.get_action() {
- $crate::ArgAction::Set => {
- if $arg.get_long().is_none() && $arg.get_short().is_none() {
- $arg.num_args(1..)
- // Allow collecting arguments interleaved with flags
- .action($crate::ArgAction::Append)
- } else {
- $arg.action($crate::ArgAction::Append)
- }
- },
- $crate::ArgAction::SetTrue | $crate::ArgAction::Help | $crate::ArgAction::Version => {
- $arg.action($crate::ArgAction::Count)
- }
- action => {
- panic!("Unexpected action {:?}", action)
- }
+ ) => {{
+ let arg = match $arg.get_action() {
+ $crate::ArgAction::Set => {
+ if $arg.get_long().is_none() && $arg.get_short().is_none() {
+ $arg.num_args(1..)
+ // Allow collecting arguments interleaved with flags
+ .action($crate::ArgAction::Append)
+ } else {
+ $arg.action($crate::ArgAction::Append)
}
- })
- $($tail)*
- }
- };
+ },
+ $crate::ArgAction::SetTrue | $crate::ArgAction::Help | $crate::ArgAction::Version => {
+ $arg.action($crate::ArgAction::Count)
+ }
+ action => {
+ panic!("Unexpected action {:?}", action)
+ }
+ };
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)*
+ };
+ arg
+ }};
(
@arg
($arg:expr)
$help:literal
- ) => {
+ ) => {{
$arg.help($help)
- };
+ }};
(
@arg
($arg:expr)
- ) => {
+ ) => {{
$arg
- };
+ }};
}
/// Create an [`Arg`] from a usage string.
@@ -536,14 +524,17 @@
/// [`Arg`]: crate::Arg
#[macro_export]
macro_rules! arg {
- ( $name:ident: $($tail:tt)+ ) => {
- $crate::arg_impl! {
- @arg ($crate::Arg::new($crate::arg_impl! { @string $name })) $($tail)+
- }
- };
- ( $($tail:tt)+ ) => {{
+ ( $name:ident: $($tail:tt)+ ) => {{
+ let arg = $crate::Arg::new($crate::arg_impl! { @string $name });
let arg = $crate::arg_impl! {
- @arg ($crate::Arg::default()) $($tail)+
+ @arg (arg) $($tail)+
+ };
+ arg
+ }};
+ ( $($tail:tt)+ ) => {{
+ let arg = $crate::Arg::default();
+ let arg = $crate::arg_impl! {
+ @arg (arg) $($tail)+
};
debug_assert_ne!(arg.get_id(), "", "Without a value or long flag, the `name:` prefix is required");
arg
diff --git a/src/output/help_template.rs b/src/output/help_template.rs
index 3db80da..4c7adda 100644
--- a/src/output/help_template.rs
+++ b/src/output/help_template.rs
@@ -137,6 +137,7 @@
"name" => {
self.write_display_name();
}
+ #[cfg(not(feature = "unstable-v5"))]
"bin" => {
self.write_bin_name();
}
@@ -409,7 +410,7 @@
self.none("\n\n");
}
first = false;
- self.header(format!("{}:\n", heading));
+ self.header(format!("{heading}:\n"));
self.write_args(&args, heading, option_sort_key);
}
}
@@ -484,7 +485,7 @@
debug!("HelpTemplate::short");
if let Some(s) = arg.get_short() {
- self.literal(format!("-{}", s));
+ self.literal(format!("-{s}"));
} else if arg.get_long().is_some() {
self.none(" ");
}
@@ -497,7 +498,7 @@
if arg.get_short().is_some() {
self.none(", ");
}
- self.literal(format!("--{}", long));
+ self.literal(format!("--{long}"));
}
}
@@ -737,7 +738,7 @@
.map(|pvs| pvs.to_string_lossy())
.map(|pvs| {
if pvs.contains(char::is_whitespace) {
- Cow::from(format!("{:?}", pvs))
+ Cow::from(format!("{pvs:?}"))
} else {
pvs
}
@@ -745,7 +746,7 @@
.collect::<Vec<_>>()
.join(" ");
- spec_vals.push(format!("[default: {}]", pvs));
+ spec_vals.push(format!("[default: {pvs}]"));
}
let als = a
@@ -757,7 +758,7 @@
.join(", ");
if !als.is_empty() {
debug!("HelpTemplate::spec_vals: Found aliases...{:?}", a.aliases);
- spec_vals.push(format!("[aliases: {}]", als));
+ spec_vals.push(format!("[aliases: {als}]"));
}
let als = a
@@ -772,7 +773,7 @@
"HelpTemplate::spec_vals: Found short aliases...{:?}",
a.short_aliases
);
- spec_vals.push(format!("[short aliases: {}]", als));
+ spec_vals.push(format!("[short aliases: {als}]"));
}
let possible_vals = a.get_possible_values();
@@ -791,7 +792,7 @@
.collect::<Vec<_>>()
.join(", ");
- spec_vals.push(format!("[possible values: {}]", pvs));
+ spec_vals.push(format!("[possible values: {pvs}]"));
}
let connector = if self.use_long { "\n" } else { " " };
spec_vals.join(connector)
@@ -834,11 +835,11 @@
styled.literal(subcommand.get_name());
if let Some(short) = subcommand.get_short_flag() {
styled.none(", ");
- styled.literal(format!("-{}", short));
+ styled.literal(format!("-{short}"));
}
if let Some(long) = subcommand.get_long_flag() {
styled.none(", ");
- styled.literal(format!("--{}", long));
+ styled.literal(format!("--{long}"));
}
longest = longest.max(styled.display_width());
ord_v.push((subcommand.get_display_order(), styled, subcommand));
@@ -901,7 +902,7 @@
let mut short_als = a
.get_visible_short_flag_aliases()
- .map(|a| format!("-{}", a))
+ .map(|a| format!("-{a}"))
.collect::<Vec<_>>();
let als = a.get_visible_aliases().map(|s| s.to_string());
short_als.extend(als);
@@ -915,7 +916,7 @@
"HelpTemplate::spec_vals: Found short flag aliases...{:?}",
a.get_all_short_flag_aliases().collect::<Vec<_>>()
);
- spec_vals.push(format!("[aliases: {}]", all_als));
+ spec_vals.push(format!("[aliases: {all_als}]"));
}
spec_vals.join(" ")
diff --git a/src/output/textwrap/core.rs b/src/output/textwrap/core.rs
index b890c6c..25c9eb6 100644
--- a/src/output/textwrap/core.rs
+++ b/src/output/textwrap/core.rs
@@ -105,7 +105,7 @@
assert_eq!(ch.width().unwrap(), 1, "char: {}", desc);
#[cfg(not(feature = "unicode"))]
- assert_eq!(ch_width(ch), 1, "char: {}", desc);
+ assert_eq!(ch_width(ch), 1, "char: {desc}");
}
}
@@ -123,7 +123,7 @@
assert!(ch.width().unwrap() <= 2, "char: {}", desc);
#[cfg(not(feature = "unicode"))]
- assert_eq!(ch_width(ch), 1, "char: {}", desc);
+ assert_eq!(ch_width(ch), 1, "char: {desc}");
}
}
diff --git a/src/parser/arg_matcher.rs b/src/parser/arg_matcher.rs
index 93bac7e..d584689 100644
--- a/src/parser/arg_matcher.rs
+++ b/src/parser/arg_matcher.rs
@@ -113,6 +113,10 @@
self.matches.args.keys()
}
+ pub(crate) fn args(&self) -> crate::util::flat_map::Iter<'_, Id, MatchedArg> {
+ self.matches.args.iter()
+ }
+
pub(crate) fn entry(&mut self, arg: Id) -> crate::util::Entry<Id, MatchedArg> {
self.matches.args.entry(arg)
}
@@ -182,7 +186,7 @@
let num_pending = self
.pending
.as_ref()
- .and_then(|p| (p.id == *o.get_id()).then(|| p.raw_vals.len()))
+ .and_then(|p| (p.id == *o.get_id()).then_some(p.raw_vals.len()))
.unwrap_or(0);
debug!(
"ArgMatcher::needs_more_vals: o={}, pending={}",
@@ -213,9 +217,9 @@
raw_vals: Default::default(),
trailing_idx: None,
});
- debug_assert_eq!(pending.id, *id, "{}", INTERNAL_ERROR_MSG);
+ debug_assert_eq!(pending.id, *id, "{INTERNAL_ERROR_MSG}");
if ident.is_some() {
- debug_assert_eq!(pending.ident, ident, "{}", INTERNAL_ERROR_MSG);
+ debug_assert_eq!(pending.ident, ident, "{INTERNAL_ERROR_MSG}");
}
if trailing_values {
pending.trailing_idx.get_or_insert(pending.raw_vals.len());
diff --git a/src/parser/error.rs b/src/parser/error.rs
index 5652336..66b2bc7 100644
--- a/src/parser/error.rs
+++ b/src/parser/error.rs
@@ -27,10 +27,7 @@
}
Err(err) => err,
};
- panic!(
- "Mismatch between definition and access of `{}`. {}",
- id, err
- )
+ panic!("Mismatch between definition and access of `{id}`. {err}",)
}
}
@@ -42,8 +39,7 @@
Self::Downcast { actual, expected } => {
writeln!(
f,
- "Could not downcast to {:?}, need to downcast to {:?}",
- expected, actual
+ "Could not downcast to {expected:?}, need to downcast to {actual:?}"
)
}
Self::UnknownArgument {} => {
diff --git a/src/parser/features/suggestions.rs b/src/parser/features/suggestions.rs
index f0aa502..b8bb7ad 100644
--- a/src/parser/features/suggestions.rs
+++ b/src/parser/features/suggestions.rs
@@ -4,10 +4,9 @@
// Internal
use crate::builder::Command;
-/// Produces multiple strings from a given list of possible values which are similar
-/// to the passed in value `v` within a certain confidence by least confidence.
-/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
-/// `Some("foo")`, whereas "blark" would yield `None`.
+/// Find strings from an iterable of `possible_values` similar to a given value `v`
+/// Returns a Vec of all possible values that exceed a similarity threshold
+/// sorted by ascending similarity, most similar comes last
#[cfg(feature = "suggestions")]
pub(crate) fn did_you_mean<T, I>(v: &str, possible_values: I) -> Vec<String>
where
@@ -16,8 +15,11 @@
{
let mut candidates: Vec<(f64, String)> = possible_values
.into_iter()
- .map(|pv| (strsim::jaro_winkler(v, pv.as_ref()), pv.as_ref().to_owned()))
- .filter(|(confidence, _)| *confidence > 0.8)
+ // GH #4660: using `jaro` because `jaro_winkler` implementation in `strsim-rs` is wrong
+ // causing strings with common prefix >=10 to be considered perfectly similar
+ .map(|pv| (strsim::jaro(v, pv.as_ref()), pv.as_ref().to_owned()))
+ // Confidence of 0.7 so that bar -> baz is suggested
+ .filter(|(confidence, _)| *confidence > 0.7)
.collect();
candidates.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal));
candidates.into_iter().map(|(_, pv)| pv).collect()
@@ -72,34 +74,94 @@
}
}
-#[cfg(all(test, features = "suggestions"))]
+#[cfg(all(test, feature = "suggestions"))]
mod test {
use super::*;
#[test]
- fn possible_values_match() {
+ fn missing_letter() {
let p_vals = ["test", "possible", "values"];
- assert_eq!(did_you_mean("tst", p_vals.iter()), Some("test"));
+ assert_eq!(did_you_mean("tst", p_vals.iter()), vec!["test"]);
}
#[test]
- fn possible_values_match() {
- let p_vals = ["test", "temp"];
- assert_eq!(did_you_mean("te", p_vals.iter()), Some("test"));
+ fn ambiguous() {
+ let p_vals = ["test", "temp", "possible", "values"];
+ assert_eq!(did_you_mean("te", p_vals.iter()), vec!["test", "temp"]);
}
#[test]
- fn possible_values_nomatch() {
- let p_vals = ["test", "possible", "values"];
- assert!(did_you_mean("hahaahahah", p_vals.iter()).is_none());
- }
-
- #[test]
- fn flag() {
+ fn unrelated() {
let p_vals = ["test", "possible", "values"];
assert_eq!(
- did_you_mean_flag("tst", p_vals.iter(), []),
- Some(("test", None))
+ did_you_mean("hahaahahah", p_vals.iter()),
+ Vec::<String>::new()
+ );
+ }
+
+ #[test]
+ fn best_fit() {
+ let p_vals = [
+ "test",
+ "possible",
+ "values",
+ "alignmentStart",
+ "alignmentScore",
+ ];
+ assert_eq!(
+ did_you_mean("alignmentScorr", p_vals.iter()),
+ vec!["alignmentStart", "alignmentScore"]
+ );
+ }
+
+ #[test]
+ fn best_fit_long_common_prefix_issue_4660() {
+ let p_vals = ["alignmentScore", "alignmentStart"];
+ assert_eq!(
+ did_you_mean("alignmentScorr", p_vals.iter()),
+ vec!["alignmentStart", "alignmentScore"]
+ );
+ }
+
+ #[test]
+ fn flag_missing_letter() {
+ let p_vals = ["test", "possible", "values"];
+ assert_eq!(
+ did_you_mean_flag("tst", &[], p_vals.iter(), []),
+ Some(("test".to_owned(), None))
+ );
+ }
+
+ #[test]
+ fn flag_ambiguous() {
+ let p_vals = ["test", "temp", "possible", "values"];
+ assert_eq!(
+ did_you_mean_flag("te", &[], p_vals.iter(), []),
+ Some(("temp".to_owned(), None))
+ );
+ }
+
+ #[test]
+ fn flag_unrelated() {
+ let p_vals = ["test", "possible", "values"];
+ assert_eq!(
+ did_you_mean_flag("hahaahahah", &[], p_vals.iter(), []),
+ None
+ );
+ }
+
+ #[test]
+ fn flag_best_fit() {
+ let p_vals = [
+ "test",
+ "possible",
+ "values",
+ "alignmentStart",
+ "alignmentScore",
+ ];
+ assert_eq!(
+ did_you_mean_flag("alignmentScorr", &[], p_vals.iter(), []),
+ Some(("alignmentScore".to_owned(), None))
);
}
}
diff --git a/src/parser/matches/arg_matches.rs b/src/parser/matches/arg_matches.rs
index 36d2ca9..13ceea3 100644
--- a/src/parser/matches/arg_matches.rs
+++ b/src/parser/matches/arg_matches.rs
@@ -216,6 +216,43 @@
MatchesError::unwrap(id, self.try_get_many(id))
}
+ /// Iterate over the values passed to each occurrence of an option.
+ ///
+ /// Each item is itself an iterator containing the arguments passed to a single occurrence
+ /// of the option.
+ ///
+ /// If the option doesn't support multiple occurrences, or there was only a single occurrence,
+ /// the iterator will only contain a single item.
+ ///
+ /// Returns `None` if the option wasn't present.
+ ///
+ /// # Panics
+ ///
+ /// If the argument definition and access mismatch. To handle this case programmatically, see
+ /// [`ArgMatches::try_get_occurrences`].
+ ///
+ /// # Examples
+ /// ```rust
+ /// # use clap::{Command,Arg, ArgAction, value_parser};
+ /// let m = Command::new("myprog")
+ /// .arg(Arg::new("x")
+ /// .short('x')
+ /// .num_args(2)
+ /// .action(ArgAction::Append)
+ /// .value_parser(value_parser!(String)))
+ /// .get_matches_from(vec![
+ /// "myprog", "-x", "a", "b", "-x", "c", "d"]);
+ /// let vals: Vec<Vec<&String>> = m.get_occurrences("x").unwrap().map(Iterator::collect).collect();
+ /// assert_eq!(vals, [["a", "b"], ["c", "d"]]);
+ /// ```
+ #[cfg_attr(debug_assertions, track_caller)]
+ pub fn get_occurrences<T: Any + Clone + Send + Sync + 'static>(
+ &self,
+ id: &str,
+ ) -> Option<OccurrencesRef<T>> {
+ MatchesError::unwrap(id, self.try_get_occurrences(id))
+ }
+
/// Iterate over the original argument values.
///
/// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they
@@ -262,6 +299,59 @@
MatchesError::unwrap(id, self.try_get_raw(id))
}
+ /// Iterate over the original values for each occurrence of an option.
+ ///
+ /// Similar to [`ArgMatches::get_occurrences`] but returns raw values.
+ ///
+ /// An `OsStr` on Unix-like systems is any series of bytes, regardless of whether or not they
+ /// contain valid UTF-8. Since [`String`]s in Rust are guaranteed to be valid UTF-8, a valid
+ /// filename on a Unix system as an argument value may contain invalid UTF-8.
+ ///
+ /// Returns `None` if the option wasn't present.
+ ///
+ /// # Panic
+ ///
+ /// If the argument definition and access mismatch. To handle this case programmatically, see
+ /// [`ArgMatches::try_get_raw_occurrences`].
+ ///
+ /// # Examples
+ ///
+ #[cfg_attr(not(unix), doc = " ```ignore")]
+ #[cfg_attr(unix, doc = " ```")]
+ /// # use clap::{Command, arg, value_parser, ArgAction, Arg};
+ /// # use std::ffi::{OsStr,OsString};
+ /// # use std::os::unix::ffi::{OsStrExt,OsStringExt};
+ /// use std::path::PathBuf;
+ ///
+ /// let m = Command::new("myprog")
+ /// .arg(Arg::new("x")
+ /// .short('x')
+ /// .num_args(2)
+ /// .action(ArgAction::Append)
+ /// .value_parser(value_parser!(PathBuf)))
+ /// .get_matches_from(vec![OsString::from("myprog"),
+ /// OsString::from("-x"),
+ /// OsString::from("a"), OsString::from("b"),
+ /// OsString::from("-x"),
+ /// OsString::from("c"),
+ /// // "{0xe9}!"
+ /// OsString::from_vec(vec![0xe9, b'!'])]);
+ /// let mut itr = m.get_raw_occurrences("x")
+ /// .expect("`-x`is required")
+ /// .map(Iterator::collect::<Vec<_>>);
+ /// assert_eq!(itr.next(), Some(vec![OsStr::new("a"), OsStr::new("b")]));
+ /// assert_eq!(itr.next(), Some(vec![OsStr::new("c"), OsStr::from_bytes(&[0xe9, b'!'])]));
+ /// assert_eq!(itr.next(), None);
+ /// ```
+ /// [`Iterator`]: std::iter::Iterator
+ /// [`OsStr`]: std::ffi::OsStr
+ /// [values]: OsValues
+ /// [`String`]: std::string::String
+ #[cfg_attr(debug_assertions, track_caller)]
+ pub fn get_raw_occurrences(&self, id: &str) -> Option<RawOccurrences<'_>> {
+ MatchesError::unwrap(id, self.try_get_raw_occurrences(id))
+ }
+
/// Returns the value of a specific option or positional argument.
///
/// i.e. an argument that [takes an additional value][crate::Arg::num_args] at runtime.
@@ -338,6 +428,44 @@
MatchesError::unwrap(id, self.try_remove_many(id))
}
+ /// Return values for each occurrence of an option.
+ ///
+ /// Each item is itself an iterator containing the arguments passed to a single occurrence of
+ /// the option.
+ ///
+ /// If the option doesn't support multiple occurrences, or there was only a single occurrence,
+ /// the iterator will only contain a single item.
+ ///
+ /// Returns `None` if the option wasn't present.
+ ///
+ /// # Panic
+ ///
+ /// If the argument definition and access mismatch. To handle this case programmatically, see
+ /// [`ArgMatches::try_remove_occurrences`].
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use clap::{Command, Arg, value_parser, ArgAction};
+ /// let mut m = Command::new("myprog")
+ /// .arg(Arg::new("x")
+ /// .short('x')
+ /// .num_args(2)
+ /// .action(ArgAction::Append)
+ /// .value_parser(value_parser!(String)))
+ /// .get_matches_from(vec![
+ /// "myprog", "-x", "a", "b", "-x", "c", "d"]);
+ /// let vals: Vec<Vec<String>> = m.remove_occurrences("x").unwrap().map(Iterator::collect).collect();
+ /// assert_eq!(vals, [["a", "b"], ["c", "d"]]);
+ /// ```
+ #[cfg_attr(debug_assertions, track_caller)]
+ pub fn remove_occurrences<T: Any + Clone + Send + Sync + 'static>(
+ &mut self,
+ id: &str,
+ ) -> Option<Occurrences<T>> {
+ MatchesError::unwrap(id, self.try_remove_occurrences(id))
+ }
+
/// Check if values are present for the argument or group id
///
/// *NOTE:* This will always return `true` if [`default_value`] has been set.
@@ -345,7 +473,7 @@
///
/// # Panics
///
- /// If `id` is is not a valid argument or group name. To handle this case programmatically, see
+ /// If `id` is not a valid argument or group name. To handle this case programmatically, see
/// [`ArgMatches::try_contains_id`].
///
/// # Examples
@@ -453,6 +581,11 @@
/// [`Iterator`]: std::iter::Iterator
#[cfg(feature = "unstable-grouped")]
#[cfg_attr(debug_assertions, track_caller)]
+ #[deprecated(
+ since = "4.1.0",
+ note = "Use get_occurrences or remove_occurrences instead"
+ )]
+ #[allow(deprecated)]
pub fn grouped_values_of(&self, id: &str) -> Option<GroupedValues> {
let arg = some!(self.get_arg(id));
let v = GroupedValues {
@@ -466,7 +599,7 @@
///
/// # Panics
///
- /// If `id` is is not a valid argument or group id.
+ /// If `id` is not a valid argument or group id.
///
/// # Examples
///
@@ -512,7 +645,7 @@
///
/// # Panics
///
- /// If `id` is is not a valid argument or group id.
+ /// If `id` is not a valid argument or group id.
///
/// # Examples
///
@@ -655,7 +788,7 @@
///
/// # Panics
///
- /// If `id` is is not a valid argument or group id.
+ /// If `id` is not a valid argument or group id.
///
/// # Examples
///
@@ -852,7 +985,7 @@
///
/// # Panics
///
- /// If `id` is is not a valid subcommand.
+ /// If `id` is not a valid subcommand.
///
/// # Examples
///
@@ -872,7 +1005,7 @@
/// ]);
///
/// // Both parent commands, and child subcommands can have arguments present at the same times
- /// assert!(*app_m.get_one::<bool>("debug").expect("defaulted by clap"));
+ /// assert!(app_m.get_flag("debug"));
///
/// // Get the subcommand's ArgMatches instance
/// if let Some(sub_m) = app_m.subcommand_matches("test") {
@@ -967,12 +1100,29 @@
let values = arg.vals_flatten();
let values = ValuesRef {
// enforced by `try_get_arg_t`
- iter: values.map(|v| v.downcast_ref::<T>().expect(INTERNAL_ERROR_MSG)),
+ iter: values.map(unwrap_downcast_ref),
len,
};
Ok(Some(values))
}
+ /// Non-panicking version of [`ArgMatches::get_occurrences`]
+ pub fn try_get_occurrences<T: Any + Clone + Send + Sync + 'static>(
+ &self,
+ id: &str,
+ ) -> Result<Option<OccurrencesRef<T>>, MatchesError> {
+ let arg = match ok!(self.try_get_arg_t::<T>(id)) {
+ Some(arg) => arg,
+ None => return Ok(None),
+ };
+ let values = arg.vals();
+ Ok(Some(OccurrencesRef {
+ iter: values.map(|g| OccurrenceValuesRef {
+ iter: g.iter().map(unwrap_downcast_ref),
+ }),
+ }))
+ }
+
/// Non-panicking version of [`ArgMatches::get_raw`]
pub fn try_get_raw(&self, id: &str) -> Result<Option<RawValues<'_>>, MatchesError> {
let arg = match ok!(self.try_get_arg(id)) {
@@ -988,6 +1138,24 @@
Ok(Some(values))
}
+ /// Non-panicking version of [`ArgMatches::get_raw_occurrences`]
+ pub fn try_get_raw_occurrences(
+ &self,
+ id: &str,
+ ) -> Result<Option<RawOccurrences<'_>>, MatchesError> {
+ let arg = match ok!(self.try_get_arg(id)) {
+ Some(arg) => arg,
+ None => return Ok(None),
+ };
+ let values = arg.raw_vals();
+ let occurrences = RawOccurrences {
+ iter: values.map(|g| RawOccurrenceValues {
+ iter: g.iter().map(OsString::as_os_str),
+ }),
+ };
+ Ok(Some(occurrences))
+ }
+
/// Non-panicking version of [`ArgMatches::remove_one`]
pub fn try_remove_one<T: Any + Clone + Send + Sync + 'static>(
&mut self,
@@ -997,7 +1165,7 @@
Some(values) => Ok(values
.into_vals_flatten()
// enforced by `try_get_arg_t`
- .map(|v| v.downcast_into::<T>().expect(INTERNAL_ERROR_MSG))
+ .map(unwrap_downcast_into)
.next()),
None => Ok(None),
}
@@ -1016,12 +1184,30 @@
let values = arg.into_vals_flatten();
let values = Values {
// enforced by `try_get_arg_t`
- iter: values.map(|v| v.downcast_into::<T>().expect(INTERNAL_ERROR_MSG)),
+ iter: values.map(unwrap_downcast_into),
len,
};
Ok(Some(values))
}
+ /// Non-panicking version of [`ArgMatches::remove_occurrences`]
+ pub fn try_remove_occurrences<T: Any + Clone + Send + Sync + 'static>(
+ &mut self,
+ id: &str,
+ ) -> Result<Option<Occurrences<T>>, MatchesError> {
+ let arg = match ok!(self.try_remove_arg_t::<T>(id)) {
+ Some(arg) => arg,
+ None => return Ok(None),
+ };
+ let values = arg.into_vals();
+ let occurrences = Occurrences {
+ iter: values.into_iter().map(|g| OccurrenceValues {
+ iter: g.into_iter().map(unwrap_downcast_into),
+ }),
+ };
+ Ok(Some(occurrences))
+ }
+
/// Non-panicking version of [`ArgMatches::contains_id`]
pub fn try_contains_id(&self, id: &str) -> Result<bool, MatchesError> {
ok!(self.verify_arg(id));
@@ -1116,10 +1302,9 @@
if arg == Id::EXTERNAL || self.valid_args.iter().any(|s| *s == arg) {
} else {
panic!(
- "`{:?}` is not an id of an argument or a group.\n\
+ "`{arg:?}` is not an id of an argument or a group.\n\
Make sure you're using the name of the argument itself \
- and not the name of short or long flags.",
- arg
+ and not the name of short or long flags."
);
}
}
@@ -1134,7 +1319,7 @@
{
if name.is_empty() || self.valid_subcommands.iter().any(|s| *s == name) {
} else {
- panic!("`{}` is not a name of a subcommand.", name);
+ panic!("`{name}` is not a name of a subcommand.");
}
}
@@ -1377,14 +1562,15 @@
// commit: be5e1fa3c26e351761b33010ddbdaf5f05dbcc33
// license: MIT - Copyright (c) 2015 The Rust Project Developers
-#[derive(Clone)]
-#[allow(missing_debug_implementations)]
+#[derive(Clone, Debug)]
+#[deprecated(since = "4.1.0", note = "Use Occurrences instead")]
pub struct GroupedValues<'a> {
#[allow(clippy::type_complexity)]
iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> Vec<&str>>,
len: usize,
}
+#[allow(deprecated)]
impl<'a> Iterator for GroupedValues<'a> {
type Item = Vec<&'a str>;
@@ -1396,15 +1582,18 @@
}
}
+#[allow(deprecated)]
impl<'a> DoubleEndedIterator for GroupedValues<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
+#[allow(deprecated)]
impl<'a> ExactSizeIterator for GroupedValues<'a> {}
/// Creates an empty iterator. Used for `unwrap_or_default()`.
+#[allow(deprecated)]
impl<'a> Default for GroupedValues<'a> {
fn default() -> Self {
static EMPTY: [Vec<AnyValue>; 0] = [];
@@ -1415,6 +1604,206 @@
}
}
+#[derive(Clone, Debug)]
+pub struct Occurrences<T> {
+ #[allow(clippy::type_complexity)]
+ iter: Map<std::vec::IntoIter<Vec<AnyValue>>, fn(Vec<AnyValue>) -> OccurrenceValues<T>>,
+}
+
+impl<T> Iterator for Occurrences<T> {
+ type Item = OccurrenceValues<T>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<T> DoubleEndedIterator for Occurrences<T> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+}
+
+impl<T> ExactSizeIterator for Occurrences<T> {}
+
+impl<T> Default for Occurrences<T> {
+ fn default() -> Self {
+ let empty: Vec<Vec<AnyValue>> = Default::default();
+ Occurrences {
+ iter: empty.into_iter().map(|_| unreachable!()),
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct OccurrenceValues<T> {
+ #[allow(clippy::type_complexity)]
+ iter: Map<std::vec::IntoIter<AnyValue>, fn(AnyValue) -> T>,
+}
+
+impl<T> Iterator for OccurrenceValues<T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<T> DoubleEndedIterator for OccurrenceValues<T> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+}
+
+impl<T> ExactSizeIterator for OccurrenceValues<T> {}
+
+#[derive(Clone, Debug)]
+pub struct OccurrencesRef<'a, T> {
+ #[allow(clippy::type_complexity)]
+ iter: Map<Iter<'a, Vec<AnyValue>>, fn(&Vec<AnyValue>) -> OccurrenceValuesRef<'_, T>>,
+}
+
+impl<'a, T> Iterator for OccurrencesRef<'a, T>
+where
+ Self: 'a,
+{
+ type Item = OccurrenceValuesRef<'a, T>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for OccurrencesRef<'a, T>
+where
+ Self: 'a,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+}
+
+impl<'a, T> ExactSizeIterator for OccurrencesRef<'a, T> where Self: 'a {}
+impl<'a, T> Default for OccurrencesRef<'a, T> {
+ fn default() -> Self {
+ static EMPTY: [Vec<AnyValue>; 0] = [];
+ OccurrencesRef {
+ iter: EMPTY[..].iter().map(|_| unreachable!()),
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct OccurrenceValuesRef<'a, T> {
+ #[allow(clippy::type_complexity)]
+ iter: Map<Iter<'a, AnyValue>, fn(&AnyValue) -> &T>,
+}
+
+impl<'a, T> Iterator for OccurrenceValuesRef<'a, T>
+where
+ Self: 'a,
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for OccurrenceValuesRef<'a, T>
+where
+ Self: 'a,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+}
+
+impl<'a, T> ExactSizeIterator for OccurrenceValuesRef<'a, T> where Self: 'a {}
+
+#[derive(Clone, Debug)]
+pub struct RawOccurrences<'a> {
+ #[allow(clippy::type_complexity)]
+ iter: Map<Iter<'a, Vec<OsString>>, fn(&Vec<OsString>) -> RawOccurrenceValues<'_>>,
+}
+
+impl<'a> Iterator for RawOccurrences<'a> {
+ type Item = RawOccurrenceValues<'a>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<'a> DoubleEndedIterator for RawOccurrences<'a> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+}
+
+impl<'a> ExactSizeIterator for RawOccurrences<'a> {}
+
+impl<'a> Default for RawOccurrences<'a> {
+ fn default() -> Self {
+ static EMPTY: [Vec<OsString>; 0] = [];
+ RawOccurrences {
+ iter: EMPTY[..].iter().map(|_| unreachable!()),
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct RawOccurrenceValues<'a> {
+ #[allow(clippy::type_complexity)]
+ iter: Map<Iter<'a, OsString>, fn(&OsString) -> &OsStr>,
+}
+
+impl<'a> Iterator for RawOccurrenceValues<'a>
+where
+ Self: 'a,
+{
+ type Item = &'a OsStr;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<'a> DoubleEndedIterator for RawOccurrenceValues<'a>
+where
+ Self: 'a,
+{
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter.next_back()
+ }
+}
+
+impl<'a> ExactSizeIterator for RawOccurrenceValues<'a> {}
+
/// Iterate over indices for where an argument appeared when parsing, via [`ArgMatches::indices_of`]
///
/// # Examples
@@ -1472,9 +1861,9 @@
}
}
-#[cfg(feature = "unstable-grouped")]
#[cfg_attr(debug_assertions, track_caller)]
#[inline]
+#[cfg(feature = "unstable-grouped")]
fn unwrap_string(value: &AnyValue) -> &str {
match value.downcast_ref::<String>() {
Some(value) => value,
@@ -1484,6 +1873,16 @@
}
}
+#[track_caller]
+fn unwrap_downcast_ref<T: Any + Clone + Send + Sync + 'static>(value: &AnyValue) -> &T {
+ value.downcast_ref().expect(INTERNAL_ERROR_MSG)
+}
+
+#[track_caller]
+fn unwrap_downcast_into<T: Any + Clone + Send + Sync + 'static>(value: AnyValue) -> T {
+ value.downcast_into().expect(INTERNAL_ERROR_MSG)
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/parser/matches/matched_arg.rs b/src/parser/matches/matched_arg.rs
index 6a80625..901990c 100644
--- a/src/parser/matches/matched_arg.rs
+++ b/src/parser/matches/matched_arg.rs
@@ -75,11 +75,14 @@
self.indices.push(index)
}
- #[cfg(feature = "unstable-grouped")]
pub(crate) fn vals(&self) -> Iter<Vec<AnyValue>> {
self.vals.iter()
}
+ pub(crate) fn into_vals(self) -> Vec<Vec<AnyValue>> {
+ self.vals
+ }
+
pub(crate) fn vals_flatten(&self) -> Flatten<Iter<Vec<AnyValue>>> {
self.vals.iter().flatten()
}
@@ -88,6 +91,10 @@
self.vals.into_iter().flatten()
}
+ pub(crate) fn raw_vals(&self) -> Iter<Vec<OsString>> {
+ self.raw_vals.iter()
+ }
+
pub(crate) fn raw_vals_flatten(&self) -> Flatten<Iter<Vec<OsString>>> {
self.raw_vals.iter().flatten()
}
diff --git a/src/parser/parser.rs b/src/parser/parser.rs
index 9b7f9a9..2579034 100644
--- a/src/parser/parser.rs
+++ b/src/parser/parser.rs
@@ -502,33 +502,35 @@
}
}
- let candidates = suggestions::did_you_mean(
- &arg_os.display().to_string(),
- self.cmd.all_subcommand_names(),
- );
- // If the argument looks like a subcommand.
- if !candidates.is_empty() {
- return ClapError::invalid_subcommand(
- self.cmd,
- arg_os.display().to_string(),
- candidates,
- self.cmd
- .get_bin_name()
- .unwrap_or_else(|| self.cmd.get_name())
- .to_owned(),
- Usage::new(self.cmd).create_usage_with_title(&[]),
+ if !(self.cmd.is_args_conflicts_with_subcommands_set() && valid_arg_found) {
+ let candidates = suggestions::did_you_mean(
+ &arg_os.display().to_string(),
+ self.cmd.all_subcommand_names(),
);
- }
+ // If the argument looks like a subcommand.
+ if !candidates.is_empty() {
+ return ClapError::invalid_subcommand(
+ self.cmd,
+ arg_os.display().to_string(),
+ candidates,
+ self.cmd
+ .get_bin_name()
+ .unwrap_or_else(|| self.cmd.get_name())
+ .to_owned(),
+ Usage::new(self.cmd).create_usage_with_title(&[]),
+ );
+ }
- // If the argument must be a subcommand.
- if self.cmd.has_subcommands()
- && (!self.cmd.has_positionals() || self.cmd.is_infer_subcommands_set())
- {
- return ClapError::unrecognized_subcommand(
- self.cmd,
- arg_os.display().to_string(),
- Usage::new(self.cmd).create_usage_with_title(&[]),
- );
+ // If the argument must be a subcommand.
+ if self.cmd.has_subcommands()
+ && (!self.cmd.has_positionals() || self.cmd.is_infer_subcommands_set())
+ {
+ return ClapError::unrecognized_subcommand(
+ self.cmd,
+ arg_os.display().to_string(),
+ Usage::new(self.cmd).create_usage_with_title(&[]),
+ );
+ }
}
let suggested_trailing_arg = !trailing_values
@@ -893,8 +895,7 @@
debug_assert_eq!(
res,
Ok(()),
- "tracking of `flag_subcmd_skip` is off for `{:?}`",
- short_arg
+ "tracking of `flag_subcmd_skip` is off for `{short_arg:?}`"
);
while let Some(c) = short_arg.next_flag() {
let c = match c {
@@ -980,7 +981,7 @@
Ok(ParseResult::FlagSubCommand(name))
} else {
Ok(ParseResult::NoMatchingArg {
- arg: format!("-{}", c),
+ arg: format!("-{c}"),
})
};
}
@@ -1568,7 +1569,7 @@
did_you_mean.is_none() && !trailing_values && self.cmd.has_positionals();
ClapError::unknown_argument(
self.cmd,
- format!("--{}", arg),
+ format!("--{arg}"),
did_you_mean,
suggested_trailing_arg,
Usage::new(self.cmd)
diff --git a/src/parser/validator.rs b/src/parser/validator.rs
index 0d97c2f..49d28a3 100644
--- a/src/parser/validator.rs
+++ b/src/parser/validator.rs
@@ -1,6 +1,6 @@
// Internal
use crate::builder::StyledStr;
-use crate::builder::{Arg, ArgPredicate, Command, PossibleValue};
+use crate::builder::{Arg, ArgGroup, ArgPredicate, Command, PossibleValue};
use crate::error::{Error, Result as ClapResult};
use crate::output::Usage;
use crate::parser::{ArgMatcher, ParseState};
@@ -27,7 +27,7 @@
matcher: &mut ArgMatcher,
) -> ClapResult<()> {
debug!("Validator::validate");
- let mut conflicts = Conflicts::new();
+ let conflicts = Conflicts::with_args(self.cmd, matcher);
let has_subcmd = matcher.subcommand_name().is_some();
if let ParseState::Opt(a) = parse_state {
@@ -54,8 +54,8 @@
if !has_subcmd && self.cmd.is_arg_required_else_help_set() {
let num_user_values = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
.count();
if num_user_values == 0 {
let message = self.cmd.write_help_err(false);
@@ -80,9 +80,9 @@
));
}
- ok!(self.validate_conflicts(matcher, &mut conflicts));
+ ok!(self.validate_conflicts(matcher, &conflicts));
if !(self.cmd.is_subcommand_negates_reqs_set() && has_subcmd) {
- ok!(self.validate_required(matcher, &mut conflicts));
+ ok!(self.validate_required(matcher, &conflicts));
}
Ok(())
@@ -91,19 +91,19 @@
fn validate_conflicts(
&mut self,
matcher: &ArgMatcher,
- conflicts: &mut Conflicts,
+ conflicts: &Conflicts,
) -> ClapResult<()> {
debug!("Validator::validate_conflicts");
ok!(self.validate_exclusive(matcher));
- for arg_id in matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
- .filter(|arg_id| self.cmd.find(arg_id).is_some())
+ for (arg_id, _) in matcher
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
+ .filter(|(arg_id, _)| self.cmd.find(arg_id).is_some())
{
debug!("Validator::validate_conflicts::iter: id={:?}", arg_id);
- let conflicts = conflicts.gather_conflicts(self.cmd, matcher, arg_id);
+ let conflicts = conflicts.gather_conflicts(self.cmd, arg_id);
ok!(self.build_conflict_err(arg_id, &conflicts, matcher));
}
@@ -113,9 +113,9 @@
fn validate_exclusive(&self, matcher: &ArgMatcher) -> ClapResult<()> {
debug!("Validator::validate_exclusive");
let args_count = matcher
- .arg_ids()
- .filter(|arg_id| {
- matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
+ .args()
+ .filter(|(arg_id, matched)| {
+ matched.check_explicit(&crate::builder::ArgPredicate::IsPresent)
// Avoid including our own groups by checking none of them. If a group is present, the
// args for the group will be.
&& self.cmd.find(arg_id).is_some()
@@ -127,14 +127,12 @@
}
matcher
- .arg_ids()
- .filter(|arg_id| {
- matcher.check_explicit(arg_id, &crate::builder::ArgPredicate::IsPresent)
- })
- .filter_map(|name| {
- debug!("Validator::validate_exclusive:iter:{:?}", name);
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&crate::builder::ArgPredicate::IsPresent))
+ .filter_map(|(id, _)| {
+ debug!("Validator::validate_exclusive:iter:{:?}", id);
self.cmd
- .find(name)
+ .find(id)
// Find `arg`s which are exclusive but also appear with other args.
.filter(|&arg| arg.is_exclusive_set() && args_count > 1)
})
@@ -196,8 +194,9 @@
conflicting_keys: &[Id],
) -> Option<StyledStr> {
let used_filtered: Vec<Id> = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
+ .map(|(n, _)| n)
.filter(|n| {
// Filter out the args we don't want to specify.
self.cmd.find(n).map_or(false, |a| !a.is_hide_set())
@@ -220,14 +219,14 @@
fn gather_requires(&mut self, matcher: &ArgMatcher) {
debug!("Validator::gather_requires");
- for name in matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
+ for (name, matched) in matcher
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
{
debug!("Validator::gather_requires:iter:{:?}", name);
if let Some(arg) = self.cmd.find(name) {
let is_relevant = |(val, req_arg): &(ArgPredicate, Id)| -> Option<Id> {
- let required = matcher.check_explicit(arg.get_id(), val);
+ let required = matched.check_explicit(val);
required.then(|| req_arg.clone())
};
@@ -243,11 +242,7 @@
}
}
- fn validate_required(
- &mut self,
- matcher: &ArgMatcher,
- conflicts: &mut Conflicts,
- ) -> ClapResult<()> {
+ fn validate_required(&mut self, matcher: &ArgMatcher, conflicts: &Conflicts) -> ClapResult<()> {
debug!("Validator::validate_required: required={:?}", self.required);
self.gather_requires(matcher);
@@ -255,9 +250,9 @@
let mut highest_index = 0;
let is_exclusive_present = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
- .any(|id| {
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
+ .any(|(id, _)| {
self.cmd
.find(id)
.map(|arg| arg.is_exclusive_set())
@@ -276,7 +271,7 @@
debug!("Validator::validate_required:iter:aog={:?}", arg_or_group);
if let Some(arg) = self.cmd.find(arg_or_group) {
debug!("Validator::validate_required:iter: This is an arg");
- if !is_exclusive_present && !self.is_missing_required_ok(arg, matcher, conflicts) {
+ if !is_exclusive_present && !self.is_missing_required_ok(arg, conflicts) {
debug!(
"Validator::validate_required:iter: Missing {:?}",
arg.get_id()
@@ -374,15 +369,19 @@
Ok(())
}
- fn is_missing_required_ok(
- &self,
- a: &Arg,
- matcher: &ArgMatcher,
- conflicts: &mut Conflicts,
- ) -> bool {
+ fn is_missing_required_ok(&self, a: &Arg, conflicts: &Conflicts) -> bool {
debug!("Validator::is_missing_required_ok: {}", a.get_id());
- let conflicts = conflicts.gather_conflicts(self.cmd, matcher, a.get_id());
- !conflicts.is_empty()
+ if !conflicts.gather_conflicts(self.cmd, a.get_id()).is_empty() {
+ debug!("Validator::is_missing_required_ok: true (self)");
+ return true;
+ }
+ for group_id in self.cmd.groups_for_arg(a.get_id()) {
+ if !conflicts.gather_conflicts(self.cmd, &group_id).is_empty() {
+ debug!("Validator::is_missing_required_ok: true ({})", group_id);
+ return true;
+ }
+ }
+ false
}
// Failing a required unless means, the arg's "unless" wasn't present, and neither were they
@@ -441,8 +440,9 @@
);
let used: Vec<Id> = matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
+ .map(|(n, _)| n)
.filter(|n| {
// Filter out the args we don't want to specify.
self.cmd.find(n).map_or(false, |a| !a.is_hide_set())
@@ -465,73 +465,91 @@
}
impl Conflicts {
- fn new() -> Self {
- Self::default()
+ fn with_args(cmd: &Command, matcher: &ArgMatcher) -> Self {
+ let mut potential = FlatMap::new();
+ potential.extend_unchecked(
+ matcher
+ .args()
+ .filter(|(_, matched)| matched.check_explicit(&ArgPredicate::IsPresent))
+ .map(|(id, _)| {
+ let conf = gather_direct_conflicts(cmd, id);
+ (id.clone(), conf)
+ }),
+ );
+ Self { potential }
}
- fn gather_conflicts(&mut self, cmd: &Command, matcher: &ArgMatcher, arg_id: &Id) -> Vec<Id> {
+ fn gather_conflicts(&self, cmd: &Command, arg_id: &Id) -> Vec<Id> {
debug!("Conflicts::gather_conflicts: arg={:?}", arg_id);
let mut conflicts = Vec::new();
- for other_arg_id in matcher
- .arg_ids()
- .filter(|arg_id| matcher.check_explicit(arg_id, &ArgPredicate::IsPresent))
- {
+
+ let arg_id_conflicts_storage;
+ let arg_id_conflicts = if let Some(arg_id_conflicts) = self.get_direct_conflicts(arg_id) {
+ arg_id_conflicts
+ } else {
+ // `is_missing_required_ok` is a case where we check not-present args for conflicts
+ arg_id_conflicts_storage = gather_direct_conflicts(cmd, arg_id);
+ &arg_id_conflicts_storage
+ };
+ for (other_arg_id, other_arg_id_conflicts) in self.potential.iter() {
if arg_id == other_arg_id {
continue;
}
- if self
- .gather_direct_conflicts(cmd, arg_id)
- .contains(other_arg_id)
- {
+ if arg_id_conflicts.contains(other_arg_id) {
conflicts.push(other_arg_id.clone());
}
- if self
- .gather_direct_conflicts(cmd, other_arg_id)
- .contains(arg_id)
- {
+ if other_arg_id_conflicts.contains(arg_id) {
conflicts.push(other_arg_id.clone());
}
}
+
debug!("Conflicts::gather_conflicts: conflicts={:?}", conflicts);
conflicts
}
- fn gather_direct_conflicts(&mut self, cmd: &Command, arg_id: &Id) -> &[Id] {
- self.potential.entry(arg_id.clone()).or_insert_with(|| {
- let conf = if let Some(arg) = cmd.find(arg_id) {
- let mut conf = arg.blacklist.clone();
- for group_id in cmd.groups_for_arg(arg_id) {
- let group = cmd.find_group(&group_id).expect(INTERNAL_ERROR_MSG);
- conf.extend(group.conflicts.iter().cloned());
- if !group.multiple {
- for member_id in &group.args {
- if member_id != arg_id {
- conf.push(member_id.clone());
- }
- }
- }
- }
-
- // Overrides are implicitly conflicts
- conf.extend(arg.overrides.iter().cloned());
-
- conf
- } else if let Some(group) = cmd.find_group(arg_id) {
- group.conflicts.clone()
- } else {
- debug_assert!(false, "id={:?} is unknown", arg_id);
- Vec::new()
- };
- debug!(
- "Conflicts::gather_direct_conflicts id={:?}, conflicts={:?}",
- arg_id, conf
- );
- conf
- })
+ fn get_direct_conflicts(&self, arg_id: &Id) -> Option<&[Id]> {
+ self.potential.get(arg_id).map(Vec::as_slice)
}
}
+fn gather_direct_conflicts(cmd: &Command, id: &Id) -> Vec<Id> {
+ let conf = if let Some(arg) = cmd.find(id) {
+ gather_arg_direct_conflicts(cmd, arg)
+ } else if let Some(group) = cmd.find_group(id) {
+ gather_group_direct_conflicts(group)
+ } else {
+ debug_assert!(false, "id={id:?} is unknown");
+ Vec::new()
+ };
+ debug!("Conflicts::gather_direct_conflicts id={id:?}, conflicts={conf:?}",);
+ conf
+}
+
+fn gather_arg_direct_conflicts(cmd: &Command, arg: &Arg) -> Vec<Id> {
+ let mut conf = arg.blacklist.clone();
+ for group_id in cmd.groups_for_arg(arg.get_id()) {
+ let group = cmd.find_group(&group_id).expect(INTERNAL_ERROR_MSG);
+ conf.extend(group.conflicts.iter().cloned());
+ if !group.multiple {
+ for member_id in &group.args {
+ if member_id != arg.get_id() {
+ conf.push(member_id.clone());
+ }
+ }
+ }
+ }
+
+ // Overrides are implicitly conflicts
+ conf.extend(arg.overrides.iter().cloned());
+
+ conf
+}
+
+fn gather_group_direct_conflicts(group: &ArgGroup) -> Vec<Id> {
+ group.conflicts.clone()
+}
+
pub(crate) fn get_possible_values_cli(a: &Arg) -> Vec<PossibleValue> {
if !a.is_takes_value_set() {
vec![]
diff --git a/src/util/color.rs b/src/util/color.rs
index 7c7468e..5a0a8ce 100644
--- a/src/util/color.rs
+++ b/src/util/color.rs
@@ -82,7 +82,7 @@
return Ok(*variant);
}
}
- Err(format!("Invalid variant: {}", s))
+ Err(format!("invalid variant: {s}"))
}
}
diff --git a/src/util/flat_map.rs b/src/util/flat_map.rs
index 7d689ab..468f0a9 100644
--- a/src/util/flat_map.rs
+++ b/src/util/flat_map.rs
@@ -69,7 +69,7 @@
.keys
.iter()
.enumerate()
- .find_map(|(i, k)| (k.borrow() == key).then(|| i)));
+ .find_map(|(i, k)| (k.borrow() == key).then_some(i)));
let key = self.keys.remove(index);
let value = self.values.remove(index);
Some((key, value))
diff --git a/src/util/mod.rs b/src/util/mod.rs
index ed38fbc..e6a8f70 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -1,7 +1,7 @@
#![allow(clippy::single_component_path_imports)]
-mod flat_map;
-mod flat_set;
+pub(crate) mod flat_map;
+pub(crate) mod flat_set;
mod graph;
mod id;
mod str_to_bool;