Skip to content

Commit

Permalink
Working Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ModProg committed Sep 19, 2021
1 parent 4936a04 commit e81845f
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 11 deletions.
6 changes: 6 additions & 0 deletions clap_derive/examples/arg_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
14 changes: 14 additions & 0 deletions clap_derive/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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()
Expand Down
26 changes: 18 additions & 8 deletions clap_derive/src/derives/arg_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -75,7 +76,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
fn lits(
variants: &Punctuated<Variant, Comma>,
parent_attribute: &Attrs,
) -> Vec<(TokenStream, Ident)> {
) -> Vec<(TokenStream, Ident, Attrs)> {
variants
.iter()
.filter_map(|variant| {
Expand All @@ -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::<Vec<_>>()
}

fn gen_variants(lits: &[(TokenStream, Ident)]) -> TokenStream {
let lit = lits.iter().map(|l| &l.0).collect::<Vec<_>>();
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::<Vec<_>>();

quote! {
const VARIANTS: &'static [clap::ArgValue<'static>] = &[#(clap::ArgValue::new(#lit)),*];
const VARIANTS: &'static [clap::ArgValue<'static>] = &[#(#lit),*];
}
}

Expand Down
2 changes: 2 additions & 0 deletions clap_derive/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum ClapAttr {
Subcommand(Ident),
VerbatimDocComment(Ident),
ExternalSubcommand(Ident),
Hidden(Ident),

// ident [= "string literal"]
About(Ident, Option<LitStr>),
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions src/build/arg/arg_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
}
Expand All @@ -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
}
Expand Down

0 comments on commit e81845f

Please sign in to comment.