From 0fa1ae28f88dd57afc119849d0f1132f5f627b35 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 6 Dec 2017 20:21:20 +0100 Subject: [PATCH] Let "today" command list upcoming habits --- bin/domain/imag-habit/src/main.rs | 74 +++++++++++++++++++++++-------- bin/domain/imag-habit/src/ui.rs | 8 ++++ 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/bin/domain/imag-habit/src/main.rs b/bin/domain/imag-habit/src/main.rs index 60911c56..0f753cf1 100644 --- a/bin/domain/imag-habit/src/main.rs +++ b/bin/domain/imag-habit/src/main.rs @@ -125,6 +125,9 @@ fn delete(rt: &Runtime) { // Almost the same as `list()` but with other lister functions and an additional filter for only // listing entries which are due today. fn today(rt: &Runtime) { + use libimaghabit::error::ResultExt; + use libimaghabit::error::HabitErrorKind as HEK; + fn lister_fn(h: &FileLockEntry) -> Vec { debug!("Listing: {:?}", h); let name = h.habit_name().map_err_trace_exit_unwrap(1); @@ -143,34 +146,67 @@ fn today(rt: &Runtime) { let today = ::chrono::offset::Local::today().naive_local(); - let today_relevant : Vec<_> = rt - .store() - .all_habit_templates() - .map_err_trace_exit_unwrap(1) - .filter_map(|id| match rt.store().get(id.clone()) { - Ok(Some(h)) => Some(h), - Ok(None) => { - error!("No habit found for {:?}", id); - None - }, - Err(e) => { - trace_error(&e); - None - }, - }) + let relevant : Vec<_> = { // scope, to have variable non-mutable in outer scope + let mut relevant : Vec<_> = rt + .store() + .all_habit_templates() + .map_err_trace_exit_unwrap(1) + .filter_map(|id| match rt.store().get(id.clone()) { + Ok(Some(h)) => Some(h), + Ok(None) => { + error!("No habit found for {:?}", id); + None + }, + Err(e) => { + trace_error(&e); + None + }, + }) + .filter(|h| { + let due = h.next_instance_date().map_err_trace_exit_unwrap(1); + due == today || due > today // today or in future + }) + .collect(); + + relevant.sort_by_key(|h| h.next_instance_date().map_err_trace_exit_unwrap(1)); + relevant + }; + + let any_today_relevant = relevant + .iter() .filter(|h| { let due = h.next_instance_date().map_err_trace_exit_unwrap(1); - due == today + due == today // relevant today }) - .collect(); + .count() == 0; + + if any_today_relevant { + let n = rt + .cli() + .subcommand_matches("today") + .and_then(|am| { + am.value_of("today-show-next-n") + .map(|x| { + x.parse::() + .chain_err(|| HEK::from(format!("Cannot parse String '{}' to integer", x))) + .map_err_trace_exit_unwrap(1) + }) + }).unwrap_or(5); - if today_relevant.is_empty() { info!("No Habits due today."); + info!("Upcoming:"); + // list `n` which are relevant in the future. + for element in relevant.iter().take(n) { + let date = element.next_instance_date().map_err_trace_exit_unwrap(1); + let name = element.habit_name().map_err_trace_exit_unwrap(1); + + info!(" * {date}: {name}", date = date, name = name); + } } else { TableLister::new(lister_fn) .with_header(lister_header()) .with_idx(true) - .list(today_relevant.into_iter()) + .list(relevant.into_iter()) .map_err_trace_exit_unwrap(1); } } diff --git a/bin/domain/imag-habit/src/ui.rs b/bin/domain/imag-habit/src/ui.rs index f72e67f3..72ec9498 100644 --- a/bin/domain/imag-habit/src/ui.rs +++ b/bin/domain/imag-habit/src/ui.rs @@ -111,5 +111,13 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { .subcommand(SubCommand::with_name("today") .about("List habits which are due today") .version("0.1") + .arg(Arg::with_name("today-show-next-n") + .long("show") + .short("s") + .multiple(false) + .required(false) + .takes_value(true) + .value_name("N") + .help("Show the N next relevant entries. Default = 5")) ) }