mirror of
https://github.com/clap-rs/clap
synced 2024-11-10 14:54:15 +00:00
fix(derive): Move args to new 'get_one'/'get_many' API
This commit is contained in:
parent
72c44a32e5
commit
d826ab9445
2 changed files with 84 additions and 18 deletions
|
@ -529,25 +529,25 @@ fn gen_parsers(
|
||||||
let span = parser.kind.span();
|
let span = parser.kind.span();
|
||||||
let convert_type = inner_type(**ty, &field.ty);
|
let convert_type = inner_type(**ty, &field.ty);
|
||||||
let id = attrs.id();
|
let id = attrs.id();
|
||||||
let (value_of, values_of, mut parse) = match *parser.kind {
|
let (get_one, get_many, mut parse) = match *parser.kind {
|
||||||
FromStr => (
|
FromStr => (
|
||||||
quote_spanned!(span=> value_of),
|
quote_spanned!(span=> get_one::<String>),
|
||||||
quote_spanned!(span=> values_of),
|
quote_spanned!(span=> get_many::<String>),
|
||||||
quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
|
quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
|
||||||
),
|
),
|
||||||
TryFromStr => (
|
TryFromStr => (
|
||||||
quote_spanned!(span=> value_of),
|
quote_spanned!(span=> get_one::<String>),
|
||||||
quote_spanned!(span=> values_of),
|
quote_spanned!(span=> get_many::<String>),
|
||||||
quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
|
quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
|
||||||
),
|
),
|
||||||
FromOsStr => (
|
FromOsStr => (
|
||||||
quote_spanned!(span=> value_of_os),
|
quote_spanned!(span=> get_one::<::std::ffi::OsString>),
|
||||||
quote_spanned!(span=> values_of_os),
|
quote_spanned!(span=> get_many::<::std::ffi::OsString>),
|
||||||
quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
|
quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
|
||||||
),
|
),
|
||||||
TryFromOsStr => (
|
TryFromOsStr => (
|
||||||
quote_spanned!(span=> value_of_os),
|
quote_spanned!(span=> get_one::<::std::ffi::OsString>),
|
||||||
quote_spanned!(span=> values_of_os),
|
quote_spanned!(span=> get_many::<::std::ffi::OsString>),
|
||||||
quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
|
quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
|
||||||
),
|
),
|
||||||
FromOccurrences => (
|
FromOccurrences => (
|
||||||
|
@ -587,7 +587,9 @@ fn gen_parsers(
|
||||||
|
|
||||||
Ty::Option => {
|
Ty::Option => {
|
||||||
quote_spanned! { ty.span()=>
|
quote_spanned! { ty.span()=>
|
||||||
#arg_matches.#value_of(#id)
|
#arg_matches.#get_one(#id)
|
||||||
|
.expect("unexpected type")
|
||||||
|
.map(|s| ::std::ops::Deref::deref(s))
|
||||||
.map(#parse)
|
.map(#parse)
|
||||||
.transpose()?
|
.transpose()?
|
||||||
}
|
}
|
||||||
|
@ -595,7 +597,12 @@ fn gen_parsers(
|
||||||
|
|
||||||
Ty::OptionOption => quote_spanned! { ty.span()=>
|
Ty::OptionOption => quote_spanned! { ty.span()=>
|
||||||
if #arg_matches.is_present(#id) {
|
if #arg_matches.is_present(#id) {
|
||||||
Some(#arg_matches.#value_of(#id).map(#parse).transpose()?)
|
Some(
|
||||||
|
#arg_matches.#get_one(#id)
|
||||||
|
.expect("unexpected type")
|
||||||
|
.map(|s| ::std::ops::Deref::deref(s))
|
||||||
|
.map(#parse).transpose()?
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -603,8 +610,9 @@ fn gen_parsers(
|
||||||
|
|
||||||
Ty::OptionVec => quote_spanned! { ty.span()=>
|
Ty::OptionVec => quote_spanned! { ty.span()=>
|
||||||
if #arg_matches.is_present(#id) {
|
if #arg_matches.is_present(#id) {
|
||||||
Some(#arg_matches.#values_of(#id)
|
Some(#arg_matches.#get_many(#id)
|
||||||
.map(|v| v.map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
|
.expect("unexpected type")
|
||||||
|
.map(|v| v.map(|s| ::std::ops::Deref::deref(s)).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.unwrap_or_else(Vec::new))
|
.unwrap_or_else(Vec::new))
|
||||||
} else {
|
} else {
|
||||||
|
@ -614,24 +622,31 @@ fn gen_parsers(
|
||||||
|
|
||||||
Ty::Vec => {
|
Ty::Vec => {
|
||||||
quote_spanned! { ty.span()=>
|
quote_spanned! { ty.span()=>
|
||||||
#arg_matches.#values_of(#id)
|
#arg_matches.#get_many(#id)
|
||||||
.map(|v| v.map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
|
.expect("unexpected type")
|
||||||
|
.map(|v| v.map(|s| ::std::ops::Deref::deref(s)).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.unwrap_or_else(Vec::new)
|
.unwrap_or_else(Vec::new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ty::Other if occurrences => quote_spanned! { ty.span()=>
|
Ty::Other if occurrences => quote_spanned! { ty.span()=>
|
||||||
#parse(#arg_matches.#value_of(#id))
|
#parse(
|
||||||
|
#arg_matches.#get_one(#id)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
Ty::Other if flag => quote_spanned! { ty.span()=>
|
Ty::Other if flag => quote_spanned! { ty.span()=>
|
||||||
#parse(#arg_matches.is_present(#id))
|
#parse(
|
||||||
|
#arg_matches.is_present(#id)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
Ty::Other => {
|
Ty::Other => {
|
||||||
quote_spanned! { ty.span()=>
|
quote_spanned! { ty.span()=>
|
||||||
#arg_matches.#value_of(#id)
|
#arg_matches.#get_one(#id)
|
||||||
|
.expect("unexpected type")
|
||||||
|
.map(|s| ::std::ops::Deref::deref(s))
|
||||||
.ok_or_else(|| clap::Error::raw(clap::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id)))
|
.ok_or_else(|| clap::Error::raw(clap::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id)))
|
||||||
.and_then(#parse)?
|
.and_then(#parse)?
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,57 @@ fn option_from_str() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vec_from_str() {
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for A {
|
||||||
|
fn from(_: &str) -> A {
|
||||||
|
A
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Parser, PartialEq)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(parse(from_str))]
|
||||||
|
a: Vec<A>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Opt { a: Vec::new() },
|
||||||
|
Opt::try_parse_from(&["test"]).unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Opt { a: vec![A] },
|
||||||
|
Opt::try_parse_from(&["test", "foo"]).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn option_vec_from_str() {
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for A {
|
||||||
|
fn from(_: &str) -> A {
|
||||||
|
A
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Parser, PartialEq)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(short, parse(from_str))]
|
||||||
|
a: Option<Vec<A>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(Opt { a: None }, Opt::try_parse_from(&["test"]).unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
Opt { a: Some(vec![A]) },
|
||||||
|
Opt::try_parse_from(&["test", "-a", "foo"]).unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn option_type_is_optional() {
|
fn option_type_is_optional() {
|
||||||
#[derive(Parser, PartialEq, Debug)]
|
#[derive(Parser, PartialEq, Debug)]
|
||||||
|
|
Loading…
Reference in a new issue