mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 06:42:33 +00:00
feat(derive): Allow skipping the implicit ArgGroup
This was prioritized to allow users to workaround problems when the implicit `ArgGroup` is getting in the way. Fixes #4279
This commit is contained in:
parent
35eeba0b63
commit
2498147138
4 changed files with 35 additions and 3 deletions
|
@ -315,11 +315,19 @@ pub fn gen_augment(
|
||||||
let initial_app_methods = parent_item.initial_top_level_methods();
|
let initial_app_methods = parent_item.initial_top_level_methods();
|
||||||
let group_id = parent_item.ident().unraw().to_string();
|
let group_id = parent_item.ident().unraw().to_string();
|
||||||
let final_app_methods = parent_item.final_top_level_methods();
|
let final_app_methods = parent_item.final_top_level_methods();
|
||||||
|
let group_app_methods = if parent_item.skip_group() {
|
||||||
|
quote!()
|
||||||
|
} else {
|
||||||
|
quote!(
|
||||||
|
.group(clap::ArgGroup::new(#group_id).multiple(true))
|
||||||
|
)
|
||||||
|
};
|
||||||
quote! {{
|
quote! {{
|
||||||
#deprecations
|
#deprecations
|
||||||
let #app_var = #app_var
|
let #app_var = #app_var
|
||||||
#initial_app_methods
|
#initial_app_methods
|
||||||
.group(clap::ArgGroup::new(#group_id).multiple(true));
|
#group_app_methods
|
||||||
|
;
|
||||||
#( #args )*
|
#( #args )*
|
||||||
#app_var #final_app_methods
|
#app_var #final_app_methods
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -50,6 +50,7 @@ pub struct Item {
|
||||||
next_help_heading: Option<Method>,
|
next_help_heading: Option<Method>,
|
||||||
is_enum: bool,
|
is_enum: bool,
|
||||||
is_positional: bool,
|
is_positional: bool,
|
||||||
|
skip_group: bool,
|
||||||
kind: Sp<Kind>,
|
kind: Sp<Kind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +273,7 @@ impl Item {
|
||||||
next_help_heading: None,
|
next_help_heading: None,
|
||||||
is_enum: false,
|
is_enum: false,
|
||||||
is_positional: true,
|
is_positional: true,
|
||||||
|
skip_group: false,
|
||||||
kind,
|
kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,6 +336,7 @@ impl Item {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let actual_attr_kind = *attr.kind.get();
|
||||||
let kind = match &attr.magic {
|
let kind = match &attr.magic {
|
||||||
Some(MagicAttrName::FromGlobal) => {
|
Some(MagicAttrName::FromGlobal) => {
|
||||||
if attr.value.is_some() {
|
if attr.value.is_some() {
|
||||||
|
@ -377,7 +380,7 @@ impl Item {
|
||||||
let kind = Sp::new(Kind::Flatten, attr.name.clone().span());
|
let kind = Sp::new(Kind::Flatten, attr.name.clone().span());
|
||||||
Some(kind)
|
Some(kind)
|
||||||
}
|
}
|
||||||
Some(MagicAttrName::Skip) => {
|
Some(MagicAttrName::Skip) if actual_attr_kind != AttrKind::Group => {
|
||||||
let expr = attr.value.clone();
|
let expr = attr.value.clone();
|
||||||
let kind = Sp::new(
|
let kind = Sp::new(
|
||||||
Kind::Skip(expr, self.kind.attr_kind()),
|
Kind::Skip(expr, self.kind.attr_kind()),
|
||||||
|
@ -408,6 +411,8 @@ impl Item {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(AttrKind::Group, AttrKind::Command) => {}
|
||||||
|
|
||||||
_ if attr.kind != expected_attr_kind => {
|
_ if attr.kind != expected_attr_kind => {
|
||||||
abort!(
|
abort!(
|
||||||
attr.kind.span(),
|
attr.kind.span(),
|
||||||
|
@ -803,6 +808,10 @@ impl Item {
|
||||||
self.env_casing = CasingStyle::from_lit(lit);
|
self.env_casing = CasingStyle::from_lit(lit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(MagicAttrName::Skip) if actual_attr_kind == AttrKind::Group => {
|
||||||
|
self.skip_group = true;
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
// Magic only for the default, otherwise just forward to the builder
|
// Magic only for the default, otherwise just forward to the builder
|
||||||
| Some(MagicAttrName::Short)
|
| Some(MagicAttrName::Short)
|
||||||
|
@ -1029,6 +1038,10 @@ impl Item {
|
||||||
.iter()
|
.iter()
|
||||||
.any(|m| m.name != "help" && m.name != "long_help")
|
.any(|m| m.name != "help" && m.name != "long_help")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn skip_group(&self) -> bool {
|
||||||
|
self.skip_group
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//! 2. [Attributes](#attributes)
|
//! 2. [Attributes](#attributes)
|
||||||
//! 1. [Terminology](#terminology)
|
//! 1. [Terminology](#terminology)
|
||||||
//! 2. [Command Attributes](#command-attributes)
|
//! 2. [Command Attributes](#command-attributes)
|
||||||
|
//! 2. [ArgGroup Attributes](#arggroup-attributes)
|
||||||
//! 3. [Arg Attributes](#arg-attributes)
|
//! 3. [Arg Attributes](#arg-attributes)
|
||||||
//! 4. [ValueEnum Attributes](#valueenum-attributes)
|
//! 4. [ValueEnum Attributes](#valueenum-attributes)
|
||||||
//! 5. [Possible Value Attributes](#possible-value-attributes)
|
//! 5. [Possible Value Attributes](#possible-value-attributes)
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
//! /// Doc comment
|
//! /// Doc comment
|
||||||
//! #[derive(Parser)]
|
//! #[derive(Parser)]
|
||||||
//! #[command(CMD ATTRIBUTE)]
|
//! #[command(CMD ATTRIBUTE)]
|
||||||
|
//! #[group(GROUP ATTRIBUTE)]
|
||||||
//! struct Cli {
|
//! struct Cli {
|
||||||
//! /// Doc comment
|
//! /// Doc comment
|
||||||
//! #[arg(ARG ATTRIBUTE)]
|
//! #[arg(ARG ATTRIBUTE)]
|
||||||
|
@ -46,6 +48,7 @@
|
||||||
//! /// Doc comment
|
//! /// Doc comment
|
||||||
//! #[derive(Args)]
|
//! #[derive(Args)]
|
||||||
//! #[command(PARENT CMD ATTRIBUTE)]
|
//! #[command(PARENT CMD ATTRIBUTE)]
|
||||||
|
//! #[group(GROUP ATTRIBUTE)]
|
||||||
//! struct Struct {
|
//! struct Struct {
|
||||||
//! /// Doc comment
|
//! /// Doc comment
|
||||||
//! #[command(ARG ATTRIBUTE)]
|
//! #[command(ARG ATTRIBUTE)]
|
||||||
|
@ -173,6 +176,13 @@
|
||||||
//! - `external_subcommand`: [`Command::allow_external_subcommand(true)`][crate::Command::allow_external_subcommands]
|
//! - `external_subcommand`: [`Command::allow_external_subcommand(true)`][crate::Command::allow_external_subcommands]
|
||||||
//! - Variant must be either `Variant(Vec<String>)` or `Variant(Vec<OsString>)`
|
//! - Variant must be either `Variant(Vec<String>)` or `Variant(Vec<OsString>)`
|
||||||
//!
|
//!
|
||||||
|
//! ### ArgGroup Attributes
|
||||||
|
//!
|
||||||
|
//! These correspond to the [`ArgGroup`][crate::ArgGroup] which is implicitly created for each
|
||||||
|
//! `Args` derive.
|
||||||
|
//!
|
||||||
|
//! At the moment, only `#[group(skip)]` is supported
|
||||||
|
//!
|
||||||
//! ### Arg Attributes
|
//! ### Arg Attributes
|
||||||
//!
|
//!
|
||||||
//! These correspond to a [`Arg`][crate::Arg].
|
//! These correspond to a [`Arg`][crate::Arg].
|
||||||
|
|
|
@ -23,7 +23,6 @@ fn test_safely_nest_parser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic = "'Compose' is already in use"]
|
|
||||||
fn skip_group_avoids_duplicate_ids() {
|
fn skip_group_avoids_duplicate_ids() {
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct Opt {
|
struct Opt {
|
||||||
|
@ -34,6 +33,7 @@ fn skip_group_avoids_duplicate_ids() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(clap::Args, Debug)]
|
#[derive(clap::Args, Debug)]
|
||||||
|
#[group(skip)]
|
||||||
pub struct Compose<L: clap::Args, R: clap::Args> {
|
pub struct Compose<L: clap::Args, R: clap::Args> {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
pub left: L,
|
pub left: L,
|
||||||
|
@ -42,6 +42,7 @@ fn skip_group_avoids_duplicate_ids() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(clap::Args, Clone, Copy, Debug)]
|
#[derive(clap::Args, Clone, Copy, Debug)]
|
||||||
|
#[group(skip)]
|
||||||
pub struct Empty;
|
pub struct Empty;
|
||||||
|
|
||||||
use clap::CommandFactory;
|
use clap::CommandFactory;
|
||||||
|
|
Loading…
Reference in a new issue