mirror of
https://github.com/clap-rs/clap
synced 2024-12-12 13:52:34 +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:
|
||||
```console
|
||||
$ cargo-example example
|
||||
None
|
||||
Ok(None)
|
||||
|
||||
$ 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::arg!(--"manifest-path" <PATH>)
|
||||
.required(false)
|
||||
.allow_invalid_utf8(true),
|
||||
.value_parser(clap::value_parser!(std::path::PathBuf)),
|
||||
),
|
||||
);
|
||||
let matches = cmd.get_matches();
|
||||
|
@ -16,8 +16,6 @@ fn main() {
|
|||
Some(("example", matches)) => matches,
|
||||
_ => unreachable!("clap should ensure we don't get here"),
|
||||
};
|
||||
let manifest_path = matches
|
||||
.value_of_os("manifest-path")
|
||||
.map(std::path::PathBuf::from);
|
||||
let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
|
||||
println!("{:?}", manifest_path);
|
||||
}
|
||||
|
|
|
@ -274,16 +274,16 @@ Notes:
|
|||
- Implies `arg.takes_value(true).allow_invalid_utf8(true)`
|
||||
- `from_occurrences`:
|
||||
- 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
|
||||
- `from_flag`
|
||||
- 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
|
||||
|
||||
**Warning:**
|
||||
- To support non-UTF8 paths, you must use `parse(from_os_str)`, otherwise
|
||||
`clap` will use `clap::ArgMatches::value_of` with `PathBuf::FromStr`.
|
||||
- To support non-UTF8 paths, you should use `#[clap(value_parser)]` otherwise
|
||||
`clap` will parse it as a `String` which will fail on some paths.
|
||||
|
||||
## Doc Comments
|
||||
|
||||
|
|
|
@ -1,26 +1,44 @@
|
|||
// Note: this requires the `cargo` feature
|
||||
|
||||
use clap::{arg, command};
|
||||
use clap::{arg, command, value_parser};
|
||||
|
||||
fn main() {
|
||||
let matches = command!()
|
||||
.arg(arg!(eff: -f))
|
||||
.arg(arg!(pea: -p <PEAR>).required(false))
|
||||
.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();
|
||||
|
||||
// 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!(
|
||||
"'slops' values: {:?}",
|
||||
matches
|
||||
.values_of("slop")
|
||||
.get_many::<String>("slop")
|
||||
.expect("matches definition")
|
||||
.map(|vals| vals.collect::<Vec<_>>())
|
||||
.unwrap_or_default()
|
||||
); // 'slops' values: Some(["sloppy", "slop", "slop"])
|
||||
);
|
||||
|
||||
// Continued program logic goes here...
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Note: this requires the `cargo` feature
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{arg, Command};
|
||||
|
@ -27,7 +28,7 @@ fn cli() -> Command<'static> {
|
|||
Command::new("add")
|
||||
.about("adds things")
|
||||
.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(
|
||||
Command::new("stash")
|
||||
|
@ -50,20 +51,27 @@ fn main() {
|
|||
Some(("clone", sub_matches)) => {
|
||||
println!(
|
||||
"Cloning {}",
|
||||
sub_matches.value_of("REMOTE").expect("required")
|
||||
sub_matches
|
||||
.get_one::<String>("REMOTE")
|
||||
.expect("matches definition")
|
||||
.expect("required")
|
||||
);
|
||||
}
|
||||
Some(("push", sub_matches)) => {
|
||||
println!(
|
||||
"Pushing to {}",
|
||||
sub_matches.value_of("REMOTE").expect("required")
|
||||
sub_matches
|
||||
.get_one::<String>("REMOTE")
|
||||
.expect("matches definition")
|
||||
.expect("required")
|
||||
);
|
||||
}
|
||||
Some(("add", sub_matches)) => {
|
||||
let paths = sub_matches
|
||||
.values_of_os("PATH")
|
||||
.unwrap_or_default()
|
||||
.map(PathBuf::from)
|
||||
.get_many::<PathBuf>("PATH")
|
||||
.expect("matches definition")
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
println!("Adding {:?}", paths);
|
||||
}
|
||||
|
@ -71,15 +79,21 @@ fn main() {
|
|||
let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches));
|
||||
match stash_command {
|
||||
("apply", sub_matches) => {
|
||||
let stash = sub_matches.value_of("STASH");
|
||||
let stash = sub_matches
|
||||
.get_one::<String>("STASH")
|
||||
.expect("matches definition");
|
||||
println!("Applying {:?}", stash);
|
||||
}
|
||||
("pop", sub_matches) => {
|
||||
let stash = sub_matches.value_of("STASH");
|
||||
let stash = sub_matches
|
||||
.get_one::<String>("STASH")
|
||||
.expect("matches definition");
|
||||
println!("Popping {:?}", stash);
|
||||
}
|
||||
("push", sub_matches) => {
|
||||
let message = sub_matches.value_of("message");
|
||||
let message = sub_matches
|
||||
.get_one::<String>("message")
|
||||
.expect("matches definition");
|
||||
println!("Pushing {:?}", message);
|
||||
}
|
||||
(name, _) => {
|
||||
|
@ -89,8 +103,10 @@ fn main() {
|
|||
}
|
||||
Some((ext, sub_matches)) => {
|
||||
let args = sub_matches
|
||||
.values_of_os("")
|
||||
.unwrap_or_default()
|
||||
.get_many::<OsString>("")
|
||||
.expect("matches definition")
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
println!("Calling out to {:?} with {:?}", ext, args);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
|
||||
use clap::{Arg, Command};
|
||||
use clap::{value_parser, Arg, Command};
|
||||
|
||||
fn applet_commands() -> [Command<'static>; 2] {
|
||||
[
|
||||
|
@ -24,6 +25,7 @@ fn main() {
|
|||
.exclusive(true)
|
||||
.takes_value(true)
|
||||
.default_missing_value("/usr/local/bin")
|
||||
.value_parser(value_parser!(PathBuf))
|
||||
.use_value_delimiter(false),
|
||||
)
|
||||
.subcommands(applet_commands()),
|
||||
|
|
|
@ -71,13 +71,23 @@ fn main() {
|
|||
match matches.subcommand() {
|
||||
Some(("sync", sync_matches)) => {
|
||||
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(", ");
|
||||
println!("Searching for {}...", values);
|
||||
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(", ");
|
||||
|
||||
if sync_matches.is_present("info") {
|
||||
|
@ -87,11 +97,17 @@ fn main() {
|
|||
}
|
||||
}
|
||||
Some(("query", query_matches)) => {
|
||||
if let Some(packages) = query_matches.values_of("info") {
|
||||
let comma_sep = packages.collect::<Vec<_>>().join(", ");
|
||||
if let Some(packages) = query_matches
|
||||
.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);
|
||||
} else if let Some(queries) = query_matches.values_of("search") {
|
||||
let comma_sep = queries.collect::<Vec<_>>().join(", ");
|
||||
} else if let Some(queries) = query_matches
|
||||
.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);
|
||||
} else {
|
||||
println!("Displaying all locally installed packages...");
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// Note: this requires the `cargo` feature
|
||||
|
||||
use clap::{arg, command, Command};
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{arg, command, value_parser, Command};
|
||||
|
||||
fn main() {
|
||||
let matches = command!()
|
||||
|
@ -12,8 +13,7 @@ fn main() {
|
|||
)
|
||||
// We don't have syntax yet for optional options, so manually calling `required`
|
||||
.required(false)
|
||||
// Support non-UTF8 paths
|
||||
.allow_invalid_utf8(true),
|
||||
.value_parser(value_parser!(PathBuf)),
|
||||
)
|
||||
.arg(arg!(
|
||||
-d --debug ... "Turn debugging information on"
|
||||
|
@ -26,12 +26,17 @@ fn main() {
|
|||
.get_matches();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if let Some(raw_config) = matches.value_of_os("config") {
|
||||
let config_path = Path::new(raw_config);
|
||||
if let Some(config_path) = matches
|
||||
.get_one::<PathBuf>("config")
|
||||
.expect("matches definition")
|
||||
{
|
||||
println!("Value for config: {}", config_path.display());
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,18 @@ fn main() {
|
|||
.arg(arg!(--one <VALUE>))
|
||||
.get_matches();
|
||||
|
||||
println!("two: {:?}", matches.value_of("two").expect("required"));
|
||||
println!("one: {:?}", matches.value_of("one").expect("required"));
|
||||
println!(
|
||||
"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>))
|
||||
.get_matches();
|
||||
|
||||
println!("two: {:?}", matches.value_of("two").expect("required"));
|
||||
println!("one: {:?}", matches.value_of("one").expect("required"));
|
||||
println!(
|
||||
"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>))
|
||||
.get_matches();
|
||||
|
||||
println!("two: {:?}", matches.value_of("two").expect("required"));
|
||||
println!("one: {:?}", matches.value_of("one").expect("required"));
|
||||
println!(
|
||||
"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))
|
||||
.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() {
|
||||
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() {
|
||||
Some(("add", sub_matches)) => println!(
|
||||
"'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`"),
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ fn main() {
|
|||
println!(
|
||||
"NAME: {:?}",
|
||||
matches
|
||||
.value_of("NAME")
|
||||
.get_one::<String>("NAME")
|
||||
.expect("matches definition")
|
||||
.expect("default ensures there is always a value")
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// 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)]
|
||||
enum Mode {
|
||||
|
@ -8,48 +8,19 @@ enum Mode {
|
|||
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() {
|
||||
let matches = command!()
|
||||
.arg(
|
||||
arg!(<MODE>)
|
||||
.help("What mode to run the program in")
|
||||
.possible_values(Mode::possible_values()),
|
||||
.value_parser(value_parser!(Mode)),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Note, it's safe to call unwrap() because the arg is required
|
||||
match matches
|
||||
.value_of_t("MODE")
|
||||
.get_one::<Mode>("MODE")
|
||||
.expect("matches definition")
|
||||
.expect("'MODE' is required and parsing will fail if its missing")
|
||||
{
|
||||
Mode::Fast => {
|
||||
|
|
|
@ -7,14 +7,16 @@ fn main() {
|
|||
.arg(
|
||||
arg!(<MODE>)
|
||||
.help("What mode to run the program in")
|
||||
.possible_values(["fast", "slow"]),
|
||||
.value_parser(["fast", "slow"]),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Note, it's safe to call unwrap() because the arg is required
|
||||
match matches
|
||||
.value_of("MODE")
|
||||
.get_one::<String>("MODE")
|
||||
.expect("matches definition")
|
||||
.expect("'MODE' is required and parsing will fail if its missing")
|
||||
.as_str()
|
||||
{
|
||||
"fast" => {
|
||||
println!("Hare");
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
// Note: this requires the `cargo` feature
|
||||
|
||||
use clap::{arg, command};
|
||||
use clap::{arg, command, value_parser};
|
||||
|
||||
fn main() {
|
||||
let matches = command!()
|
||||
.arg(
|
||||
arg!(<PORT>)
|
||||
.help("Network port to use")
|
||||
.validator(|s| s.parse::<usize>()),
|
||||
.value_parser(value_parser!(u16).range(1..)),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Note, it's safe to call unwrap() because the arg is required
|
||||
let port: usize = matches
|
||||
.value_of_t("PORT")
|
||||
let port: u16 = *matches
|
||||
.get_one::<u16>("PORT")
|
||||
.expect("matches definition")
|
||||
.expect("'PORT' is required and parsing will fail if its missing");
|
||||
println!("PORT = {}", port);
|
||||
}
|
||||
|
|
|
@ -9,25 +9,26 @@ fn main() {
|
|||
.arg(
|
||||
arg!(<PORT>)
|
||||
.help("Network port to use")
|
||||
.validator(port_in_range),
|
||||
.value_parser(port_in_range),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Note, it's safe to call unwrap() because the arg is required
|
||||
let port: usize = matches
|
||||
.value_of_t("PORT")
|
||||
let port: u16 = *matches
|
||||
.get_one::<u16>("PORT")
|
||||
.expect("matches definition")
|
||||
.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<(), String> {
|
||||
fn port_in_range(s: &str) -> Result<u16, String> {
|
||||
let port: usize = s
|
||||
.parse()
|
||||
.map_err(|_| format!("`{}` isn't a port number", s))?;
|
||||
if PORT_RANGE.contains(&port) {
|
||||
Ok(())
|
||||
Ok(port as u16)
|
||||
} else {
|
||||
Err(format!(
|
||||
"Port not in range {}-{}",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Note: this requires the `cargo` feature
|
||||
|
||||
use clap::{arg, command, ArgGroup};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{arg, command, value_parser, ArgGroup};
|
||||
|
||||
fn main() {
|
||||
// Create application like normal
|
||||
|
@ -18,15 +20,25 @@ fn main() {
|
|||
)
|
||||
// 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").group("input"))
|
||||
.arg(
|
||||
arg!([INPUT_FILE] "some regular input")
|
||||
.value_parser(value_parser!(PathBuf))
|
||||
.group("input"),
|
||||
)
|
||||
.arg(
|
||||
arg!(--"spec-in" <SPEC_IN> "some special input argument")
|
||||
.required(false)
|
||||
.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>).required(false).requires("input"))
|
||||
.arg(
|
||||
arg!(config: -c <CONFIG>)
|
||||
.required(false)
|
||||
.value_parser(value_parser!(PathBuf))
|
||||
.requires("input"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Let's assume the old version 1.2.3
|
||||
|
@ -35,8 +47,11 @@ fn main() {
|
|||
let mut patch = 3;
|
||||
|
||||
// See if --set-ver was used to set the version manually
|
||||
let version = if let Some(ver) = matches.value_of("set-ver") {
|
||||
ver.to_string()
|
||||
let version = if let Some(ver) = matches
|
||||
.get_one::<String>("set-ver")
|
||||
.expect("matches definition")
|
||||
{
|
||||
ver.to_owned()
|
||||
} else {
|
||||
// Increment the one requested (in a real program, we'd reset the lower numbers)
|
||||
let (maj, min, pat) = (
|
||||
|
@ -58,12 +73,23 @@ fn main() {
|
|||
// Check for usage of -c
|
||||
if matches.is_present("config") {
|
||||
let input = matches
|
||||
.value_of("INPUT_FILE")
|
||||
.unwrap_or_else(|| matches.value_of("spec-in").unwrap());
|
||||
.get_one::<PathBuf>("INPUT_FILE")
|
||||
.expect("matches definition")
|
||||
.unwrap_or_else(|| {
|
||||
matches
|
||||
.get_one::<PathBuf>("spec-in")
|
||||
.expect("matches definition")
|
||||
.unwrap()
|
||||
})
|
||||
.display();
|
||||
println!(
|
||||
"Doing work using input {} and config {}",
|
||||
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
|
||||
|
||||
use clap::{arg, command, ErrorKind};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{arg, command, value_parser, ErrorKind};
|
||||
|
||||
fn main() {
|
||||
// Create application like normal
|
||||
|
@ -12,11 +14,19 @@ fn main() {
|
|||
.arg(arg!(--patch "auto inc 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"))
|
||||
.arg(arg!(--"spec-in" <SPEC_IN> "some special input argument").required(false))
|
||||
.arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf)))
|
||||
.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
|
||||
// (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's assume the old version 1.2.3
|
||||
|
@ -25,7 +35,10 @@ fn main() {
|
|||
let mut patch = 3;
|
||||
|
||||
// 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")
|
||||
{
|
||||
cmd.error(
|
||||
|
@ -62,19 +75,29 @@ fn main() {
|
|||
// Check for usage of -c
|
||||
if matches.is_present("config") {
|
||||
let input = matches
|
||||
.value_of("INPUT_FILE")
|
||||
.or_else(|| matches.value_of("spec-in"))
|
||||
.get_one::<PathBuf>("INPUT_FILE")
|
||||
.expect("matches definition")
|
||||
.or_else(|| {
|
||||
matches
|
||||
.get_one::<PathBuf>("spec-in")
|
||||
.expect("matches definition")
|
||||
})
|
||||
.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.value_of("config").unwrap()
|
||||
matches
|
||||
.get_one::<PathBuf>("config")
|
||||
.expect("matches definition")
|
||||
.unwrap()
|
||||
.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// Note: this requires the `cargo` feature
|
||||
|
||||
use clap::{arg, command};
|
||||
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
|
||||
.value_of_t("PORT")
|
||||
let port: usize = *matches
|
||||
.get_one::<usize>("PORT")
|
||||
.expect("matches definition")
|
||||
.expect("'PORT' is required and parsing will fail if its missing");
|
||||
println!("PORT = {}", port);
|
||||
}
|
||||
|
@ -16,7 +17,7 @@ fn cmd() -> clap::Command<'static> {
|
|||
command!().arg(
|
||||
arg!(<PORT>)
|
||||
.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
|
||||
|
||||
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)
|
||||
```console
|
||||
|
@ -471,9 +471,15 @@ 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
|
||||
|
||||
```
|
||||
|
||||
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)
|
||||
```console
|
||||
|
|
Loading…
Reference in a new issue