diff --git a/clap_derive/src/attrs.rs b/clap_derive/src/attrs.rs index 648be95b..b59aa2ee 100644 --- a/clap_derive/src/attrs.rs +++ b/clap_derive/src/attrs.rs @@ -399,7 +399,9 @@ impl Attrs { fn push_attrs(&mut self, attrs: &[Attribute]) { use ClapAttr::*; - for attr in parse_clap_attributes(attrs) { + let parsed = parse_clap_attributes(attrs); + for attr in &parsed { + let attr = attr.clone(); match attr { Short(ident) => { self.push_method(ident, self.name.clone().translate_char(*self.casing)); @@ -463,16 +465,25 @@ impl Attrs { quote!(<#ty as ::std::default::Default>::default()) }; - let val = quote_spanned!(ident.span()=> { - clap::lazy_static::lazy_static! { - static ref DEFAULT_VALUE: &'static str = { + let val = if parsed.iter().any(|a| matches!(a, ArgEnum(_))) { + quote_spanned!(ident.span()=> { + { let val: #ty = #val; - let s = ::std::string::ToString::to_string(&val); - ::std::boxed::Box::leak(s.into_boxed_str()) - }; - } - *DEFAULT_VALUE - }); + val.to_possible_value().unwrap().get_name() + } + }) + } else { + quote_spanned!(ident.span()=> { + clap::lazy_static::lazy_static! { + static ref DEFAULT_VALUE: &'static str = { + let val: #ty = #val; + let s = ::std::string::ToString::to_string(&val); + ::std::boxed::Box::leak(s.into_boxed_str()) + }; + } + *DEFAULT_VALUE + }) + }; let raw_ident = Ident::new("default_value", ident.span()); self.methods.push(Method::new(raw_ident, val)); diff --git a/clap_derive/src/derives/arg_enum.rs b/clap_derive/src/derives/arg_enum.rs index 045a0af7..f128a6f3 100644 --- a/clap_derive/src/derives/arg_enum.rs +++ b/clap_derive/src/derives/arg_enum.rs @@ -51,7 +51,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr let to_possible_value = gen_to_possible_value(&lits); quote! { - #[allow(dead_code, unreachable_code, unused_variables)] + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, clippy::complexity, diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index 461892a1..2db658eb 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -73,7 +73,7 @@ pub fn gen_for_struct( quote! { #from_arg_matches - #[allow(dead_code, unreachable_code, unused_variables)] + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, clippy::complexity, diff --git a/clap_derive/src/parse.rs b/clap_derive/src/parse.rs index 504701fc..64d80a77 100644 --- a/clap_derive/src/parse.rs +++ b/clap_derive/src/parse.rs @@ -21,6 +21,7 @@ pub fn parse_clap_attributes(all_attrs: &[Attribute]) -> Vec { } #[allow(clippy::large_enum_variant)] +#[derive(Clone)] pub enum ClapAttr { // single-identifier attributes Short(Ident), diff --git a/examples/derive_ref/README.md b/examples/derive_ref/README.md index 4acebb90..2c341658 100644 --- a/examples/derive_ref/README.md +++ b/examples/derive_ref/README.md @@ -174,7 +174,7 @@ In addition to the raw attributes, the following magic attributes are supported: - Without ``: fills the field with `Default::default()` - `default_value = `: `clap::Arg::default_value` and `clap::Arg::required(false)` - `default_value_t [= ]`: `clap::Arg::default_value` and `clap::Arg::required(false)` - - Requires `std::fmt::Display` + - Requires `std::fmt::Display` or `#[clap(arg_enum)]` - Without ``, relies on `Default::default()` ### Arg Types diff --git a/src/build/arg/possible_value.rs b/src/build/arg/possible_value.rs index 142c0530..f9433315 100644 --- a/src/build/arg/possible_value.rs +++ b/src/build/arg/possible_value.rs @@ -134,13 +134,13 @@ impl<'help> PossibleValue<'help> { impl<'help> PossibleValue<'help> { /// Get the name of the argument value #[inline] - pub fn get_name(&self) -> &str { + pub fn get_name(&self) -> &'help str { self.name } /// Get the help specified for this argument, if any #[inline] - pub fn get_help(&self) -> Option<&str> { + pub fn get_help(&self) -> Option<&'help str> { self.help } @@ -151,7 +151,7 @@ impl<'help> PossibleValue<'help> { } /// Get the name if argument value is not hidden, `None` otherwise - pub fn get_visible_name(&self) -> Option<&str> { + pub fn get_visible_name(&self) -> Option<&'help str> { if self.hide { None } else { @@ -162,7 +162,7 @@ impl<'help> PossibleValue<'help> { /// Returns all valid values of the argument value. /// /// Namely the name and all aliases. - pub fn get_name_and_aliases(&self) -> impl Iterator { + pub fn get_name_and_aliases(&self) -> impl Iterator + '_ { iter::once(&self.name).chain(&self.aliases).copied() } diff --git a/tests/derive/arg_enum.rs b/tests/derive/arg_enum.rs index 6f439919..22f86c21 100644 --- a/tests/derive/arg_enum.rs +++ b/tests/derive/arg_enum.rs @@ -52,12 +52,6 @@ fn default_value() { } } - impl std::fmt::Display for ArgChoice { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - std::fmt::Display::fmt(self.to_possible_value().unwrap().get_name(), f) - } - } - #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(arg_enum, default_value_t)]