mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
Merge #1884
1884: Make validator take &str instead of String r=pksunkara a=CreepySkeleton Co-authored-by: CreepySkeleton <creepy-skeleton@yandex.ru>
This commit is contained in:
commit
70287eae82
9 changed files with 36 additions and 10 deletions
|
@ -934,7 +934,7 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_number(s: String) -> Result<(), String> {
|
fn validate_number(s: &str) -> Result<(), String> {
|
||||||
s.parse::<usize>()
|
s.parse::<usize>()
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|err| err.to_string())
|
.map_err(|err| err.to_string())
|
||||||
|
|
|
@ -205,13 +205,13 @@ pub fn gen_app_augmentation(
|
||||||
_ if attrs.is_enum() => quote!(),
|
_ if attrs.is_enum() => quote!(),
|
||||||
ParserKind::TryFromStr => quote_spanned! { func.span()=>
|
ParserKind::TryFromStr => quote_spanned! { func.span()=>
|
||||||
.validator(|s| {
|
.validator(|s| {
|
||||||
#func(s.as_str())
|
#func(s)
|
||||||
.map(|_: #convert_type| ())
|
.map(|_: #convert_type| ())
|
||||||
.map_err(|e| e.to_string())
|
.map_err(|e| e.to_string())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
|
ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
|
||||||
.validator_os(|s| #func(&s).map(|_: #convert_type| ()))
|
.validator_os(|s| #func(s).map(|_: #convert_type| ()))
|
||||||
},
|
},
|
||||||
_ => quote!(),
|
_ => quote!(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn main() {
|
||||||
println!("The .PNG file is: {}", matches.value_of("input").unwrap());
|
println!("The .PNG file is: {}", matches.value_of("input").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_png(val: String) -> Result<(), String> {
|
fn is_png(val: &str) -> Result<(), String> {
|
||||||
// val is the argument value passed in by the user
|
// val is the argument value passed in by the user
|
||||||
// val has type of String.
|
// val has type of String.
|
||||||
if val.ends_with(".png") {
|
if val.ends_with(".png") {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use clap::clap_app;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Validation example testing that a file exists
|
// Validation example testing that a file exists
|
||||||
let file_exists = |path| {
|
let file_exists = |path: &str| {
|
||||||
if std::fs::metadata(path).is_ok() {
|
if std::fs::metadata(path).is_ok() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1711,6 +1711,13 @@ impl<'b> App<'b> {
|
||||||
"Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
|
"Global arguments cannot be required.\n\n\t'{}' is marked as both global and required",
|
||||||
arg.name
|
arg.name
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// validators
|
||||||
|
assert!(
|
||||||
|
arg.validator.is_none() || arg.validator_os.is_none(),
|
||||||
|
"Argument '{}' has both `validator` and `validator_os` set which is not allowed",
|
||||||
|
arg.name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for group in &self.groups {
|
for group in &self.groups {
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::{
|
||||||
INTERNAL_ERROR_MSG,
|
INTERNAL_ERROR_MSG,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Validator = Rc<dyn Fn(String) -> Result<(), String>>;
|
type Validator = Rc<dyn Fn(&str) -> Result<(), String>>;
|
||||||
type ValidatorOs = Rc<dyn Fn(&OsStr) -> Result<(), String>>;
|
type ValidatorOs = Rc<dyn Fn(&OsStr) -> Result<(), String>>;
|
||||||
|
|
||||||
/// The abstract representation of a command line argument. Used to set all the options and
|
/// The abstract representation of a command line argument. Used to set all the options and
|
||||||
|
@ -1927,7 +1927,7 @@ impl<'help> Arg<'help> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use clap::{App, Arg};
|
/// # use clap::{App, Arg};
|
||||||
/// fn has_at(v: String) -> Result<(), String> {
|
/// fn has_at(v: &str) -> Result<(), String> {
|
||||||
/// if v.contains("@") { return Ok(()); }
|
/// if v.contains("@") { return Ok(()); }
|
||||||
/// Err(String::from("The value did not contain the required @ sigil"))
|
/// Err(String::from("The value did not contain the required @ sigil"))
|
||||||
/// }
|
/// }
|
||||||
|
@ -1947,7 +1947,7 @@ impl<'help> Arg<'help> {
|
||||||
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||||
pub fn validator<F, O, E>(mut self, f: F) -> Self
|
pub fn validator<F, O, E>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(String) -> Result<O, E> + 'static,
|
F: Fn(&str) -> Result<O, E> + 'static,
|
||||||
E: ToString,
|
E: ToString,
|
||||||
{
|
{
|
||||||
self.validator = Some(Rc::new(move |s| {
|
self.validator = Some(Rc::new(move |s| {
|
||||||
|
|
|
@ -130,7 +130,7 @@ pub enum ErrorKind {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use clap::{App, Arg, ErrorKind};
|
/// # use clap::{App, Arg, ErrorKind};
|
||||||
/// fn is_numeric(val: String) -> Result<(), String> {
|
/// fn is_numeric(val: &str) -> Result<(), String> {
|
||||||
/// match val.parse::<i64>() {
|
/// match val.parse::<i64>() {
|
||||||
/// Ok(..) => Ok(()),
|
/// Ok(..) => Ok(()),
|
||||||
/// Err(..) => Err(String::from("Value wasn't a number!")),
|
/// Err(..) => Err(String::from("Value wasn't a number!")),
|
||||||
|
|
|
@ -137,7 +137,7 @@ impl<'b, 'c, 'z> Validator<'b, 'c, 'z> {
|
||||||
}
|
}
|
||||||
if let Some(ref vtor) = arg.validator {
|
if let Some(ref vtor) = arg.validator {
|
||||||
debug!("Validator::validate_arg_values: checking validator...");
|
debug!("Validator::validate_arg_values: checking validator...");
|
||||||
if let Err(e) = vtor(val.to_string_lossy().into_owned()) {
|
if let Err(e) = vtor(&*val.to_string_lossy()) {
|
||||||
debug!("error");
|
debug!("error");
|
||||||
return Err(Error::value_validation(Some(arg), &e, self.p.app.color())?);
|
return Err(Error::value_validation(Some(arg), &e, self.p.app.color())?);
|
||||||
} else {
|
} else {
|
||||||
|
|
19
tests/validators.rs
Normal file
19
tests/validators.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use clap::{App, Arg};
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[test]
|
||||||
|
#[should_panic = "Argument 'test' has both `validator` and `validator_os` set which is not allowed"]
|
||||||
|
fn both_validator_and_validator_os() {
|
||||||
|
let _ = App::new("test")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("test")
|
||||||
|
.validator(|val| val.parse::<u32>().map_err(|e| e.to_string()))
|
||||||
|
.validator_os(|val| {
|
||||||
|
val.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.parse::<u32>()
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.try_get_matches_from(&["app", "1"]);
|
||||||
|
}
|
Loading…
Reference in a new issue