mirror of
https://github.com/clap-rs/clap
synced 2024-12-12 22:02:35 +00:00
docs(tutorial): Demonstrate custom parsing
Adds a more in depth validator to validate that the port is in range in the derive and builder tutorial (section 4.2). This supersedes #3416
This commit is contained in:
parent
1b5f9e6450
commit
ee3eab1614
7 changed files with 143 additions and 11 deletions
10
Cargo.toml
10
Cargo.toml
|
@ -240,6 +240,11 @@ name = "04_01_enum"
|
|||
path = "examples/tutorial_builder/04_01_enum.rs"
|
||||
required-features = ["cargo", "derive"]
|
||||
|
||||
[[example]]
|
||||
name = "04_02_parse"
|
||||
path = "examples/tutorial_builder/04_02_parse.rs"
|
||||
required-features = ["cargo"]
|
||||
|
||||
[[example]]
|
||||
name = "04_02_validate"
|
||||
path = "examples/tutorial_builder/04_02_validate.rs"
|
||||
|
@ -316,6 +321,11 @@ name = "04_01_enum_derive"
|
|||
path = "examples/tutorial_derive/04_01_enum.rs"
|
||||
required-features = ["derive"]
|
||||
|
||||
[[example]]
|
||||
name = "04_02_parse_derive"
|
||||
path = "examples/tutorial_derive/04_02_parse.rs"
|
||||
required-features = ["derive"]
|
||||
|
||||
[[example]]
|
||||
name = "04_02_validate_derive"
|
||||
path = "examples/tutorial_derive/04_02_validate.rs"
|
||||
|
|
17
examples/tutorial_builder/04_02_parse.rs
Normal file
17
examples/tutorial_builder/04_02_parse.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use clap::{app_from_crate, arg};
|
||||
|
||||
fn main() {
|
||||
let matches = app_from_crate!()
|
||||
.arg(
|
||||
arg!(<PORT>)
|
||||
.help("Network port to use")
|
||||
.validator(|s| s.parse::<usize>()),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Note, it's safe to call unwrap() because the arg is required
|
||||
let port: usize = matches
|
||||
.value_of_t("PORT")
|
||||
.expect("'PORT' is required and parsing will fail if its missing");
|
||||
println!("PORT = {}", port);
|
||||
}
|
|
@ -1,12 +1,24 @@
|
|||
use clap::{app_from_crate, arg};
|
||||
use std::ops::RangeInclusive;
|
||||
use std::str::FromStr;
|
||||
|
||||
const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
|
||||
|
||||
fn main() {
|
||||
let matches = app_from_crate!()
|
||||
.arg(
|
||||
arg!(<PORT>)
|
||||
.help("Network port to use")
|
||||
.validator(|s| s.parse::<usize>()),
|
||||
)
|
||||
.arg(arg!(<PORT>).help("Network port to use").validator(|s| {
|
||||
usize::from_str(s)
|
||||
.map(|port| PORT_RANGE.contains(&port))
|
||||
.map_err(|e| e.to_string())
|
||||
.and_then(|result| match result {
|
||||
true => Ok(()),
|
||||
false => Err(format!(
|
||||
"Port not in range {}-{}",
|
||||
PORT_RANGE.start(),
|
||||
PORT_RANGE.end()
|
||||
)),
|
||||
})
|
||||
}))
|
||||
.get_matches();
|
||||
|
||||
// Note, it's safe to call unwrap() because the arg is required
|
||||
|
|
|
@ -449,7 +449,36 @@ For more information try --help
|
|||
|
||||
### Validated values
|
||||
|
||||
More generally, you can validate and parse into any data type.
|
||||
More generally, you can parse into any data type.
|
||||
|
||||
[Example:](04_02_parse.rs)
|
||||
```console
|
||||
$ 04_02_parse --help
|
||||
clap [..]
|
||||
A simple to use, efficient, and full-featured Command Line Argument Parser
|
||||
|
||||
USAGE:
|
||||
04_02_parse[EXE] <PORT>
|
||||
|
||||
ARGS:
|
||||
<PORT> Network port to use
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Print help information
|
||||
-V, --version Print version information
|
||||
|
||||
$ 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
|
||||
|
||||
```
|
||||
|
||||
A custom validator can be used to improve the error messages or provide additional validation:
|
||||
|
||||
[Example:](04_02_validate.rs)
|
||||
```console
|
||||
|
@ -470,9 +499,9 @@ OPTIONS:
|
|||
$ 04_02_validate 22
|
||||
PORT = 22
|
||||
|
||||
$ 04_02_validate foobar
|
||||
$ 04_02_validate 0
|
||||
? failed
|
||||
error: Invalid value "foobar" for '<PORT>': invalid digit found in string
|
||||
error: Invalid value "0" for '<PORT>': Port not in range 1-65535
|
||||
|
||||
For more information try --help
|
||||
|
||||
|
|
15
examples/tutorial_derive/04_02_parse.rs
Normal file
15
examples/tutorial_derive/04_02_parse.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use clap::Parser;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// Network port to use
|
||||
#[clap(parse(try_from_str))]
|
||||
port: usize,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
println!("PORT = {}", cli.port);
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
use clap::Parser;
|
||||
use std::ops::RangeInclusive;
|
||||
use std::str::FromStr;
|
||||
|
||||
const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// Network port to use
|
||||
#[clap(parse(try_from_str))]
|
||||
#[clap(validator = port_in_range)]
|
||||
port: usize,
|
||||
}
|
||||
|
||||
|
@ -13,3 +17,17 @@ fn main() {
|
|||
|
||||
println!("PORT = {}", cli.port);
|
||||
}
|
||||
|
||||
fn port_in_range(s: &str) -> Result<(), String> {
|
||||
usize::from_str(s)
|
||||
.map(|port| PORT_RANGE.contains(&port))
|
||||
.map_err(|e| e.to_string())
|
||||
.and_then(|result| match result {
|
||||
true => Ok(()),
|
||||
false => Err(format!(
|
||||
"Port not in range {}-{}",
|
||||
PORT_RANGE.start(),
|
||||
PORT_RANGE.end()
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -417,6 +417,37 @@ For more information try --help
|
|||
|
||||
More generally, you can validate and parse into any data type.
|
||||
|
||||
More generally, you can parse into any data type.
|
||||
|
||||
[Example:](04_02_parse.rs)
|
||||
```console
|
||||
$ 04_02_parse_derive --help
|
||||
clap [..]
|
||||
A simple to use, efficient, and full-featured Command Line Argument Parser
|
||||
|
||||
USAGE:
|
||||
04_02_parse_derive[EXE] <PORT>
|
||||
|
||||
ARGS:
|
||||
<PORT> Network port to use
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Print help information
|
||||
-V, --version Print version information
|
||||
|
||||
$ 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
|
||||
|
||||
```
|
||||
|
||||
A custom validator can be used to improve the error messages or provide additional validation:
|
||||
|
||||
[Example:](04_02_validate.rs)
|
||||
```console
|
||||
$ 04_02_validate_derive --help
|
||||
|
@ -436,9 +467,9 @@ OPTIONS:
|
|||
$ 04_02_validate_derive 22
|
||||
PORT = 22
|
||||
|
||||
$ 04_02_validate_derive foobar
|
||||
$ 04_02_validate_derive 0
|
||||
? failed
|
||||
error: Invalid value "foobar" for '<PORT>': invalid digit found in string
|
||||
error: Invalid value "0" for '<PORT>': Port not in range 1-65535
|
||||
|
||||
For more information try --help
|
||||
|
||||
|
|
Loading…
Reference in a new issue