Skip to content

Commit

Permalink
feat: Add default_value_os_t (#3333)
Browse files Browse the repository at this point in the history
The order of suffixes allows us to preserve the original builder function name.

This is a part of #2813
  • Loading branch information
omjadas committed Jan 24, 2022
1 parent e5b06c3 commit 86c83d2
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
43 changes: 43 additions & 0 deletions clap_derive/src/attrs.rs
Expand Up @@ -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)));
}
Expand Down
3 changes: 3 additions & 0 deletions clap_derive/src/parse.rs
Expand Up @@ -53,6 +53,7 @@ pub enum ClapAttr {
// ident = arbitrary_expr
NameExpr(Ident, Expr),
DefaultValueT(Ident, Option<Expr>),
DefaultValueOsT(Ident, Option<Expr>),
HelpHeading(Ident, Expr),

// ident(arbitrary_expr,*)
Expand Down Expand Up @@ -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)),
},
Expand Down Expand Up @@ -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)),
Expand Down
3 changes: 3 additions & 0 deletions examples/derive_ref/README.md
Expand Up @@ -185,6 +185,9 @@ In addition to the raw attributes, the following magic attributes are supported:
- `default_value_t [= <expr>]`: `clap::Arg::default_value` and `clap::Arg::required(false)`
- Requires `std::fmt::Display` or `#[clap(arg_enum)]`
- Without `<expr>`, relies on `Default::default()`
- `default_value_os_t [= <expr>]`: `clap::Arg::default_value_os` and `clap::Arg::required(false)`
- Requires `std::convert::Into<OsString>` or `#[clap(arg_enum)]`
- Without `<expr>`, relies on `Default::default()`

### Arg Types

Expand Down

0 comments on commit 86c83d2

Please sign in to comment.