tiempo-rs/src/commands/configure.rs

174 lines
5.7 KiB
Rust

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<PathBuf>,
round_in_seconds: Option<u32>,
append_notes_delimiter: Option<String>,
formatter_search_paths: Option<Vec<PathBuf>>,
default_formatter: Option<Formatter>,
auto_sheet: Option<String>,
auto_sheet_search_paths: Option<Vec<PathBuf>>,
default_command: Option<String>,
auto_checkout: Option<bool>,
require_note: Option<bool>,
note_editor: Option<String>,
week_start: Option<WeekDay>,
interactive_entries: Option<usize>,
}
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.
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() ||
self.interactive_entries.is_some()
)
}
}
fn yes_no_none(matches: &ArgMatches, opt: &str) -> Option<bool> {
if matches.is_present(opt) {
Some(true)
} else if matches.is_present(format!("no_{}", opt)) {
Some(false)
} else {
None
}
}
impl<'a> TryFrom<&'a ArgMatches> for Args {
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> Result<Self> {
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()?,
interactive_entries: matches.value_of("interactive_entries").map(|n| n.parse().unwrap()),
})
}
}
pub struct ConfigureCommand {}
impl<'a> Command<'a> for ConfigureCommand {
type Args = Args;
fn handle<D, I, O, E>(args: Args, streams: &mut Streams<D, I, O, E>, 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(n) = args.interactive_entries {
new_config.interactive_entries = n;
}
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(())
}
}
}