From 751f4aa7500289af831d61a3940e92d09cd35bfb Mon Sep 17 00:00:00 2001 From: Abraham Toriz Date: Thu, 19 Aug 2021 20:50:34 -0500 Subject: [PATCH] respect the default_formatter config --- src/commands/display.rs | 47 ++++++++++++++++++++++++++++++++++----- src/commands/month.rs | 39 ++++++++++++++++++++++++++++---- src/commands/today.rs | 41 ++++++++++++++++++++++++++++++---- src/commands/week.rs | 36 +++++++++++++++++++++++++----- src/commands/yesterday.rs | 36 +++++++++++++++++++++++++----- src/main.rs | 2 +- 6 files changed, 175 insertions(+), 26 deletions(-) diff --git a/src/commands/display.rs b/src/commands/display.rs index 95ca613..7b1320f 100644 --- a/src/commands/display.rs +++ b/src/commands/display.rs @@ -91,7 +91,7 @@ pub struct Args { ids: bool, start: Option>, end: Option>, - format: Formatter, + format: Option, grep: Option, sheet: Option, } @@ -104,7 +104,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args { ids: matches.is_present("ids"), start: matches.value_of("start").map(|s| parse_time(s)).transpose()?, end: matches.value_of("end").map(|s| parse_time(s)).transpose()?, - format: matches.value_of("format").unwrap().parse()?, + format: matches.value_of("format").map(|v| v.parse()).transpose()?, grep: matches.value_of("grep").map(parse_regex).transpose()?, sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?, }) @@ -116,13 +116,24 @@ pub struct DisplayCommand { } impl<'a> Command<'a> for DisplayCommand { type Args = Args; - fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config, now: DateTime) -> Result<()> + fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, config: &Config, now: DateTime) -> Result<()> where D: Database, O: Write, E: Write, { - entries_for_display(args.start, args.end, args.sheet, db, out, err, args.format, args.ids, args.grep, now) + entries_for_display( + args.start, + args.end, + args.sheet, + db, + out, + err, + args.format.unwrap_or_else(|| config.default_formatter.clone()), + args.ids, + args.grep, + now + ) } } @@ -165,7 +176,7 @@ mod tests { #[test] fn filter_by_start() { let args = Args { - format: Formatter::Csv, + format: Some(Formatter::Csv), start: Some(Utc.ymd(2021, 6, 30).and_hms(10, 5, 0)), ..Default::default() }; @@ -298,7 +309,7 @@ Timesheet: sheet1 std::env::set_var("TZ", "CST+6"); let args = Args { - format: Formatter::Csv, + format: Some(Formatter::Csv), start: Some(Utc.ymd(2021, 6, 29).and_hms(12, 0, 0)), end: Some(Utc.ymd(2021, 6, 29).and_hms(13, 0, 0)), ..Default::default() @@ -323,4 +334,28 @@ Timesheet: sheet1 format!("{} You are using the old timetrap format, it is advised that you update your database using t migrate\n", Yellow.bold().paint("[WARNING]")), ); } + + #[test] + fn respect_default_formatter() { + std::env::set_var("TZ", "CST+6"); + + let args = Default::default(); + let mut db = SqliteDatabase::from_memory().unwrap(); + let mut out = Vec::new(); + let mut err = Vec::new(); + let config = Config { + default_formatter: Formatter::Ids, + ..Default::default() + }; + + db.init().unwrap(); + + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap(); + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default".into()).unwrap(); + + DisplayCommand::handle(args, &mut db, &mut out, &mut err, &config, Utc::now()).unwrap(); + + assert_eq!(&String::from_utf8_lossy(&out), "1 2\n"); + assert_eq!(String::from_utf8_lossy(&err), ""); + } } diff --git a/src/commands/month.rs b/src/commands/month.rs index 5580819..37ad4eb 100644 --- a/src/commands/month.rs +++ b/src/commands/month.rs @@ -69,7 +69,7 @@ impl FromStr for MonthSpec { pub struct Args { ids: bool, month: MonthSpec, - format: Formatter, + format: Option, grep: Option, sheet: Option, } @@ -81,7 +81,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args { Ok(Args { ids: matches.is_present("ids"), month: matches.value_of("month").map(|s| s.parse()).transpose()?.unwrap_or(MonthSpec::This), - format: matches.value_of("format").unwrap().parse()?, + format: matches.value_of("format").map(|v| v.parse()).transpose()?, grep: matches.value_of("grep").map(parse_regex).transpose()?, sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?, }) @@ -93,7 +93,7 @@ pub struct MonthCommand { } impl<'a> Command<'a> for MonthCommand { type Args = Args; - fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config, now: DateTime) -> Result<()> + fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, config: &Config, now: DateTime) -> Result<()> where D: Database, O: Write, @@ -129,6 +129,37 @@ impl<'a> Command<'a> for MonthCommand { }, }; - entries_for_display(Some(start), Some(end), args.sheet, db, out, err, args.format, args.ids, args.grep, now) + entries_for_display(Some(start), Some(end), args.sheet, db, out, err, args.format.unwrap_or_else(|| config.default_formatter.clone()), args.ids, args.grep, now) + } +} + +#[cfg(test)] +mod tests { + use crate::database::SqliteDatabase; + + use super::*; + + #[test] + fn respect_default_formatter() { + std::env::set_var("TZ", "CST+6"); + + let args = Default::default(); + let mut db = SqliteDatabase::from_memory().unwrap(); + let mut out = Vec::new(); + let mut err = Vec::new(); + let config = Config { + default_formatter: Formatter::Ids, + ..Default::default() + }; + + db.init().unwrap(); + + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap(); + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default".into()).unwrap(); + + MonthCommand::handle(args, &mut db, &mut out, &mut err, &config, Utc.ymd(2021, 6, 30).and_hms(11, 0, 0)).unwrap(); + + assert_eq!(&String::from_utf8_lossy(&out), "1 2\n"); + assert_eq!(String::from_utf8_lossy(&err), ""); } } diff --git a/src/commands/today.rs b/src/commands/today.rs index dcd3f5d..ff45999 100644 --- a/src/commands/today.rs +++ b/src/commands/today.rs @@ -18,7 +18,7 @@ use super::{Command, display::{Sheet, entries_for_display}}; pub struct Args { ids: bool, end: Option>, - format: Formatter, + format: Option, grep: Option, sheet: Option, } @@ -30,7 +30,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args { Ok(Args { ids: matches.is_present("ids"), end: matches.value_of("end").map(|s| parse_time(s)).transpose()?, - format: matches.value_of("format").unwrap().parse()?, + format: matches.value_of("format").map(|v| v.parse()).transpose()?, grep: matches.value_of("grep").map(parse_regex).transpose()?, sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?, }) @@ -42,7 +42,7 @@ pub struct TodayCommand { } impl<'a> Command<'a> for TodayCommand { type Args = Args; - fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config, now: DateTime) -> Result<()> + fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, config: &Config, now: DateTime) -> Result<()> where D: Database, O: Write, @@ -50,6 +50,39 @@ impl<'a> Command<'a> for TodayCommand { { let start = Some(now.with_timezone(&Local).date().and_hms(0, 0, 0).with_timezone(&Utc)); - entries_for_display(start, args.end, args.sheet, db, out, err, args.format, args.ids, args.grep, now) + entries_for_display(start, args.end, args.sheet, db, out, err, args.format.unwrap_or_else(|| config.default_formatter.clone()), args.ids, args.grep, now) + } +} + +#[cfg(test)] +mod tests { + use chrono::TimeZone; + + use crate::database::SqliteDatabase; + + use super::*; + + #[test] + fn respect_default_formatter() { + std::env::set_var("TZ", "CST+6"); + + let args = Default::default(); + let mut db = SqliteDatabase::from_memory().unwrap(); + let mut out = Vec::new(); + let mut err = Vec::new(); + let config = Config { + default_formatter: Formatter::Ids, + ..Default::default() + }; + + db.init().unwrap(); + + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap(); + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default".into()).unwrap(); + + TodayCommand::handle(args, &mut db, &mut out, &mut err, &config, Utc.ymd(2021, 6, 30).and_hms(11, 0, 0)).unwrap(); + + assert_eq!(&String::from_utf8_lossy(&out), "1 2\n"); + assert_eq!(String::from_utf8_lossy(&err), ""); } } diff --git a/src/commands/week.rs b/src/commands/week.rs index 0d59b48..95564d6 100644 --- a/src/commands/week.rs +++ b/src/commands/week.rs @@ -62,7 +62,7 @@ fn prev_day(now: DateTime, week_start: WeekDay) -> DateTime { pub struct Args { ids: bool, end: Option>, - format: Formatter, + format: Option, grep: Option, sheet: Option, } @@ -74,7 +74,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args { Ok(Args { ids: matches.is_present("ids"), end: matches.value_of("end").map(|s| parse_time(s)).transpose()?, - format: matches.value_of("format").unwrap().parse()?, + format: matches.value_of("format").map(|v| v.parse()).transpose()?, grep: matches.value_of("grep").map(parse_regex).transpose()?, sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?, }) @@ -94,16 +94,18 @@ impl<'a> Command<'a> for WeekCommand { { let start = prev_day(now.with_timezone(&Local), config.week_start); - entries_for_display(Some(start), args.end, args.sheet, db, out, err, args.format, args.ids, args.grep, now) + entries_for_display(Some(start), args.end, args.sheet, db, out, err, args.format.unwrap_or_else(|| config.default_formatter.clone()), args.ids, args.grep, now) } } #[cfg(test)] mod tests { - use super::*; - use chrono::TimeZone; + use crate::database::SqliteDatabase; + + use super::*; + #[test] fn test_prev_day() { // starting a saturday @@ -117,4 +119,28 @@ mod tests { assert_eq!(prev_day(now, WeekDay::Saturday), Local.ymd(2021, 7, 10).and_hms(0, 0, 0).with_timezone(&Utc)); assert_eq!(prev_day(now, WeekDay::Sunday), Local.ymd(2021, 7, 4).and_hms(0, 0, 0).with_timezone(&Utc)); } + + #[test] + fn respect_default_formatter() { + std::env::set_var("TZ", "CST+6"); + + let args = Default::default(); + let mut db = SqliteDatabase::from_memory().unwrap(); + let mut out = Vec::new(); + let mut err = Vec::new(); + let config = Config { + default_formatter: Formatter::Ids, + ..Default::default() + }; + + db.init().unwrap(); + + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap(); + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default".into()).unwrap(); + + WeekCommand::handle(args, &mut db, &mut out, &mut err, &config, Utc.ymd(2021, 7, 1).and_hms(10, 0, 0)).unwrap(); + + assert_eq!(&String::from_utf8_lossy(&out), "1 2\n"); + assert_eq!(String::from_utf8_lossy(&err), ""); + } } diff --git a/src/commands/yesterday.rs b/src/commands/yesterday.rs index f2d935a..878c6ae 100644 --- a/src/commands/yesterday.rs +++ b/src/commands/yesterday.rs @@ -16,7 +16,7 @@ use super::{Command, display::{Sheet, entries_for_display}}; #[derive(Default)] pub struct Args { ids: bool, - format: Formatter, + format: Option, grep: Option, sheet: Option, } @@ -27,7 +27,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args { fn try_from(matches: &'a ArgMatches) -> Result { Ok(Args { ids: matches.is_present("ids"), - format: matches.value_of("format").unwrap().parse()?, + format: matches.value_of("format").map(|v| v.parse()).transpose()?, grep: matches.value_of("grep").map(parse_regex).transpose()?, sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?, }) @@ -39,7 +39,7 @@ pub struct YesterdayCommand { } impl<'a> Command<'a> for YesterdayCommand { type Args = Args; - fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config, now: DateTime) -> Result<()> + fn handle(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, config: &Config, now: DateTime) -> Result<()> where D: Database, O: Write, @@ -49,13 +49,13 @@ impl<'a> Command<'a> for YesterdayCommand { let start = Some((today - Duration::days(1)).and_hms(0, 0, 0).with_timezone(&Utc)); let end = Some(today.and_hms(0, 0, 0).with_timezone(&Utc)); - entries_for_display(start, end, args.sheet, db, out, err, args.format, args.ids, args.grep, now) + entries_for_display(start, end, args.sheet, db, out, err, args.format.unwrap_or_else(|| config.default_formatter.clone()), args.ids, args.grep, now) } } #[cfg(test)] mod tests { - use chrono::Duration; + use chrono::{Duration, TimeZone}; use pretty_assertions::assert_eq; use crate::database::SqliteDatabase; @@ -66,7 +66,7 @@ mod tests { #[test] fn returns_yesterday_entries_only() { let args = Args { - format: Formatter::Csv, + format: Some(Formatter::Csv), ..Default::default() }; let mut db = SqliteDatabase::from_memory().unwrap(); @@ -95,4 +95,28 @@ mod tests { String::new(), ); } + + #[test] + fn respect_default_formatter() { + std::env::set_var("TZ", "CST+6"); + + let args = Default::default(); + let mut db = SqliteDatabase::from_memory().unwrap(); + let mut out = Vec::new(); + let mut err = Vec::new(); + let config = Config { + default_formatter: Formatter::Ids, + ..Default::default() + }; + + db.init().unwrap(); + + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap(); + db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("hola".into()), "default".into()).unwrap(); + + YesterdayCommand::handle(args, &mut db, &mut out, &mut err, &config, Utc.ymd(2021, 7, 1).and_hms(10, 0, 0)).unwrap(); + + assert_eq!(&String::from_utf8_lossy(&out), "1 2\n"); + assert_eq!(String::from_utf8_lossy(&err), ""); + } } diff --git a/src/main.rs b/src/main.rs index de5e128..560657e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,7 @@ fn main() { let format_arg = Arg::with_name("format") .short("f").long("format") - .takes_value(true).value_name("FORMAT").default_value("text") + .takes_value(true).value_name("FORMAT") .help( "The output format. Valid built-in formats are ical, csv, json, \ ids, and text. Documentation on defining custom formats can be \