From 5df97d2621072834590cce603ee92da3b4cb4eb2 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Wed, 31 Aug 2022 12:29:24 +0300 Subject: [PATCH] added "back" option --- examples/advanced_struct.rs | 6 ++--- examples/to_cli_args.rs | 26 ++++++++++++------- .../methods/choose_variant.rs | 26 +++++++++++++------ .../methods/from_cli_for_enum.rs | 24 ++++++++++++----- .../methods/from_cli_for_struct.rs | 26 ++++++++++++++++--- 5 files changed, 79 insertions(+), 29 deletions(-) diff --git a/examples/advanced_struct.rs b/examples/advanced_struct.rs index e382e91..6452f1e 100644 --- a/examples/advanced_struct.rs +++ b/examples/advanced_struct.rs @@ -26,7 +26,7 @@ impl Args { pub fn from_cli( optional_clap_variant: Option, context: (), - ) -> color_eyre::eyre::Result { + ) -> color_eyre::eyre::Result> { let age = Self::from_cli_age( optional_clap_variant .clone() @@ -50,11 +50,11 @@ impl Args { first_name, second_name, }; - Ok(Self { + Ok(Some(Self { age: new_context_scope.age, first_name: new_context_scope.first_name, second_name: new_context_scope.second_name, - }) + })) } fn input_age(_context: &()) -> color_eyre::eyre::Result { diff --git a/examples/to_cli_args.rs b/examples/to_cli_args.rs index 6c0fae0..90a22db 100644 --- a/examples/to_cli_args.rs +++ b/examples/to_cli_args.rs @@ -33,32 +33,34 @@ pub enum Submit { impl Submit { fn choose_variant( connection_config: common::ConnectionConfig, - ) -> color_eyre::eyre::Result { + ) -> color_eyre::eyre::Result> { let variants = SubmitDiscriminants::iter().collect::>(); - let submits = variants + let mut submits = variants .iter() .map(|p| p.get_message().unwrap().to_owned()) .collect::>(); + submits.push("back".to_string()); let select_submit = Select::with_theme(&ColorfulTheme::default()) .with_prompt("How would you like to proceed") .items(&submits) .default(0) .interact() .unwrap(); - match variants[select_submit] { - SubmitDiscriminants::Send => Ok(Submit::Send), - SubmitDiscriminants::Display => Ok(Submit::Display), + match variants.get(select_submit) { + Some(SubmitDiscriminants::Send) => Ok(Some(Submit::Send)), + Some(SubmitDiscriminants::Display) => Ok(Some(Submit::Display)), + None => Ok(None), } } fn from_cli( optional_clap_variant: Option<::CliVariant>, context: common::ConnectionConfig, - ) -> color_eyre::eyre::Result { + ) -> color_eyre::eyre::Result> { let submit: Option = optional_clap_variant.clone(); match submit { - Some(submit) => Ok(submit), - None => Ok(Submit::Display), + Some(submit) => Ok(Some(submit)), + None => Ok(Some(Submit::Display)), } } } @@ -70,7 +72,13 @@ impl interactive_clap::ToCli for Submit { fn main() { let mut cli_online_args = OnlineArgs::parse(); let context = common::ConnectionConfig::Testnet; //#[interactive_clap(context = common::ConnectionConfig)] - let online_args = OnlineArgs::from_cli(Some(cli_online_args), context).unwrap(); + let online_args = loop { + if let Some(args) = + OnlineArgs::from_cli(Some(cli_online_args.clone()), context.clone()).unwrap() + { + break args; + } + }; cli_online_args = online_args.into(); let completed_cli = cli_online_args.to_cli_args(); println!( diff --git a/interactive_clap_derive/src/derives/interactive_clap/methods/choose_variant.rs b/interactive_clap_derive/src/derives/interactive_clap/methods/choose_variant.rs index 8000ea9..b507c31 100644 --- a/interactive_clap_derive/src/derives/interactive_clap/methods/choose_variant.rs +++ b/interactive_clap_derive/src/derives/interactive_clap/methods/choose_variant.rs @@ -102,13 +102,13 @@ pub fn fn_choose_variant( cli_variant = quote! { use dialoguer::{theme::ColorfulTheme, Select}; use strum::{EnumMessage, IntoEnumIterator}; - fn prompt_variant(prompt: &str) -> T + fn prompt_variant(prompt: &str) -> Option where T: IntoEnumIterator + EnumMessage, T: Copy + Clone, { let variants = T::iter().collect::>(); - let actions = variants + let mut actions = variants .iter() .map(|p| { p.get_message() @@ -116,6 +116,7 @@ pub fn fn_choose_variant( .to_owned() }) .collect::>(); + actions.push("back".to_string()); let selected = Select::with_theme(&ColorfulTheme::default()) .with_prompt(prompt) @@ -124,9 +125,14 @@ pub fn fn_choose_variant( .interact() .unwrap(); - variants[selected] - } - let cli_variant = match prompt_variant(#literal.to_string().as_str()) { + variants.get(selected).cloned() + }; + let variant = if let Some(variant) = prompt_variant(#literal.to_string().as_str()) { + variant + } else { + return Ok(None); + }; + let cli_variant = match variant { #( #enum_variants, )* }; }; @@ -141,9 +147,13 @@ pub fn fn_choose_variant( let input_context = interactive_clap_attrs_context.get_input_context_dir(); quote! { - pub fn choose_variant(context: #input_context) -> color_eyre::eyre::Result { - #cli_variant - Ok(Self::from_cli(Some(cli_variant), context.clone())?) + pub fn choose_variant(context: #input_context) -> color_eyre::eyre::Result> { + loop { + #cli_variant + if let Some(variant) = Self::from_cli(Some(cli_variant), context.clone())? { + return Ok(Some(variant)); + } + } } } } diff --git a/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_enum.rs b/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_enum.rs index c8c1c87..c00c514 100644 --- a/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_enum.rs +++ b/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_enum.rs @@ -28,21 +28,33 @@ pub fn from_cli_for_enum( match &interactive_clap_attrs_context.output_context_dir { Some(_) => quote! { - Some(#cli_name::#variant_ident(args)) => { + Some(#cli_name::#variant_ident(inner_cli_args)) => { type Alias = <#name as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope; let new_context_scope = Alias::#variant_ident; - let new_context = #context_name::from_previous_context((), &new_context_scope); - Ok(Self::#variant_ident(#ty::from_cli(Some(args), new_context.into())?,)) + let new_context = #context_name::from_previous_context(context.clone(), &new_context_scope); + let optional_inner_args = #ty::from_cli(Some(inner_cli_args), new_context.into())?; + if let Some(inner_args) = optional_inner_args { + Ok(Some(Self::#variant_ident(inner_args,))) + } else { + Self::choose_variant(context.clone()) + } } }, None => quote! { - Some(#cli_name::#variant_ident(args)) => Ok(Self::#variant_ident(#ty::from_cli(Some(args), context.clone())?,)), + Some(#cli_name::#variant_ident(inner_cli_args)) => { + let optional_inner_args = #ty::from_cli(Some(inner_cli_args), context.clone())?; + if let Some(inner_args) = optional_inner_args { + Ok(Some(Self::#variant_ident(inner_args,))) + } else { + Self::choose_variant(context.clone()) + } + } } } }, syn::Fields::Unit => { quote! { - Some(#cli_name::#variant_ident) => Ok(Self::#variant_ident), + Some(#cli_name::#variant_ident) => Ok(Some(Self::#variant_ident)), } }, _ => abort_call_site!("Only option `Fields::Unnamed` or `Fields::Unit` is needed") @@ -57,7 +69,7 @@ pub fn from_cli_for_enum( pub fn from_cli( optional_clap_variant: Option<#cli_name>, context: #input_context_dir, - ) -> color_eyre::eyre::Result { + ) -> color_eyre::eyre::Result> { match optional_clap_variant { #(#from_cli_variants)* None => Self::choose_variant(context.clone()), diff --git a/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_struct.rs b/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_struct.rs index 4315c9b..4c87294 100644 --- a/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_struct.rs +++ b/interactive_clap_derive/src/derives/interactive_clap/methods/from_cli_for_struct.rs @@ -84,12 +84,12 @@ pub fn from_cli_for_struct( pub fn from_cli( optional_clap_variant: Option<#cli_name>, context: #input_context_dir, - ) -> color_eyre::eyre::Result { + ) -> color_eyre::eyre::Result> { #(#fields_value)* #new_context_scope #field_value_named_arg - #field_value_subcommand - Ok(Self{ #(#struct_fields,)* }) + #field_value_subcommand; + Ok(Some(Self{ #(#struct_fields,)* })) } } } @@ -162,6 +162,11 @@ fn field_value_named_arg( }), new_context.into(), )?; + let #ident_field = if let Some(value) = #ident_field { + value + } else { + return Ok(None); + } } }, None => quote! { @@ -172,6 +177,11 @@ fn field_value_named_arg( }), context.into(), )?; + let #ident_field = if let Some(value) = #ident_field { + value + } else { + return Ok(None); + } } } }) @@ -218,6 +228,11 @@ fn field_value_subcommand( Some(cli_arg) => #ty::from_cli(Some(cli_arg), new_context.into())?, None => #ty::choose_variant(new_context.into())?, }; + let #ident_field = if let Some(value) = #ident_field { + value + } else { + return Ok(None); + } } }, None => quote! { @@ -225,6 +240,11 @@ fn field_value_subcommand( Some(cli_arg) => #ty::from_cli(Some(cli_arg), context)?, None => #ty::choose_variant(context.into())?, }; + let #ident_field = if let Some(value) = #ident_field { + value + } else { + return Ok(None); + } } } })