From 433e5368c68cd4f0b021009a5c225fc7e7cb8412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20B=C3=A1ez?= Date: Sat, 6 Apr 2024 12:44:01 -0500 Subject: [PATCH] [HOUSEKEEPING] add object-oriented structure to the setup command (#128) --- src/cli/opt.rs | 4 +- src/controllers/cmd_setup_async.rs | 111 ++++++++++++++++++++++ src/controllers/{ => legacy}/cmd_setup.rs | 0 src/controllers/mod.rs | 2 +- src/main.rs | 8 +- 5 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 src/controllers/cmd_setup_async.rs rename src/controllers/{ => legacy}/cmd_setup.rs (100%) diff --git a/src/cli/opt.rs b/src/cli/opt.rs index 14e2b9e..4191e75 100644 --- a/src/cli/opt.rs +++ b/src/cli/opt.rs @@ -8,13 +8,13 @@ use std::path::PathBuf; use structopt::clap::ArgGroup; use structopt::StructOpt; -use crate::controllers::cmd_setup::show_help_setup; +use crate::controllers::cmd_setup_async::SetupController; /// Setup subcommand #[derive(StructOpt, Debug)] pub enum SetUp { /// Subcommand that allows to change settings - #[structopt(after_help = show_help_setup())] + #[structopt(after_help = SetupController::show_help_setup())] Config { /// Label of the configuration to update #[structopt(short = "l", long = "label")] diff --git a/src/controllers/cmd_setup_async.rs b/src/controllers/cmd_setup_async.rs new file mode 100644 index 0000000..4396ee8 --- /dev/null +++ b/src/controllers/cmd_setup_async.rs @@ -0,0 +1,111 @@ +use exitfailure::ExitFailure; + +use crate::{ + cli::model::setup_command::SetupCommand, + config::load_config::{read_language_configuration, write_language_configuration}, + constants::LANGUAGE_CONFIG_FILE, + error::handle_error::throw_setup_label_is_not_correct_msg, + file_handler::async_file::remove_files_async, + language::json::language_scheme::Languages, + views::{setup::show_argument_was_updated_success, style::show_config_file_deleted_path}, +}; + +pub struct SetupController { + command: SetupCommand, +} + +impl SetupController { + pub fn new(command: SetupCommand) -> SetupController { + SetupController { command } + } + + pub async fn run(&mut self) -> Result<(), ExitFailure> { + let languages_wrapper = self.get_languages(); + + if !self.has_correct_structure() || languages_wrapper.is_err() { + return self.throw_setup_label_error(); + } + + let mut languages = languages_wrapper.unwrap(); + + let cmds = self.get_commands(); + let language_key = cmds[0]; + let label = cmds[1]; + let value = self.get_value(); + + for lang in &mut languages.languages { + if lang.id == language_key && lang.env.contains_key(label) { + lang.env.insert(label.to_string(), value.to_string()); + write_language_configuration(&languages)?; + + show_argument_was_updated_success(language_key, label, value); + + return Ok(()); + } + } + Ok(()) + } + + fn get_languages(&self) -> serde_json::Result { + let text: &str = &read_language_configuration()[..]; + serde_json::from_str(text) + } + + fn get_commands(&self) -> Vec<&str> { + let cmds: Vec<&str> = self.command.label.split('.').collect(); + cmds + } + + fn get_label(&self) -> &str { + &self.command.label[..] + } + + fn get_value(&self) -> &str { + &self.command.value[..] + } + + fn has_correct_structure(&self) -> bool { + let cmds = self.get_commands(); + cmds.len() == 2 + } + + fn throw_setup_label_error(&self) -> Result<(), ExitFailure> { + let label = self.get_label(); + throw_setup_label_is_not_correct_msg(label) + } + + pub async fn reset() -> Result<(), ExitFailure> { + let config_file = &shellexpand::tilde(LANGUAGE_CONFIG_FILE).to_string()[..]; + if remove_files_async(vec![config_file]).await.is_ok() { + show_config_file_deleted_path(config_file); + } + Ok(()) + } + + // Show Help setup after help: quicktest setup config --help + // EXAMPLES: + // quicktest setup config --label="Language::Cpp.PROGRAM" --value="g++" + // quicktest setup config --label="Language::Cpp.STANDARD" --value="-std=c++17" + // quicktest setup config --label="Language::Python.PROGRAM" --value="python" + pub fn show_help_setup() -> &'static str { + let text = read_language_configuration(); + + let mut langs: serde_json::Result = serde_json::from_str(&text[..]); + + let mut labels = vec!["EXAMPLES:".to_string()]; + + if let Ok(lg) = &mut langs { + for idx in 0..lg.languages.len() { + for (key, value) in &lg.languages[idx].env { + let label = format!( + " quicktest setup config --label=\"{}.{}\" --value=\"{}\"", + lg.languages[idx].id, key, value + ); + labels.push(label); + } + } + } + let labels: String = labels.join("\n"); + Box::leak(labels.into_boxed_str()) + } +} diff --git a/src/controllers/cmd_setup.rs b/src/controllers/legacy/cmd_setup.rs similarity index 100% rename from src/controllers/cmd_setup.rs rename to src/controllers/legacy/cmd_setup.rs diff --git a/src/controllers/mod.rs b/src/controllers/mod.rs index 7f4eee8..b90c84f 100644 --- a/src/controllers/mod.rs +++ b/src/controllers/mod.rs @@ -7,7 +7,7 @@ pub mod cmd_check; pub mod cmd_cmp; pub mod cmd_example; -pub mod cmd_setup; pub mod cmd_stress; pub mod cmd_output_async; +pub mod cmd_setup_async; diff --git a/src/main.rs b/src/main.rs index 3a7698b..31c47f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -159,9 +159,13 @@ async fn main() -> Result<(), ExitFailure> { } Opt::Setup { subcommand } => match subcommand { cli::opt::SetUp::Config { label, value } => { - controllers::cmd_setup::run(&SetupCommand::new(label, value)) + controllers::cmd_setup_async::SetupController::new(SetupCommand::new(label, value)) + .run() + .await + } + cli::opt::SetUp::Reset {} => { + controllers::cmd_setup_async::SetupController::reset().await } - cli::opt::SetUp::Reset {} => controllers::cmd_setup::reset(), }, Opt::Example { cmp,