mirror of
https://github.com/clap-rs/clap
synced 2025-01-18 23:53:54 +00:00
Added alias support for arg_enum
This commit is contained in:
parent
01c179f527
commit
c4c6c35da7
4 changed files with 94 additions and 15 deletions
|
@ -27,7 +27,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
|
|||
|
||||
let lits = lits(&e.variants, &attrs);
|
||||
let variants = gen_variants(&lits);
|
||||
let from_str = gen_from_str(&e.variants, &lits);
|
||||
let from_str = gen_from_str(&lits);
|
||||
|
||||
quote! {
|
||||
#[allow(dead_code, unreachable_code, unused_variables)]
|
||||
|
@ -49,10 +49,13 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
|
|||
}
|
||||
}
|
||||
|
||||
fn lits(variants: &Punctuated<Variant, Comma>, parent_attribute: &Attrs) -> Vec<TokenStream> {
|
||||
fn lits(
|
||||
variants: &Punctuated<Variant, Comma>,
|
||||
parent_attribute: &Attrs,
|
||||
) -> Vec<(TokenStream, Ident)> {
|
||||
variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
.flat_map(|variant| {
|
||||
let attrs = Attrs::from_struct(
|
||||
variant.span(),
|
||||
&variant.attrs,
|
||||
|
@ -61,19 +64,28 @@ fn lits(variants: &Punctuated<Variant, Comma>, parent_attribute: &Attrs) -> Vec<
|
|||
parent_attribute.env_casing(),
|
||||
);
|
||||
|
||||
attrs.cased_name()
|
||||
let mut ret = vec![(attrs.cased_name(), variant.ident.clone())];
|
||||
|
||||
attrs
|
||||
.enum_aliases()
|
||||
.into_iter()
|
||||
.for_each(|x| ret.push((x, variant.ident.clone())));
|
||||
|
||||
ret
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn gen_variants(lits: &Vec<TokenStream>) -> TokenStream {
|
||||
fn gen_variants(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
let lit = lits.iter().map(|l| l.0.clone()).collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
const VARIANTS: &'static [&'static str] = &[#(#lits),*];
|
||||
const VARIANTS: &'static [&'static str] = &[#(#lit),*];
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_from_str(variants: &Punctuated<Variant, Comma>, lits: &Vec<TokenStream>) -> TokenStream {
|
||||
let matches = variants.iter().map(|v| &v.ident).collect::<Vec<_>>();
|
||||
fn gen_from_str(lits: &[(TokenStream, Ident)]) -> TokenStream {
|
||||
let (lit, variant): (Vec<TokenStream>, Vec<Ident>) = lits.iter().cloned().unzip();
|
||||
|
||||
quote! {
|
||||
fn from_str(input: &str, case_insensitive: bool) -> ::std::result::Result<Self, String> {
|
||||
|
@ -84,7 +96,7 @@ fn gen_from_str(variants: &Punctuated<Variant, Comma>, lits: &Vec<TokenStream>)
|
|||
};
|
||||
|
||||
match input {
|
||||
#(val if func(val, #lits) => Ok(Self::#matches),)*
|
||||
#(val if func(val, #lit) => Ok(Self::#variant),)*
|
||||
_ => Err(String::from("something went wrong parsing the value")),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -630,6 +630,14 @@ impl Attrs {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn enum_aliases(&self) -> Vec<TokenStream> {
|
||||
self.methods
|
||||
.iter()
|
||||
.filter(|m| m.name == "alias")
|
||||
.map(|m| m.args.clone())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn casing(&self) -> Sp<CasingStyle> {
|
||||
self.casing.clone()
|
||||
}
|
||||
|
|
|
@ -71,12 +71,9 @@ fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStream
|
|||
let from_arg_matches = from_argmatches::gen_for_enum(name);
|
||||
let subcommand = subcommand::gen_for_enum(name, attrs, e);
|
||||
|
||||
let arg_enum = if e.variants.iter().all(|v| {
|
||||
if let syn::Fields::Unit = v.fields {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
let arg_enum = if e.variants.iter().all(|v| match v.fields {
|
||||
syn::Fields::Unit => true,
|
||||
_ => false,
|
||||
}) {
|
||||
arg_enum::gen_for_enum(name, attrs, e)
|
||||
} else {
|
||||
|
|
|
@ -187,3 +187,65 @@ fn case_insensitive_set_to_false() {
|
|||
);
|
||||
assert!(Opt::try_parse_from(&["", "fOo"]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias() {
|
||||
#[derive(Clap, PartialEq, Debug)]
|
||||
enum ArgChoice {
|
||||
#[clap(alias = "TOTP")]
|
||||
TOTP,
|
||||
}
|
||||
|
||||
#[derive(Clap, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(arg_enum, case_insensitive(false))]
|
||||
arg: ArgChoice,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::TOTP
|
||||
},
|
||||
Opt::parse_from(&["", "totp"])
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::TOTP
|
||||
},
|
||||
Opt::parse_from(&["", "TOTP"])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_alias() {
|
||||
#[derive(Clap, PartialEq, Debug)]
|
||||
enum ArgChoice {
|
||||
#[clap(alias = "TOTP", alias = "t")]
|
||||
TOTP,
|
||||
}
|
||||
|
||||
#[derive(Clap, PartialEq, Debug)]
|
||||
struct Opt {
|
||||
#[clap(arg_enum, case_insensitive(false))]
|
||||
arg: ArgChoice,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::TOTP
|
||||
},
|
||||
Opt::parse_from(&["", "totp"])
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::TOTP
|
||||
},
|
||||
Opt::parse_from(&["", "TOTP"])
|
||||
);
|
||||
assert_eq!(
|
||||
Opt {
|
||||
arg: ArgChoice::TOTP
|
||||
},
|
||||
Opt::parse_from(&["", "t"])
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue