From 86c83d296fe962eafb9e72ed016315fc42f3fcdc Mon Sep 17 00:00:00 2001 From: omjadas Date: Tue, 25 Jan 2022 08:32:21 +1100 Subject: [PATCH] feat: Add default_value_os_t (#3333) The order of suffixes allows us to preserve the original builder function name. This is a part of #2813 --- clap_derive/src/attrs.rs | 43 +++++++++++++++++++++++++++++++++++ clap_derive/src/parse.rs | 3 +++ examples/derive_ref/README.md | 3 +++ 3 files changed, 49 insertions(+) diff --git a/clap_derive/src/attrs.rs b/clap_derive/src/attrs.rs index 366e4b39df4..861c052e3d5 100644 --- a/clap_derive/src/attrs.rs +++ b/clap_derive/src/attrs.rs @@ -489,6 +489,49 @@ impl Attrs { self.methods.push(Method::new(raw_ident, val)); } + DefaultValueOsT(ident, expr) => { + let ty = if let Some(ty) = self.ty.as_ref() { + ty + } else { + abort!( + ident, + "#[clap(default_value_os_t)] (without an argument) can be used \ + only on field level"; + + note = "see \ + https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") + }; + + let val = if let Some(expr) = expr { + quote!(#expr) + } else { + quote!(<#ty as ::std::default::Default>::default()) + }; + + let val = if parsed.iter().any(|a| matches!(a, ArgEnum(_))) { + quote_spanned!(ident.span()=> { + { + let val: #ty = #val; + clap::ArgEnum::to_possible_value(&val).unwrap().get_name() + } + }) + } else { + quote_spanned!(ident.span()=> { + clap::lazy_static::lazy_static! { + static ref DEFAULT_VALUE: &'static ::std::ffi::OsStr = { + let val: #ty = #val; + let s: ::std::ffi::OsString = val.into(); + ::std::boxed::Box::leak(s.into_boxed_os_str()) + }; + } + *DEFAULT_VALUE + }) + }; + + let raw_ident = Ident::new("default_value_os", ident.span()); + self.methods.push(Method::new(raw_ident, val)); + } + HelpHeading(ident, expr) => { self.help_heading = Some(Method::new(ident, quote!(#expr))); } diff --git a/clap_derive/src/parse.rs b/clap_derive/src/parse.rs index 5eb0eb50f27..76444d28ffc 100644 --- a/clap_derive/src/parse.rs +++ b/clap_derive/src/parse.rs @@ -53,6 +53,7 @@ pub enum ClapAttr { // ident = arbitrary_expr NameExpr(Ident, Expr), DefaultValueT(Ident, Option), + DefaultValueOsT(Ident, Option), HelpHeading(Ident, Expr), // ident(arbitrary_expr,*) @@ -129,6 +130,7 @@ impl Parse for ClapAttr { Ok(expr) => match &*name_str { "skip" => Ok(Skip(name, Some(expr))), "default_value_t" => Ok(DefaultValueT(name, Some(expr))), + "default_value_os_t" => Ok(DefaultValueOsT(name, Some(expr))), "help_heading" => Ok(HelpHeading(name, expr)), _ => Ok(NameExpr(name, expr)), }, @@ -203,6 +205,7 @@ impl Parse for ClapAttr { ) } "default_value_t" => Ok(DefaultValueT(name, None)), + "default_value_os_t" => Ok(DefaultValueOsT(name, None)), "about" => (Ok(About(name, None))), "author" => (Ok(Author(name, None))), "version" => Ok(Version(name, None)), diff --git a/examples/derive_ref/README.md b/examples/derive_ref/README.md index 55665fff5d7..9af1aadb4a3 100644 --- a/examples/derive_ref/README.md +++ b/examples/derive_ref/README.md @@ -185,6 +185,9 @@ In addition to the raw attributes, the following magic attributes are supported: - `default_value_t [= ]`: `clap::Arg::default_value` and `clap::Arg::required(false)` - Requires `std::fmt::Display` or `#[clap(arg_enum)]` - Without ``, relies on `Default::default()` +- `default_value_os_t [= ]`: `clap::Arg::default_value_os` and `clap::Arg::required(false)` + - Requires `std::convert::Into` or `#[clap(arg_enum)]` + - Without ``, relies on `Default::default()` ### Arg Types