From e81845f1cb6d5ce32be591cc69753592c992d862 Mon Sep 17 00:00:00 2001 From: Roland Fredenhagen Date: Sat, 18 Sep 2021 14:13:44 +0200 Subject: [PATCH] Working Implementation --- clap_derive/examples/arg_enum.rs | 6 ++++++ clap_derive/src/attrs.rs | 14 ++++++++++++++ clap_derive/src/derives/arg_enum.rs | 26 ++++++++++++++++++-------- clap_derive/src/parse.rs | 2 ++ src/build/arg/arg_value.rs | 6 +++--- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/clap_derive/examples/arg_enum.rs b/clap_derive/examples/arg_enum.rs index e233b053b4a2..3f13658ee7f6 100644 --- a/clap_derive/examples/arg_enum.rs +++ b/clap_derive/examples/arg_enum.rs @@ -6,11 +6,17 @@ use clap::{ArgEnum, Clap}; #[derive(ArgEnum, Debug, PartialEq)] enum ArgChoice { + /// Descriptions are supported as doc-comment Foo, + // Renames are supported + #[clap(name = "b-a-r")] Bar, // Aliases are supported #[clap(alias = "b", alias = "z")] Baz, + // Hiding variants from help and completion is supported + #[clap(hidden)] + Hidden, } #[derive(Clap, PartialEq, Debug)] diff --git a/clap_derive/src/attrs.rs b/clap_derive/src/attrs.rs index 0d465f817ca9..2fd7feba383c 100644 --- a/clap_derive/src/attrs.rs +++ b/clap_derive/src/attrs.rs @@ -308,6 +308,8 @@ impl Attrs { self.push_method(ident, self.name.clone().translate(*self.env_casing)); } + Hidden(ident) => self.push_method(ident, true), + ArgEnum(_) => self.is_enum = true, FromGlobal(ident) => { @@ -782,6 +784,18 @@ impl Attrs { quote!( #(#doc_comment)* #(#methods)* ) } + /// generate methods on top of a field + /// filter out any passed method names + pub fn field_methods_filtered(&self, filter: &[&str]) -> proc_macro2::TokenStream { + let methods: Vec<_> = self + .methods + .iter() + .filter(|m| !filter.contains(&m.name.to_string().as_str())) + .collect(); + let doc_comment = &self.doc_comment; + quote!( #(#doc_comment)* #(#methods)* ) + } + pub fn version(&self) -> TokenStream { self.version .clone() diff --git a/clap_derive/src/derives/arg_enum.rs b/clap_derive/src/derives/arg_enum.rs index 0d3b182b1e05..766edf0b1e6a 100644 --- a/clap_derive/src/derives/arg_enum.rs +++ b/clap_derive/src/derives/arg_enum.rs @@ -47,9 +47,10 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr ); let lits = lits(&e.variants, &attrs); + let lits_wo_attrs: Vec<_> = lits.iter().cloned().map(|(ts, i, _)| (ts, i)).collect(); let variants = gen_variants(&lits); - let from_str = gen_from_str(&lits); - let as_arg = gen_as_arg(&lits); + let from_str = gen_from_str(&lits_wo_attrs); + let as_arg = gen_as_arg(&lits_wo_attrs); quote! { #[allow(dead_code, unreachable_code, unused_variables)] @@ -75,7 +76,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr fn lits( variants: &Punctuated, parent_attribute: &Attrs, -) -> Vec<(TokenStream, Ident)> { +) -> Vec<(TokenStream, Ident, Attrs)> { variants .iter() .filter_map(|variant| { @@ -91,23 +92,32 @@ fn lits( } }) .flat_map(|(variant, attrs)| { - let mut ret = vec![(attrs.cased_name(), variant.ident.clone())]; + let mut ret = vec![(attrs.cased_name(), variant.ident.clone(), attrs.clone())]; attrs .enum_aliases() .into_iter() - .for_each(|x| ret.push((x, variant.ident.clone()))); + .for_each(|x| ret.push((x, variant.ident.clone(), attrs.clone()))); ret }) .collect::>() } -fn gen_variants(lits: &[(TokenStream, Ident)]) -> TokenStream { - let lit = lits.iter().map(|l| &l.0).collect::>(); +fn gen_variants(lits: &[(TokenStream, Ident, Attrs)]) -> TokenStream { + let lit = lits + .iter() + .map(|(name, _, attrs)| { + let fields = attrs.field_methods_filtered(&["alias"]); + quote! { + clap::ArgValue::new(#name) + #fields + } + }) + .collect::>(); quote! { - const VARIANTS: &'static [clap::ArgValue<'static>] = &[#(clap::ArgValue::new(#lit)),*]; + const VARIANTS: &'static [clap::ArgValue<'static>] = &[#(#lit),*]; } } diff --git a/clap_derive/src/parse.rs b/clap_derive/src/parse.rs index e563bc72cdd1..eb487a3ba2bc 100644 --- a/clap_derive/src/parse.rs +++ b/clap_derive/src/parse.rs @@ -21,6 +21,7 @@ pub enum ClapAttr { Subcommand(Ident), VerbatimDocComment(Ident), ExternalSubcommand(Ident), + Hidden(Ident), // ident [= "string literal"] About(Ident, Option), @@ -172,6 +173,7 @@ impl Parse for ClapAttr { "subcommand" => Ok(Subcommand(name)), "external_subcommand" => Ok(ExternalSubcommand(name)), "verbatim_doc_comment" => Ok(VerbatimDocComment(name)), + "hidden" => Ok(Hidden(name)), "default_value" => { abort!(name, diff --git a/src/build/arg/arg_value.rs b/src/build/arg/arg_value.rs index 0d5fdc126d41..88400a161be9 100644 --- a/src/build/arg/arg_value.rs +++ b/src/build/arg/arg_value.rs @@ -80,7 +80,7 @@ impl<'help> ArgValue<'help> { /// [hidden]: ArgValue::hide /// [possible value]: crate::Arg::possible_values /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values() - pub fn new(name: &'help str) -> Self { + pub const fn new(name: &'help str) -> Self { ArgValue { name, about: None, @@ -100,7 +100,7 @@ impl<'help> ArgValue<'help> { /// # ; /// ``` #[inline] - pub fn about(mut self, about: &'help str) -> Self { + pub const fn about(mut self, about: &'help str) -> Self { self.about = Some(about); self } @@ -120,7 +120,7 @@ impl<'help> ArgValue<'help> { /// ``` /// [`Arg::hide_possible_values(true)`]: crate::Arg::hide_possible_values() #[inline] - pub fn hidden(mut self, yes: bool) -> Self { + pub const fn hidden(mut self, yes: bool) -> Self { self.hidden = yes; self }