mirror of
https://github.com/clap-rs/clap
synced 2024-12-13 22:32:33 +00:00
Attach validation error as Error::source
This commit is contained in:
parent
5a1a209965
commit
b31df047b8
8 changed files with 63 additions and 17 deletions
|
@ -4,12 +4,12 @@ use clap::Clap;
|
|||
use std::error::Error;
|
||||
|
||||
/// Parse a single key-value pair
|
||||
fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error>>
|
||||
fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
|
||||
where
|
||||
T: std::str::FromStr,
|
||||
T::Err: Error + 'static,
|
||||
T::Err: Error + Send + Sync + 'static,
|
||||
U: std::str::FromStr,
|
||||
U::Err: Error + 'static,
|
||||
U::Err: Error + Send + Sync + 'static,
|
||||
{
|
||||
let pos = s
|
||||
.find('=')
|
||||
|
|
|
@ -227,7 +227,6 @@ pub fn gen_app_augmentation(
|
|||
.validator(|s| {
|
||||
#func(s)
|
||||
.map(|_: #convert_type| ())
|
||||
.map_err(|e| e.to_string())
|
||||
})
|
||||
},
|
||||
ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
|
||||
|
|
|
@ -90,7 +90,15 @@ fn test_parse_hex() {
|
|||
fn custom_parser_1(_: &str) -> &'static str {
|
||||
"A"
|
||||
}
|
||||
fn custom_parser_2(_: &str) -> Result<&'static str, u32> {
|
||||
#[derive(Debug)]
|
||||
struct ErrCode(u32);
|
||||
impl std::error::Error for ErrCode {}
|
||||
impl std::fmt::Display for ErrCode {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
fn custom_parser_2(_: &str) -> Result<&'static str, ErrCode> {
|
||||
Ok("B")
|
||||
}
|
||||
fn custom_parser_3(_: &OsStr) -> &'static str {
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::{
|
|||
borrow::Cow,
|
||||
cmp::{Ord, Ordering},
|
||||
env,
|
||||
error::Error,
|
||||
ffi::{OsStr, OsString},
|
||||
fmt::{self, Display, Formatter},
|
||||
str,
|
||||
|
@ -38,8 +39,8 @@ use crate::{
|
|||
#[cfg(feature = "yaml")]
|
||||
use yaml_rust::Yaml;
|
||||
|
||||
type Validator<'a> = dyn FnMut(&str) -> Result<(), String> + Send + 'a;
|
||||
type ValidatorOs<'a> = dyn FnMut(&OsStr) -> Result<(), String> + Send + 'a;
|
||||
type Validator<'a> = dyn FnMut(&str) -> Result<(), Box<dyn Error + Send + Sync>> + Send + 'a;
|
||||
type ValidatorOs<'a> = dyn FnMut(&OsStr) -> Result<(), Box<dyn Error + Send + Sync>> + Send + 'a;
|
||||
|
||||
/// The abstract representation of a command line argument. Used to set all the options and
|
||||
/// relationships that define a valid argument for the program.
|
||||
|
@ -1879,10 +1880,10 @@ impl<'help> Arg<'help> {
|
|||
pub fn validator<F, O, E>(mut self, mut f: F) -> Self
|
||||
where
|
||||
F: FnMut(&str) -> Result<O, E> + Send + 'help,
|
||||
E: ToString,
|
||||
E: Into<Box<dyn Error + Send + Sync + 'static>>,
|
||||
{
|
||||
self.validator = Some(Arc::new(Mutex::new(move |s: &str| {
|
||||
f(s).map(|_| ()).map_err(|e| e.to_string())
|
||||
f(s).map(|_| ()).map_err(|e| e.into())
|
||||
})));
|
||||
self
|
||||
}
|
||||
|
@ -1917,11 +1918,14 @@ impl<'help> Arg<'help> {
|
|||
/// [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html
|
||||
/// [`Err(String)`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
|
||||
/// [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
|
||||
pub fn validator_os<F, O>(mut self, mut f: F) -> Self
|
||||
pub fn validator_os<F, O, E>(mut self, mut f: F) -> Self
|
||||
where
|
||||
F: FnMut(&OsStr) -> Result<O, String> + Send + 'help,
|
||||
F: FnMut(&OsStr) -> Result<O, E> + Send + 'help,
|
||||
E: Into<Box<dyn Error + Send + Sync + 'static>>,
|
||||
{
|
||||
self.validator_os = Some(Arc::new(Mutex::new(move |s: &OsStr| f(s).map(|_| ()))));
|
||||
self.validator_os = Some(Arc::new(Mutex::new(move |s: &OsStr| {
|
||||
f(s).map(|_| ()).map_err(|e| e.into())
|
||||
})));
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -385,6 +385,7 @@ pub struct Error {
|
|||
/// Additional information depending on the error kind, like values and argument names.
|
||||
/// Useful when you want to render an error of your own.
|
||||
pub info: Vec<String>,
|
||||
pub(crate) source: Option<Box<dyn error::Error + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
|
@ -478,6 +479,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::ArgumentConflict,
|
||||
info,
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,6 +497,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::EmptyValue,
|
||||
info: vec![arg],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,6 +560,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::InvalidValue,
|
||||
info: vec![],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -587,6 +591,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::InvalidSubcommand,
|
||||
info: vec![subcmd],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,6 +613,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::UnrecognizedSubcommand,
|
||||
info: vec![subcmd],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -637,6 +643,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::MissingRequiredArgument,
|
||||
info,
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -653,6 +660,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::MissingSubcommand,
|
||||
info: vec![],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -670,6 +678,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::InvalidUtf8,
|
||||
info: vec![],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -693,6 +702,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::TooManyValues,
|
||||
info: vec![arg.to_string(), val],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,13 +730,14 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::TooFewValues,
|
||||
info: vec![arg.to_string(), curr_vals.to_string(), min_vals.to_string()],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn value_validation(
|
||||
arg: String,
|
||||
val: String,
|
||||
err: String,
|
||||
err: Box<dyn error::Error + Send + Sync>,
|
||||
color: ColorChoice,
|
||||
) -> Self {
|
||||
let mut c = Colorizer::new(true, color);
|
||||
|
@ -743,7 +754,8 @@ impl Error {
|
|||
Error {
|
||||
message: c,
|
||||
kind: ErrorKind::ValueValidation,
|
||||
info: vec![arg, val, err],
|
||||
info: vec![arg, val, err.to_string()],
|
||||
source: Some(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -771,6 +783,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::WrongNumberOfValues,
|
||||
info: vec![arg.to_string(), curr_vals.to_string(), num_vals.to_string()],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,6 +801,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::UnexpectedMultipleUsage,
|
||||
info: vec![arg],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,6 +850,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::UnknownArgument,
|
||||
info: vec![arg],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -857,6 +872,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::UnknownArgument,
|
||||
info: vec![arg],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -872,6 +888,7 @@ impl Error {
|
|||
message: c,
|
||||
kind: ErrorKind::ArgumentNotFound,
|
||||
info: vec![arg],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -888,6 +905,7 @@ impl Error {
|
|||
message: c,
|
||||
kind,
|
||||
info: vec![],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -904,4 +922,12 @@ impl From<fmt::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
if let Some(source) = self.source.as_deref() {
|
||||
Some(source)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -351,7 +351,12 @@ impl ArgMatches {
|
|||
v, name, e
|
||||
);
|
||||
|
||||
Error::value_validation(name.to_string(), v.to_string(), message, ColorChoice::Auto)
|
||||
Error::value_validation(
|
||||
name.to_string(),
|
||||
v.to_string(),
|
||||
message.into(),
|
||||
ColorChoice::Auto,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
Err(Error::argument_not_found_auto(name.to_string()))
|
||||
|
@ -439,7 +444,7 @@ impl ArgMatches {
|
|||
Error::value_validation(
|
||||
name.to_string(),
|
||||
v.to_string(),
|
||||
message,
|
||||
message.into(),
|
||||
ColorChoice::Auto,
|
||||
)
|
||||
})
|
||||
|
|
|
@ -752,6 +752,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
|||
message,
|
||||
kind: ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand,
|
||||
info: vec![],
|
||||
source: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1747,6 +1748,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
|||
message: c,
|
||||
kind: ErrorKind::DisplayHelp,
|
||||
info: vec![],
|
||||
source: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1761,6 +1763,7 @@ impl<'help, 'app> Parser<'help, 'app> {
|
|||
message: c,
|
||||
kind: ErrorKind::DisplayVersion,
|
||||
info: vec![],
|
||||
source: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ impl<'help, 'app, 'parser> Validator<'help, 'app, 'parser> {
|
|||
message,
|
||||
kind: ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand,
|
||||
info: vec![],
|
||||
source: None,
|
||||
});
|
||||
}
|
||||
self.validate_conflicts(matcher)?;
|
||||
|
|
Loading…
Reference in a new issue