mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 14:52:33 +00:00
feat(derive): Add skip attribute support for enum variants
> Resolves #493 This is a port of https://github.com/TeXitoi/structopt/pull/494 This is part of #2809
This commit is contained in:
parent
5512c90380
commit
16023cf157
3 changed files with 62 additions and 12 deletions
|
@ -552,9 +552,7 @@ impl Attrs {
|
||||||
|
|
||||||
res.kind = Sp::new(Kind::Subcommand(ty), res.kind.span());
|
res.kind = Sp::new(Kind::Subcommand(ty), res.kind.span());
|
||||||
}
|
}
|
||||||
Kind::Skip(_) => {
|
Kind::Skip(_) => (),
|
||||||
abort!(res.kind.span(), "skip is not supported on variants");
|
|
||||||
}
|
|
||||||
Kind::FromGlobal(_) => {
|
Kind::FromGlobal(_) => {
|
||||||
abort!(res.kind.span(), "from_global is not supported on variants");
|
abort!(res.kind.span(), "from_global is not supported on variants");
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ fn gen_augment(
|
||||||
|
|
||||||
let subcommands: Vec<_> = variants
|
let subcommands: Vec<_> = variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|variant| {
|
.filter_map(|variant| {
|
||||||
let attrs = Attrs::from_variant(
|
let attrs = Attrs::from_variant(
|
||||||
variant,
|
variant,
|
||||||
parent_attribute.casing(),
|
parent_attribute.casing(),
|
||||||
|
@ -130,6 +130,8 @@ fn gen_augment(
|
||||||
let kind = attrs.kind();
|
let kind = attrs.kind();
|
||||||
|
|
||||||
match &*kind {
|
match &*kind {
|
||||||
|
Kind::Skip(_) => None,
|
||||||
|
|
||||||
Kind::ExternalSubcommand => {
|
Kind::ExternalSubcommand => {
|
||||||
let ty = match variant.fields {
|
let ty = match variant.fields {
|
||||||
Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
|
Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
|
||||||
|
@ -141,7 +143,7 @@ fn gen_augment(
|
||||||
or `Vec<OsString>`."
|
or `Vec<OsString>`."
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
match subty_if_name(ty, "Vec") {
|
let subcommand = match subty_if_name(ty, "Vec") {
|
||||||
Some(subty) => {
|
Some(subty) => {
|
||||||
if is_simple_ty(subty, "OsString") {
|
if is_simple_ty(subty, "OsString") {
|
||||||
quote_spanned! { kind.span()=>
|
quote_spanned! { kind.span()=>
|
||||||
|
@ -159,13 +161,14 @@ fn gen_augment(
|
||||||
"The type must be `Vec<_>` \
|
"The type must be `Vec<_>` \
|
||||||
to be used with `external_subcommand`."
|
to be used with `external_subcommand`."
|
||||||
),
|
),
|
||||||
}
|
};
|
||||||
|
Some(subcommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
Kind::Flatten => match variant.fields {
|
Kind::Flatten => match variant.fields {
|
||||||
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
|
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
|
||||||
let ty = &unnamed[0];
|
let ty = &unnamed[0];
|
||||||
if override_required {
|
let subcommand = if override_required {
|
||||||
quote! {
|
quote! {
|
||||||
let app = <#ty as clap::Subcommand>::augment_subcommands_for_update(app);
|
let app = <#ty as clap::Subcommand>::augment_subcommands_for_update(app);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +176,8 @@ fn gen_augment(
|
||||||
quote! {
|
quote! {
|
||||||
let app = <#ty as clap::Subcommand>::augment_subcommands(app);
|
let app = <#ty as clap::Subcommand>::augment_subcommands(app);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
Some(subcommand)
|
||||||
}
|
}
|
||||||
_ => abort!(
|
_ => abort!(
|
||||||
variant,
|
variant,
|
||||||
|
@ -212,14 +216,15 @@ fn gen_augment(
|
||||||
let name = attrs.cased_name();
|
let name = attrs.cased_name();
|
||||||
let from_attrs = attrs.top_level_methods();
|
let from_attrs = attrs.top_level_methods();
|
||||||
let version = attrs.version();
|
let version = attrs.version();
|
||||||
quote! {
|
let subcommand = quote! {
|
||||||
let app = app.subcommand({
|
let app = app.subcommand({
|
||||||
let #app_var = clap::App::new(#name);
|
let #app_var = clap::App::new(#name);
|
||||||
let #app_var = #arg_block;
|
let #app_var = #arg_block;
|
||||||
let #app_var = #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp);
|
let #app_var = #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp);
|
||||||
#app_var#from_attrs#version
|
#app_var#from_attrs#version
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
Some(subcommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -253,13 +258,14 @@ fn gen_augment(
|
||||||
let name = attrs.cased_name();
|
let name = attrs.cased_name();
|
||||||
let from_attrs = attrs.top_level_methods();
|
let from_attrs = attrs.top_level_methods();
|
||||||
let version = attrs.version();
|
let version = attrs.version();
|
||||||
quote! {
|
let subcommand = quote! {
|
||||||
let app = app.subcommand({
|
let app = app.subcommand({
|
||||||
let #app_var = clap::App::new(#name);
|
let #app_var = clap::App::new(#name);
|
||||||
let #app_var = #arg_block;
|
let #app_var = #arg_block;
|
||||||
#app_var#from_attrs#version
|
#app_var#from_attrs#version
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
Some(subcommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -474,3 +474,49 @@ fn subcommand_name_not_literal() {
|
||||||
|
|
||||||
assert!(Opt::try_parse_from(&["test", "renamed"]).is_ok());
|
assert!(Opt::try_parse_from(&["test", "renamed"]).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn skip_subcommand() {
|
||||||
|
#[derive(Debug, PartialEq, Clap)]
|
||||||
|
struct Opt {
|
||||||
|
#[clap(subcommand)]
|
||||||
|
sub: Subcommands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clap)]
|
||||||
|
enum Subcommands {
|
||||||
|
Add,
|
||||||
|
Remove,
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[clap(skip)]
|
||||||
|
Skip,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Opt::parse_from(&["test", "add"]),
|
||||||
|
Opt {
|
||||||
|
sub: Subcommands::Add
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Opt::parse_from(&["test", "remove"]),
|
||||||
|
Opt {
|
||||||
|
sub: Subcommands::Remove
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = Opt::try_parse_from(&["test", "skip"]);
|
||||||
|
assert!(
|
||||||
|
matches!(
|
||||||
|
res,
|
||||||
|
Err(clap::Error {
|
||||||
|
kind: clap::ErrorKind::UnknownArgument,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
),
|
||||||
|
"Unexpected result: {:?}",
|
||||||
|
res
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue