mirror of
https://github.com/clap-rs/clap
synced 2025-03-04 15:27:16 +00:00
docs(example): Update for value_parser
This commit is contained in:
parent
9a913c40e1
commit
33e94df212
23 changed files with 254 additions and 119 deletions
|
@ -37,9 +37,9 @@ OPTIONS:
|
||||||
Then to directly invoke the command, run:
|
Then to directly invoke the command, run:
|
||||||
```console
|
```console
|
||||||
$ cargo-example example
|
$ cargo-example example
|
||||||
None
|
Ok(None)
|
||||||
|
|
||||||
$ cargo-example example --manifest-path Cargo.toml
|
$ cargo-example example --manifest-path Cargo.toml
|
||||||
Some("Cargo.toml")
|
Ok(Some("Cargo.toml"))
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
||||||
clap::command!("example").arg(
|
clap::command!("example").arg(
|
||||||
clap::arg!(--"manifest-path" <PATH>)
|
clap::arg!(--"manifest-path" <PATH>)
|
||||||
.required(false)
|
.required(false)
|
||||||
.allow_invalid_utf8(true),
|
.value_parser(clap::value_parser!(std::path::PathBuf)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let matches = cmd.get_matches();
|
let matches = cmd.get_matches();
|
||||||
|
@ -16,8 +16,6 @@ fn main() {
|
||||||
Some(("example", matches)) => matches,
|
Some(("example", matches)) => matches,
|
||||||
_ => unreachable!("clap should ensure we don't get here"),
|
_ => unreachable!("clap should ensure we don't get here"),
|
||||||
};
|
};
|
||||||
let manifest_path = matches
|
let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
|
||||||
.value_of_os("manifest-path")
|
|
||||||
.map(std::path::PathBuf::from);
|
|
||||||
println!("{:?}", manifest_path);
|
println!("{:?}", manifest_path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,16 +274,16 @@ Notes:
|
||||||
- Implies `arg.takes_value(true).allow_invalid_utf8(true)`
|
- Implies `arg.takes_value(true).allow_invalid_utf8(true)`
|
||||||
- `from_occurrences`:
|
- `from_occurrences`:
|
||||||
- Implies `arg.takes_value(false).multiple_occurrences(true)`
|
- Implies `arg.takes_value(false).multiple_occurrences(true)`
|
||||||
- Reads from `clap::ArgMatches::occurrences_of` rather than a `value_of` function
|
- Reads from `clap::ArgMatches::occurrences_of` rather than a `get_one` function
|
||||||
- Note: operations on values, like `default_value`, are unlikely to do what you want
|
- Note: operations on values, like `default_value`, are unlikely to do what you want
|
||||||
- `from_flag`
|
- `from_flag`
|
||||||
- Implies `arg.takes_value(false)`
|
- Implies `arg.takes_value(false)`
|
||||||
- Reads from `clap::ArgMatches::is_present` rather than a `value_of` function
|
- Reads from `clap::ArgMatches::is_present` rather than a `get_one` function
|
||||||
- Note: operations on values, like `default_value`, are unlikely to do what you want
|
- Note: operations on values, like `default_value`, are unlikely to do what you want
|
||||||
|
|
||||||
**Warning:**
|
**Warning:**
|
||||||
- To support non-UTF8 paths, you must use `parse(from_os_str)`, otherwise
|
- To support non-UTF8 paths, you should use `#[clap(value_parser)]` otherwise
|
||||||
`clap` will use `clap::ArgMatches::value_of` with `PathBuf::FromStr`.
|
`clap` will parse it as a `String` which will fail on some paths.
|
||||||
|
|
||||||
## Doc Comments
|
## Doc Comments
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,44 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command};
|
use clap::{arg, command, value_parser};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = command!()
|
let matches = command!()
|
||||||
.arg(arg!(eff: -f))
|
.arg(arg!(eff: -f))
|
||||||
.arg(arg!(pea: -p <PEAR>).required(false))
|
|
||||||
.arg(
|
.arg(
|
||||||
arg!(slop: [SLOP]).multiple_occurrences(true).last(true), // Indicates that `slop` is only accessible after `--`.
|
arg!(pea: -p <PEAR>)
|
||||||
|
.required(false)
|
||||||
|
.value_parser(value_parser!(String)),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
// Indicates that `slop` is only accessible after `--`.
|
||||||
|
arg!(slop: [SLOP])
|
||||||
|
.multiple_occurrences(true)
|
||||||
|
.last(true)
|
||||||
|
.value_parser(value_parser!(String)),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// This is what will happen with `myprog -f -p=bob -- sloppy slop slop`...
|
// This is what will happen with `myprog -f -p=bob -- sloppy slop slop`...
|
||||||
println!("-f used: {:?}", matches.is_present("eff")); // -f used: true
|
|
||||||
println!("-p's value: {:?}", matches.value_of("pea")); // -p's value: Some("bob")
|
// -f used: true
|
||||||
|
println!("-f used: {:?}", matches.is_present("eff"));
|
||||||
|
// -p's value: Some("bob")
|
||||||
|
println!(
|
||||||
|
"-p's value: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("pea")
|
||||||
|
.expect("matches definition")
|
||||||
|
);
|
||||||
|
// 'slops' values: Some(["sloppy", "slop", "slop"])
|
||||||
println!(
|
println!(
|
||||||
"'slops' values: {:?}",
|
"'slops' values: {:?}",
|
||||||
matches
|
matches
|
||||||
.values_of("slop")
|
.get_many::<String>("slop")
|
||||||
|
.expect("matches definition")
|
||||||
.map(|vals| vals.collect::<Vec<_>>())
|
.map(|vals| vals.collect::<Vec<_>>())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
); // 'slops' values: Some(["sloppy", "slop", "slop"])
|
);
|
||||||
|
|
||||||
// Continued program logic goes here...
|
// Continued program logic goes here...
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{arg, Command};
|
use clap::{arg, Command};
|
||||||
|
@ -27,7 +28,7 @@ fn cli() -> Command<'static> {
|
||||||
Command::new("add")
|
Command::new("add")
|
||||||
.about("adds things")
|
.about("adds things")
|
||||||
.arg_required_else_help(true)
|
.arg_required_else_help(true)
|
||||||
.arg(arg!(<PATH> ... "Stuff to add").allow_invalid_utf8(true)),
|
.arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
Command::new("stash")
|
Command::new("stash")
|
||||||
|
@ -50,20 +51,27 @@ fn main() {
|
||||||
Some(("clone", sub_matches)) => {
|
Some(("clone", sub_matches)) => {
|
||||||
println!(
|
println!(
|
||||||
"Cloning {}",
|
"Cloning {}",
|
||||||
sub_matches.value_of("REMOTE").expect("required")
|
sub_matches
|
||||||
|
.get_one::<String>("REMOTE")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(("push", sub_matches)) => {
|
Some(("push", sub_matches)) => {
|
||||||
println!(
|
println!(
|
||||||
"Pushing to {}",
|
"Pushing to {}",
|
||||||
sub_matches.value_of("REMOTE").expect("required")
|
sub_matches
|
||||||
|
.get_one::<String>("REMOTE")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(("add", sub_matches)) => {
|
Some(("add", sub_matches)) => {
|
||||||
let paths = sub_matches
|
let paths = sub_matches
|
||||||
.values_of_os("PATH")
|
.get_many::<PathBuf>("PATH")
|
||||||
.unwrap_or_default()
|
.expect("matches definition")
|
||||||
.map(PathBuf::from)
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
println!("Adding {:?}", paths);
|
println!("Adding {:?}", paths);
|
||||||
}
|
}
|
||||||
|
@ -71,15 +79,21 @@ fn main() {
|
||||||
let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches));
|
let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches));
|
||||||
match stash_command {
|
match stash_command {
|
||||||
("apply", sub_matches) => {
|
("apply", sub_matches) => {
|
||||||
let stash = sub_matches.value_of("STASH");
|
let stash = sub_matches
|
||||||
|
.get_one::<String>("STASH")
|
||||||
|
.expect("matches definition");
|
||||||
println!("Applying {:?}", stash);
|
println!("Applying {:?}", stash);
|
||||||
}
|
}
|
||||||
("pop", sub_matches) => {
|
("pop", sub_matches) => {
|
||||||
let stash = sub_matches.value_of("STASH");
|
let stash = sub_matches
|
||||||
|
.get_one::<String>("STASH")
|
||||||
|
.expect("matches definition");
|
||||||
println!("Popping {:?}", stash);
|
println!("Popping {:?}", stash);
|
||||||
}
|
}
|
||||||
("push", sub_matches) => {
|
("push", sub_matches) => {
|
||||||
let message = sub_matches.value_of("message");
|
let message = sub_matches
|
||||||
|
.get_one::<String>("message")
|
||||||
|
.expect("matches definition");
|
||||||
println!("Pushing {:?}", message);
|
println!("Pushing {:?}", message);
|
||||||
}
|
}
|
||||||
(name, _) => {
|
(name, _) => {
|
||||||
|
@ -89,8 +103,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
Some((ext, sub_matches)) => {
|
Some((ext, sub_matches)) => {
|
||||||
let args = sub_matches
|
let args = sub_matches
|
||||||
.values_of_os("")
|
.get_many::<OsString>("")
|
||||||
.unwrap_or_default()
|
.expect("matches definition")
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
println!("Calling out to {:?} with {:?}", ext, args);
|
println!("Calling out to {:?} with {:?}", ext, args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
use clap::{Arg, Command};
|
use clap::{value_parser, Arg, Command};
|
||||||
|
|
||||||
fn applet_commands() -> [Command<'static>; 2] {
|
fn applet_commands() -> [Command<'static>; 2] {
|
||||||
[
|
[
|
||||||
|
@ -24,6 +25,7 @@ fn main() {
|
||||||
.exclusive(true)
|
.exclusive(true)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_missing_value("/usr/local/bin")
|
.default_missing_value("/usr/local/bin")
|
||||||
|
.value_parser(value_parser!(PathBuf))
|
||||||
.use_value_delimiter(false),
|
.use_value_delimiter(false),
|
||||||
)
|
)
|
||||||
.subcommands(applet_commands()),
|
.subcommands(applet_commands()),
|
||||||
|
|
|
@ -71,13 +71,23 @@ fn main() {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("sync", sync_matches)) => {
|
Some(("sync", sync_matches)) => {
|
||||||
if sync_matches.is_present("search") {
|
if sync_matches.is_present("search") {
|
||||||
let packages: Vec<_> = sync_matches.values_of("search").unwrap().collect();
|
let packages: Vec<_> = sync_matches
|
||||||
|
.get_many::<String>("search")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("is present")
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.collect();
|
||||||
let values = packages.join(", ");
|
let values = packages.join(", ");
|
||||||
println!("Searching for {}...", values);
|
println!("Searching for {}...", values);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let packages: Vec<_> = sync_matches.values_of("package").unwrap().collect();
|
let packages: Vec<_> = sync_matches
|
||||||
|
.get_many::<String>("package")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("is present")
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.collect();
|
||||||
let values = packages.join(", ");
|
let values = packages.join(", ");
|
||||||
|
|
||||||
if sync_matches.is_present("info") {
|
if sync_matches.is_present("info") {
|
||||||
|
@ -87,11 +97,17 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(("query", query_matches)) => {
|
Some(("query", query_matches)) => {
|
||||||
if let Some(packages) = query_matches.values_of("info") {
|
if let Some(packages) = query_matches
|
||||||
let comma_sep = packages.collect::<Vec<_>>().join(", ");
|
.get_many::<String>("info")
|
||||||
|
.expect("matches definition")
|
||||||
|
{
|
||||||
|
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.values_of("search") {
|
} else if let Some(queries) = query_matches
|
||||||
let comma_sep = queries.collect::<Vec<_>>().join(", ");
|
.get_many::<String>("search")
|
||||||
|
.expect("matches definition")
|
||||||
|
{
|
||||||
|
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 {
|
} else {
|
||||||
println!("Displaying all locally installed packages...");
|
println!("Displaying all locally installed packages...");
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command, Command};
|
use std::path::PathBuf;
|
||||||
use std::path::Path;
|
|
||||||
|
use clap::{arg, command, value_parser, Command};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = command!()
|
let matches = command!()
|
||||||
|
@ -12,8 +13,7 @@ fn main() {
|
||||||
)
|
)
|
||||||
// We don't have syntax yet for optional options, so manually calling `required`
|
// We don't have syntax yet for optional options, so manually calling `required`
|
||||||
.required(false)
|
.required(false)
|
||||||
// Support non-UTF8 paths
|
.value_parser(value_parser!(PathBuf)),
|
||||||
.allow_invalid_utf8(true),
|
|
||||||
)
|
)
|
||||||
.arg(arg!(
|
.arg(arg!(
|
||||||
-d --debug ... "Turn debugging information on"
|
-d --debug ... "Turn debugging information on"
|
||||||
|
@ -26,12 +26,17 @@ fn main() {
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// You can check the value provided by positional arguments, or option arguments
|
// You can check the value provided by positional arguments, or option arguments
|
||||||
if let Some(name) = matches.value_of("name") {
|
if let Some(name) = matches
|
||||||
|
.get_one::<String>("name")
|
||||||
|
.expect("matches definition")
|
||||||
|
{
|
||||||
println!("Value for name: {}", name);
|
println!("Value for name: {}", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(raw_config) = matches.value_of_os("config") {
|
if let Some(config_path) = matches
|
||||||
let config_path = Path::new(raw_config);
|
.get_one::<PathBuf>("config")
|
||||||
|
.expect("matches definition")
|
||||||
|
{
|
||||||
println!("Value for config: {}", config_path.display());
|
println!("Value for config: {}", config_path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,18 @@ fn main() {
|
||||||
.arg(arg!(--one <VALUE>))
|
.arg(arg!(--one <VALUE>))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
println!("two: {:?}", matches.value_of("two").expect("required"));
|
println!(
|
||||||
println!("one: {:?}", matches.value_of("one").expect("required"));
|
"two: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("two")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"one: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("one")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,18 @@ fn main() {
|
||||||
.arg(arg!(--one <VALUE>))
|
.arg(arg!(--one <VALUE>))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
println!("two: {:?}", matches.value_of("two").expect("required"));
|
println!(
|
||||||
println!("one: {:?}", matches.value_of("one").expect("required"));
|
"two: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("two")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"one: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("one")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,18 @@ fn main() {
|
||||||
.arg(arg!(--one <VALUE>))
|
.arg(arg!(--one <VALUE>))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
println!("two: {:?}", matches.value_of("two").expect("required"));
|
println!(
|
||||||
println!("one: {:?}", matches.value_of("one").expect("required"));
|
"two: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("two")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"one: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("one")
|
||||||
|
.expect("matches definition")
|
||||||
|
.expect("required")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,10 @@ fn main() {
|
||||||
.arg(arg!(-n --name <NAME>).required(false))
|
.arg(arg!(-n --name <NAME>).required(false))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
println!("name: {:?}", matches.value_of("name"));
|
println!(
|
||||||
|
"name: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("name")
|
||||||
|
.expect("matches definition")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,10 @@ use clap::{arg, command};
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = command!().arg(arg!([NAME])).get_matches();
|
let matches = command!().arg(arg!([NAME])).get_matches();
|
||||||
|
|
||||||
println!("NAME: {:?}", matches.value_of("NAME"));
|
println!(
|
||||||
|
"NAME: {:?}",
|
||||||
|
matches
|
||||||
|
.get_one::<String>("NAME")
|
||||||
|
.expect("matches definition")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@ fn main() {
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("add", sub_matches)) => println!(
|
Some(("add", sub_matches)) => println!(
|
||||||
"'myapp add' was used, name is: {:?}",
|
"'myapp add' was used, name is: {:?}",
|
||||||
sub_matches.value_of("NAME")
|
sub_matches
|
||||||
|
.get_one::<String>("NAME")
|
||||||
|
.expect("matches definition")
|
||||||
),
|
),
|
||||||
_ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
|
_ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,8 @@ fn main() {
|
||||||
println!(
|
println!(
|
||||||
"NAME: {:?}",
|
"NAME: {:?}",
|
||||||
matches
|
matches
|
||||||
.value_of("NAME")
|
.get_one::<String>("NAME")
|
||||||
|
.expect("matches definition")
|
||||||
.expect("default ensures there is always a value")
|
.expect("default ensures there is always a value")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command, ArgEnum, PossibleValue};
|
use clap::{arg, command, value_parser, ArgEnum};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ArgEnum)]
|
||||||
enum Mode {
|
enum Mode {
|
||||||
|
@ -8,48 +8,19 @@ enum Mode {
|
||||||
Slow,
|
Slow,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mode {
|
|
||||||
pub fn possible_values() -> impl Iterator<Item = PossibleValue<'static>> {
|
|
||||||
Mode::value_variants()
|
|
||||||
.iter()
|
|
||||||
.filter_map(ArgEnum::to_possible_value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
fn main() {
|
||||||
let matches = command!()
|
let matches = command!()
|
||||||
.arg(
|
.arg(
|
||||||
arg!(<MODE>)
|
arg!(<MODE>)
|
||||||
.help("What mode to run the program in")
|
.help("What mode to run the program in")
|
||||||
.possible_values(Mode::possible_values()),
|
.value_parser(value_parser!(Mode)),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// Note, it's safe to call unwrap() because the arg is required
|
// Note, it's safe to call unwrap() because the arg is required
|
||||||
match matches
|
match matches
|
||||||
.value_of_t("MODE")
|
.get_one::<Mode>("MODE")
|
||||||
|
.expect("matches definition")
|
||||||
.expect("'MODE' is required and parsing will fail if its missing")
|
.expect("'MODE' is required and parsing will fail if its missing")
|
||||||
{
|
{
|
||||||
Mode::Fast => {
|
Mode::Fast => {
|
||||||
|
|
|
@ -7,14 +7,16 @@ fn main() {
|
||||||
.arg(
|
.arg(
|
||||||
arg!(<MODE>)
|
arg!(<MODE>)
|
||||||
.help("What mode to run the program in")
|
.help("What mode to run the program in")
|
||||||
.possible_values(["fast", "slow"]),
|
.value_parser(["fast", "slow"]),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// Note, it's safe to call unwrap() because the arg is required
|
// Note, it's safe to call unwrap() because the arg is required
|
||||||
match matches
|
match matches
|
||||||
.value_of("MODE")
|
.get_one::<String>("MODE")
|
||||||
|
.expect("matches definition")
|
||||||
.expect("'MODE' is required and parsing will fail if its missing")
|
.expect("'MODE' is required and parsing will fail if its missing")
|
||||||
|
.as_str()
|
||||||
{
|
{
|
||||||
"fast" => {
|
"fast" => {
|
||||||
println!("Hare");
|
println!("Hare");
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command};
|
use clap::{arg, command, value_parser};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = command!()
|
let matches = command!()
|
||||||
.arg(
|
.arg(
|
||||||
arg!(<PORT>)
|
arg!(<PORT>)
|
||||||
.help("Network port to use")
|
.help("Network port to use")
|
||||||
.validator(|s| s.parse::<usize>()),
|
.value_parser(value_parser!(u16).range(1..)),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// Note, it's safe to call unwrap() because the arg is required
|
// Note, it's safe to call unwrap() because the arg is required
|
||||||
let port: usize = matches
|
let port: u16 = *matches
|
||||||
.value_of_t("PORT")
|
.get_one::<u16>("PORT")
|
||||||
|
.expect("matches definition")
|
||||||
.expect("'PORT' is required and parsing will fail if its missing");
|
.expect("'PORT' is required and parsing will fail if its missing");
|
||||||
println!("PORT = {}", port);
|
println!("PORT = {}", port);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,25 +9,26 @@ fn main() {
|
||||||
.arg(
|
.arg(
|
||||||
arg!(<PORT>)
|
arg!(<PORT>)
|
||||||
.help("Network port to use")
|
.help("Network port to use")
|
||||||
.validator(port_in_range),
|
.value_parser(port_in_range),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// Note, it's safe to call unwrap() because the arg is required
|
// Note, it's safe to call unwrap() because the arg is required
|
||||||
let port: usize = matches
|
let port: u16 = *matches
|
||||||
.value_of_t("PORT")
|
.get_one::<u16>("PORT")
|
||||||
|
.expect("matches definition")
|
||||||
.expect("'PORT' is required and parsing will fail if its missing");
|
.expect("'PORT' is required and parsing will fail if its missing");
|
||||||
println!("PORT = {}", port);
|
println!("PORT = {}", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
|
const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
|
||||||
|
|
||||||
fn port_in_range(s: &str) -> Result<(), String> {
|
fn port_in_range(s: &str) -> Result<u16, String> {
|
||||||
let port: usize = s
|
let port: usize = s
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| format!("`{}` isn't a port number", s))?;
|
.map_err(|_| format!("`{}` isn't a port number", s))?;
|
||||||
if PORT_RANGE.contains(&port) {
|
if PORT_RANGE.contains(&port) {
|
||||||
Ok(())
|
Ok(port as u16)
|
||||||
} else {
|
} else {
|
||||||
Err(format!(
|
Err(format!(
|
||||||
"Port not in range {}-{}",
|
"Port not in range {}-{}",
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command, ArgGroup};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use clap::{arg, command, value_parser, ArgGroup};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create application like normal
|
// Create application like normal
|
||||||
|
@ -18,15 +20,25 @@ fn main() {
|
||||||
)
|
)
|
||||||
// Arguments can also be added to a group individually, these two arguments
|
// Arguments can also be added to a group individually, these two arguments
|
||||||
// are part of the "input" group which is not required
|
// are part of the "input" group which is not required
|
||||||
.arg(arg!([INPUT_FILE] "some regular input").group("input"))
|
.arg(
|
||||||
|
arg!([INPUT_FILE] "some regular input")
|
||||||
|
.value_parser(value_parser!(PathBuf))
|
||||||
|
.group("input"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
arg!(--"spec-in" <SPEC_IN> "some special input argument")
|
arg!(--"spec-in" <SPEC_IN> "some special input argument")
|
||||||
.required(false)
|
.required(false)
|
||||||
|
.value_parser(value_parser!(PathBuf))
|
||||||
.group("input"),
|
.group("input"),
|
||||||
)
|
)
|
||||||
// Now let's assume we have a -c [config] argument which requires one of
|
// Now let's assume we have a -c [config] argument which requires one of
|
||||||
// (but **not** both) the "input" arguments
|
// (but **not** both) the "input" arguments
|
||||||
.arg(arg!(config: -c <CONFIG>).required(false).requires("input"))
|
.arg(
|
||||||
|
arg!(config: -c <CONFIG>)
|
||||||
|
.required(false)
|
||||||
|
.value_parser(value_parser!(PathBuf))
|
||||||
|
.requires("input"),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
// Let's assume the old version 1.2.3
|
// Let's assume the old version 1.2.3
|
||||||
|
@ -35,8 +47,11 @@ fn main() {
|
||||||
let mut patch = 3;
|
let mut patch = 3;
|
||||||
|
|
||||||
// See if --set-ver was used to set the version manually
|
// See if --set-ver was used to set the version manually
|
||||||
let version = if let Some(ver) = matches.value_of("set-ver") {
|
let version = if let Some(ver) = matches
|
||||||
ver.to_string()
|
.get_one::<String>("set-ver")
|
||||||
|
.expect("matches definition")
|
||||||
|
{
|
||||||
|
ver.to_owned()
|
||||||
} else {
|
} else {
|
||||||
// Increment the one requested (in a real program, we'd reset the lower numbers)
|
// Increment the one requested (in a real program, we'd reset the lower numbers)
|
||||||
let (maj, min, pat) = (
|
let (maj, min, pat) = (
|
||||||
|
@ -58,12 +73,23 @@ fn main() {
|
||||||
// Check for usage of -c
|
// Check for usage of -c
|
||||||
if matches.is_present("config") {
|
if matches.is_present("config") {
|
||||||
let input = matches
|
let input = matches
|
||||||
.value_of("INPUT_FILE")
|
.get_one::<PathBuf>("INPUT_FILE")
|
||||||
.unwrap_or_else(|| matches.value_of("spec-in").unwrap());
|
.expect("matches definition")
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
matches
|
||||||
|
.get_one::<PathBuf>("spec-in")
|
||||||
|
.expect("matches definition")
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.display();
|
||||||
println!(
|
println!(
|
||||||
"Doing work using input {} and config {}",
|
"Doing work using input {} and config {}",
|
||||||
input,
|
input,
|
||||||
matches.value_of("config").unwrap()
|
matches
|
||||||
|
.get_one::<PathBuf>("config")
|
||||||
|
.expect("matches definition")
|
||||||
|
.unwrap()
|
||||||
|
.display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command, ErrorKind};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use clap::{arg, command, value_parser, ErrorKind};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Create application like normal
|
// Create application like normal
|
||||||
|
@ -12,11 +14,19 @@ fn main() {
|
||||||
.arg(arg!(--patch "auto inc patch"))
|
.arg(arg!(--patch "auto inc patch"))
|
||||||
// Arguments can also be added to a group individually, these two arguments
|
// Arguments can also be added to a group individually, these two arguments
|
||||||
// are part of the "input" group which is not required
|
// are part of the "input" group which is not required
|
||||||
.arg(arg!([INPUT_FILE] "some regular input"))
|
.arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf)))
|
||||||
.arg(arg!(--"spec-in" <SPEC_IN> "some special input argument").required(false))
|
.arg(
|
||||||
|
arg!(--"spec-in" <SPEC_IN> "some special input argument")
|
||||||
|
.required(false)
|
||||||
|
.value_parser(value_parser!(PathBuf)),
|
||||||
|
)
|
||||||
// Now let's assume we have a -c [config] argument which requires one of
|
// Now let's assume we have a -c [config] argument which requires one of
|
||||||
// (but **not** both) the "input" arguments
|
// (but **not** both) the "input" arguments
|
||||||
.arg(arg!(config: -c <CONFIG>).required(false));
|
.arg(
|
||||||
|
arg!(config: -c <CONFIG>)
|
||||||
|
.required(false)
|
||||||
|
.value_parser(value_parser!(PathBuf)),
|
||||||
|
);
|
||||||
let matches = cmd.get_matches_mut();
|
let matches = cmd.get_matches_mut();
|
||||||
|
|
||||||
// Let's assume the old version 1.2.3
|
// Let's assume the old version 1.2.3
|
||||||
|
@ -25,7 +35,10 @@ fn main() {
|
||||||
let mut patch = 3;
|
let mut patch = 3;
|
||||||
|
|
||||||
// See if --set-ver was used to set the version manually
|
// See if --set-ver was used to set the version manually
|
||||||
let version = if let Some(ver) = matches.value_of("set-ver") {
|
let version = if let Some(ver) = matches
|
||||||
|
.get_one::<String>("set-ver")
|
||||||
|
.expect("matches definition")
|
||||||
|
{
|
||||||
if matches.is_present("major") || matches.is_present("minor") || matches.is_present("patch")
|
if matches.is_present("major") || matches.is_present("minor") || matches.is_present("patch")
|
||||||
{
|
{
|
||||||
cmd.error(
|
cmd.error(
|
||||||
|
@ -62,19 +75,29 @@ fn main() {
|
||||||
// Check for usage of -c
|
// Check for usage of -c
|
||||||
if matches.is_present("config") {
|
if matches.is_present("config") {
|
||||||
let input = matches
|
let input = matches
|
||||||
.value_of("INPUT_FILE")
|
.get_one::<PathBuf>("INPUT_FILE")
|
||||||
.or_else(|| matches.value_of("spec-in"))
|
.expect("matches definition")
|
||||||
|
.or_else(|| {
|
||||||
|
matches
|
||||||
|
.get_one::<PathBuf>("spec-in")
|
||||||
|
.expect("matches definition")
|
||||||
|
})
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
cmd.error(
|
cmd.error(
|
||||||
ErrorKind::MissingRequiredArgument,
|
ErrorKind::MissingRequiredArgument,
|
||||||
"INPUT_FILE or --spec-in is required when using --config",
|
"INPUT_FILE or --spec-in is required when using --config",
|
||||||
)
|
)
|
||||||
.exit()
|
.exit()
|
||||||
});
|
})
|
||||||
|
.display();
|
||||||
println!(
|
println!(
|
||||||
"Doing work using input {} and config {}",
|
"Doing work using input {} and config {}",
|
||||||
input,
|
input,
|
||||||
matches.value_of("config").unwrap()
|
matches
|
||||||
|
.get_one::<PathBuf>("config")
|
||||||
|
.expect("matches definition")
|
||||||
|
.unwrap()
|
||||||
|
.display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
// Note: this requires the `cargo` feature
|
// Note: this requires the `cargo` feature
|
||||||
|
|
||||||
use clap::{arg, command};
|
use clap::{arg, command, value_parser};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches = cmd().get_matches();
|
let matches = cmd().get_matches();
|
||||||
|
|
||||||
// Note, it's safe to call unwrap() because the arg is required
|
// Note, it's safe to call unwrap() because the arg is required
|
||||||
let port: usize = matches
|
let port: usize = *matches
|
||||||
.value_of_t("PORT")
|
.get_one::<usize>("PORT")
|
||||||
|
.expect("matches definition")
|
||||||
.expect("'PORT' is required and parsing will fail if its missing");
|
.expect("'PORT' is required and parsing will fail if its missing");
|
||||||
println!("PORT = {}", port);
|
println!("PORT = {}", port);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +17,7 @@ fn cmd() -> clap::Command<'static> {
|
||||||
command!().arg(
|
command!().arg(
|
||||||
arg!(<PORT>)
|
arg!(<PORT>)
|
||||||
.help("Network port to use")
|
.help("Network port to use")
|
||||||
.validator(|s| s.parse::<usize>()),
|
.value_parser(value_parser!(usize)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -444,7 +444,7 @@ For more information try --help
|
||||||
|
|
||||||
### Validated values
|
### Validated values
|
||||||
|
|
||||||
More generally, you can parse into any data type.
|
More generally, you can validate and parse into any data type.
|
||||||
|
|
||||||
[Example:](04_02_parse.rs)
|
[Example:](04_02_parse.rs)
|
||||||
```console
|
```console
|
||||||
|
@ -471,9 +471,15 @@ 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
|
||||||
|
|
||||||
|
For more information try --help
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
A custom validator can be used to improve the error messages or provide additional validation:
|
A custom parser can be used to improve the error messages or provide additional validation:
|
||||||
|
|
||||||
[Example:](04_02_validate.rs)
|
[Example:](04_02_validate.rs)
|
||||||
```console
|
```console
|
||||||
|
|
Loading…
Add table
Reference in a new issue