Skip to content

Commit

Permalink
feat(derive): Add additional group methods
Browse files Browse the repository at this point in the history
This adds the ability derive additional options for the group creation.
Needed for clap-rs#4574.
  • Loading branch information
klnusbaum committed Feb 3, 2023
1 parent 931eac5 commit 19f3b37
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 34 deletions.
2 changes: 0 additions & 2 deletions clap_derive/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ impl Parse for ClapAttr {
let magic = match name_str.as_str() {
"rename_all" => Some(MagicAttrName::RenameAll),
"rename_all_env" => Some(MagicAttrName::RenameAllEnv),
"required" => Some(MagicAttrName::Required),
"skip" => Some(MagicAttrName::Skip),
"next_display_order" => Some(MagicAttrName::NextDisplayOrder),
"next_help_heading" => Some(MagicAttrName::NextHelpHeading),
Expand Down Expand Up @@ -169,7 +168,6 @@ pub enum MagicAttrName {
Version,
RenameAllEnv,
RenameAll,
Required,
Skip,
DefaultValueT,
DefaultValuesT,
Expand Down
5 changes: 3 additions & 2 deletions clap_derive/src/derives/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,6 @@ pub fn gen_augment(
quote!()
} else {
let group_id = parent_item.ident().unraw().to_string();
let required = parent_item.required_group();
let literal_group_members = fields
.iter()
.filter_map(|(_field, item)| {
Expand Down Expand Up @@ -401,11 +400,13 @@ pub fn gen_augment(
}};
}

let group_methods = parent_item.group_methods();

quote!(
.group(
clap::ArgGroup::new(#group_id)
.multiple(true)
.required(#required)
#group_methods
.args(#literal_group_members)
)
)
Expand Down
23 changes: 11 additions & 12 deletions clap_derive/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ pub struct Item {
next_help_heading: Option<Method>,
is_enum: bool,
is_positional: bool,
required_group: bool,
skip_group: bool,
group_methods: Vec<Method>,
kind: Sp<Kind>,
}

Expand Down Expand Up @@ -273,8 +273,8 @@ impl Item {
next_help_heading: None,
is_enum: false,
is_positional: true,
required_group: false,
skip_group: false,
group_methods: vec![],
kind,
}
}
Expand Down Expand Up @@ -327,7 +327,10 @@ impl Item {
if name == "short" || name == "long" {
self.is_positional = false;
}
self.methods.push(Method::new(name, quote!(#arg)));
match kind {
AttrKind::Group => self.group_methods.push(Method::new(name, quote!(#arg))),
_ => self.methods.push(Method::new(name, quote!(#arg))),
};
}
}

Expand Down Expand Up @@ -826,10 +829,6 @@ impl Item {
self.env_casing = CasingStyle::from_lit(lit);
}

Some(MagicAttrName::Required) if actual_attr_kind == AttrKind::Group => {
self.required_group = true;
}

Some(MagicAttrName::Skip) if actual_attr_kind == AttrKind::Group => {
self.skip_group = true;
}
Expand All @@ -844,7 +843,6 @@ impl Item {
| Some(MagicAttrName::LongHelp)
| Some(MagicAttrName::Author)
| Some(MagicAttrName::Version)
| Some(MagicAttrName::Required)
=> {
let expr = attr.value_or_abort();
self.push_method(*attr.kind.get(), attr.name.clone(), expr);
Expand Down Expand Up @@ -971,6 +969,11 @@ impl Item {
quote!( #(#doc_comment)* #(#methods)* )
}

pub fn group_methods(&self) -> TokenStream {
let group_methods = &self.group_methods;
quote!( #(#group_methods)* )
}

pub fn deprecations(&self) -> proc_macro2::TokenStream {
let deprecations = &self.deprecations;
quote!( #(#deprecations)* )
Expand Down Expand Up @@ -1066,10 +1069,6 @@ impl Item {
.any(|m| m.name != "help" && m.name != "long_help")
}

pub fn required_group(&self) -> bool {
self.required_group
}

pub fn skip_group(&self) -> bool {
self.skip_group
}
Expand Down
19 changes: 1 addition & 18 deletions tests/derive/groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,40 +127,23 @@ fn required_group() {
struct Opt {
#[command(flatten)]
source: Source,
#[command(flatten)]
dest: Dest,
}

#[derive(clap::Args, Debug)]
#[group(required)]
#[group(required = true)]
struct Source {
#[arg(long)]
from_path: Option<std::path::PathBuf>,
#[arg(long)]
from_git: Option<String>,
}

#[derive(clap::Args, Debug)]
#[group(required = true)]
struct Dest {
#[arg(long)]
to_path: Option<std::path::PathBuf>,
#[arg(long)]
to_git: Option<String>,
}

use clap::CommandFactory;
let source_id = clap::Id::from("Source");
let dest_id = clap::Id::from("Dest");
let opt_command = Opt::command();
let source_group = opt_command
.get_groups()
.find(|g| g.get_id() == &source_id)
.unwrap();
let dest_group = opt_command
.get_groups()
.find(|g| g.get_id() == &dest_id)
.unwrap();
assert!(source_group.is_required_set());
assert!(dest_group.is_required_set());
}

0 comments on commit 19f3b37

Please sign in to comment.