use std::convert::TryFrom; use std::io::{BufRead, Write}; use std::path::PathBuf; use clap::ArgMatches; use crate::database::Database; use crate::error::{Error, Result}; use crate::commands::{Command, Facts}; use crate::config::WeekDay; use crate::formatters::Formatter; use crate::io::Streams; #[derive(Default)] pub struct Args { database_file: Option, round_in_seconds: Option, append_notes_delimiter: Option, formatter_search_paths: Option>, default_formatter: Option, auto_sheet: Option, auto_sheet_search_paths: Option>, default_command: Option, auto_checkout: Option, require_note: Option, note_editor: Option, week_start: Option, } impl Args { /// returns true only if no argument was passed other that possibly --id. /// This means that an edit was requested without specifying what to edit, /// therefore let's edit the note because why not fn none_given(&self) -> bool { !( self.database_file.is_some() || self.round_in_seconds.is_some() || self.append_notes_delimiter.is_some() || self.formatter_search_paths.is_some() || self.default_formatter.is_some() || self.auto_sheet.is_some() || self.auto_sheet_search_paths.is_some() || self.default_command.is_some() || self.auto_checkout.is_some() || self.require_note.is_some() || self.note_editor.is_some() || self.week_start.is_some() ) } } fn yes_no_none(matches: &ArgMatches, opt: &str) -> Option { if matches.is_present(opt) { Some(true) } else if matches.is_present(&format!("no_{}", opt)) { Some(false) } else { None } } impl<'a> TryFrom<&'a ArgMatches<'a>> for Args { type Error = Error; fn try_from(matches: &'a ArgMatches) -> Result { Ok(Args { database_file: matches.value_of("database_file").map(|e| e.into()), round_in_seconds: matches.value_of("round_in_seconds").map(|v| v.parse().unwrap()), append_notes_delimiter: matches.value_of("append_notes_delimiter").map(|v| v.to_owned()), formatter_search_paths: matches.values_of("formatter_search_paths").map(|v| v.map(|a| a.into()).collect()), default_formatter: matches.value_of("default_formatter").map(|v| v.parse().unwrap()), auto_sheet: matches.value_of("auto_sheet").map(|v| v.to_owned()), auto_sheet_search_paths: matches.values_of("auto_sheet_search_paths").map(|v| v.map(|a| a.into()).collect()), default_command: matches.value_of("default_command").map(|v| v.to_owned()), auto_checkout: yes_no_none(matches, "auto_checkout"), require_note: yes_no_none(matches, "require_note"), note_editor: matches.value_of("note_editor").map(|v| v.to_owned()), week_start: matches.value_of("week_start").map(|w| w.parse()).transpose()?, }) } } pub struct ConfigureCommand {} impl<'a> Command<'a> for ConfigureCommand { type Args = Args; fn handle(args: Args, streams: &mut Streams, facts: &Facts) -> Result<()> where D: Database, I: BufRead, O: Write, E: Write, { if args.none_given() { if let Some(path) = facts.config.path.as_deref() { writeln!(streams.out, "{}", path.display())?; } else { writeln!(streams.out, "Config file is in memory")?; } Ok(()) } else { let mut new_config = facts.config.clone(); if let Some(path) = args.database_file { new_config.database_file = path; } if let Some(val) = args.round_in_seconds { new_config.round_in_seconds = val; } if let Some(val) = args.append_notes_delimiter { new_config.append_notes_delimiter = val; } if let Some(val) = args.formatter_search_paths { new_config.formatter_search_paths = val; } if let Some(val) = args.default_formatter { new_config.default_formatter = val; } if let Some(val) = args.auto_sheet { new_config.auto_sheet = val; } if let Some(val) = args.auto_sheet_search_paths { new_config.auto_sheet_search_paths = val; } if let Some(val) = args.default_command { new_config.default_command = Some(val); } if let Some(val) = args.auto_checkout { new_config.auto_checkout = val; } if let Some(val) = args.require_note { new_config.require_note = val; } if let Some(val) = args.note_editor { new_config.note_editor = Some(val); } if let Some(val) = args.week_start { new_config.week_start = val; } if let Some(path) = facts.config.path.as_deref() { let output = new_config.write(path)?; writeln!(streams.out, "Your new config:\n")?; streams.out.write_all(output.as_bytes())?; } else { writeln!(streams.out, "Your config file is in memory and cannot be written to")?; } Ok(()) } } }