From b4ff528a2cf439e0b173336391af913729e36bd7 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 20 Jul 2017 23:21:57 +0200 Subject: [PATCH] [WIP] Implement "imag timetrack list" command --- imag-timetrack/src/list.rs | 124 +++++++++++++++++++++++++++++++++++++ imag-timetrack/src/main.rs | 3 + imag-timetrack/src/ui.rs | 30 ++++++++- 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 imag-timetrack/src/list.rs diff --git a/imag-timetrack/src/list.rs b/imag-timetrack/src/list.rs new file mode 100644 index 00000000..b7d8dcd3 --- /dev/null +++ b/imag-timetrack/src/list.rs @@ -0,0 +1,124 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use std::cmp::Ord; +use std::cmp::Ordering; +use std::str::FromStr; + +use filters::ops::not::Not; +use filters::filter::Filter; +use itertools::Itertools; +use itertools::MinMaxResult; +use chrono::NaiveDateTime; + +use libimagerror::trace::trace_error; +use libimagerror::trace::MapErrTrace; +use libimagerror::iter::TraceIterator; +use libimagstore::store::FileLockEntry; +use libimagentrytimetrack::timetrackingstore::TimeTrackStore; +use libimagentrytimetrack::timetracking::TimeTracking; +use libimagentrytimetrack::iter::filter::*; + +use libimagrt::runtime::Runtime; + +pub fn list(rt: &Runtime) -> i32 { + let (_, cmd) = rt.cli().subcommand(); + let cmd = cmd.unwrap(); // checked in main() + + let start = match cmd.value_of("start-time").map(::chrono::naive::NaiveDateTime::from_str) { + None => None, + Some(Ok(dt)) => Some(dt), + Some(Err(e)) => { + trace_error(&e); + None + } + }; + let end = match cmd.value_of("end-time").map(::chrono::naive::NaiveDateTime::from_str) { + None => None, + Some(Ok(dt)) => Some(dt), + Some(Err(e)) => { + trace_error(&e); + None + } + }; + + let list_not_ended = cmd.is_present("list-not-ended"); + + let start_time_filter = |timetracking: &FileLockEntry| { + start.map(|s| match timetracking.get_start_datetime() { + Ok(Some(dt)) => dt >= s, + Ok(None) => { + warn!("Funny things are happening: Timetracking has no start time"); + false + } + Err(e) => { + trace_error(&e); + false + } + }) + .unwrap_or(true) + }; + + let end_time_filter = |timetracking: &FileLockEntry| { + start.map(|s| match timetracking.get_end_datetime() { + Ok(Some(dt)) => dt <= s, + Ok(None) => list_not_ended, + Err(e) => { + trace_error(&e); + false + } + }) + .unwrap_or(true) + }; + + let filter = start_time_filter.and(end_time_filter); + + rt.store() + .get_timetrackings() + .and_then(|iter| { + iter.trace_unwrap() + .filter(|e| filter.filter(e)) + .fold(Ok(()), |acc, e| { + acc.and_then(|_| { + debug!("Processing {:?}", e.get_location()); + + let tag = try!(e.get_timetrack_tag()); + debug!(" -> tag = {:?}", tag); + + let start = try!(e.get_start_datetime()); + debug!(" -> start = {:?}", start); + + let end = try!(e.get_end_datetime()); + debug!(" -> end = {:?}", end); + + match (start, end) { + (None, _) => println!("{} has no start time.", tag), + (Some(s), None) => println!("{} | {} - ...", tag, s), + (Some(s), Some(e)) => println!("{} | {} - {}", tag, s, e), + } + + Ok(()) + }) + }) + }) + .map(|_| 0) + .map_err_trace() + .unwrap_or(1) +} + diff --git a/imag-timetrack/src/main.rs b/imag-timetrack/src/main.rs index de09a859..7546e6b9 100644 --- a/imag-timetrack/src/main.rs +++ b/imag-timetrack/src/main.rs @@ -38,6 +38,7 @@ extern crate libimagutil; mod cont; mod day; +mod list; mod month; mod start; mod stop; @@ -48,6 +49,7 @@ mod year; use cont::cont; use day::day; +use list::list; use month::month; use start::start; use stop::stop; @@ -70,6 +72,7 @@ fn main() { match command { "continue" => cont(&rt), "day" => day(&rt), + "list" => list(&rt), "month" => month(&rt), "start" => start(&rt), "stop" => stop(&rt), diff --git a/imag-timetrack/src/ui.rs b/imag-timetrack/src/ui.rs index a27c4ced..cefcef86 100644 --- a/imag-timetrack/src/ui.rs +++ b/imag-timetrack/src/ui.rs @@ -20,7 +20,35 @@ use clap::{Arg, App, SubCommand}; pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> { - app.subcommand(SubCommand::with_name("start") + app + .subcommand(SubCommand::with_name("list") + .about("List time trackings") + .version("0.1") + .arg(Arg::with_name("start-time") + .short("f") + .long("from") + .takes_value(true) + .multiple(false) + .required(false) + .help("Set earliest time from which on time trackings should be shown (use 'now' for current time)")) + .arg(Arg::with_name("end-time") + .short("t") + .long("to") + .takes_value(true) + .multiple(false) + .required(false) + .help("Set latest time of time trackings to be shown (use 'now' for current time)")) + + .arg(Arg::with_name("list-not-ended") + .short("l") + .long("list-not-ended") + .takes_value(false) + .multiple(false) + .required(false) + .help("List not yet ended timetrackings even if after 'end-time'")) + ) + + .subcommand(SubCommand::with_name("start") .about("Start time tracking") .version("0.1") .arg(Arg::with_name("start-time")