wip: Add a variant for augment* for updates

This commit is contained in:
Luca Barbato 2020-08-25 11:03:09 +02:00
parent 8b6255057d
commit a9276576d7
4 changed files with 85 additions and 12 deletions

View file

@ -103,6 +103,15 @@ pub fn gen_for_enum(name: &Ident) -> TokenStream {
fn augment_clap<'b>(app: ::clap::App<'b>) -> ::clap::App<'b> {
<#name as ::clap::Subcommand>::augment_subcommands(app)
}
fn into_update_app<'b>() -> ::clap::App<'b> {
let app = ::clap::App::new(#app_name);
<#name as ::clap::IntoApp>::augment_update_clap(app)
}
fn augment_update_clap<'b>(app: ::clap::App<'b>) -> ::clap::App<'b> {
<#name as ::clap::Subcommand>::augment_update_subcommands(app)
}
}
}
}
@ -123,6 +132,9 @@ fn gen_into_app_fn(attrs: &[Attribute]) -> GenOutput {
fn into_app<'b>() -> ::clap::App<'b> {
Self::augment_clap(::clap::App::new(#name))
}
fn into_update_app<'b>() -> ::clap::App<'b> {
Self::augment_update_clap(::clap::App::new(#name))
}
};
(tokens, attrs)
@ -130,11 +142,15 @@ fn gen_into_app_fn(attrs: &[Attribute]) -> GenOutput {
fn gen_augment_clap_fn(fields: &Punctuated<Field, Comma>, parent_attribute: &Attrs) -> TokenStream {
let app_var = Ident::new("app", Span::call_site());
let augmentation = gen_app_augmentation(fields, &app_var, parent_attribute);
let augmentation = gen_app_augmentation(fields, &app_var, parent_attribute, false);
let augmentation_update = gen_app_augmentation(fields, &app_var, parent_attribute, true);
quote! {
fn augment_clap<'b>(#app_var: ::clap::App<'b>) -> ::clap::App<'b> {
#augmentation
}
fn augment_update_clap<'b>(#app_var: ::clap::App<'b>) -> ::clap::App<'b> {
#augmentation_update
}
}
}
@ -150,6 +166,7 @@ pub fn gen_app_augmentation(
fields: &Punctuated<Field, Comma>,
app_var: &Ident,
parent_attribute: &Attrs,
override_required: bool,
) -> TokenStream {
let mut subcmds = fields.iter().filter_map(|field| {
let attrs = Attrs::from_field(
@ -174,9 +191,15 @@ pub fn gen_app_augmentation(
};
let span = field.span();
let ts = quote! {
let #app_var = <#subcmd_type as ::clap::Subcommand>::augment_subcommands( #app_var );
#required
let ts = if override_required {
quote! {
let #app_var = <#subcmd_type as ::clap::Subcommand>::augment_update_subcommands( #app_var );
}
} else{
quote! {
let #app_var = <#subcmd_type as ::clap::Subcommand>::augment_subcommands( #app_var );
#required
}
};
Some((span, ts))
} else {
@ -296,7 +319,7 @@ pub fn gen_app_augmentation(
},
Ty::Other => {
let required = !attrs.has_method("default_value");
let required = !attrs.has_method("default_value") && !override_required;
let mut possible_values = quote!();
if attrs.is_enum() {

View file

@ -35,6 +35,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
let from_subcommand = gen_from_subcommand(name, &e.variants, &attrs);
let augment_subcommands = gen_augment_subcommands(&e.variants, &attrs);
let augment_update_subcommands = gen_augment_update_subcommands(&e.variants, &attrs);
let update_from_subcommand = gen_update_from_subcommand(name, &e.variants, &attrs);
quote! {
@ -53,6 +54,7 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
impl ::clap::Subcommand for #name {
#augment_subcommands
#from_subcommand
#augment_update_subcommands
#update_from_subcommand
}
}
@ -61,6 +63,27 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
fn gen_augment_subcommands(
variants: &Punctuated<Variant, Token![,]>,
parent_attribute: &Attrs,
) -> TokenStream {
gen_augment("augment_subcommands", variants, parent_attribute, false)
}
fn gen_augment_update_subcommands(
variants: &Punctuated<Variant, Token![,]>,
parent_attribute: &Attrs,
) -> TokenStream {
gen_augment(
"augment_update_subcommands",
variants,
parent_attribute,
true,
)
}
fn gen_augment(
fn_name: &str,
variants: &Punctuated<Variant, Token![,]>,
parent_attribute: &Attrs,
override_required: bool,
) -> TokenStream {
use syn::Fields::*;
@ -99,9 +122,12 @@ fn gen_augment_subcommands(
_ => {
let app_var = Ident::new("subcommand", Span::call_site());
let arg_block = match variant.fields {
Named(ref fields) => {
into_app::gen_app_augmentation(&fields.named, &app_var, &attrs)
}
Named(ref fields) => into_app::gen_app_augmentation(
&fields.named,
&app_var,
&attrs,
override_required,
),
Unit => quote!( #app_var ),
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
let ty = &unnamed[0];
@ -133,8 +159,9 @@ fn gen_augment_subcommands(
let app_methods = parent_attribute.top_level_methods();
let version = parent_attribute.version();
let fn_name = Ident::new(fn_name, Span::call_site());
quote! {
fn augment_subcommands<'b>(app: ::clap::App<'b>) -> ::clap::App<'b> {
fn #fn_name <'b>(app: ::clap::App<'b>) -> ::clap::App<'b> {
let app = app #app_methods;
#( #subcommands )*;
app #version

View file

@ -27,6 +27,12 @@ pub fn into_app(name: &Ident) {
fn augment_clap<'b>(_app: ::clap::App<'b>) -> ::clap::App<'b> {
unimplemented!()
}
fn into_update_app<'b>() -> ::clap::App<'b> {
unimplemented!()
}
fn augment_update_clap<'b>(_app: ::clap::App<'b>) -> ::clap::App<'b> {
unimplemented!()
}
}
});
}
@ -56,6 +62,9 @@ pub fn subcommand(name: &Ident) {
fn augment_subcommands(_app: ::clap::App<'_>) -> ::clap::App<'_> {
unimplemented!()
}
fn augment_update_subcommands(_app: ::clap::App<'_>) -> ::clap::App<'_> {
unimplemented!()
}
}
});
}

View file

@ -113,7 +113,7 @@ pub trait Clap: FromArgMatches + IntoApp + Sized {
T: Into<OsString> + Clone,
{
// TODO find a way to get partial matches
let matches = <Self as IntoApp>::into_app().get_matches_from(itr);
let matches = <Self as IntoApp>::into_update_app().get_matches_from(itr);
<Self as FromArgMatches>::update_from_arg_matches(self, &matches);
}
@ -124,8 +124,7 @@ pub trait Clap: FromArgMatches + IntoApp + Sized {
// TODO (@CreepySkeleton): discover a way to avoid cloning here
T: Into<OsString> + Clone,
{
// TODO find a way to get partial matches
let matches = <Self as IntoApp>::into_app().try_get_matches_from(itr)?;
let matches = <Self as IntoApp>::into_update_app().try_get_matches_from(itr)?;
<Self as FromArgMatches>::update_from_arg_matches(self, &matches);
Ok(())
}
@ -139,6 +138,10 @@ pub trait IntoApp: Sized {
fn into_app<'help>() -> App<'help>;
/// @TODO @release @docs
fn augment_clap(app: App<'_>) -> App<'_>;
/// @TODO @release @docs
fn into_update_app<'help>() -> App<'help>;
/// @TODO @release @docs
fn augment_update_clap(app: App<'_>) -> App<'_>;
}
/// Converts an instance of [`ArgMatches`] to a consumer defined struct.
@ -192,6 +195,8 @@ pub trait Subcommand: Sized {
fn update_from_subcommand(&mut self, name: &str, matches: Option<&ArgMatches>);
/// @TODO @release @docs
fn augment_subcommands(app: App<'_>) -> App<'_>;
/// @TODO @release @docs
fn augment_update_subcommands(app: App<'_>) -> App<'_>;
}
/// @TODO @release @docs
@ -238,6 +243,12 @@ impl<T: IntoApp> IntoApp for Box<T> {
fn augment_clap(app: App<'_>) -> App<'_> {
<T as IntoApp>::augment_clap(app)
}
fn into_update_app<'help>() -> App<'help> {
<T as IntoApp>::into_update_app()
}
fn augment_update_clap(app: App<'_>) -> App<'_> {
<T as IntoApp>::augment_update_clap(app)
}
}
impl<T: FromArgMatches> FromArgMatches for Box<T> {
@ -259,4 +270,7 @@ impl<T: Subcommand> Subcommand for Box<T> {
fn augment_subcommands(app: App<'_>) -> App<'_> {
<T as Subcommand>::augment_subcommands(app)
}
fn augment_update_subcommands(app: App<'_>) -> App<'_> {
<T as Subcommand>::augment_update_subcommands(app)
}
}