Add done
functionality
This commit is contained in:
parent
b78095d8bc
commit
7cf46f99d4
2 changed files with 70 additions and 11 deletions
|
@ -57,6 +57,8 @@ use libimaghabit::store::HabitStore;
|
||||||
use libimaghabit::habit::builder::HabitBuilder;
|
use libimaghabit::habit::builder::HabitBuilder;
|
||||||
use libimaghabit::habit::HabitTemplate;
|
use libimaghabit::habit::HabitTemplate;
|
||||||
use libimagstore::store::FileLockEntry;
|
use libimagstore::store::FileLockEntry;
|
||||||
|
use libimagstore::store::Store;
|
||||||
|
use libimagstore::storeid::StoreId;
|
||||||
use libimagentrylist::listers::table::TableLister;
|
use libimagentrylist::listers::table::TableLister;
|
||||||
use libimagentrylist::lister::Lister;
|
use libimagentrylist::lister::Lister;
|
||||||
use libimaginteraction::ask::ask_bool;
|
use libimaginteraction::ask::ask_bool;
|
||||||
|
@ -81,6 +83,7 @@ fn main() {
|
||||||
"list" => list(&rt),
|
"list" => list(&rt),
|
||||||
"today" => today(&rt),
|
"today" => today(&rt),
|
||||||
"show" => show(&rt),
|
"show" => show(&rt),
|
||||||
|
"done" => done(&rt),
|
||||||
_ => {
|
_ => {
|
||||||
debug!("Unknown command"); // More error handling
|
debug!("Unknown command"); // More error handling
|
||||||
exit(1)
|
exit(1)
|
||||||
|
@ -349,17 +352,7 @@ fn show(rt: &Runtime) {
|
||||||
.store()
|
.store()
|
||||||
.all_habit_templates()
|
.all_habit_templates()
|
||||||
.map_err_trace_exit_unwrap(1)
|
.map_err_trace_exit_unwrap(1)
|
||||||
.filter_map(|id| match rt.store().get(id.clone()) {
|
.filter_map(|id| get_from_store(rt.store(), id))
|
||||||
Ok(Some(h)) => Some(h),
|
|
||||||
Ok(None) => {
|
|
||||||
error!("Cannot get habit for {:?} in 'show' subcommand", id);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
trace_error(&e);
|
|
||||||
None
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.filter(|h| h.habit_name().map(|n| name == n).map_err_trace_exit_unwrap(1))
|
.filter(|h| h.habit_name().map(|n| name == n).map_err_trace_exit_unwrap(1))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, habit)| {
|
.map(|(i, habit)| {
|
||||||
|
@ -393,3 +386,57 @@ fn show(rt: &Runtime) {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn done(rt: &Runtime) {
|
||||||
|
let scmd = rt.cli().subcommand_matches("done").unwrap(); // safe by call from main()
|
||||||
|
let names : Vec<_> = scmd.values_of("done-name").unwrap().map(String::from).collect();
|
||||||
|
|
||||||
|
let today = ::chrono::offset::Local::today().naive_local();
|
||||||
|
|
||||||
|
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| get_from_store(rt.store(), id))
|
||||||
|
.filter(|h| {
|
||||||
|
let due = h.next_instance_date().map_err_trace_exit_unwrap(1);
|
||||||
|
(due == today || due < today) || scmd.is_present("allow-future")
|
||||||
|
})
|
||||||
|
.filter(|h| {
|
||||||
|
names.contains(&h.habit_name().map_err_trace_exit_unwrap(1))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
relevant.sort_by_key(|h| h.next_instance_date().map_err_trace_exit_unwrap(1));
|
||||||
|
relevant
|
||||||
|
};
|
||||||
|
|
||||||
|
for r in relevant.iter() {
|
||||||
|
let next_instance_name = r.habit_name().map_err_trace_exit_unwrap(1);
|
||||||
|
let next_instance_date = r.next_instance_date().map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
|
debug!("Creating new instance on {:?}", next_instance_date);
|
||||||
|
r.create_instance_with_date(rt.store(), &next_instance_date)
|
||||||
|
.map_err_trace_exit_unwrap(1);
|
||||||
|
|
||||||
|
info!("Done on {date}: {name}",
|
||||||
|
date = libimaghabit::util::date_to_string(&next_instance_date),
|
||||||
|
name = next_instance_name);
|
||||||
|
}
|
||||||
|
info!("Done.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function for `Iterator::filter_map()`ing `all_habit_templates()` and `Store::get` them.
|
||||||
|
fn get_from_store<'a>(store: &'a Store, id: StoreId) -> Option<FileLockEntry<'a>> {
|
||||||
|
match store.get(id.clone()) {
|
||||||
|
Ok(Some(h)) => Some(h),
|
||||||
|
Ok(None) => {
|
||||||
|
error!("No habit found for {:?}", id);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
trace_error(&e);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -120,4 +120,16 @@ pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
|
||||||
.value_name("N")
|
.value_name("N")
|
||||||
.help("Show the N next relevant entries. Default = 5"))
|
.help("Show the N next relevant entries. Default = 5"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.subcommand(SubCommand::with_name("done")
|
||||||
|
.about("Mark one or more habits (which are pending) as done")
|
||||||
|
.version("0.1")
|
||||||
|
.arg(Arg::with_name("done-name")
|
||||||
|
.index(1)
|
||||||
|
.multiple(true)
|
||||||
|
.required(true)
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("NAME")
|
||||||
|
.help("The names of the habits to be marked as done."))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue