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:
Ed Page 2021-10-06 13:52:02 -05:00
parent 5512c90380
commit 16023cf157
3 changed files with 62 additions and 12 deletions

View file

@ -552,9 +552,7 @@ impl Attrs {
res.kind = Sp::new(Kind::Subcommand(ty), res.kind.span());
}
Kind::Skip(_) => {
abort!(res.kind.span(), "skip is not supported on variants");
}
Kind::Skip(_) => (),
Kind::FromGlobal(_) => {
abort!(res.kind.span(), "from_global is not supported on variants");
}

View file

@ -121,7 +121,7 @@ fn gen_augment(
let subcommands: Vec<_> = variants
.iter()
.map(|variant| {
.filter_map(|variant| {
let attrs = Attrs::from_variant(
variant,
parent_attribute.casing(),
@ -130,6 +130,8 @@ fn gen_augment(
let kind = attrs.kind();
match &*kind {
Kind::Skip(_) => None,
Kind::ExternalSubcommand => {
let ty = match variant.fields {
Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
@ -141,7 +143,7 @@ fn gen_augment(
or `Vec<OsString>`."
),
};
match subty_if_name(ty, "Vec") {
let subcommand = match subty_if_name(ty, "Vec") {
Some(subty) => {
if is_simple_ty(subty, "OsString") {
quote_spanned! { kind.span()=>
@ -159,13 +161,14 @@ fn gen_augment(
"The type must be `Vec<_>` \
to be used with `external_subcommand`."
),
}
};
Some(subcommand)
}
Kind::Flatten => match variant.fields {
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
let ty = &unnamed[0];
if override_required {
let subcommand = if override_required {
quote! {
let app = <#ty as clap::Subcommand>::augment_subcommands_for_update(app);
}
@ -173,7 +176,8 @@ fn gen_augment(
quote! {
let app = <#ty as clap::Subcommand>::augment_subcommands(app);
}
}
};
Some(subcommand)
}
_ => abort!(
variant,
@ -212,14 +216,15 @@ fn gen_augment(
let name = attrs.cased_name();
let from_attrs = attrs.top_level_methods();
let version = attrs.version();
quote! {
let subcommand = quote! {
let app = app.subcommand({
let #app_var = clap::App::new(#name);
let #app_var = #arg_block;
let #app_var = #app_var.setting(::clap::AppSettings::SubcommandRequiredElseHelp);
#app_var#from_attrs#version
});
}
};
Some(subcommand)
}
_ => {
@ -253,13 +258,14 @@ fn gen_augment(
let name = attrs.cased_name();
let from_attrs = attrs.top_level_methods();
let version = attrs.version();
quote! {
let subcommand = quote! {
let app = app.subcommand({
let #app_var = clap::App::new(#name);
let #app_var = #arg_block;
#app_var#from_attrs#version
});
}
};
Some(subcommand)
}
}
})

View file

@ -474,3 +474,49 @@ fn subcommand_name_not_literal() {
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
);
}