Initial vendor packages

Signed-off-by: Valentin Popov <valentin@popov.link>
This commit is contained in:
2024-01-08 01:21:28 +04:00
parent 5ecd8cf2cb
commit 1b6a04ca55
7309 changed files with 2160054 additions and 0 deletions

16
vendor/clap/examples/README.md vendored Normal file
View File

@ -0,0 +1,16 @@
# Examples
We try to focus our documentation on the [four types of
documentation](https://documentation.divio.com/). Examples fit into this by
providing:
- [Cookbook / How-To Guides](https://docs.rs/clap/latest/clap/_cookbook/index.html)
- Tutorials ([derive](https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html), [builder](https://docs.rs/clap/latest/clap/_tutorial/index.html))
This directory contains the source for the above.
## Contributing
New examples should fit within the above structure and support their narrative
- Add the example to [Cargo.toml](../Cargo.toml) for any `required-features`
- Document how the example works with a `.md` file which will be verified using [trycmd](https://docs.rs/trycmd)
- Pull the `.rs` and `.md` file into the appropriate module doc comment to be accessible on docs.rs

View File

@ -0,0 +1,38 @@
For more on creating a custom subcommand, see [the cargo
book](https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands).
The crate [`clap-cargo`](https://github.com/crate-ci/clap-cargo) can help in
mimicking cargo's interface.
The help looks like:
```console
$ cargo-example-derive --help
Usage: cargo <COMMAND>
Commands:
example-derive A simple to use, efficient, and full-featured Command Line Argument Parser
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
$ cargo-example-derive example-derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: cargo example-derive [OPTIONS]
Options:
--manifest-path <MANIFEST_PATH>
-h, --help Print help
-V, --version Print version
```
Then to directly invoke the command, run:
```console
$ cargo-example-derive example-derive
None
$ cargo-example-derive example-derive --manifest-path Cargo.toml
Some("Cargo.toml")
```

View File

@ -0,0 +1,20 @@
use clap::Parser;
#[derive(Parser)] // requires `derive` feature
#[command(name = "cargo")]
#[command(bin_name = "cargo")]
enum CargoCli {
ExampleDerive(ExampleDeriveArgs),
}
#[derive(clap::Args)]
#[command(author, version, about, long_about = None)]
struct ExampleDeriveArgs {
#[arg(long)]
manifest_path: Option<std::path::PathBuf>,
}
fn main() {
let CargoCli::ExampleDerive(args) = CargoCli::parse();
println!("{:?}", args.manifest_path);
}

38
vendor/clap/examples/cargo-example.md vendored Normal file
View File

@ -0,0 +1,38 @@
For more on creating a custom subcommand, see [the cargo
book](https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands).
The crate [`clap-cargo`](https://github.com/crate-ci/clap-cargo) can help in
mimicking cargo's interface.
The help looks like:
```console
$ cargo-example --help
Usage: cargo <COMMAND>
Commands:
example A simple to use, efficient, and full-featured Command Line Argument Parser
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
$ cargo-example example --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: cargo example [OPTIONS]
Options:
--manifest-path <PATH>
-h, --help Print help
-V, --version Print version
```
Then to directly invoke the command, run:
```console
$ cargo-example example
None
$ cargo-example example --manifest-path Cargo.toml
Some("Cargo.toml")
```

18
vendor/clap/examples/cargo-example.rs vendored Normal file
View File

@ -0,0 +1,18 @@
fn main() {
let cmd = clap::Command::new("cargo")
.bin_name("cargo")
.subcommand_required(true)
.subcommand(
clap::command!("example").arg(
clap::arg!(--"manifest-path" <PATH>)
.value_parser(clap::value_parser!(std::path::PathBuf)),
),
);
let matches = cmd.get_matches();
let matches = match matches.subcommand() {
Some(("example", matches)) => matches,
_ => unreachable!("clap should ensure we don't get here"),
};
let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
println!("{manifest_path:?}");
}

17
vendor/clap/examples/demo.md vendored Normal file
View File

@ -0,0 +1,17 @@
```console
$ demo --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: demo[EXE] [OPTIONS] --name <NAME>
Options:
-n, --name <NAME> Name of the person to greet
-c, --count <COUNT> Number of times to greet [default: 1]
-h, --help Print help
-V, --version Print version
$ demo --name Me
Hello Me!
```
*(version number and `.exe` extension on windows replaced by placeholders)*

22
vendor/clap/examples/demo.rs vendored Normal file
View File

@ -0,0 +1,22 @@
use clap::Parser;
/// Simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Name of the person to greet
#[arg(short, long)]
name: String,
/// Number of times to greet
#[arg(short, long, default_value_t = 1)]
count: u8,
}
fn main() {
let args = Args::parse();
for _ in 0..args.count {
println!("Hello {}!", args.name)
}
}

View File

@ -0,0 +1,27 @@
use clap::{arg, Args, Command, FromArgMatches as _};
#[derive(Args, Debug)]
struct DerivedArgs {
#[arg(short, long)]
derived: bool,
}
fn main() {
let cli = Command::new("CLI").arg(arg!(-b - -built).action(clap::ArgAction::SetTrue));
// Augment built args with derived args
let cli = DerivedArgs::augment_args(cli);
let matches = cli.get_matches();
println!("Value of built: {:?}", matches.get_flag("built"));
println!(
"Value of derived via ArgMatches: {:?}",
matches.get_flag("derived")
);
// Since DerivedArgs implements FromArgMatches, we can extract it from the unstructured ArgMatches.
// This is the main benefit of using derived arguments.
let derived_matches = DerivedArgs::from_arg_matches(&matches)
.map_err(|err| err.exit())
.unwrap();
println!("Value of derived: {derived_matches:#?}");
}

View File

@ -0,0 +1,21 @@
use clap::{Command, FromArgMatches as _, Parser, Subcommand as _};
#[derive(Parser, Debug)]
enum Subcommands {
Derived {
#[arg(short, long)]
derived_flag: bool,
},
}
fn main() {
let cli = Command::new("Built CLI");
// Augment with derived subcommands
let cli = Subcommands::augment_subcommands(cli);
let matches = cli.get_matches();
let derived_subcommands = Subcommands::from_arg_matches(&matches)
.map_err(|err| err.exit())
.unwrap();
println!("Derived subcommands: {derived_subcommands:#?}");
}

View File

@ -0,0 +1,91 @@
use clap::error::Error;
use clap::{Arg, ArgAction, ArgMatches, Args, Command, FromArgMatches, Parser};
#[derive(Debug)]
struct CliArgs {
foo: bool,
bar: bool,
quuz: Option<String>,
}
impl FromArgMatches for CliArgs {
fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
let mut matches = matches.clone();
Self::from_arg_matches_mut(&mut matches)
}
fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
Ok(Self {
foo: matches.get_flag("foo"),
bar: matches.get_flag("bar"),
quuz: matches.remove_one::<String>("quuz"),
})
}
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
let mut matches = matches.clone();
self.update_from_arg_matches_mut(&mut matches)
}
fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
self.foo |= matches.get_flag("foo");
self.bar |= matches.get_flag("bar");
if let Some(quuz) = matches.remove_one::<String>("quuz") {
self.quuz = Some(quuz);
}
Ok(())
}
}
impl Args for CliArgs {
fn augment_args(cmd: Command) -> Command {
cmd.arg(
Arg::new("foo")
.short('f')
.long("foo")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("bar")
.short('b')
.long("bar")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("quuz")
.short('q')
.long("quuz")
.action(ArgAction::Set),
)
}
fn augment_args_for_update(cmd: Command) -> Command {
cmd.arg(
Arg::new("foo")
.short('f')
.long("foo")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("bar")
.short('b')
.long("bar")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("quuz")
.short('q')
.long("quuz")
.action(ArgAction::Set),
)
}
}
#[derive(Parser, Debug)]
struct Cli {
#[arg(short, long)]
top_level: bool,
#[command(flatten)]
more_args: CliArgs,
}
fn main() {
let args = Cli::parse();
println!("{args:#?}");
}

View File

@ -0,0 +1,79 @@
use clap::error::{Error, ErrorKind};
use clap::{ArgMatches, Args as _, Command, FromArgMatches, Parser, Subcommand};
#[derive(Parser, Debug)]
struct AddArgs {
name: Vec<String>,
}
#[derive(Parser, Debug)]
struct RemoveArgs {
#[arg(short, long)]
force: bool,
name: Vec<String>,
}
#[derive(Debug)]
enum CliSub {
Add(AddArgs),
Remove(RemoveArgs),
}
impl FromArgMatches for CliSub {
fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
match matches.subcommand() {
Some(("add", args)) => Ok(Self::Add(AddArgs::from_arg_matches(args)?)),
Some(("remove", args)) => Ok(Self::Remove(RemoveArgs::from_arg_matches(args)?)),
Some((_, _)) => Err(Error::raw(
ErrorKind::InvalidSubcommand,
"Valid subcommands are `add` and `remove`",
)),
None => Err(Error::raw(
ErrorKind::MissingSubcommand,
"Valid subcommands are `add` and `remove`",
)),
}
}
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
match matches.subcommand() {
Some(("add", args)) => *self = Self::Add(AddArgs::from_arg_matches(args)?),
Some(("remove", args)) => *self = Self::Remove(RemoveArgs::from_arg_matches(args)?),
Some((_, _)) => {
return Err(Error::raw(
ErrorKind::InvalidSubcommand,
"Valid subcommands are `add` and `remove`",
))
}
None => (),
};
Ok(())
}
}
impl Subcommand for CliSub {
fn augment_subcommands(cmd: Command) -> Command {
cmd.subcommand(AddArgs::augment_args(Command::new("add")))
.subcommand(RemoveArgs::augment_args(Command::new("remove")))
.subcommand_required(true)
}
fn augment_subcommands_for_update(cmd: Command) -> Command {
cmd.subcommand(AddArgs::augment_args(Command::new("add")))
.subcommand(RemoveArgs::augment_args(Command::new("remove")))
.subcommand_required(true)
}
fn has_subcommand(name: &str) -> bool {
matches!(name, "add" | "remove")
}
}
#[derive(Parser, Debug)]
struct Cli {
#[arg(short, long)]
top_level: bool,
#[command(subcommand)]
subcommand: CliSub,
}
fn main() {
let args = Cli::parse();
println!("{args:#?}");
}

View File

@ -0,0 +1,248 @@
Following are tests for the interop examples in this directory.
## Augment Args
```console
$ interop_augment_args
Value of built: false
Value of derived via ArgMatches: false
Value of derived: DerivedArgs {
derived: false,
}
```
```console
$ interop_augment_args -b --derived
Value of built: true
Value of derived via ArgMatches: true
Value of derived: DerivedArgs {
derived: true,
}
```
```console
$ interop_augment_args -d --built
Value of built: true
Value of derived via ArgMatches: true
Value of derived: DerivedArgs {
derived: true,
}
```
```console
$ interop_augment_args --unknown
? failed
error: unexpected argument '--unknown' found
Usage: interop_augment_args[EXE] [OPTIONS]
For more information, try '--help'.
```
## Augment Subcommands
```console
$ interop_augment_subcommands
? failed
error: A subcommand is required but one was not provided.
```
```console
$ interop_augment_subcommands derived
Derived subcommands: Derived {
derived_flag: false,
}
```
```console
$ interop_augment_subcommands derived --derived-flag
Derived subcommands: Derived {
derived_flag: true,
}
```
```console
$ interop_augment_subcommands derived --unknown
? failed
error: unexpected argument '--unknown' found
Usage: interop_augment_subcommands[EXE] derived [OPTIONS]
For more information, try '--help'.
```
```console
$ interop_augment_subcommands unknown
? failed
error: unrecognized subcommand 'unknown'
Usage: interop_augment_subcommands[EXE] [COMMAND]
For more information, try '--help'.
```
## Hand-Implemented Subcommand
```console
$ interop_hand_subcommand
? failed
Usage: interop_hand_subcommand[EXE] [OPTIONS] <COMMAND>
Commands:
add
remove
help Print this message or the help of the given subcommand(s)
Options:
-t, --top-level
-h, --help Print help
```
```console
$ interop_hand_subcommand add
Cli {
top_level: false,
subcommand: Add(
AddArgs {
name: [],
},
),
}
```
```console
$ interop_hand_subcommand add a b c
Cli {
top_level: false,
subcommand: Add(
AddArgs {
name: [
"a",
"b",
"c",
],
},
),
}
```
```console
$ interop_hand_subcommand add --unknown
? failed
error: unexpected argument '--unknown' found
tip: to pass '--unknown' as a value, use '-- --unknown'
Usage: interop_hand_subcommand[EXE] add [NAME]...
For more information, try '--help'.
```
```console
$ interop_hand_subcommand remove
Cli {
top_level: false,
subcommand: Remove(
RemoveArgs {
force: false,
name: [],
},
),
}
```
```console
$ interop_hand_subcommand remove --force a b c
Cli {
top_level: false,
subcommand: Remove(
RemoveArgs {
force: true,
name: [
"a",
"b",
"c",
],
},
),
}
```
```console
$ interop_hand_subcommand unknown
? failed
error: unrecognized subcommand 'unknown'
Usage: interop_hand_subcommand[EXE] [OPTIONS] <COMMAND>
For more information, try '--help'.
```
## Flatten Hand-Implemented Args
```console
$ interop_flatten_hand_args
Cli {
top_level: false,
more_args: CliArgs {
foo: false,
bar: false,
quuz: None,
},
}
```
```console
$ interop_flatten_hand_args -f --bar
Cli {
top_level: false,
more_args: CliArgs {
foo: true,
bar: true,
quuz: None,
},
}
```
```console
$ interop_flatten_hand_args --quuz abc
Cli {
top_level: false,
more_args: CliArgs {
foo: false,
bar: false,
quuz: Some(
"abc",
),
},
}
```
```console
$ interop_flatten_hand_args --unknown
? failed
error: unexpected argument '--unknown' found
Usage: interop_flatten_hand_args[EXE] [OPTIONS]
For more information, try '--help'.
```

View File

@ -0,0 +1,60 @@
**This requires enabling the [`derive` feature flag][crate::_features].**
You can use `--` to escape further arguments.
Let's see what this looks like in the help:
```console
$ escaped-positional-derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: escaped-positional-derive[EXE] [OPTIONS] [-- <SLOP>...]
Arguments:
[SLOP]...
Options:
-f
-p <PEAR>
-h, --help Print help
-V, --version Print version
```
Here is a baseline without any arguments:
```console
$ escaped-positional-derive
-f used: false
-p's value: None
'slops' values: []
```
Notice that we can't pass positional arguments before `--`:
```console
$ escaped-positional-derive foo bar
? failed
error: unexpected argument 'foo' found
Usage: escaped-positional-derive[EXE] [OPTIONS] [-- <SLOP>...]
For more information, try '--help'.
```
But you can after:
```console
$ escaped-positional-derive -f -p=bob -- sloppy slop slop
-f used: true
-p's value: Some("bob")
'slops' values: ["sloppy", "slop", "slop"]
```
As mentioned, the parser will directly pass everything through:
```console
$ escaped-positional-derive -- -f -p=bob sloppy slop slop
-f used: false
-p's value: None
'slops' values: ["-f", "-p=bob", "sloppy", "slop", "slop"]
```

View File

@ -0,0 +1,25 @@
use clap::Parser;
#[derive(Parser)] // requires `derive` feature
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(short = 'f')]
eff: bool,
#[arg(short = 'p', value_name = "PEAR")]
pea: Option<String>,
#[arg(last = true)]
slop: Vec<String>,
}
fn main() {
let args = Cli::parse();
// This is what will happen with `myprog -f -p=bob -- sloppy slop slop`...
println!("-f used: {:?}", args.eff); // -f used: true
println!("-p's value: {:?}", args.pea); // -p's value: Some("bob")
println!("'slops' values: {:?}", args.slop); // 'slops' values: Some(["sloppy", "slop", "slop"])
// Continued program logic goes here...
}

View File

@ -0,0 +1,60 @@
**This requires enabling the [`cargo` feature flag][crate::_features].**
You can use `--` to escape further arguments.
Let's see what this looks like in the help:
```console
$ escaped-positional --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: escaped-positional[EXE] [OPTIONS] [-- <SLOP>...]
Arguments:
[SLOP]...
Options:
-f
-p <PEAR>
-h, --help Print help
-V, --version Print version
```
Here is a baseline without any arguments:
```console
$ escaped-positional
-f used: false
-p's value: None
'slops' values: []
```
Notice that we can't pass positional arguments before `--`:
```console
$ escaped-positional foo bar
? failed
error: unexpected argument 'foo' found
Usage: escaped-positional[EXE] [OPTIONS] [-- <SLOP>...]
For more information, try '--help'.
```
But you can after:
```console
$ escaped-positional -f -p=bob -- sloppy slop slop
-f used: true
-p's value: Some("bob")
'slops' values: ["sloppy", "slop", "slop"]
```
As mentioned, the parser will directly pass everything through:
```console
$ escaped-positional -- -f -p=bob sloppy slop slop
-f used: false
-p's value: None
'slops' values: ["-f", "-p=bob", "sloppy", "slop", "slop"]
```

View File

@ -0,0 +1,32 @@
use clap::{arg, command, value_parser, ArgAction};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(arg!(eff: -f).action(ArgAction::SetTrue))
.arg(arg!(pea: -p <PEAR>).value_parser(value_parser!(String)))
.arg(
// Indicates that `slop` is only accessible after `--`.
arg!(slop: [SLOP])
.num_args(1..)
.last(true)
.value_parser(value_parser!(String)),
)
.get_matches();
// This is what will happen with `myprog -f -p=bob -- sloppy slop slop`...
// -f used: true
println!("-f used: {:?}", matches.get_flag("eff"));
// -p's value: Some("bob")
println!("-p's value: {:?}", matches.get_one::<String>("pea"));
// 'slops' values: Some(["sloppy", "slop", "slop"])
println!(
"'slops' values: {:?}",
matches
.get_many::<String>("slop")
.map(|vals| vals.collect::<Vec<_>>())
.unwrap_or_default()
);
// Continued program logic goes here...
}

45
vendor/clap/examples/find.md vendored Normal file
View File

@ -0,0 +1,45 @@
`find` is an example of position-sensitive flags
```console
$ find --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: find[EXE] [OPTIONS]
Options:
-h, --help Print help
-V, --version Print version
TESTS:
--empty File is empty and is either a regular file or a directory
--name <NAME> Base of file name (the path with the leading directories removed) matches shell
pattern pattern
OPERATORS:
-o, --or expr2 is not evaluate if exp1 is true
-a, --and Same as `expr1 expr1`
$ find --empty -o --name .keep
[
(
"empty",
Bool(
true,
),
),
(
"or",
Bool(
true,
),
),
(
"name",
String(
".keep",
),
),
]
```

99
vendor/clap/examples/find.rs vendored Normal file
View File

@ -0,0 +1,99 @@
use std::collections::BTreeMap;
use clap::{arg, command, ArgGroup, ArgMatches, Command};
fn main() {
let matches = cli().get_matches();
let values = Value::from_matches(&matches);
println!("{values:#?}");
}
fn cli() -> Command {
command!()
.group(ArgGroup::new("tests").multiple(true))
.next_help_heading("TESTS")
.args([
arg!(--empty "File is empty and is either a regular file or a directory").group("tests"),
arg!(--name <NAME> "Base of file name (the path with the leading directories removed) matches shell pattern pattern").group("tests"),
])
.group(ArgGroup::new("operators").multiple(true))
.next_help_heading("OPERATORS")
.args([
arg!(-o - -or "expr2 is not evaluate if exp1 is true").group("operators"),
arg!(-a - -and "Same as `expr1 expr1`").group("operators"),
])
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub enum Value {
Bool(bool),
String(String),
}
impl Value {
pub fn from_matches(matches: &ArgMatches) -> Vec<(clap::Id, Self)> {
let mut values = BTreeMap::new();
for id in matches.ids() {
if matches.try_get_many::<clap::Id>(id.as_str()).is_ok() {
// ignore groups
continue;
}
let value_source = matches
.value_source(id.as_str())
.expect("id came from matches");
if value_source != clap::parser::ValueSource::CommandLine {
// Any other source just gets tacked on at the end (like default values)
continue;
}
if Self::extract::<String>(matches, id, &mut values) {
continue;
}
if Self::extract::<bool>(matches, id, &mut values) {
continue;
}
unimplemented!("unknown type for {id}: {matches:?}");
}
values.into_values().collect::<Vec<_>>()
}
fn extract<T: Clone + Into<Value> + Send + Sync + 'static>(
matches: &ArgMatches,
id: &clap::Id,
output: &mut BTreeMap<usize, (clap::Id, Self)>,
) -> bool {
match matches.try_get_many::<T>(id.as_str()) {
Ok(Some(values)) => {
for (value, index) in values.zip(
matches
.indices_of(id.as_str())
.expect("id came from matches"),
) {
output.insert(index, (id.clone(), value.clone().into()));
}
true
}
Ok(None) => {
unreachable!("`ids` only reports what is present")
}
Err(clap::parser::MatchesError::UnknownArgument { .. }) => {
unreachable!("id came from matches")
}
Err(clap::parser::MatchesError::Downcast { .. }) => false,
Err(_) => {
unreachable!("id came from matches")
}
}
}
}
impl From<String> for Value {
fn from(other: String) -> Self {
Self::String(other)
}
}
impl From<bool> for Value {
fn from(other: bool) -> Self {
Self::Bool(other)
}
}

172
vendor/clap/examples/git-derive.md vendored Normal file
View File

@ -0,0 +1,172 @@
**This requires enabling the [`derive` feature flag][crate::_features].**
Git is an example of several common subcommand patterns.
Help:
```console
$ git-derive
? failed
A fictional versioning CLI
Usage: git-derive[EXE] <COMMAND>
Commands:
clone Clones repos
diff Compare two commits
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
$ git-derive help
A fictional versioning CLI
Usage: git-derive[EXE] <COMMAND>
Commands:
clone Clones repos
diff Compare two commits
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
$ git-derive help add
adds things
Usage: git-derive[EXE] add <PATH>...
Arguments:
<PATH>... Stuff to add
Options:
-h, --help Print help
```
A basic argument:
```console
$ git-derive add
? failed
adds things
Usage: git-derive[EXE] add <PATH>...
Arguments:
<PATH>... Stuff to add
Options:
-h, --help Print help
$ git-derive add Cargo.toml Cargo.lock
Adding ["Cargo.toml", "Cargo.lock"]
```
Default subcommand:
```console
$ git-derive stash -h
Usage: git-derive[EXE] stash [OPTIONS]
git-derive[EXE] stash push [OPTIONS]
git-derive[EXE] stash pop [STASH]
git-derive[EXE] stash apply [STASH]
git-derive[EXE] stash help [COMMAND]...
Options:
-m, --message <MESSAGE>
-h, --help Print help
git-derive[EXE] stash push:
-m, --message <MESSAGE>
-h, --help Print help
git-derive[EXE] stash pop:
-h, --help Print help
[STASH]
git-derive[EXE] stash apply:
-h, --help Print help
[STASH]
git-derive[EXE] stash help:
Print this message or the help of the given subcommand(s)
[COMMAND]... Print help for the subcommand(s)
$ git-derive stash push -h
Usage: git-derive[EXE] stash push [OPTIONS]
Options:
-m, --message <MESSAGE>
-h, --help Print help
$ git-derive stash pop -h
Usage: git-derive[EXE] stash pop [STASH]
Arguments:
[STASH]
Options:
-h, --help Print help
$ git-derive stash -m "Prototype"
Pushing StashPushArgs { message: Some("Prototype") }
$ git-derive stash pop
Popping None
$ git-derive stash push -m "Prototype"
Pushing StashPushArgs { message: Some("Prototype") }
$ git-derive stash pop
Popping None
```
External subcommands:
```console
$ git-derive custom-tool arg1 --foo bar
Calling out to "custom-tool" with ["arg1", "--foo", "bar"]
```
Last argument:
```console
$ git-derive diff --help
Compare two commits
Usage: git-derive[EXE] diff [OPTIONS] [COMMIT] [COMMIT] [-- <PATH>]
Arguments:
[COMMIT]
[COMMIT]
[PATH]
Options:
--color[=<WHEN>] [default: auto] [possible values: always, auto, never]
-h, --help Print help
$ git-derive diff
Diffing stage..worktree (color=auto)
$ git-derive diff ./src
Diffing stage..worktree ./src (color=auto)
$ git-derive diff HEAD ./src
Diffing HEAD..worktree ./src (color=auto)
$ git-derive diff HEAD~~ -- HEAD
Diffing HEAD~~..worktree HEAD (color=auto)
$ git-derive diff --color
Diffing stage..worktree (color=always)
$ git-derive diff --color=never
Diffing stage..worktree (color=never)
```

165
vendor/clap/examples/git-derive.rs vendored Normal file
View File

@ -0,0 +1,165 @@
use std::ffi::OsStr;
use std::ffi::OsString;
use std::path::PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum};
/// A fictional versioning CLI
#[derive(Debug, Parser)] // requires `derive` feature
#[command(name = "git")]
#[command(about = "A fictional versioning CLI", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
/// Clones repos
#[command(arg_required_else_help = true)]
Clone {
/// The remote to clone
remote: String,
},
/// Compare two commits
Diff {
#[arg(value_name = "COMMIT")]
base: Option<OsString>,
#[arg(value_name = "COMMIT")]
head: Option<OsString>,
#[arg(last = true)]
path: Option<OsString>,
#[arg(
long,
require_equals = true,
value_name = "WHEN",
num_args = 0..=1,
default_value_t = ColorWhen::Auto,
default_missing_value = "always",
value_enum
)]
color: ColorWhen,
},
/// pushes things
#[command(arg_required_else_help = true)]
Push {
/// The remote to target
remote: String,
},
/// adds things
#[command(arg_required_else_help = true)]
Add {
/// Stuff to add
#[arg(required = true)]
path: Vec<PathBuf>,
},
Stash(StashArgs),
#[command(external_subcommand)]
External(Vec<OsString>),
}
#[derive(ValueEnum, Copy, Clone, Debug, PartialEq, Eq)]
enum ColorWhen {
Always,
Auto,
Never,
}
impl std::fmt::Display for ColorWhen {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.to_possible_value()
.expect("no values are skipped")
.get_name()
.fmt(f)
}
}
#[derive(Debug, Args)]
#[command(args_conflicts_with_subcommands = true)]
#[command(flatten_help = true)]
struct StashArgs {
#[command(subcommand)]
command: Option<StashCommands>,
#[command(flatten)]
push: StashPushArgs,
}
#[derive(Debug, Subcommand)]
enum StashCommands {
Push(StashPushArgs),
Pop { stash: Option<String> },
Apply { stash: Option<String> },
}
#[derive(Debug, Args)]
struct StashPushArgs {
#[arg(short, long)]
message: Option<String>,
}
fn main() {
let args = Cli::parse();
match args.command {
Commands::Clone { remote } => {
println!("Cloning {remote}");
}
Commands::Diff {
mut base,
mut head,
mut path,
color,
} => {
if path.is_none() {
path = head;
head = None;
if path.is_none() {
path = base;
base = None;
}
}
let base = base
.as_deref()
.map(|s| s.to_str().unwrap())
.unwrap_or("stage");
let head = head
.as_deref()
.map(|s| s.to_str().unwrap())
.unwrap_or("worktree");
let path = path.as_deref().unwrap_or_else(|| OsStr::new(""));
println!(
"Diffing {}..{} {} (color={})",
base,
head,
path.to_string_lossy(),
color
);
}
Commands::Push { remote } => {
println!("Pushing to {remote}");
}
Commands::Add { 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:?}");
}
StashCommands::Pop { stash } => {
println!("Popping {stash:?}");
}
StashCommands::Apply { stash } => {
println!("Applying {stash:?}");
}
}
}
Commands::External(args) => {
println!("Calling out to {:?} with {:?}", &args[0], &args[1..]);
}
}
// Continued program logic goes here...
}

170
vendor/clap/examples/git.md vendored Normal file
View File

@ -0,0 +1,170 @@
Git is an example of several common subcommand patterns.
Help:
```console
$ git
? failed
A fictional versioning CLI
Usage: git[EXE] <COMMAND>
Commands:
clone Clones repos
diff Compare two commits
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
$ git help
A fictional versioning CLI
Usage: git[EXE] <COMMAND>
Commands:
clone Clones repos
diff Compare two commits
push pushes things
add adds things
stash
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
$ git help add
adds things
Usage: git[EXE] add <PATH>...
Arguments:
<PATH>... Stuff to add
Options:
-h, --help Print help
```
A basic argument:
```console
$ git add
? failed
adds things
Usage: git[EXE] add <PATH>...
Arguments:
<PATH>... Stuff to add
Options:
-h, --help Print help
$ git add Cargo.toml Cargo.lock
Adding ["Cargo.toml", "Cargo.lock"]
```
Default subcommand:
```console
$ git stash -h
Usage: git[EXE] stash [OPTIONS]
git[EXE] stash push [OPTIONS]
git[EXE] stash pop [STASH]
git[EXE] stash apply [STASH]
git[EXE] stash help [COMMAND]...
Options:
-m, --message <MESSAGE>
-h, --help Print help
git[EXE] stash push:
-m, --message <MESSAGE>
-h, --help Print help
git[EXE] stash pop:
-h, --help Print help
[STASH]
git[EXE] stash apply:
-h, --help Print help
[STASH]
git[EXE] stash help:
Print this message or the help of the given subcommand(s)
[COMMAND]... Print help for the subcommand(s)
$ git stash push -h
Usage: git[EXE] stash push [OPTIONS]
Options:
-m, --message <MESSAGE>
-h, --help Print help
$ git stash pop -h
Usage: git[EXE] stash pop [STASH]
Arguments:
[STASH]
Options:
-h, --help Print help
$ git stash -m "Prototype"
Pushing Some("Prototype")
$ git stash pop
Popping None
$ git stash push -m "Prototype"
Pushing Some("Prototype")
$ git stash pop
Popping None
```
External subcommands:
```console
$ git custom-tool arg1 --foo bar
Calling out to "custom-tool" with ["arg1", "--foo", "bar"]
```
Last argument:
```console
$ git diff --help
Compare two commits
Usage: git[EXE] diff [OPTIONS] [COMMIT] [COMMIT] [-- <PATH>]
Arguments:
[COMMIT]
[COMMIT]
[PATH]
Options:
--color[=<WHEN>] [default: auto] [possible values: always, auto, never]
-h, --help Print help
$ git diff
Diffing stage..worktree (color=auto)
$ git diff ./src
Diffing stage..worktree ./src (color=auto)
$ git diff HEAD ./src
Diffing HEAD..worktree ./src (color=auto)
$ git diff HEAD~~ -- HEAD
Diffing HEAD~~..worktree HEAD (color=auto)
$ git diff --color
Diffing stage..worktree (color=always)
$ git diff --color=never
Diffing stage..worktree (color=never)
```

138
vendor/clap/examples/git.rs vendored Normal file
View File

@ -0,0 +1,138 @@
use std::ffi::OsString;
use std::path::PathBuf;
use clap::{arg, Command};
fn cli() -> Command {
Command::new("git")
.about("A fictional versioning CLI")
.subcommand_required(true)
.arg_required_else_help(true)
.allow_external_subcommands(true)
.subcommand(
Command::new("clone")
.about("Clones repos")
.arg(arg!(<REMOTE> "The remote to clone"))
.arg_required_else_help(true),
)
.subcommand(
Command::new("diff")
.about("Compare two commits")
.arg(arg!(base: [COMMIT]))
.arg(arg!(head: [COMMIT]))
.arg(arg!(path: [PATH]).last(true))
.arg(
arg!(--color <WHEN>)
.value_parser(["always", "auto", "never"])
.num_args(0..=1)
.require_equals(true)
.default_value("auto")
.default_missing_value("always"),
),
)
.subcommand(
Command::new("push")
.about("pushes things")
.arg(arg!(<REMOTE> "The remote to target"))
.arg_required_else_help(true),
)
.subcommand(
Command::new("add")
.about("adds things")
.arg_required_else_help(true)
.arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
)
.subcommand(
Command::new("stash")
.args_conflicts_with_subcommands(true)
.flatten_help(true)
.args(push_args())
.subcommand(Command::new("push").args(push_args()))
.subcommand(Command::new("pop").arg(arg!([STASH])))
.subcommand(Command::new("apply").arg(arg!([STASH]))),
)
}
fn push_args() -> Vec<clap::Arg> {
vec![arg!(-m --message <MESSAGE>)]
}
fn main() {
let matches = cli().get_matches();
match matches.subcommand() {
Some(("clone", sub_matches)) => {
println!(
"Cloning {}",
sub_matches.get_one::<String>("REMOTE").expect("required")
);
}
Some(("diff", sub_matches)) => {
let color = sub_matches
.get_one::<String>("color")
.map(|s| s.as_str())
.expect("defaulted in clap");
let mut base = sub_matches.get_one::<String>("base").map(|s| s.as_str());
let mut head = sub_matches.get_one::<String>("head").map(|s| s.as_str());
let mut path = sub_matches.get_one::<String>("path").map(|s| s.as_str());
if path.is_none() {
path = head;
head = None;
if path.is_none() {
path = base;
base = None;
}
}
let base = base.unwrap_or("stage");
let head = head.unwrap_or("worktree");
let path = path.unwrap_or("");
println!("Diffing {base}..{head} {path} (color={color})");
}
Some(("push", sub_matches)) => {
println!(
"Pushing to {}",
sub_matches.get_one::<String>("REMOTE").expect("required")
);
}
Some(("add", sub_matches)) => {
let paths = sub_matches
.get_many::<PathBuf>("PATH")
.into_iter()
.flatten()
.collect::<Vec<_>>();
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:?}");
}
("pop", sub_matches) => {
let stash = sub_matches.get_one::<String>("STASH");
println!("Popping {stash:?}");
}
("push", sub_matches) => {
let message = sub_matches.get_one::<String>("message");
println!("Pushing {message:?}");
}
(name, _) => {
unreachable!("Unsupported subcommand `{name}`")
}
}
}
Some((ext, sub_matches)) => {
let args = sub_matches
.get_many::<OsString>("")
.into_iter()
.flatten()
.collect::<Vec<_>>();
println!("Calling out to {ext:?} with {args:?}");
}
_ => unreachable!(), // If all subcommands are defined above, anything else is unreachable!()
}
// Continued program logic goes here...
}

View File

@ -0,0 +1,39 @@
See the documentation for [`Command::multicall`][crate::Command::multicall] for rationale.
This example omits every command except true and false,
which are the most trivial to implement,
```console
$ busybox true
? 0
$ busybox false
? 1
```
*Note: without the links setup, we can't demonstrate the multicall behavior*
But includes the `--install` option as an example of why it can be useful
for the main program to take arguments that aren't applet subcommands.
```console
$ busybox --install
? failed
...
```
Though users must pass something:
```console
$ busybox
? failed
Usage: busybox [OPTIONS] [APPLET]
APPLETS:
true does nothing successfully
false does nothing unsuccessfully
help Print this message or the help of the given subcommand(s)
Options:
--install <install> Install hardlinks for all subcommands in path
-h, --help Print help
```

View File

@ -0,0 +1,47 @@
use std::path::PathBuf;
use std::process::exit;
use clap::{value_parser, Arg, ArgAction, Command};
fn applet_commands() -> [Command; 2] {
[
Command::new("true").about("does nothing successfully"),
Command::new("false").about("does nothing unsuccessfully"),
]
}
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.subcommand(
Command::new("busybox")
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.arg(
Arg::new("install")
.long("install")
.help("Install hardlinks for all subcommands in path")
.exclusive(true)
.action(ArgAction::Set)
.default_missing_value("/usr/local/bin")
.value_parser(value_parser!(PathBuf)),
)
.subcommands(applet_commands()),
)
.subcommands(applet_commands());
let matches = cmd.get_matches();
let mut subcommand = matches.subcommand();
if let Some(("busybox", cmd)) = subcommand {
if cmd.contains_id("install") {
unimplemented!("Make hardlinks to the executable here");
}
subcommand = cmd.subcommand();
}
match subcommand {
Some(("false", _)) => exit(1),
Some(("true", _)) => exit(0),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}

View File

@ -0,0 +1,10 @@
See the documentation for [`Command::multicall`][crate::Command::multicall] for rationale.
This example omits the implementation of displaying address config
```console
$ hostname
www
```
*Note: without the links setup, we can't demonstrate the multicall behavior*

View File

@ -0,0 +1,17 @@
use clap::Command;
fn main() {
let cmd = Command::new(env!("CARGO_CRATE_NAME"))
.multicall(true)
.arg_required_else_help(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.subcommand(Command::new("hostname").about("show hostname part of FQDN"))
.subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
match cmd.get_matches().subcommand_name() {
Some("hostname") => println!("www"),
Some("dnsdomainname") => println!("example.com"),
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}

79
vendor/clap/examples/pacman.md vendored Normal file
View File

@ -0,0 +1,79 @@
[`pacman`](https://wiki.archlinux.org/index.php/pacman) defines subcommands via flags.
Here, `-S` is a short flag subcommand:
```console
$ pacman -S package
Installing package...
```
Here `--sync` is a long flag subcommand:
```console
$ pacman --sync package
Installing package...
```
Now the short flag subcommand (`-S`) with a long flag:
```console
$ pacman -S --search name
Searching for name...
```
And the various forms of short flags that work:
```console
$ pacman -S -s name
Searching for name...
$ pacman -Ss name
Searching for name...
```
*(users can "stack" short subcommands with short flags or with other short flag subcommands)*
In the help, this looks like:
```console
$ pacman -h
package manager utility
Usage: pacman[EXE] <COMMAND>
Commands:
query, -Q, --query Query the package database.
sync, -S, --sync Synchronize packages.
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
$ pacman -S -h
Synchronize packages.
Usage: pacman[EXE] {sync|--sync|-S} [OPTIONS] [package]...
Arguments:
[package]... packages
Options:
-s, --search <search>... search remote repositories for matching strings
-i, --info view package information
-h, --help Print help
```
And errors:
```console
$ pacman -S -s foo -i bar
? failed
error: the argument '--search <search>...' cannot be used with '--info'
Usage: pacman[EXE] {sync|--sync|-S} --search <search>... <package>...
For more information, try '--help'.
```
**NOTE:** Keep in mind that subcommands, flags, and long flags are *case sensitive*: `-Q` and `-q` are different flags/subcommands. For example, you can have both `-Q` subcommand and `-q` flag, and they will be properly disambiguated.
Let's make a quick program to illustrate.

111
vendor/clap/examples/pacman.rs vendored Normal file
View File

@ -0,0 +1,111 @@
use clap::{Arg, ArgAction, Command};
fn main() {
let matches = Command::new("pacman")
.about("package manager utility")
.version("5.2.1")
.subcommand_required(true)
.arg_required_else_help(true)
.author("Pacman Development Team")
// Query subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("query")
.short_flag('Q')
.long_flag("query")
.about("Query the package database.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.help("search locally installed packages for matching strings")
.conflicts_with("info")
.action(ArgAction::Set)
.num_args(1..),
)
.arg(
Arg::new("info")
.long("info")
.short('i')
.conflicts_with("search")
.help("view package information")
.action(ArgAction::Set)
.num_args(1..),
),
)
// Sync subcommand
//
// Only a few of its arguments are implemented below.
.subcommand(
Command::new("sync")
.short_flag('S')
.long_flag("sync")
.about("Synchronize packages.")
.arg(
Arg::new("search")
.short('s')
.long("search")
.conflicts_with("info")
.action(ArgAction::Set)
.num_args(1..)
.help("search remote repositories for matching strings"),
)
.arg(
Arg::new("info")
.long("info")
.conflicts_with("search")
.short('i')
.action(ArgAction::SetTrue)
.help("view package information"),
)
.arg(
Arg::new("package")
.help("packages")
.required_unless_present("search")
.action(ArgAction::Set)
.num_args(1..),
),
)
.get_matches();
match matches.subcommand() {
Some(("sync", sync_matches)) => {
if sync_matches.contains_id("search") {
let packages: Vec<_> = sync_matches
.get_many::<String>("search")
.expect("contains_id")
.map(|s| s.as_str())
.collect();
let values = packages.join(", ");
println!("Searching for {values}...");
return;
}
let packages: Vec<_> = sync_matches
.get_many::<String>("package")
.expect("is present")
.map(|s| s.as_str())
.collect();
let values = packages.join(", ");
if sync_matches.get_flag("info") {
println!("Retrieving info for {values}...");
} else {
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}...");
} 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}...");
} else {
println!("Displaying all locally installed packages...");
}
}
_ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
}
}

92
vendor/clap/examples/repl.rs vendored Normal file
View File

@ -0,0 +1,92 @@
use std::io::Write;
use clap::Command;
fn main() -> Result<(), String> {
loop {
let line = readline()?;
let line = line.trim();
if line.is_empty() {
continue;
}
match respond(line) {
Ok(quit) => {
if quit {
break;
}
}
Err(err) => {
write!(std::io::stdout(), "{err}").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
}
}
}
Ok(())
}
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)
.map_err(|e| e.to_string())?;
match matches.subcommand() {
Some(("ping", _matches)) => {
write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
}
Some(("quit", _matches)) => {
write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
return Ok(true);
}
Some((name, _matches)) => unimplemented!("{name}"),
None => unreachable!("subcommand required"),
}
Ok(false)
}
fn cli() -> Command {
// strip out usage
const PARSER_TEMPLATE: &str = "\
{all-args}
";
// strip out name/version
const APPLET_TEMPLATE: &str = "\
{about-with-newline}\n\
{usage-heading}\n {usage}\n\
\n\
{all-args}{after-help}\
";
Command::new("repl")
.multicall(true)
.arg_required_else_help(true)
.subcommand_required(true)
.subcommand_value_name("APPLET")
.subcommand_help_heading("APPLETS")
.help_template(PARSER_TEMPLATE)
.subcommand(
Command::new("ping")
.about("Get a response")
.help_template(APPLET_TEMPLATE),
)
.subcommand(
Command::new("quit")
.alias("exit")
.about("Quit the REPL")
.help_template(APPLET_TEMPLATE),
)
}
fn readline() -> Result<String, String> {
write!(std::io::stdout(), "$ ").map_err(|e| e.to_string())?;
std::io::stdout().flush().map_err(|e| e.to_string())?;
let mut buffer = String::new();
std::io::stdin()
.read_line(&mut buffer)
.map_err(|e| e.to_string())?;
Ok(buffer)
}

View File

@ -0,0 +1,35 @@
```console
$ 01_quick --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 01_quick[EXE] [OPTIONS] [name] [COMMAND]
Commands:
test does testing things
help Print this message or the help of the given subcommand(s)
Arguments:
[name] Optional name to operate on
Options:
-c, --config <FILE> Sets a custom config file
-d, --debug... Turn debugging information on
-h, --help Print help
-V, --version Print version
```
By default, the program does nothing:
```console
$ 01_quick
Debug mode is off
```
But you can mix and match the various features
```console
$ 01_quick -dd test
Debug mode is on
Not printing testing lists...
```

View File

@ -0,0 +1,60 @@
use std::path::PathBuf;
use clap::{arg, command, value_parser, ArgAction, Command};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(arg!([name] "Optional name to operate on"))
.arg(
arg!(
-c --config <FILE> "Sets a custom config file"
)
// We don't have syntax yet for optional options, so manually calling `required`
.required(false)
.value_parser(value_parser!(PathBuf)),
)
.arg(arg!(
-d --debug ... "Turn debugging information on"
))
.subcommand(
Command::new("test")
.about("does testing things")
.arg(arg!(-l --list "lists test values").action(ArgAction::SetTrue)),
)
.get_matches();
// You can check the value provided by positional arguments, or option arguments
if let Some(name) = matches.get_one::<String>("name") {
println!("Value for name: {name}");
}
if let Some(config_path) = matches.get_one::<PathBuf>("config") {
println!("Value for config: {}", config_path.display());
}
// You can see how many times a particular flag or argument occurred
// Note, only flags can have multiple occurrences
match matches
.get_one::<u8>("debug")
.expect("Count's are defaulted")
{
0 => println!("Debug mode is off"),
1 => println!("Debug mode is kind of on"),
2 => println!("Debug mode is on"),
_ => println!("Don't be crazy"),
}
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
if let Some(matches) = matches.subcommand_matches("test") {
// "$ myapp test" was run
if matches.get_flag("list") {
// "$ myapp test -l" was run
println!("Printing testing lists...");
} else {
println!("Not printing testing lists...");
}
}
// Continued program logic goes here...
}

View File

@ -0,0 +1,17 @@
```console
$ 02_app_settings --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 02_app_settings[EXE] --two <VALUE> --one <VALUE>
Options:
--two <VALUE>
--one <VALUE>
-h, --help
Print help
-V, --version
Print version
```

View File

@ -0,0 +1,18 @@
use clap::{arg, command, ArgAction};
fn main() {
let matches = command!() // requires `cargo` feature
.next_line_help(true)
.arg(arg!(--two <VALUE>).required(true).action(ArgAction::Set))
.arg(arg!(--one <VALUE>).required(true).action(ArgAction::Set))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}

View File

@ -0,0 +1,16 @@
```console
$ 02_apps --help
Does awesome things
Usage: 02_apps[EXE] --two <VALUE> --one <VALUE>
Options:
--two <VALUE>
--one <VALUE>
-h, --help Print help
-V, --version Print version
$ 02_apps --version
MyApp 1.0
```

View File

@ -0,0 +1,20 @@
use clap::{arg, Command};
fn main() {
let matches = Command::new("MyApp")
.version("1.0")
.author("Kevin K. <kbknapp@gmail.com>")
.about("Does awesome things")
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}

View File

@ -0,0 +1,16 @@
```console
$ 02_crate --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 02_crate[EXE] --two <VALUE> --one <VALUE>
Options:
--two <VALUE>
--one <VALUE>
-h, --help Print help
-V, --version Print version
$ 02_crate --version
clap [..]
```

View File

@ -0,0 +1,18 @@
use clap::{arg, command};
fn main() {
// requires `cargo` feature, reading name, version, author, and description from `Cargo.toml`
let matches = command!()
.arg(arg!(--two <VALUE>).required(true))
.arg(arg!(--one <VALUE>).required(true))
.get_matches();
println!(
"two: {:?}",
matches.get_one::<String>("two").expect("required")
);
println!(
"one: {:?}",
matches.get_one::<String>("one").expect("required")
);
}

View File

@ -0,0 +1,26 @@
```console
$ 03_01_flag_bool --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_01_flag_bool[EXE] [OPTIONS]
Options:
-v, --verbose
-h, --help Print help
-V, --version Print version
$ 03_01_flag_bool
verbose: false
$ 03_01_flag_bool --verbose
verbose: true
$ 03_01_flag_bool --verbose --verbose
? failed
error: the argument '--verbose' cannot be used multiple times
Usage: 03_01_flag_bool[EXE] [OPTIONS]
For more information, try '--help'.
```

View File

@ -0,0 +1,14 @@
use clap::{command, Arg, ArgAction};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.action(ArgAction::SetTrue),
)
.get_matches();
println!("verbose: {:?}", matches.get_flag("verbose"));
}

View File

@ -0,0 +1,21 @@
```console
$ 03_01_flag_count --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_01_flag_count[EXE] [OPTIONS]
Options:
-v, --verbose...
-h, --help Print help
-V, --version Print version
$ 03_01_flag_count
verbose: 0
$ 03_01_flag_count --verbose
verbose: 1
$ 03_01_flag_count --verbose --verbose
verbose: 2
```

View File

@ -0,0 +1,14 @@
use clap::{command, Arg, ArgAction};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.action(ArgAction::Count),
)
.get_matches();
println!("verbose: {:?}", matches.get_count("verbose"));
}

View File

@ -0,0 +1,30 @@
```console
$ 03_02_option --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_02_option[EXE] [OPTIONS]
Options:
-n, --name <name>
-h, --help Print help
-V, --version Print version
$ 03_02_option
name: None
$ 03_02_option --name bob
name: Some("bob")
$ 03_02_option --name=bob
name: Some("bob")
$ 03_02_option -n bob
name: Some("bob")
$ 03_02_option -n=bob
name: Some("bob")
$ 03_02_option -nbob
name: Some("bob")
```

View File

@ -0,0 +1,9 @@
use clap::{command, Arg};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(Arg::new("name").short('n').long("name"))
.get_matches();
println!("name: {:?}", matches.get_one::<String>("name"));
}

View File

@ -0,0 +1,30 @@
```console
$ 03_02_option_mult --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_02_option_mult[EXE] [OPTIONS]
Options:
-n, --name <name>
-h, --help Print help
-V, --version Print version
$ 03_02_option_mult
name: None
$ 03_02_option_mult --name bob
name: Some("bob")
$ 03_02_option_mult --name=bob
name: Some("bob")
$ 03_02_option_mult -n bob
name: Some("bob")
$ 03_02_option_mult -n=bob
name: Some("bob")
$ 03_02_option_mult -nbob
name: Some("bob")
```

View File

@ -0,0 +1,14 @@
use clap::{command, Arg, ArgAction};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
Arg::new("name")
.short('n')
.long("name")
.action(ArgAction::Append),
)
.get_matches();
println!("name: {:?}", matches.get_one::<String>("name"));
}

View File

@ -0,0 +1,20 @@
```console
$ 03_03_positional --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_03_positional[EXE] [name]
Arguments:
[name]
Options:
-h, --help Print help
-V, --version Print version
$ 03_03_positional
name: None
$ 03_03_positional bob
name: Some("bob")
```

View File

@ -0,0 +1,9 @@
use clap::{command, Arg};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(Arg::new("name"))
.get_matches();
println!("name: {:?}", matches.get_one::<String>("name"));
}

View File

@ -0,0 +1,23 @@
```console
$ 03_03_positional_mult --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_03_positional_mult[EXE] [name]...
Arguments:
[name]...
Options:
-h, --help Print help
-V, --version Print version
$ 03_03_positional_mult
names: []
$ 03_03_positional_mult bob
names: ["bob"]
$ 03_03_positional_mult bob john
names: ["bob", "john"]
```

View File

@ -0,0 +1,15 @@
use clap::{command, Arg, ArgAction};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(Arg::new("name").action(ArgAction::Append))
.get_matches();
let args = matches
.get_many::<String>("name")
.unwrap_or_default()
.map(|v| v.as_str())
.collect::<Vec<_>>();
println!("names: {:?}", &args);
}

View File

@ -0,0 +1,59 @@
```console
$ 03_04_subcommands help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_04_subcommands[EXE] <COMMAND>
Commands:
add Adds files to myapp
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
$ 03_04_subcommands help add
Adds files to myapp
Usage: 03_04_subcommands[EXE] add [NAME]
Arguments:
[NAME]
Options:
-h, --help Print help
-V, --version Print version
$ 03_04_subcommands add bob
'myapp add' was used, name is: Some("bob")
```
Because we set [`Command::arg_required_else_help`][crate::Command::arg_required_else_help]:
```console
$ 03_04_subcommands
? failed
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_04_subcommands[EXE] <COMMAND>
Commands:
add Adds files to myapp
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
```
Since we specified [`Command::propagate_version`][crate::Command::propagate_version], the `--version` flag
is available in all subcommands:
```console
$ 03_04_subcommands --version
clap [..]
$ 03_04_subcommands add --version
clap-add [..]
```

View File

@ -0,0 +1,22 @@
use clap::{arg, command, Command};
fn main() {
let matches = command!() // requires `cargo` feature
.propagate_version(true)
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new("add")
.about("Adds files to myapp")
.arg(arg!([NAME])),
)
.get_matches();
match matches.subcommand() {
Some(("add", sub_matches)) => println!(
"'myapp add' was used, name is: {:?}",
sub_matches.get_one::<String>("NAME")
),
_ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
}
}

View File

@ -0,0 +1,20 @@
```console
$ 03_05_default_values --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_05_default_values[EXE] [PORT]
Arguments:
[PORT] [default: 2020]
Options:
-h, --help Print help
-V, --version Print version
$ 03_05_default_values
port: 2020
$ 03_05_default_values 22
port: 22
```

View File

@ -0,0 +1,18 @@
use clap::{arg, command, value_parser};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
arg!([PORT])
.value_parser(value_parser!(u16))
.default_value("2020"),
)
.get_matches();
println!(
"port: {:?}",
matches
.get_one::<u16>("PORT")
.expect("default ensures there is always a value")
);
}

View File

@ -0,0 +1,47 @@
```console
$ 04_01_enum --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_01_enum[EXE] <MODE>
Arguments:
<MODE>
What mode to run the program in
Possible values:
- fast: Run swiftly
- slow: Crawl slowly but steadily
Options:
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
$ 04_01_enum -h
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_01_enum[EXE] <MODE>
Arguments:
<MODE> What mode to run the program in [possible values: fast, slow]
Options:
-h, --help Print help (see more with '--help')
-V, --version Print version
$ 04_01_enum fast
Hare
$ 04_01_enum slow
Tortoise
$ 04_01_enum medium
? failed
error: invalid value 'medium' for '<MODE>'
[possible values: fast, slow]
For more information, try '--help'.
```

View File

@ -0,0 +1,66 @@
use clap::{arg, builder::PossibleValue, command, value_parser, ValueEnum};
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
enum Mode {
Fast,
Slow,
}
// Can also be derived with feature flag `derive`
impl ValueEnum for Mode {
fn value_variants<'a>() -> &'a [Self] {
&[Mode::Fast, Mode::Slow]
}
fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
Some(match self {
Mode::Fast => PossibleValue::new("fast").help("Run swiftly"),
Mode::Slow => PossibleValue::new("slow").help("Crawl slowly but steadily"),
})
}
}
impl std::fmt::Display for Mode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.to_possible_value()
.expect("no values are skipped")
.get_name()
.fmt(f)
}
}
impl std::str::FromStr for Mode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
for variant in Self::value_variants() {
if variant.to_possible_value().unwrap().matches(s, false) {
return Ok(*variant);
}
}
Err(format!("invalid variant: {s}"))
}
}
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
arg!(<MODE>)
.help("What mode to run the program in")
.value_parser(value_parser!(Mode)),
)
.get_matches();
// Note, it's safe to call unwrap() because the arg is required
match matches
.get_one::<Mode>("MODE")
.expect("'MODE' is required and parsing will fail if its missing")
{
Mode::Fast => {
println!("Hare");
}
Mode::Slow => {
println!("Tortoise");
}
}
}

View File

@ -0,0 +1,27 @@
```console
$ 04_01_possible --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_01_possible[EXE] <MODE>
Arguments:
<MODE> What mode to run the program in [possible values: fast, slow]
Options:
-h, --help Print help
-V, --version Print version
$ 04_01_possible fast
Hare
$ 04_01_possible slow
Tortoise
$ 04_01_possible medium
? failed
error: invalid value 'medium' for '<MODE>'
[possible values: fast, slow]
For more information, try '--help'.
```

View File

@ -0,0 +1,26 @@
use clap::{arg, command};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
arg!(<MODE>)
.help("What mode to run the program in")
.value_parser(["fast", "slow"]),
)
.get_matches();
// Note, it's safe to call unwrap() because the arg is required
match matches
.get_one::<String>("MODE")
.expect("'MODE' is required and parsing will fail if its missing")
.as_str()
{
"fast" => {
println!("Hare");
}
"slow" => {
println!("Tortoise");
}
_ => unreachable!(),
}
}

View File

@ -0,0 +1,29 @@
```console
$ 04_02_parse --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_02_parse[EXE] <PORT>
Arguments:
<PORT> Network port to use
Options:
-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
For more information, try '--help'.
$ 04_02_parse_derive 0
? failed
error: invalid value '0' for '<PORT>': 0 is not in 1..=65535
For more information, try '--help'.
```

View File

@ -0,0 +1,17 @@
use clap::{arg, command, value_parser};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
arg!(<PORT>)
.help("Network port to use")
.value_parser(value_parser!(u16).range(1..)),
)
.get_matches();
// Note, it's safe to call unwrap() because the arg is required
let port: u16 = *matches
.get_one::<u16>("PORT")
.expect("'PORT' is required and parsing will fail if its missing");
println!("PORT = {port}");
}

View File

@ -0,0 +1,29 @@
```console
$ 04_02_validate --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_02_validate[EXE] <PORT>
Arguments:
<PORT> Network port to use
Options:
-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
For more information, try '--help'.
$ 04_02_validate 0
? failed
error: invalid value '0' for '<PORT>': port not in range 1-65535
For more information, try '--help'.
```

View File

@ -0,0 +1,36 @@
use std::ops::RangeInclusive;
use clap::{arg, command};
fn main() {
let matches = command!() // requires `cargo` feature
.arg(
arg!(<PORT>)
.help("Network port to use")
.value_parser(port_in_range),
)
.get_matches();
// Note, it's safe to call unwrap() because the arg is required
let port: u16 = *matches
.get_one::<u16>("PORT")
.expect("'PORT' is required and parsing will fail if its missing");
println!("PORT = {port}");
}
const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
fn port_in_range(s: &str) -> Result<u16, String> {
let port: usize = s
.parse()
.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_RANGE.start(),
PORT_RANGE.end()
))
}
}

View File

@ -0,0 +1,53 @@
```console
$ 04_03_relations --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_03_relations[EXE] [OPTIONS] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
Arguments:
[INPUT_FILE] some regular input
Options:
--set-ver <VER> set version manually
--major auto inc major
--minor auto inc minor
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
-h, --help Print help
-V, --version Print version
$ 04_03_relations
? failed
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'.
$ 04_03_relations --major
Version: 2.2.3
$ 04_03_relations --major --minor
? failed
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'.
$ 04_03_relations --major -c config.toml
? failed
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'.
$ 04_03_relations --major -c config.toml --spec-in input.txt
Version: 2.2.3
Doing work using input input.txt and config config.toml
```

View File

@ -0,0 +1,78 @@
use std::path::PathBuf;
use clap::{arg, command, value_parser, ArgAction, ArgGroup};
fn main() {
// Create application like normal
let matches = command!() // requires `cargo` feature
// Add the version arguments
.arg(arg!(--"set-ver" <VER> "set version manually"))
.arg(arg!(--major "auto inc major").action(ArgAction::SetTrue))
.arg(arg!(--minor "auto inc minor").action(ArgAction::SetTrue))
.arg(arg!(--patch "auto inc patch").action(ArgAction::SetTrue))
// Create a group, make it required, and add the above arguments
.group(
ArgGroup::new("vers")
.required(true)
.args(["set-ver", "major", "minor", "patch"]),
)
// Arguments can also be added to a group individually, these two arguments
// are part of the "input" group which is not required
.arg(
arg!([INPUT_FILE] "some regular input")
.value_parser(value_parser!(PathBuf))
.group("input"),
)
.arg(
arg!(--"spec-in" <SPEC_IN> "some special input argument")
.value_parser(value_parser!(PathBuf))
.group("input"),
)
// Now let's assume we have a -c [config] argument which requires one of
// (but **not** both) the "input" arguments
.arg(
arg!(config: -c <CONFIG>)
.value_parser(value_parser!(PathBuf))
.requires("input"),
)
.get_matches();
// Let's assume the old version 1.2.3
let mut major = 1;
let mut minor = 2;
let mut patch = 3;
// See if --set-ver was used to set the version manually
let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
ver.to_owned()
} else {
// Increment the one requested (in a real program, we'd reset the lower numbers)
let (maj, min, pat) = (
matches.get_flag("major"),
matches.get_flag("minor"),
matches.get_flag("patch"),
);
match (maj, min, pat) {
(true, _, _) => major += 1,
(_, true, _) => minor += 1,
(_, _, true) => patch += 1,
_ => unreachable!(),
};
format!("{major}.{minor}.{patch}")
};
println!("Version: {version}");
// Check for usage of -c
if matches.contains_id("config") {
let input = matches
.get_one::<PathBuf>("INPUT_FILE")
.unwrap_or_else(|| matches.get_one::<PathBuf>("spec-in").unwrap())
.display();
println!(
"Doing work using input {} and config {}",
input,
matches.get_one::<PathBuf>("config").unwrap().display()
);
}
}

View File

@ -0,0 +1,52 @@
```console
$ 04_04_custom --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
Arguments:
[INPUT_FILE] some regular input
Options:
--set-ver <VER> set version manually
--major auto inc major
--minor auto inc minor
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
-h, --help Print help
-V, --version Print version
$ 04_04_custom
? failed
error: Can only modify one version field
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
For more information, try '--help'.
$ 04_04_custom --major
Version: 2.2.3
$ 04_04_custom --major --minor
? failed
error: Can only modify one version field
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
For more information, try '--help'.
$ 04_04_custom --major -c config.toml
? failed
Version: 2.2.3
error: INPUT_FILE or --spec-in is required when using --config
Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
For more information, try '--help'.
$ 04_04_custom --major -c config.toml --spec-in input.txt
Version: 2.2.3
Doing work using input input.txt and config config.toml
```

View File

@ -0,0 +1,84 @@
use std::path::PathBuf;
use clap::error::ErrorKind;
use clap::{arg, command, value_parser, ArgAction};
fn main() {
// Create application like normal
let mut cmd = command!() // requires `cargo` feature
// Add the version arguments
.arg(arg!(--"set-ver" <VER> "set version manually"))
.arg(arg!(--major "auto inc major").action(ArgAction::SetTrue))
.arg(arg!(--minor "auto inc minor").action(ArgAction::SetTrue))
.arg(arg!(--patch "auto inc patch").action(ArgAction::SetTrue))
// Arguments can also be added to a group individually, these two arguments
// are part of the "input" group which is not required
.arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf)))
.arg(
arg!(--"spec-in" <SPEC_IN> "some special input argument")
.value_parser(value_parser!(PathBuf)),
)
// Now let's assume we have a -c [config] argument which requires one of
// (but **not** both) the "input" arguments
.arg(arg!(config: -c <CONFIG>).value_parser(value_parser!(PathBuf)));
let matches = cmd.get_matches_mut();
// Let's assume the old version 1.2.3
let mut major = 1;
let mut minor = 2;
let mut patch = 3;
// See if --set-ver was used to set the version manually
let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
if matches.get_flag("major") || matches.get_flag("minor") || matches.get_flag("patch") {
cmd.error(
ErrorKind::ArgumentConflict,
"Can't do relative and absolute version change",
)
.exit();
}
ver.to_string()
} else {
// Increment the one requested (in a real program, we'd reset the lower numbers)
let (maj, min, pat) = (
matches.get_flag("major"),
matches.get_flag("minor"),
matches.get_flag("patch"),
);
match (maj, min, pat) {
(true, false, false) => major += 1,
(false, true, false) => minor += 1,
(false, false, true) => patch += 1,
_ => {
cmd.error(
ErrorKind::ArgumentConflict,
"Can only modify one version field",
)
.exit();
}
};
format!("{major}.{minor}.{patch}")
};
println!("Version: {version}");
// Check for usage of -c
if matches.contains_id("config") {
let input = matches
.get_one::<PathBuf>("INPUT_FILE")
.or_else(|| matches.get_one::<PathBuf>("spec-in"))
.unwrap_or_else(|| {
cmd.error(
ErrorKind::MissingRequiredArgument,
"INPUT_FILE or --spec-in is required when using --config",
)
.exit()
})
.display();
println!(
"Doing work using input {} and config {}",
input,
matches.get_one::<PathBuf>("config").unwrap().display()
);
}
}

View File

@ -0,0 +1,25 @@
use clap::{arg, command, value_parser};
fn main() {
let matches = cmd().get_matches();
// Note, it's safe to call unwrap() because the arg is required
let port: usize = *matches
.get_one::<usize>("PORT")
.expect("'PORT' is required and parsing will fail if its missing");
println!("PORT = {port}");
}
fn cmd() -> clap::Command {
command!() // requires `cargo` feature
.arg(
arg!(<PORT>)
.help("Network port to use")
.value_parser(value_parser!(usize)),
)
}
#[test]
fn verify_cmd() {
cmd().debug_assert();
}

View File

@ -0,0 +1,35 @@
```console
$ 01_quick_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 01_quick_derive[EXE] [OPTIONS] [NAME] [COMMAND]
Commands:
test does testing things
help Print this message or the help of the given subcommand(s)
Arguments:
[NAME] Optional name to operate on
Options:
-c, --config <FILE> Sets a custom config file
-d, --debug... Turn debugging information on
-h, --help Print help
-V, --version Print version
```
By default, the program does nothing:
```console
$ 01_quick_derive
Debug mode is off
```
But you can mix and match the various features
```console
$ 01_quick_derive -dd test
Debug mode is on
Not printing testing lists...
```

View File

@ -0,0 +1,68 @@
use std::path::PathBuf;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Optional name to operate on
name: Option<String>,
/// Sets a custom config file
#[arg(short, long, value_name = "FILE")]
config: Option<PathBuf>,
/// Turn debugging information on
#[arg(short, long, action = clap::ArgAction::Count)]
debug: u8,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
/// does testing things
Test {
/// lists test values
#[arg(short, long)]
list: bool,
},
}
fn main() {
let cli = Cli::parse();
// 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}");
}
if let Some(config_path) = cli.config.as_deref() {
println!("Value for config: {}", config_path.display());
}
// You can see how many times a particular flag or argument occurred
// Note, only flags can have multiple occurrences
match cli.debug {
0 => println!("Debug mode is off"),
1 => println!("Debug mode is kind of on"),
2 => println!("Debug mode is on"),
_ => println!("Don't be crazy"),
}
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
match &cli.command {
Some(Commands::Test { list }) => {
if *list {
println!("Printing testing lists...");
} else {
println!("Not printing testing lists...");
}
}
None => {}
}
// Continued program logic goes here...
}

View File

@ -0,0 +1,17 @@
```console
$ 02_app_settings_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 02_app_settings_derive[EXE] --two <TWO> --one <ONE>
Options:
--two <TWO>
--one <ONE>
-h, --help
Print help
-V, --version
Print version
```

View File

@ -0,0 +1,18 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(next_line_help = true)]
struct Cli {
#[arg(long)]
two: String,
#[arg(long)]
one: String,
}
fn main() {
let cli = Cli::parse();
println!("two: {:?}", cli.two);
println!("one: {:?}", cli.one);
}

View File

@ -0,0 +1,16 @@
```console
$ 02_apps_derive --help
Does awesome things
Usage: 02_apps_derive[EXE] --two <TWO> --one <ONE>
Options:
--two <TWO>
--one <ONE>
-h, --help Print help
-V, --version Print version
$ 02_apps_derive --version
MyApp 1.0
```

View File

@ -0,0 +1,20 @@
use clap::Parser;
#[derive(Parser)]
#[command(name = "MyApp")]
#[command(author = "Kevin K. <kbknapp@gmail.com>")]
#[command(version = "1.0")]
#[command(about = "Does awesome things", long_about = None)]
struct Cli {
#[arg(long)]
two: String,
#[arg(long)]
one: String,
}
fn main() {
let cli = Cli::parse();
println!("two: {:?}", cli.two);
println!("one: {:?}", cli.one);
}

View File

@ -0,0 +1,16 @@
```console
$ 02_crate_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 02_crate_derive[EXE] --two <TWO> --one <ONE>
Options:
--two <TWO>
--one <ONE>
-h, --help Print help
-V, --version Print version
$ 02_crate_derive --version
clap [..]
```

View File

@ -0,0 +1,17 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)] // Read from `Cargo.toml`
struct Cli {
#[arg(long)]
two: String,
#[arg(long)]
one: String,
}
fn main() {
let cli = Cli::parse();
println!("two: {:?}", cli.two);
println!("one: {:?}", cli.one);
}

View File

@ -0,0 +1,26 @@
```console
$ 03_01_flag_bool_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_01_flag_bool_derive[EXE] [OPTIONS]
Options:
-v, --verbose
-h, --help Print help
-V, --version Print version
$ 03_01_flag_bool_derive
verbose: false
$ 03_01_flag_bool_derive --verbose
verbose: true
$ 03_01_flag_bool_derive --verbose --verbose
? failed
error: the argument '--verbose' cannot be used multiple times
Usage: 03_01_flag_bool_derive[EXE] [OPTIONS]
For more information, try '--help'.
```

View File

@ -0,0 +1,14 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(short, long)]
verbose: bool,
}
fn main() {
let cli = Cli::parse();
println!("verbose: {:?}", cli.verbose);
}

View File

@ -0,0 +1,21 @@
```console
$ 03_01_flag_count_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_01_flag_count_derive[EXE] [OPTIONS]
Options:
-v, --verbose...
-h, --help Print help
-V, --version Print version
$ 03_01_flag_count_derive
verbose: 0
$ 03_01_flag_count_derive --verbose
verbose: 1
$ 03_01_flag_count_derive --verbose --verbose
verbose: 2
```

View File

@ -0,0 +1,14 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
}
fn main() {
let cli = Cli::parse();
println!("verbose: {:?}", cli.verbose);
}

View File

@ -0,0 +1,30 @@
```console
$ 03_02_option_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_02_option_derive[EXE] [OPTIONS]
Options:
-n, --name <NAME>
-h, --help Print help
-V, --version Print version
$ 03_02_option_derive
name: None
$ 03_02_option_derive --name bob
name: Some("bob")
$ 03_02_option_derive --name=bob
name: Some("bob")
$ 03_02_option_derive -n bob
name: Some("bob")
$ 03_02_option_derive -n=bob
name: Some("bob")
$ 03_02_option_derive -nbob
name: Some("bob")
```

View File

@ -0,0 +1,14 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(short, long)]
name: Option<String>,
}
fn main() {
let cli = Cli::parse();
println!("name: {:?}", cli.name.as_deref());
}

View File

@ -0,0 +1,30 @@
```console
$ 03_02_option_mult_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_02_option_mult_derive[EXE] [OPTIONS]
Options:
-n, --name <NAME>
-h, --help Print help
-V, --version Print version
$ 03_02_option_mult_derive
name: []
$ 03_02_option_mult_derive --name bob
name: ["bob"]
$ 03_02_option_mult_derive --name=bob
name: ["bob"]
$ 03_02_option_mult_derive -n bob
name: ["bob"]
$ 03_02_option_mult_derive -n=bob
name: ["bob"]
$ 03_02_option_mult_derive -nbob
name: ["bob"]
```

View File

@ -0,0 +1,14 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(short, long)]
name: Vec<String>,
}
fn main() {
let cli = Cli::parse();
println!("name: {:?}", cli.name);
}

View File

@ -0,0 +1,20 @@
```console
$ 03_03_positional_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_03_positional_derive[EXE] [NAME]
Arguments:
[NAME]
Options:
-h, --help Print help
-V, --version Print version
$ 03_03_positional_derive
name: None
$ 03_03_positional_derive bob
name: Some("bob")
```

View File

@ -0,0 +1,13 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
name: Option<String>,
}
fn main() {
let cli = Cli::parse();
println!("name: {:?}", cli.name.as_deref());
}

View File

@ -0,0 +1,23 @@
```console
$ 03_03_positional_mult_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_03_positional_mult_derive[EXE] [NAME]...
Arguments:
[NAME]...
Options:
-h, --help Print help
-V, --version Print version
$ 03_03_positional_mult_derive
name: []
$ 03_03_positional_mult_derive bob
name: ["bob"]
$ 03_03_positional_mult_derive bob john
name: ["bob", "john"]
```

View File

@ -0,0 +1,13 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
name: Vec<String>,
}
fn main() {
let cli = Cli::parse();
println!("name: {:?}", cli.name);
}

View File

@ -0,0 +1,60 @@
```console
$ 03_04_subcommands_derive help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_04_subcommands_derive[EXE] <COMMAND>
Commands:
add Adds files to myapp
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
$ 03_04_subcommands_derive help add
Adds files to myapp
Usage: 03_04_subcommands_derive[EXE] add [NAME]
Arguments:
[NAME]
Options:
-h, --help Print help
-V, --version Print version
$ 03_04_subcommands_derive add bob
'myapp add' was used, name is: Some("bob")
```
When specifying commands with `command: Commands`, they are required.
Alternatively, you could do `command: Option<Commands>` to make it optional.
```console
$ 03_04_subcommands_derive
? failed
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_04_subcommands_derive[EXE] <COMMAND>
Commands:
add Adds files to myapp
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
```
Since we specified [`#[command(propagate_version = true)]`][crate::Command::propagate_version],
the `--version` flag is available in all subcommands:
```console
$ 03_04_subcommands_derive --version
clap [..]
$ 03_04_subcommands_derive add --version
clap-add [..]
```

View File

@ -0,0 +1,27 @@
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Adds files to myapp
Add { name: Option<String> },
}
fn main() {
let cli = Cli::parse();
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
match &cli.command {
Commands::Add { name } => {
println!("'myapp add' was used, name is: {name:?}")
}
}
}

View File

@ -0,0 +1,32 @@
use clap::{Args, Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Adds files to myapp
Add(AddArgs),
}
#[derive(Args)]
struct AddArgs {
name: Option<String>,
}
fn main() {
let cli = Cli::parse();
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
match &cli.command {
Commands::Add(name) => {
println!("'myapp add' was used, name is: {:?}", name.name)
}
}
}

View File

@ -0,0 +1,20 @@
```console
$ 03_05_default_values_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 03_05_default_values_derive[EXE] [PORT]
Arguments:
[PORT] [default: 2020]
Options:
-h, --help Print help
-V, --version Print version
$ 03_05_default_values_derive
port: 2020
$ 03_05_default_values_derive 22
port: 22
```

View File

@ -0,0 +1,14 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(default_value_t = 2020)]
port: u16,
}
fn main() {
let cli = Cli::parse();
println!("port: {:?}", cli.port);
}

View File

@ -0,0 +1,47 @@
```console
$ 04_01_enum_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_01_enum_derive[EXE] <MODE>
Arguments:
<MODE>
What mode to run the program in
Possible values:
- fast: Run swiftly
- slow: Crawl slowly but steadily
Options:
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
$ 04_01_enum_derive -h
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_01_enum_derive[EXE] <MODE>
Arguments:
<MODE> What mode to run the program in [possible values: fast, slow]
Options:
-h, --help Print help (see more with '--help')
-V, --version Print version
$ 04_01_enum_derive fast
Hare
$ 04_01_enum_derive slow
Tortoise
$ 04_01_enum_derive medium
? failed
error: invalid value 'medium' for '<MODE>'
[possible values: fast, slow]
For more information, try '--help'.
```

View File

@ -0,0 +1,32 @@
use clap::{Parser, ValueEnum};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// What mode to run the program in
#[arg(value_enum)]
mode: Mode,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum Mode {
/// Run swiftly
Fast,
/// Crawl slowly but steadily
///
/// This paragraph is ignored because there is no long help text for possible values.
Slow,
}
fn main() {
let cli = Cli::parse();
match cli.mode {
Mode::Fast => {
println!("Hare");
}
Mode::Slow => {
println!("Tortoise");
}
}
}

View File

@ -0,0 +1,29 @@
```console
$ 04_02_parse_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_02_parse_derive[EXE] <PORT>
Arguments:
<PORT> Network port to use
Options:
-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
For more information, try '--help'.
$ 04_02_parse_derive 0
? failed
error: invalid value '0' for '<PORT>': 0 is not in 1..=65535
For more information, try '--help'.
```

View File

@ -0,0 +1,15 @@
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Network port to use
#[arg(value_parser = clap::value_parser!(u16).range(1..))]
port: u16,
}
fn main() {
let cli = Cli::parse();
println!("PORT = {}", cli.port);
}

View File

@ -0,0 +1,29 @@
```console
$ 04_02_validate_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_02_validate_derive[EXE] <PORT>
Arguments:
<PORT> Network port to use
Options:
-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
For more information, try '--help'.
$ 04_02_validate_derive 0
? failed
error: invalid value '0' for '<PORT>': port not in range 1-65535
For more information, try '--help'.
```

View File

@ -0,0 +1,34 @@
use std::ops::RangeInclusive;
use clap::Parser;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Network port to use
#[arg(value_parser = port_in_range)]
port: u16,
}
fn main() {
let cli = Cli::parse();
println!("PORT = {}", cli.port);
}
const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
fn port_in_range(s: &str) -> Result<u16, String> {
let port: usize = s
.parse()
.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_RANGE.start(),
PORT_RANGE.end()
))
}
}

View File

@ -0,0 +1,53 @@
```console
$ 04_03_relations_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_03_relations_derive[EXE] [OPTIONS] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
Arguments:
[INPUT_FILE] some regular input
Options:
--set-ver <VER> set version manually
--major auto inc major
--minor auto inc minor
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
-h, --help Print help
-V, --version Print version
$ 04_03_relations_derive
? failed
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'.
$ 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'
Usage: 04_03_relations_derive[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
For more information, try '--help'.
$ 04_03_relations_derive --major -c config.toml
? failed
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'.
$ 04_03_relations_derive --major -c config.toml --spec-in input.txt
Version: 2.2.3
Doing work using input input.txt and config config.toml
```

View File

@ -0,0 +1,75 @@
use clap::{Args, Parser};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(flatten)]
vers: Vers,
/// some regular input
#[arg(group = "input")]
input_file: Option<String>,
/// some special input argument
#[arg(long, group = "input")]
spec_in: Option<String>,
#[arg(short, requires = "input")]
config: Option<String>,
}
#[derive(Args)]
#[group(required = true, multiple = false)]
struct Vers {
/// set version manually
#[arg(long, value_name = "VER")]
set_ver: Option<String>,
/// auto inc major
#[arg(long)]
major: bool,
/// auto inc minor
#[arg(long)]
minor: bool,
/// auto inc patch
#[arg(long)]
patch: bool,
}
fn main() {
let cli = Cli::parse();
// Let's assume the old version 1.2.3
let mut major = 1;
let mut minor = 2;
let mut patch = 3;
// See if --set_ver was used to set the version manually
let vers = &cli.vers;
let version = if let Some(ver) = vers.set_ver.as_deref() {
ver.to_string()
} else {
// Increment the one requested (in a real program, we'd reset the lower numbers)
let (maj, min, pat) = (vers.major, vers.minor, vers.patch);
match (maj, min, pat) {
(true, _, _) => major += 1,
(_, true, _) => minor += 1,
(_, _, true) => patch += 1,
_ => unreachable!(),
};
format!("{major}.{minor}.{patch}")
};
println!("Version: {version}");
// Check for usage of -c
if let Some(config) = cli.config.as_deref() {
let input = cli
.input_file
.as_deref()
.unwrap_or_else(|| cli.spec_in.as_deref().unwrap());
println!("Doing work using input {input} and config {config}");
}
}

View File

@ -0,0 +1,52 @@
```console
$ 04_04_custom_derive --help
A simple to use, efficient, and full-featured Command Line Argument Parser
Usage: 04_04_custom_derive[EXE] [OPTIONS] [INPUT_FILE]
Arguments:
[INPUT_FILE] some regular input
Options:
--set-ver <VER> set version manually
--major auto inc major
--minor auto inc minor
--patch auto inc patch
--spec-in <SPEC_IN> some special input argument
-c <CONFIG>
-h, --help Print help
-V, --version Print version
$ 04_04_custom_derive
? failed
error: Can only modify one version field
Usage: clap [OPTIONS] [INPUT_FILE]
For more information, try '--help'.
$ 04_04_custom_derive --major
Version: 2.2.3
$ 04_04_custom_derive --major --minor
? failed
error: Can only modify one version field
Usage: clap [OPTIONS] [INPUT_FILE]
For more information, try '--help'.
$ 04_04_custom_derive --major -c config.toml
? failed
Version: 2.2.3
error: INPUT_FILE or --spec-in is required when using --config
Usage: clap [OPTIONS] [INPUT_FILE]
For more information, try '--help'.
$ 04_04_custom_derive --major -c config.toml --spec-in input.txt
Version: 2.2.3
Doing work using input input.txt and config config.toml
```

Some files were not shown because too many files have changed in this diff Show More