Skip to content

Commit

Permalink
WIP: fix(derive)!: Remove update support
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed Jun 19, 2023
1 parent 482012a commit 300e721
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 445 deletions.
67 changes: 0 additions & 67 deletions clap_builder/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,34 +71,6 @@ pub trait Parser: FromArgMatches + CommandFactory + Sized {
let mut matches = ok!(<Self as CommandFactory>::command().try_get_matches_from(itr));
<Self as FromArgMatches>::from_arg_matches_mut(&mut matches).map_err(format_error::<Self>)
}

/// Update from iterator, exit on error
fn update_from<I, T>(&mut self, itr: I)
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
let mut matches = <Self as CommandFactory>::command_for_update().get_matches_from(itr);
let res = <Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
.map_err(format_error::<Self>);
if let Err(e) = res {
// Since this is more of a development-time error, we aren't doing as fancy of a quit
// as `get_matches_from`
e.exit()
}
}

/// Update from iterator, return Err on error.
fn try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error>
where
I: IntoIterator<Item = T>,
T: Into<OsString> + Clone,
{
let mut matches =
ok!(<Self as CommandFactory>::command_for_update().try_get_matches_from(itr));
<Self as FromArgMatches>::update_from_arg_matches_mut(self, &mut matches)
.map_err(format_error::<Self>)
}
}

/// Create a [`Command`] relevant for a user-defined container.
Expand All @@ -109,10 +81,6 @@ pub trait CommandFactory: Sized {
///
/// See [`FromArgMatches::from_arg_matches_mut`] for instantiating `Self`.
fn command() -> Command;
/// Build a [`Command`] that can update `self`.
///
/// See [`FromArgMatches::update_from_arg_matches_mut`] for updating `self`.
fn command_for_update() -> Command;
}

/// Converts an instance of [`ArgMatches`] to a user-defined container.
Expand Down Expand Up @@ -192,14 +160,6 @@ pub trait FromArgMatches: Sized {
fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
Self::from_arg_matches(matches)
}

/// Assign values from `ArgMatches` to `self`.
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error>;

/// Assign values from `ArgMatches` to `self`.
fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
self.update_from_arg_matches(matches)
}
}

/// Parse a set of arguments into a user-defined container.
Expand All @@ -220,12 +180,6 @@ pub trait Args: FromArgMatches + Sized {
///
/// See also [`CommandFactory`].
fn augment_args(cmd: Command) -> Command;
/// Append to [`Command`] so it can update `self`.
///
/// This is used to implement `#[command(flatten)]`
///
/// See also [`CommandFactory`].
fn augment_args_for_update(cmd: Command) -> Command;
}

/// Parse a sub-command into a user-defined enum.
Expand All @@ -243,12 +197,6 @@ pub trait Subcommand: FromArgMatches + Sized {
///
/// See also [`CommandFactory`].
fn augment_subcommands(cmd: Command) -> Command;
/// Append to [`Command`] so it can update `self`.
///
/// This is used to implement `#[command(flatten)]`
///
/// See also [`CommandFactory`].
fn augment_subcommands_for_update(cmd: Command) -> Command;
/// Test whether `Self` can parse a specific subcommand
fn has_subcommand(name: &str) -> bool;
}
Expand Down Expand Up @@ -314,9 +262,6 @@ impl<T: CommandFactory> CommandFactory for Box<T> {
fn command<'help>() -> Command {
<T as CommandFactory>::command()
}
fn command_for_update<'help>() -> Command {
<T as CommandFactory>::command_for_update()
}
}

impl<T: FromArgMatches> FromArgMatches for Box<T> {
Expand All @@ -326,30 +271,18 @@ impl<T: FromArgMatches> FromArgMatches for Box<T> {
fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
<T as FromArgMatches>::from_arg_matches_mut(matches).map(Box::new)
}
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
<T as FromArgMatches>::update_from_arg_matches(self, matches)
}
fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
<T as FromArgMatches>::update_from_arg_matches_mut(self, matches)
}
}

impl<T: Args> Args for Box<T> {
fn augment_args(cmd: Command) -> Command {
<T as Args>::augment_args(cmd)
}
fn augment_args_for_update(cmd: Command) -> Command {
<T as Args>::augment_args_for_update(cmd)
}
}

impl<T: Subcommand> Subcommand for Box<T> {
fn augment_subcommands(cmd: Command) -> Command {
<T as Subcommand>::augment_subcommands(cmd)
}
fn augment_subcommands_for_update(cmd: Command) -> Command {
<T as Subcommand>::augment_subcommands_for_update(cmd)
}
fn has_subcommand(name: &str) -> bool {
<T as Subcommand>::has_subcommand(name)
}
Expand Down
176 changes: 10 additions & 166 deletions clap_derive/src/derives/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,10 @@ pub fn gen_for_struct(
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let constructor = gen_constructor(fields)?;
let updater = gen_updater(fields, true)?;
let raw_deprecated = raw_deprecated();

let app_var = Ident::new("__clap_app", Span::call_site());
let augmentation = gen_augment(fields, &app_var, item, false)?;
let augmentation_update = gen_augment(fields, &app_var, item, true)?;
let augmentation = gen_augment(fields, &app_var, item)?;

let group_id = if item.skip_group() {
quote!(None)
Expand Down Expand Up @@ -116,16 +114,6 @@ pub fn gen_for_struct(
let v = #item_name #constructor;
::std::result::Result::Ok(v)
}

fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> {
self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone())
}

fn update_from_arg_matches_mut(&mut self, __clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<(), clap::Error> {
#raw_deprecated
#updater
::std::result::Result::Ok(())
}
}

#[allow(
Expand Down Expand Up @@ -155,9 +143,6 @@ pub fn gen_for_struct(
fn augment_args<'b>(#app_var: clap::Command) -> clap::Command {
#augmentation
}
fn augment_args_for_update<'b>(#app_var: clap::Command) -> clap::Command {
#augmentation_update
}
}
})
}
Expand All @@ -168,7 +153,6 @@ pub fn gen_augment(
fields: &[(&Field, Item)],
app_var: &Ident,
parent_item: &Item,
override_required: bool,
) -> Result<TokenStream, syn::Error> {
let mut subcommand_specified = false;
let mut args = Vec::new();
Expand Down Expand Up @@ -202,20 +186,10 @@ pub fn gen_augment(
}
};

let override_methods = if override_required {
quote_spanned! { kind.span()=>
.subcommand_required(false)
.arg_required_else_help(false)
}
} else {
quote!()
};

Some(quote! {
let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands( #app_var );
let #app_var = #app_var
#implicit_methods
#override_methods;
#implicit_methods;
})
}
Kind::Flatten(ty) => {
Expand All @@ -226,21 +200,12 @@ pub fn gen_augment(

let next_help_heading = item.next_help_heading();
let next_display_order = item.next_display_order();
if override_required {
Some(quote_spanned! { kind.span()=>
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#inner_type as clap::Args>::augment_args_for_update(#app_var);
})
} else {
Some(quote_spanned! { kind.span()=>
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#inner_type as clap::Args>::augment_args(#app_var);
})
}
Some(quote_spanned! { kind.span()=>
let #app_var = #app_var
#next_help_heading
#next_display_order;
let #app_var = <#inner_type as clap::Args>::augment_args(#app_var);
})
}
Kind::Arg(ty) => {
let value_parser = item.value_parser(&field.ty);
Expand Down Expand Up @@ -329,18 +294,7 @@ pub fn gen_augment(

let id = item.id();
let explicit_methods = item.field_methods();
let deprecations = if !override_required {
item.deprecations()
} else {
quote!()
};
let override_methods = if override_required {
quote_spanned! { kind.span()=>
.required(false)
}
} else {
quote!()
};
let deprecations = item.deprecations();

Some(quote_spanned! { field.span()=>
let #app_var = #app_var.arg({
Expand All @@ -353,9 +307,6 @@ pub fn gen_augment(
let arg = arg
#explicit_methods;

let arg = arg
#override_methods;

arg
});
})
Expand All @@ -364,11 +315,7 @@ pub fn gen_augment(
args.push(genned);
}

let deprecations = if !override_required {
parent_item.deprecations()
} else {
quote!()
};
let deprecations = parent_item.deprecations();
let initial_app_methods = parent_item.initial_top_level_methods();
let final_app_methods = parent_item.final_top_level_methods();
let group_app_methods = if parent_item.skip_group() {
Expand Down Expand Up @@ -540,109 +487,6 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream, syn::Er
}})
}

pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> Result<TokenStream, syn::Error> {
let mut genned_fields = Vec::new();
for (field, item) in fields {
let field_name = field.ident.as_ref().unwrap();
let kind = item.kind();

let access = if use_self {
quote! {
#[allow(non_snake_case)]
let #field_name = &mut self.#field_name;
}
} else {
quote!()
};
let arg_matches = format_ident!("__clap_arg_matches");

let genned = match &*kind {
Kind::Command(_) | Kind::Value | Kind::ExternalSubcommand => {
abort! { kind.span(),
"`{}` cannot be used with `arg`",
kind.name(),
}
}
Kind::Subcommand(ty) => {
let subcmd_type = match (**ty, sub_type(&field.ty)) {
(Ty::Option, Some(sub_type)) => sub_type,
_ => &field.ty,
};

let updater = quote_spanned! { ty.span()=>
<#subcmd_type as clap::FromArgMatches>::update_from_arg_matches_mut(#field_name, #arg_matches)?;
};

let updater = match **ty {
Ty::Option => quote_spanned! { kind.span()=>
if let Some(#field_name) = #field_name.as_mut() {
#updater
} else {
*#field_name = Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(
#arg_matches
)?);
}
},
_ => quote_spanned! { kind.span()=>
#updater
},
};

quote_spanned! { kind.span()=>
{
#access
#updater
}
}
}

Kind::Flatten(ty) => {
let inner_type = match (**ty, sub_type(&field.ty)) {
(Ty::Option, Some(sub_type)) => sub_type,
_ => &field.ty,
};

let updater = quote_spanned! { ty.span()=>
<#inner_type as clap::FromArgMatches>::update_from_arg_matches_mut(#field_name, #arg_matches)?;
};

let updater = match **ty {
Ty::Option => quote_spanned! { kind.span()=>
if let Some(#field_name) = #field_name.as_mut() {
#updater
} else {
*#field_name = Some(<#inner_type as clap::FromArgMatches>::from_arg_matches_mut(
#arg_matches
)?);
}
},
_ => quote_spanned! { kind.span()=>
#updater
},
};

quote_spanned! { kind.span()=>
{
#access
#updater
}
}
}

Kind::Skip(_, _) => quote!(),

Kind::Arg(ty) | Kind::FromGlobal(ty) => {
gen_parsers(item, ty, field_name, field, Some(&access))?
}
};
genned_fields.push(genned);
}

Ok(quote! {
#( #genned_fields )*
})
}

fn gen_parsers(
item: &Item,
ty: &Sp<Ty>,
Expand Down

0 comments on commit 300e721

Please sign in to comment.