use super::log; use clap::Clap; use std::io::Write; use crate::error_handling::CtUnwrap; enum OpMode<'a> { Project(&'a str), // Maybe string All, Faulty, } #[derive(Clap, Debug)] #[clap(name = "delete")] pub struct Opts { #[clap(long)] /// Delete all projects on this PC (ignored if is specified) all: bool, #[clap(long)] /// Don't ask for confirmation (risky) no_confirm: bool, /// Whats the name of the task/project project_name: Option, } impl Opts { /// Get a reference to the delete ops's task name. fn project_name(&self) -> &Option { &self.project_name } fn delete_all(&self) -> bool { self.all } fn skip_confirmation(&self) -> bool { self.no_confirm } fn op_mode(&self) -> OpMode { if let Some(proj) = self.project_name() { OpMode::Project(proj.as_str()) } else if self.delete_all() { OpMode::All } else { OpMode::Faulty } } } impl Opts { pub fn execute(&self) { match self.op_mode() { OpMode::Project(name) => { if self.delete_all() { bunt::writeln!( log::out(), "{$yellow}Option {$bold}'--all'{/$} \ is ignored because a project is specified.{/$}" ) .ct_unwrap(); } delete_named(name, self.skip_confirmation()); } OpMode::All => { delete_all(self.skip_confirmation()); } OpMode::Faulty => { handle_faulty_args(); } } } } fn delete_named(name: &str, skip_confirmation: bool) { if !ct::projects::has(name).ct_unwrap() { bunt::writeln!( log::out(), "{$red}Project {[blue]} doesn't exist!{/$}", name ) .ct_unwrap(); return; } if !skip_confirmation { bunt::writeln!( log::out(), "Do you really want to delete time tracking data for the project {[blue]}?", name ) .ct_unwrap(); if !cli_confirmation() { bunt::writeln!( log::out(), "{$red}Aborted deleting project {[blue]}{/$}", name ) .ct_unwrap(); return; } } else { bunt::writeln!(log::out(), "{$yellow}Skipped confirmation due to flag!{/$}").ct_unwrap(); } if let Err(e) = ct::projects::delete::named(name) { bunt::writeln!( log::out(), "{$red} Error while deleting project {[blue]}: {}{/$}", name, e ) .ct_unwrap(); } else { bunt::writeln!(log::out(), "{$green}Deleted project {[blue]}{/$}", name).ct_unwrap(); } } fn delete_all(skip_confirmation: bool) { if !skip_confirmation { bunt::writeln!( log::out(), "Do you really want to delete {$red+italic}all{/$} time tracking data from this PC?" ) .ct_unwrap(); if !cli_confirmation() { bunt::writeln!(log::out(), "{$red}Aborted deleting all projects...{/$}").ct_unwrap(); return; } bunt::writeln!( log::out(), "Are you really sure? {$italic}This cannot be reversed...{/$}" ) .ct_unwrap(); if !cli_confirmation() { bunt::writeln!(log::out(), "{$red}Aborted deleting all projects...{/$}").ct_unwrap(); return; } } else { bunt::writeln!( log::out(), "{$yellow+bold}Deleting {$italic}all{/$} projects from PC{/$}" ) .ct_unwrap(); bunt::writeln!(log::out(), "{$yellow}Skipped confirmation due to flag!{/$}").ct_unwrap(); } if let Err(e) = ct::projects::delete::all(true) { bunt::writeln!( log::out(), "{$red}Error while deleting all projects: {}{/$}", e ) .ct_unwrap(); } else { bunt::writeln!(log::out(), "{$green}Deleted all projects...{/$}").ct_unwrap(); } } fn cli_confirmation() -> bool { bunt::write!(log::out(), "({$green}y{/$}/{$red}N{/$}) > ").ct_unwrap(); std::io::stdout().flush().unwrap(); let mut input = String::new(); std::io::stdin() .read_line(&mut input) .expect("Failed To read Input"); match input.chars().next() { Some(c) if c == 'y' || c == 'Y' => true, Some(c) if c == 'n' || c == 'N' => false, Some(_) => { bunt::writeln!( log::out(), "{$yellow}Unknown option{/$}, treating as {$italic}no{/$}" ) .ct_unwrap(); false } None => { bunt::writeln!( log::out(), "{$yellow}Empty input{/$}, treating as {$italic}no{/$}" ) .ct_unwrap(); false } } } fn handle_faulty_args() { bunt::writeln!( log::err(), "{$red}Error: this command needs something to delete!{/$}" ) .ct_unwrap(); bunt::writeln!( log::err(), "{$yellow}Consider either setting {$bold}'--all'{/$} \ or providing a project to delete{/$}" ) .ct_unwrap(); eprintln!("Exiting..."); }