From 54b154b0f86a3960cdb1ac4d5ae35862edc0e9b0 Mon Sep 17 00:00:00 2001 From: FroVolod Date: Wed, 1 Mar 2023 22:32:39 +0200 Subject: [PATCH] draft: Result to ResultFromCli --- examples/to_cli_args.rs | 115 +++++++++++++++--- .../methods/from_cli_for_enum.rs | 2 +- .../methods/from_cli_for_struct.rs | 16 ++- src/lib.rs | 10 +- 4 files changed, 121 insertions(+), 22 deletions(-) diff --git a/examples/to_cli_args.rs b/examples/to_cli_args.rs index c1e06b3..d9d015a 100644 --- a/examples/to_cli_args.rs +++ b/examples/to_cli_args.rs @@ -10,19 +10,69 @@ use inquire::Select; use strum::{EnumDiscriminants, EnumIter, EnumMessage, IntoEnumIterator}; -use interactive_clap::{SelectVariantOrBack, ToCliArgs}; +use interactive_clap::{ResultFromCli, SelectVariantOrBack, ToCliArgs}; mod common; #[derive(Debug, Clone, interactive_clap_derive::InteractiveClap)] #[interactive_clap(context = common::ConnectionConfig)] +#[interactive_clap(skip_default_from_cli)] struct OnlineArgs { + /// What is the name of the network + // #[interactive_clap(skip_default_input_arg)] + network_name: String, #[interactive_clap(subcommand)] submit: Submit, } -#[derive(Debug, EnumDiscriminants, Clone, clap::Parser, interactive_clap_derive::ToCliArgs)] +impl interactive_clap::FromCli for OnlineArgs { + type FromCliContext = common::ConnectionConfig; + type FromCliError = color_eyre::eyre::Error; + + fn from_cli( + optional_clap_variant: Option<::CliVariant>, + context: Self::FromCliContext, + ) -> ResultFromCli<::CliVariant, Self::FromCliError> + where + Self: Sized + interactive_clap::ToCli, + { + let optional_network_name = match optional_clap_variant + .clone() + .and_then(|clap_variant| clap_variant.network_name) + { + Some(network_name) => Some(network_name), + None => match Self::input_network_name(&context) { + Ok(network_name) => Some(network_name), + Err(_) => { + return ResultFromCli::Exit; + } + }, + }; + + let optional_submit = + match optional_clap_variant.and_then(|clap_variant| clap_variant.submit) { + Some(submit) => Some(submit), + None => match Submit::choose_variant(context) { + Ok(Some(submit)) => Some(submit.into()), + Ok(None) => { + return ResultFromCli::Back; + } + Err(_) => { + return ResultFromCli::Exit; + } + }, + }; + ResultFromCli::Ok(CliOnlineArgs { + network_name: optional_network_name, + submit: optional_submit, + }) + } +} + +#[derive(Debug, EnumDiscriminants, Clone, clap::Parser)] #[strum_discriminants(derive(EnumMessage, EnumIter))] +// #[interactive_clap(context = common::ConnectionConfig)] +// #[interactive_clap(skip_default_from_cli)] pub enum Submit { #[strum_discriminants(strum(message = "I want to send the transaction to the network"))] Send, @@ -32,21 +82,56 @@ pub enum Submit { Display, } +#[derive(Debug, EnumDiscriminants, Clone, clap::Parser)] +pub enum CliSubmit { + Send, + Display, +} + +impl From for CliSubmit { + fn from(command: Submit) -> Self { + match command { + Submit::Send => Self::Send, + Submit::Display => Self::Display, + } + } +} + impl interactive_clap::FromCli for Submit { type FromCliContext = common::ConnectionConfig; type FromCliError = color_eyre::eyre::Error; fn from_cli( optional_clap_variant: Option<::CliVariant>, - _context: Self::FromCliContext, - ) -> Result, Self::FromCliError> + context: Self::FromCliContext, + ) -> ResultFromCli<::CliVariant, Self::FromCliError> where Self: Sized + interactive_clap::ToCli, { - let submit: Option = optional_clap_variant.clone(); - match submit { - Some(submit) => Ok(Some(submit)), - None => Ok(Some(Submit::Display)), + match optional_clap_variant { + Some(submit) => ResultFromCli::Ok(submit), + None => match Self::choose_variant(context) { + Ok(Some(submit)) => ResultFromCli::Ok(submit.into()), + Ok(None) => ResultFromCli::Back, + Err(_) => ResultFromCli::Exit, + }, + } + } +} + +impl interactive_clap::ToCliArgs for CliSubmit { + fn to_cli_args(&self) -> std::collections::VecDeque { + match self { + Self::Send => { + let mut args = std::collections::VecDeque::new(); + args.push_front("send".to_owned()); + args + } + Self::Display => { + let mut args = std::collections::VecDeque::new(); + args.push_front("display".to_owned()); + args + } } } } @@ -71,9 +156,8 @@ impl Submit { } } } - impl interactive_clap::ToCli for Submit { - type CliVariant = Submit; + type CliVariant = CliSubmit; } impl std::fmt::Display for SubmitDiscriminants { @@ -89,13 +173,14 @@ fn main() { let mut cli_online_args = OnlineArgs::parse(); let context = common::ConnectionConfig::Testnet; //#[interactive_clap(context = common::ConnectionConfig)] let online_args = loop { - if let Some(args) = ::from_cli( + match ::from_cli( Some(cli_online_args.clone()), context.clone(), - ) - .unwrap() - { - break args; + ) { + ResultFromCli::Ok(args) => break args, + ResultFromCli::Back => (), + ResultFromCli::Exit => todo!(), + ResultFromCli::Err(cli_args, err) => todo!(), } }; cli_online_args = online_args.into(); 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 eb22e0f..ef1f0d4 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 @@ -73,7 +73,7 @@ pub fn from_cli_for_enum( fn from_cli( optional_clap_variant: Option<::CliVariant>, context: Self::FromCliContext, - ) -> Result, Self::FromCliError> where Self: Sized + interactive_clap::ToCli { + ) -> ResultFromCli<::CliVariant, Self::FromCliError> where Self: Sized + interactive_clap::ToCli { 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 e532bca..ac484b0 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,7 +84,7 @@ pub fn from_cli_for_struct( fn from_cli( optional_clap_variant: Option<::CliVariant>, context: Self::FromCliContext, - ) -> Result, Self::FromCliError> where Self: Sized + interactive_clap::ToCli { + ) -> ResultFromCli<::CliVariant, Self::FromCliError> where Self: Sized + interactive_clap::ToCli { #(#fields_value)* #new_context_scope #field_value_named_arg @@ -100,12 +100,15 @@ fn fields_value(field: &syn::Field) -> proc_macro2::TokenStream { let fn_from_cli_arg = syn::Ident::new(&format!("from_cli_{}", &ident_field), Span::call_site()); if super::fields_without_subcommand::is_field_without_subcommand(field) { quote! { - let #ident_field = Self::#fn_from_cli_arg( + let #ident_field = match Self::#fn_from_cli_arg( optional_clap_variant .clone() .and_then(|clap_variant| clap_variant.#ident_field), &context, - )?; + ) { + Ok(#ident_field) => #ident_field, + Err(err) => return ResultFromCli::Err(color_eyre::Report::msg(err.to_string())); + }; } } else { quote!() @@ -148,9 +151,12 @@ fn field_value_named_arg( Some(output_context_dir) => { let context_for_struct = syn::Ident::new(&format!("{}Context", &name), Span::call_site()); quote! { - let new_context = #context_for_struct::from_previous_context(context, &new_context_scope)?; + let new_context = match #context_for_struct::from_previous_context(context, &new_context_scope) { + Ok(new_context) => new_context, + Err(err) => return ResultFromCli::Err(color_eyre::Report::msg(err.to_string())); + }; let output_context = #output_context_dir::from(new_context); - let #ident_field = <#ty as interactive_clap::FromCli>::from_cli( + let #ident_field = match <#ty as interactive_clap::FromCli>::from_cli( optional_clap_variant.and_then(|clap_variant| match clap_variant.#ident_field { Some(#enum_for_clap_named_arg::#variant_name(cli_arg)) => Some(cli_arg), None => None, diff --git a/src/lib.rs b/src/lib.rs index 1e65808..9c1b84e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,13 +30,21 @@ pub trait ToCliArgs { fn to_cli_args(&self) -> std::collections::VecDeque; } +pub enum ResultFromCli { + Ok(T), + Back, + Exit, + Err(T, E), +} + + pub trait FromCli { type FromCliContext; type FromCliError; fn from_cli( optional_clap_variant: Option<::CliVariant>, context: Self::FromCliContext, - ) -> Result, Self::FromCliError> + ) -> ResultFromCli<::CliVariant, Self::FromCliError> where Self: Sized + ToCli; }