summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/domain/imag-diary/Cargo.toml1
-rw-r--r--bin/domain/imag-diary/src/create.rs117
-rw-r--r--bin/domain/imag-diary/src/delete.rs38
-rw-r--r--bin/domain/imag-diary/src/lib.rs50
-rw-r--r--bin/domain/imag-diary/src/list.rs37
-rw-r--r--bin/domain/imag-diary/src/util.rs4
-rw-r--r--bin/domain/imag-diary/src/view.rs51
-rw-r--r--bin/domain/imag-log/Cargo.toml1
-rw-r--r--bin/domain/imag-log/src/lib.rs169
-rw-r--r--bin/domain/imag-timetrack/Cargo.toml1
-rw-r--r--bin/domain/imag-timetrack/src/cont.rs56
-rw-r--r--bin/domain/imag-timetrack/src/day.rs54
-rw-r--r--bin/domain/imag-timetrack/src/lib.rs23
-rw-r--r--bin/domain/imag-timetrack/src/list.rs233
-rw-r--r--bin/domain/imag-timetrack/src/month.rs53
-rw-r--r--bin/domain/imag-timetrack/src/shell.rs65
-rw-r--r--bin/domain/imag-timetrack/src/start.rs35
-rw-r--r--bin/domain/imag-timetrack/src/stop.rs85
-rw-r--r--bin/domain/imag-timetrack/src/track.rs62
-rw-r--r--bin/domain/imag-timetrack/src/week.rs78
-rw-r--r--bin/domain/imag-timetrack/src/year.rs69
21 files changed, 507 insertions, 775 deletions
diff --git a/bin/domain/imag-diary/Cargo.toml b/bin/domain/imag-diary/Cargo.toml
index e46a36f3..26432644 100644
--- a/bin/domain/imag-diary/Cargo.toml
+++ b/bin/domain/imag-diary/Cargo.toml
@@ -26,6 +26,7 @@ toml = "0.5.1"
toml-query = "0.9.2"
itertools = "0.8.0"
failure = "0.1.5"
+resiter = "0.4.0"
libimagerror = { version = "0.10.0", path = "../../../lib/core/libimagerror" }
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
diff --git a/bin/domain/imag-diary/src/create.rs b/bin/domain/imag-diary/src/create.rs
index 8a3f80a3..c6c4687f 100644
--- a/bin/domain/imag-diary/src/create.rs
+++ b/bin/domain/imag-diary/src/create.rs
@@ -24,14 +24,11 @@ use chrono::Timelike;
use failure::Error;
use failure::ResultExt;
use failure::err_msg;
+use failure::Fallible as Result;
use libimagdiary::diary::Diary;
use libimagentryedit::edit::Edit;
use libimagrt::runtime::Runtime;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::exit::ExitUnwrap;
-use libimagutil::warn_exit::warn_exit;
-use libimagutil::debug_result::DebugResult;
use libimagutil::debug_option::DebugOption;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
@@ -40,60 +37,46 @@ use crate::util::get_diary_name;
use crate::util::get_diary_timed_config;
use crate::util::Timed;
-pub fn create(rt: &Runtime) {
+pub fn create(rt: &Runtime) -> Result<()> {
let diaryname = get_diary_name(rt)
- .unwrap_or_else( || warn_exit("No diary selected. Use either the configuration file or the commandline option", 1));
+ .ok_or_else(|| err_msg("No diary selected. Use either the configuration file or the commandline option"))?;
- let mut entry = create_entry(rt.store(), &diaryname, rt);
+ let mut entry = create_entry(rt.store(), &diaryname, rt)?;
+ rt.report_touched(entry.get_location())?;
- rt.report_touched(entry.get_location()).unwrap_or_exit();
-
- let res = if rt.cli().subcommand_matches("create").unwrap().is_present("no-edit") {
+ if rt.cli().subcommand_matches("create").unwrap().is_present("no-edit") {
debug!("Not editing new diary entry");
+ info!("Ok!");
Ok(())
} else {
debug!("Editing new diary entry");
entry.edit_content(rt).context(err_msg("Diary edit error")).map_err(Error::from)
- };
-
- res.map_err_trace_exit_unwrap();
- info!("Ok!");
+ }
}
-fn create_entry<'a>(diary: &'a Store, diaryname: &str, rt: &Runtime) -> FileLockEntry<'a> {
+fn create_entry<'a>(diary: &'a Store, diaryname: &str, rt: &Runtime) -> Result<FileLockEntry<'a>> {
use crate::util::parse_timed_string;
let create = rt.cli().subcommand_matches("create").unwrap();
- create.value_of("timed")
- .map(|t| parse_timed_string(t, diaryname).map_err_trace_exit_unwrap())
- .map(Some)
- .unwrap_or_else(|| {
- match get_diary_timed_config(rt, diaryname).map_err_trace_exit_unwrap() {
- Some(t) => Some(t),
- None => {
- warn!("Missing config: 'diary.diaries.{}.timed'", diaryname);
- warn!("Assuming 'false'");
- None
- }
- }
- })
- .map(|timed| {
- let time = create_id_from_clispec(&create, timed);
- diary.new_entry_at(&diaryname, &time)
- .context(err_msg("Store write error"))
- .map_err(Error::from)
- })
- .unwrap_or_else(|| {
- debug!("Creating non-timed entry");
- diary.new_entry_today(diaryname)
- })
- .map_dbg(|e| format!("Created: {}", e.get_location()))
- .map_err_trace_exit_unwrap()
+ let timed = match create.value_of("timed").map(|t| parse_timed_string(t, diaryname)) {
+ Some(t) => t.map(Some),
+ None => get_diary_timed_config(rt, diaryname)
+ }?;
+
+ if let Some(timed) = timed {
+ let time = create_id_from_clispec(&create, timed)?;
+ diary.new_entry_at(&diaryname, &time)
+ .context(err_msg("Store write error"))
+ .map_err(Error::from)
+ } else {
+ debug!("Creating non-timed entry");
+ diary.new_entry_today(diaryname)
+ }
}
-fn create_id_from_clispec(create: &ArgMatches, timed_type: Timed) -> NaiveDateTime {
+fn create_id_from_clispec(create: &ArgMatches, timed_type: Timed) -> Result<NaiveDateTime> {
use std::str::FromStr;
let dt = Local::now();
@@ -102,71 +85,73 @@ fn create_id_from_clispec(create: &ArgMatches, timed_type: Timed) -> NaiveDateTi
match timed_type {
Timed::Daily => {
debug!("Creating daily-timed entry");
- ndt.with_hour(0)
+ Ok(ndt.with_hour(0)
.unwrap() // safe because hour = 0 is safe
.with_minute(0)
.unwrap() // safe because minute = 0 is safe
.with_second(0)
- .unwrap() // safe because second = 0 is safe
+ .unwrap()) // safe because second = 0 is safe
},
Timed::Hourly => {
debug!("Creating hourly-timed entry");
- ndt.with_minute(0)
+ Ok(ndt.with_minute(0)
.unwrap() // safe because minute = 0 is safe
.with_second(0)
- .unwrap() // safe because second = 0 is safe
+ .unwrap()) // safe because second = 0 is safe
},
Timed::Minutely => {
let min = create
.value_of("minute")
.map_dbg(|m| format!("minute = {:?}", m))
- .and_then(|s| {
+ .map(|s| {
FromStr::from_str(s)
- .map_err(|_| warn!("Could not parse minute: '{}'", s))
- .ok()
+ .map_err(Error::from)
+ .context(format_err!("Could not parse minute: '{}'", s))
+ .map_err(Error::from)
})
+ .transpose()?
.unwrap_or_else(|| ndt.minute());
ndt.with_minute(min)
- .unwrap_or_else(|| {
- error!("Cannot set {} as minute, would yield invalid time!", min);
- ::std::process::exit(1)
+ .ok_or_else(|| {
+ format_err!("Cannot set {} as minute, would yield invalid time!", min)
})
- .with_second(0)
- .unwrap() // safe because second = 0 is safe
+ .map(|ndt| ndt.with_second(0).unwrap()) // safe because second = 0 is safe
},
Timed::Secondly => {
let min = create
.value_of("minute")
.map_dbg(|m| format!("minute = {:?}", m))
- .and_then(|s| {
+ .map(|s| {
FromStr::from_str(s)
- .map_err(|_| warn!("Could not parse minute: '{}'", s))
- .ok()
+ .map_err(Error::from)
+ .context(format_err!("Could not parse minute: '{}'", s))
+ .map_err(Error::from)
})
+ .transpose()?
.unwrap_or_else(|| ndt.minute());
let sec = create
.value_of("second")
.map_dbg(|s| format!("second = {:?}", s))
- .and_then(|s| {
+ .map(|s| {
FromStr::from_str(s)
- .map_err(|_| warn!("Could not parse second: '{}'", s))
- .ok()
+ .map_err(Error::from)
+ .context(format_err!("Could not parse second: '{}'", s))
+ .map_err(Error::from)
})
+ .transpose()?
.unwrap_or_else(|| ndt.second());
ndt.with_minute(min)
- .unwrap_or_else(|| {
- error!("Cannot set {} as minute, would yield invalid time!", min);
- ::std::process::exit(1)
- })
+ .ok_or_else(|| {
+ format_err!("Cannot set {} as minute, would yield invalid time!", min)
+ })?
.with_second(sec)
- .unwrap_or_else(|| {
- error!("Cannot set {} as second, would yield invalid time!", sec);
- ::std::process::exit(1)
+ .ok_or_else(|| {
+ format_err!("Cannot set {} as second, would yield invalid time!", sec)
})
},
}
diff --git a/bin/domain/imag-diary/src/delete.rs b/bin/domain/imag-diary/src/delete.rs
index 1b254c18..84a2e586 100644
--- a/bin/domain/imag-diary/src/delete.rs
+++ b/bin/domain/imag-diary/src/delete.rs
@@ -17,26 +17,23 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
-use std::process::exit;
-
use chrono::naive::NaiveDateTime as NDT;
+use failure::Fallible as Result;
+use failure::err_msg;
use libimagdiary::diaryid::DiaryId;
use libimagrt::runtime::Runtime;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;
-use libimagutil::warn_exit::warn_exit;
use libimagstore::storeid::IntoStoreId;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::exit::ExitUnwrap;
use crate::util::get_diary_name;
-pub fn delete(rt: &Runtime) {
+pub fn delete(rt: &Runtime) -> Result<()> {
use libimaginteraction::ask::ask_bool;
let diaryname = get_diary_name(rt)
- .unwrap_or_else(|| warn_exit("No diary selected. Use either the configuration file or the commandline option", 1));
+ .ok_or_else(|| err_msg("No diary selected. Use either the configuration file or the commandline option"))?;
let to_del_location = rt
.cli()
@@ -46,34 +43,21 @@ pub fn delete(rt: &Runtime) {
.map(|dt| { debug!("DateTime = {:?}", dt); dt })
.and_then(DateTime::parse)
.map(Into::into)
- .ok_or_else(|| warn_exit("Not deleting entries: missing date/time specification", 1))
+ .ok_or_else(|| err_msg("Not deleting entries: missing date/time specification"))
.and_then(|dt: NDT| DiaryId::from_datetime(diaryname.clone(), dt).into_storeid())
- .and_then(|id| rt.store().retrieve(id))
- .map_err_trace_exit_unwrap()
+ .and_then(|id| rt.store().retrieve(id))?
.get_location()
.clone();
- let mut input = rt.stdin().unwrap_or_else(|| {
- error!("No input stream. Cannot ask for permission");
- exit(1);
- });
-
+ let mut input = rt.stdin().ok_or_else(|| err_msg("No input stream. Cannot ask for permission"))?;
let mut output = rt.stdout();
- if !ask_bool(&format!("Deleting {:?}", to_del_location), Some(true), &mut input, &mut output)
- .map_err_trace_exit_unwrap()
- {
+ if !ask_bool(&format!("Deleting {:?}", to_del_location), Some(true), &mut input, &mut output)? {
info!("Aborting delete action");
- return;
+ return Ok(());
}
- rt.report_touched(&to_del_location).unwrap_or_exit();
-
- rt
- .store()
- .delete(to_del_location)
- .map_err_trace_exit_unwrap();
-
- info!("Ok!");
+ rt.report_touched(&to_del_location)?;
+ rt.store().delete(to_del_location)
}
diff --git a/bin/domain/imag-diary/src/lib.rs b/bin/domain/imag-diary/src/lib.rs
index 23629dc9..f87cd927 100644
--- a/bin/domain/imag-diary/src/lib.rs
+++ b/bin/domain/imag-diary/src/lib.rs
@@ -36,6 +36,7 @@
#[macro_use] extern crate log;
#[macro_use] extern crate failure;
+extern crate resiter;
extern crate clap;
extern crate chrono;
extern crate toml;
@@ -56,11 +57,12 @@ use std::io::Write;
use libimagrt::runtime::Runtime;
use libimagrt::application::ImagApplication;
-use libimagerror::trace::MapErrTrace;
use itertools::Itertools;
use clap::App;
use failure::Fallible as Result;
+use failure::err_msg;
+use failure::Error;
mod create;
mod delete;
@@ -81,25 +83,21 @@ use crate::view::view;
pub enum ImagDiary {}
impl ImagApplication for ImagDiary {
fn run(rt: Runtime) -> Result<()> {
- if let Some(name) = rt.cli().subcommand_name() {
- debug!("Call {}", name);
- match name {
- "diaries" => diaries(&rt),
- "create" => create(&rt),
- "delete" => delete(&rt),
- "list" => list(&rt),
- "view" => view(&rt),
- other => {
- debug!("Unknown command");
- let _ = rt.handle_unknown_subcommand("imag-diary", other, rt.cli())
- .map_err_trace_exit_unwrap()
- .code()
- .map(::std::process::exit);
- },
- }
+ match rt.cli().subcommand_name().ok_or_else(|| err_msg("No subcommand called"))? {
+ "diaries" => diaries(&rt),
+ "create" => create(&rt),
+ "delete" => delete(&rt),
+ "list" => list(&rt),
+ "view" => view(&rt),
+ other => {
+ debug!("Unknown command");
+ if rt.handle_unknown_subcommand("imag-diary", other, rt.cli())?.success() {
+ Ok(())
+ } else {
+ Err(err_msg("Failed to handle unknown subcommand"))
+ }
+ },
}
-
- Ok(())
}
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
@@ -119,20 +117,18 @@ impl ImagApplication for ImagDiary {
}
}
-fn diaries(rt: &Runtime) {
+fn diaries(rt: &Runtime) -> Result<()> {
use libimagdiary::diary::Diary;
- use libimagerror::io::ToExitCode;
- use libimagerror::exit::ExitUnwrap;
- use libimagerror::iter::TraceIterator;
let out = rt.stdout();
let mut outlock = out.lock();
rt.store()
- .diary_names()
- .map_err_trace_exit_unwrap()
- .trace_unwrap_exit()
+ .diary_names()?
+ .collect::<Result<Vec<String>>>()?
+ .into_iter()
.unique()
- .for_each(|n| writeln!(outlock, "{}", n).to_exit_code().unwrap_or_exit())
+ .map(|n| writeln!(outlock, "{}", n).map_err(Error::from))
+ .collect()
}
diff --git a/bin/domain/imag-diary/src/list.rs b/bin/domain/imag-diary/src/list.rs
index 9c4593ec..634b0ff7 100644
--- a/bin/domain/imag-diary/src/list.rs
+++ b/bin/domain/imag-diary/src/list.rs
@@ -19,33 +19,28 @@
use std::io::Write;
+use failure::Fallible as Result;
+use failure::err_msg;
+use failure::Error;
+use resiter::AndThen;
+
use libimagdiary::diary::Diary;
use libimagrt::runtime::Runtime;
-use libimagutil::warn_exit::warn_exit;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::io::ToExitCode;
-use libimagerror::exit::ExitUnwrap;
use libimagutil::debug_result::*;
use libimagdiary::diaryid::DiaryId;
use libimagdiary::diaryid::FromStoreId;
use libimagstore::storeid::IntoStoreId;
-use failure::Fallible as Result;
-
use crate::util::get_diary_name;
-pub fn list(rt: &Runtime) {
+pub fn list(rt: &Runtime) -> Result<()> {
let diaryname = get_diary_name(rt)
- .unwrap_or_else(|| warn_exit("No diary selected. Use either the configuration file or the commandline option", 1));
+ .ok_or_else(|| err_msg("No diary selected. Use either the configuration file or the commandline option"))?;
let mut ids = Diary::entries(rt.store(), &diaryname)
- .map_dbg_str("Ok")
- .map_err_trace_exit_unwrap()
- .trace_unwrap_exit()
- .map(|id| DiaryId::from_storeid(&id))
- .collect::<Result<Vec<_>>>()
- .map_err_trace_exit_unwrap();
+ .map_dbg_str("Ok")?
+ .and_then_ok(|id| DiaryId::from_storeid(&id))
+ .collect::<Result<Vec<_>>>()?;
ids.sort_by_key(|id| {
[id.year() as u32, id.month(), id.day(), id.hour(), id.minute(), id.second()]
@@ -53,13 +48,15 @@ pub fn list(rt: &Runtime) {
ids.into_iter()
.map(IntoStoreId::into_storeid)
- .trace_unwrap_exit()
- .for_each(|id| {
- rt.report_touched(&id).unwrap_or_exit();
+ .and_then_ok(|id| {
+ rt.report_touched(&id)?;
if !rt.output_is_pipe() {
- writeln!(rt.stdout(), "{}", id).to_exit_code().unwrap_or_exit()
+ writeln!(rt.stdout(), "{}", id).map_err(Error::from)
+ } else {
+ Ok(())
}
- });
+ })
+ .collect()
}
diff --git a/bin/domain/imag-diary/src/util.rs b/bin/domain/imag-diary/src/util.rs
index 3059b6db..2ae01172 100644
--- a/bin/domain/imag-diary/src/util.rs
+++ b/bin/domain/imag-diary/src/util.rs
@@ -89,8 +89,6 @@ pub fn parse_timed_string(s: &str, diary_name: &str) -> Result<Timed> {
} else if s == "s" || s == "secondly" {
Ok(Timed::Secondly)
} else {
- let s = format!("Cannot parse config: 'diary.diaries.{}.timed = {}'",
- diary_name, s);
- Err(format_err!("{}", s))
+ Err(format_err!("Cannot parse config: 'diary.diaries.{}.timed = {}'", diary_name, s))
}
}
diff --git a/bin/domain/imag-diary/src/view.rs b/bin/domain/imag-diary/src/view.rs
index 9c77691f..c52d274f 100644
--- a/bin/domain/imag-diary/src/view.rs
+++ b/bin/domain/imag-diary/src/view.rs
@@ -17,47 +17,32 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
+use failure::Fallible as Result;
+use failure::err_msg;
+use failure::Error;
+use resiter::AndThen;
+use resiter::IterInnerOkOrElse;
+
use libimagdiary::diary::Diary;
-use libimagdiary::viewer::DiaryViewer as DV;
+use libimagdiary::viewer::DiaryViewer;
use libimagrt::runtime::Runtime;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::exit::ExitUnwrap;
-use libimagerror::io::ToExitCode;
-use libimagutil::warn_exit::warn_exit;
use libimagstore::iter::get::StoreIdGetIteratorExtension;
use libimagentryview::viewer::Viewer;
-use libimagentryview::error::Error;
use crate::util::get_diary_name;
-pub fn view(rt: &Runtime) {
- let diaryname = get_diary_name(rt).unwrap_or_else(|| warn_exit("No diary name", 1));
- let hdr = rt.cli().subcommand_matches("view").unwrap().is_present("show-header");
-
- let entries = Diary::entries(rt.store(), &diaryname)
- .map_err_trace_exit_unwrap()
- .into_get_iter(rt.store())
- .trace_unwrap_exit()
- .map(|e| e.unwrap_or_else(|| {
- error!("Failed to fetch entry");
- ::std::process::exit(1)
- }));
-
- let entries = entries.map(|e| {
- rt.report_touched(e.get_location()).unwrap_or_exit();
-
- e
- });
-
- let out = rt.stdout();
+pub fn view(rt: &Runtime) -> Result<()> {
+ let diaryname = get_diary_name(rt).ok_or_else(|| err_msg("No diary name"))?;
+ let hdr = rt.cli().subcommand_matches("view").unwrap().is_present("show-header");
+ let out = rt.stdout();
let mut outlock = out.lock();
+ let viewer = DiaryViewer::new(hdr);
- if let Err(e) = DV::new(hdr).view_entries(entries, &mut outlock) {
- match e {
- Error::Io(e) => Err(e).to_exit_code().unwrap_or_exit(),
- Error::Other(e) => Err(e).map_err_trace_exit_unwrap()
- }
- }
+ Diary::entries(rt.store(), &diaryname)?
+ .into_get_iter(rt.store())
+ .map_inner_ok_or_else(|| err_msg("Did not find one entry"))
+ .and_then_ok(|e| viewer.view_entry(&e, &mut outlock).map_err(Error::from).map(|_| e))
+ .and_then_ok(|e| rt.report_touched(e.get_location()).map_err(Error::from))
+ .collect()
}
diff --git a/bin/domain/imag-log/Cargo.toml b/bin/domain/imag-log/Cargo.toml
index 5466caab..6bb3eeb2 100644
--- a/bin/domain/imag-log/Cargo.toml
+++ b/bin/domain/imag-log/Cargo.toml
@@ -27,6 +27,7 @@ is-match = "0.1.0"
itertools = "0.8.0"
failure = "0.1.5"
textwrap = "0.11.0"
+resiter = "0.4.0"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
diff --git a/bin/domain/imag-log/src/lib.rs b/bin/domain/imag-log/src/lib.rs
index 338a482d..a6d21427 100644
--- a/bin/domain/imag-log/src/lib.rs
+++ b/bin/domain/imag-log/src/lib.rs
@@ -42,6 +42,7 @@ extern crate toml_query;
extern crate itertools;
extern crate failure;
extern crate textwrap;
+extern crate resiter;
extern crate libimaglog;
extern crate libimagrt;
@@ -51,20 +52,18 @@ extern crate libimagdiary;
use std::io::Write;
use std::io::Cursor;
-use std::result::Result as RResult;
use std::str::FromStr;
use failure::Error;
use failure::err_msg;
use failure::Fallible as Result;
+use resiter::Map;
+use resiter::AndThen;
+use resiter::IterInnerOkOrElse;
+use resiter::Filter;
use libimagrt::application::ImagApplication;
use libimagrt::runtime::Runtime;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::io::ToExitCode;
-use libimagerror::exit::ExitUnwrap;
-use libimagerror::iter::TraceIterator;
-use libimagerror::exit::ExitCode;
use libimagdiary::diary::Diary;
use libimagdiary::diaryid::DiaryId;
use libimaglog::log::Log;
@@ -88,37 +87,33 @@ impl ImagApplication for ImagLog {
if let Some(scmd) = rt.cli().subcommand_name() {
match scmd {
"show" => show(&rt),
- other => {
+ other => {
debug!("Unknown command");
- let _ = rt.handle_unknown_subcommand("imag-log", other, rt.cli())
- .map_err_trace_exit_unwrap()
- .code()
- .map(::std::process::exit);
+ if rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli())?.success() {
+ Ok(())
+ } else {
+ Err(err_msg("Failed to handle unknown subcommand"))
+ }
},
}
} else {
let text = get_log_text(&rt);
- let diary_name = rt.cli()
- .value_of("diaryname")
- .map(String::from)
- .unwrap_or_else(|| get_diary_name(&rt));
+ let diary_name = match rt.cli().value_of("diaryname").map(String::from) {
+ Some(s) => s,
+ None => get_diary_name(&rt)?,
+ };
debug!("Writing to '{}': {}", diary_name, text);
- rt
- .store()
+ rt.store()
.new_entry_now(&diary_name)
- .map(|mut fle| {
- fle.make_log_entry().map_err_trace_exit_unwrap();
+ .and_then(|mut fle| {
+ fle.make_log_entry()?;
*fle.get_content_mut() = text;
- fle
+ Ok(fle)
})
- .map(|fle| rt.report_touched(fle.get_location()).unwrap_or_exit())
- .map_err_trace_exit_unwrap();
-
+ .and_then(|fle| rt.report_touched(fle.get_location()).map_err(Error::from))
}
-
- Ok(())
}
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
@@ -138,7 +133,7 @@ impl ImagApplication for ImagLog {
}
}
-fn show(rt: &Runtime) {
+fn show(rt: &Runtime) -> Result<()> {
use std::borrow::Cow;
use libimagdiary::iter::DiaryEntryIterator;
@@ -147,29 +142,33 @@ fn show(rt: &Runtime) {
let scmd = rt.cli().subcommand_matches("show").unwrap(); // safed by main()
let iters : Vec<DiaryEntryIterator> = match scmd.values_of("show-name") {
Some(values) => values
- .map(|diary_name| Diary::entries(rt.store(), diary_name).map_err_trace_exit_unwrap())
- .collect(),
+ .map(|diary_name| Diary::entries(rt.store(), diary_name))
+ .collect::<Result<Vec<DiaryEntryIterator>>>(),
None => if scmd.is_present("show-all") {
debug!("Showing for all diaries");
- rt.store()
- .diary_names()
- .map_err_trace_exit_unwrap()
+ let iter = rt.store()
+ .diary_names()?
.map(|diary_name| {
- let diary_name = diary_name.map_err_trace_exit_unwrap();
+ let diary_name = diary_name?;
debug!("Getting entries for Diary: {}", diary_name);
- let entries = Diary::entries(rt.store(), &diary_name).map_err_trace_exit_unwrap();
+ let entries = Diary::entries(rt.store(), &diary_name)?;
let diary_name = Cow::from(diary_name);
- (entries, diary_name)
+ Ok((entries, diary_name))
})
+ .collect::<Result<Vec<(DiaryEntryIterator, Cow<str>)>>>()?;
+
+ let iter = iter.into_iter()
.unique_by(|tpl| tpl.1.clone())
.map(|tpl| tpl.0)
- .collect()
+ .collect::<Vec<DiaryEntryIterator>>();
+
+ Ok(iter)
} else {
// showing default logs
- vec![Diary::entries(rt.store(), &get_diary_name(rt)).map_err_trace_exit_unwrap()]
+ get_diary_name(rt).and_then(|dname| Diary::entries(rt.store(), &dname)).map(|e| vec![e])
}
- };
+ }?;
let mut do_wrap = if scmd.is_present("show-wrap") {
Some(80)
@@ -179,26 +178,25 @@ fn show(rt: &Runtime) {
let do_remove_newlines = scmd.is_present("show-skipnewlines");
if let Some(wrap_value) = scmd.value_of("show-wrap") {
- do_wrap = Some(usize::from_str(wrap_value).map_err(Error::from).map_err_trace_exit_unwrap());
+ do_wrap = Some(usize::from_str(wrap_value).map_err(Error::from)?);
}
let mut output = rt.stdout();
- iters.into_iter()
+ let v = iters.into_iter()
.flatten()
.into_get_iter(rt.store())
- .trace_unwrap_exit()
- .filter_map(|opt| {
- if opt.is_none() {
- warn!("Failed to retrieve an entry from an existing store id");
- }
-
- opt
- })
- .filter(|e| e.is_log().map_err_trace_exit_unwrap())
- .map(|entry| (entry.diary_id().map_err_trace_exit_unwrap(), entry))
- .sorted_by_key(|tpl| tpl.0.get_date_representation())
- .map(|tpl| { debug!("Found entry: {:?}", tpl.1); tpl })
+ .map_inner_ok_or_else(|| err_msg("Did not find one entry"))
+ .and_then_ok(|e| e.is_log().map(|b| (b, e)))
+ .filter_ok(|tpl| tpl.0)
+ .map_ok(|tpl| tpl.1)
+ .and_then_ok(|entry| entry.diary_id().map(|did| (did.get_date_representation(), did, entry)))
+ .collect::<Result<Vec<_>>>()?;
+
+ v.into_iter()
+ .sorted_by_key(|tpl| tpl.0)
+ .map(|tpl| (tpl.1, tpl.2))
+ .inspect(|tpl| debug!("Found entry: {:?}", tpl.1))
.map(|(id, entry)| {
if let Some(wrap_limit) = do_wrap {
// assume a capacity here:
@@ -206,70 +204,57 @@ fn show(rt: &Runtime) {
// 10 + 4 + 2 + 2 + 2 + 2 + 6 + 4 = 32
// plus text, which we assume to be 120 characters... lets allocate 256 bytes.
let mut buffer = Cursor::new(Vec::with_capacity(256));
- do_write_to(&mut buffer, id, &entry, do_remove_newlines).unwrap_or_exit();
- let buffer = String::from_utf8(buffer.into_inner())
- .map_err(Error::from)
- .map_err_trace_exit_unwrap();
+ do_write_to(&mut buffer, id, &entry, do_remove_newlines)?;
+ let buffer = String::from_utf8(buffer.into_inner())?;
// now lets wrap
- for line in ::textwrap::wrap(&buffer, wrap_limit).iter() {
- writeln!(&mut output, "{}", line).to_exit_code()?;
- }
+ ::textwrap::wrap(&buffer, wrap_limit)
+ .iter()
+ .map(|line| writeln!(&mut output, "{}", line).map_err(Error::from))
+ .collect::<Result<Vec<_>>>()?;
} else {
- do_write_to(&mut output, id, &entry, do_remove_newlines).unwrap_or_exit();
+ do_write_to(&mut output, id, &entry, do_remove_newlines)?;
}
- rt
- .report_touched(entry.get_location())
- .unwrap_or_exit();
- Ok(())
+ rt.report_touched(entry.get_location()).map_err(Error::from)
})
- .collect::<RResult<Vec<()>, ExitCode>>()
- .unwrap_or_exit();
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
-fn get_diary_name(rt: &Runtime) -> String {
+fn get_diary_name(rt: &Runtime) -> Result<String> {
use toml_query::read::TomlValueReadExt;
use toml_query::read::TomlValueReadTypeExt;
let cfg = rt
.config()
- .ok_or_else(|| err_msg("Configuration not present, cannot continue"))
- .map_err_trace_exit_unwrap();
+ .ok_or_else(|| err_msg("Configuration not present, cannot continue"))?;
let current_log = cfg
- .read_string("log.default")
- .map_err(Error::from)
- .map_err_trace_exit_unwrap()
- .ok_or_else(|| err_msg("Configuration missing: 'log.default'"))
- .map_err_trace_exit_unwrap();
+ .read_string("log.default")?
+ .ok_or_else(|| err_msg("Configuration missing: 'log.default'"))?;
if cfg
- .read("log.logs")
- .map_err(Error::from)
- .map_err_trace_exit_unwrap()
- .ok_or_else(|| err_msg("Configuration missing: 'log.logs'"))
- .map_err_trace_exit_unwrap()
+ .read("log.logs")?
+ .ok_or_else(|| err_msg("Configuration missing: 'log.logs'"))?
.as_array()
- .ok_or_else(|| err_msg("Configuration 'log.logs' is not an Array"))
- .map_err_trace_exit_unwrap()
+ .ok_or_else(|| err_msg("Configuration 'log.logs' is not an Array"))?
.iter()
.map(|e| if !is_match!(e, &Value::String(_)) {
- error!("Configuration 'log.logs' is not an Array<String>!");
- ::std::process::exit(1)
+ Err(err_msg("Configuration 'log.logs' is not an Array<String>!"))
} else {
- e
+ Ok(e)
})
- .map(Value::as_str)
- .map(Option::unwrap) // safe by map from above
- .map(String::from)
- .find(|log| log == &current_log)
+ .map_ok(|value| value.as_str().unwrap())
+ .map_ok(String::from)
+ .collect::<Result<Vec<_>>>()?
+ .iter()
+ .find(|log| *log == &current_log)
.is_none()
{
- error!("'log.logs' does not contain 'log.default'");
- ::std::process::exit(1)
+ Err(err_msg("'log.logs' does not contain 'log.default'"))
} else {
- current_log
+ Ok(current_log)
}
}
@@ -287,7 +272,7 @@ fn get_log_text(rt: &Runtime) -> String {
})
}
-fn do_write_to<'a>(sink: &mut dyn Write, id: DiaryId, entry: &FileLockEntry<'a>, do_remove_newlines: bool) -> RResult<(), ExitCode> {
+fn do_write_to<'a>(sink: &mut dyn Write, id: DiaryId, entry: &FileLockEntry<'a>, do_remove_newlines: bool) -> Result<()> {
let text = if do_remove_newlines {
entry.get_content().trim_end().replace("\n", "")
} else {
@@ -303,6 +288,6 @@ fn do_write_to<'a>(sink: &mut dyn Write, id: DiaryId, entry: &FileLockEntry<'a>,
H = id.hour(),
M = id.minute(),
text = text)
- .to_exit_code()
+ .map_err(Error::from)
}
diff --git a/bin/domain/imag-timetrack/Cargo.toml b/bin/domain/imag-timetrack/Cargo.toml
index 88408449..ee4ae249 100644
--- a/bin/domain/imag-timetrack/Cargo.toml
+++ b/bin/domain/imag-timetrack/Cargo.toml
@@ -27,6 +27,7 @@ itertools = "0.8.0"
prettytable-rs = "0.8.0"
kairos = "0.3.0"
failure = "0.1.5"
+resiter = "0.4.0"
libimagstore = { version = "0.10.0", path = "../../../lib/core/libimagstore" }
libimagrt = { version = "0.10.0", path = "../../../lib/core/libimagrt" }
diff --git a/bin/domain/imag-timetrack/src/cont.rs b/bin/domain/imag-timetrack/src/cont.rs
index e5efb16a..2c77e575 100644
--- a/bin/domain/imag-timetrack/src/cont.rs
+++ b/bin/domain/imag-timetrack/src/cont.rs
@@ -22,36 +22,35 @@ use std::cmp::Ord;
use filters::filter::Filter;
use itertools::Itertools;
use chrono::NaiveDateTime;
+use failure::Fallible as Result;
+use failure::Error;
+use resiter::Filter as RFilter;
-use libimagerror::trace::trace_error;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::exit::ExitUnwrap;
use libimagtimetrack::store::TimeTrackStore;
-use libimagtimetrack::timetracking::TimeTracking;
use libimagtimetrack::iter::filter::*;
+use libimagtimetrack::timetracking::TimeTracking;
use libimagrt::runtime::Runtime;
-pub fn cont(rt: &Runtime) -> i32 {
+pub fn cont(rt: &Runtime) -> Result<()> {
let groups = rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| has_end_time.filter(&e))
+ .get_timetrackings()?
+ .filter_ok(|e| has_end_time.filter(&e))
+
+ // It is very unfortunate that we have to collect() here, but this is the least complex
+ // solution for the problem of grouping elements of an Iterator<Item = Result<_>>.
+ .collect::<Result<Vec<_>>>()?
+ .into_iter()
.group_by(|elem| match elem.get_end_datetime() { // Now group them by the end time
+ Err(_) => NaiveDateTime::from_timestamp(0, 0), // placeholder
Ok(Some(dt)) => dt,
- Ok(None) => {
+ Ok(None) => {
// error. We expect all of them having an end-time.
error!("Has no end time, but should be filtered out: {:?}", elem);
error!("This is a bug. Please report.");
error!("Will panic now");
panic!("Unknown bug")
}
- Err(e) => {
- trace_error(&e);
- NaiveDateTime::from_timestamp(0, 0) // placeholder
- }
});
// sort the trackings by key, so by end datetime
@@ -76,28 +75,27 @@ pub fn cont(rt: &Runtime) -> i32 {
Some((_, trackings)) => {
// and then, for all trackings
trackings
- .fold(Ok(0), |acc, tracking| {
+ .collect::<Vec<_>>()
+ .into_iter()
+ .map(|tracking| {
debug!("Having tracking: {:?}", tracking);
- acc.and_then(|_| {
- // create a new tracking with the same tag
- let val = tracking
- .get_timetrack_tag()
- .and_then(|tag| rt.store().create_timetracking_now(&tag))
- .map(|_| 0)
- .map_err_trace();
-
- rt.report_touched(tracking.get_location()).unwrap_or_exit();
+ // create a new tracking with the same tag
+ let val = tracking
+ .get_timetrack_tag()
+ .and_then(|tag| rt.store().create_timetracking_now(&tag))
+ .map(|_| 0)?;
- val
- })
+ rt.report_touched(tracking.get_location()).map_err(Error::from).map(|_| val)
})
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
},
None => {
info!("No trackings to continue");
- Ok(1)
+ Ok(())
},
- }.map_err_trace_exit_unwrap()
+ }
}
diff --git a/bin/domain/imag-timetrack/src/day.rs b/bin/domain/imag-timetrack/src/day.rs
index 3bcd0990..287ca0e9 100644
--- a/bin/domain/imag-timetrack/src/day.rs
+++ b/bin/domain/imag-timetrack/src/day.rs
@@ -22,47 +22,32 @@ use std::str::FromStr;
use filters::filter::Filter;
use chrono::NaiveDateTime;
+use failure::Fallible as Result;
use failure::Error;
+use resiter::AndThen;
+use resiter::Filter as RFilter;
-use libimagerror::trace::trace_error;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::io::ToExitCode;
-use libimagerror::exit::ExitUnwrap;
use libimagstore::store::FileLockEntry;
use libimagtimetrack::store::TimeTrackStore;
-use libimagtimetrack::timetracking::TimeTracking;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::iter::filter::*;
+use libimagtimetrack::timetracking::TimeTracking;
use libimagrt::runtime::Runtime;
-
-pub fn day(rt: &Runtime) -> i32 {
+pub fn day(rt: &Runtime) -> Result<()> {
let (_, cmd) = rt.cli().subcommand();
let cmd = cmd.unwrap(); // checked in main()
let filter = {
let start = match cmd.value_of("start").map(NaiveDateTime::from_str) {
None => ::chrono::offset::Local::today().and_hms(0, 0, 0).naive_local(),
- Some(s) => match s.map_err(Error::from) {
- Ok(dt) => dt,
- Err(e) => {
- trace_error(&e);
- return 1
- }
- }
+ Some(s) => s.map_err(Error::from)?,
};
let end = match cmd.value_of("end").map(NaiveDateTime::from_str) {
None => ::chrono::offset::Local::today().and_hms(23, 59, 59).naive_local(),
- Some(s) => match s.map_err(Error::from) {
- Ok(dt) => dt,
- Err(e) => {
- trace_error(&e);
- return 1
- }
- }
+ Some(s) => s?,
};
let tags = cmd
@@ -88,11 +73,9 @@ pub fn day(rt: &Runtime) -> i32 {
};
rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| filter.filter(e))
- .map(|e| -> Result<_, Error> {
+ .get_timetrackings()?
+ .filter_ok(|e| filter.filter(e))
+ .and_then_ok(|e| -> Result<_> {
debug!("Processing {:?}", e.get_location());
let tag = e.get_timetrack_tag()?;
@@ -104,21 +87,18 @@ pub fn day(rt: &Runtime) -> i32 {
let end = e.get_end_datetime()?;
debug!(" -> end = {:?}", end);
- rt.report_touched(e.get_location()).unwrap_or_exit();
-
- Ok((tag, start, end))
+ rt.report_touched(e.get_location())
+ .map_err(Error::from)
+ .map(|_| (tag, start, end))
})
- .trace_unwrap_exit()
- .map(|(tag, start, end)| {
+ .and_then_ok(|(tag, start, end)| {
match (start, end) {
(None, _) => writeln!(rt.stdout(), "{} has no start time.", tag),
(Some(s), None) => writeln!(rt.stdout(), "{} | {} - ...", tag, s),
(Some(s), Some(e)) => writeln!(rt.stdout(), "{} | {} - {}", tag, s, e),
- }
- .to_exit_code()
+ }.map_err(Error::from)
})
- .collect::<Result<Vec<()>, _>>()
- .map(|_| 0)
- .unwrap_or_else(|e| e.code())
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/lib.rs b/bin/domain/imag-timetrack/src/lib.rs
index 6b94477f..fb44f493 100644
--- a/bin/domain/imag-timetrack/src/lib.rs
+++ b/bin/domain/imag-timetrack/src/lib.rs
@@ -43,7 +43,8 @@ extern crate filters;
extern crate itertools;
extern crate prettytable;
extern crate kairos;
-extern crate failure;
+#[macro_use] extern crate failure;
+extern crate resiter;
extern crate libimagerror;
extern crate libimagstore;
@@ -76,10 +77,10 @@ use crate::year::year;
use clap::App;
use failure::Fallible as Result;
+use failure::err_msg;
use libimagrt::runtime::Runtime;
use libimagrt::application::ImagApplication;
-use libimagerror::trace::MapErrTrace;
/// Marker enum for implementing ImagApplication on
///
@@ -89,8 +90,7 @@ pub enum ImagTimetrack {}
impl ImagApplication for ImagTimetrack {
fn run(rt: Runtime) -> Result<()> {
let command = rt.cli().subcommand_name();
- let retval = if let Some(command) = command {
- debug!("Call: {}", command);
+ if let Some(command) = command {
match command {
"continue" => cont(&rt),
"day" => day(&rt),
@@ -102,21 +102,20 @@ impl ImagApplication for ImagTimetrack {
"track" => track(&rt),
"week" => week(&rt),
"year" => year(&rt),
- other => {
+ other => {
debug!("Unknown command");
- rt.handle_unknown_subcommand("imag-timetrack", other, rt.cli())
- .map_err_trace_exit_unwrap()
- .code()
- .unwrap_or(0)
+ if rt.handle_unknown_subcommand("imag-bookmark", other, rt.cli())?.success() {
+ Ok(())
+ } else {
+ Err(err_msg("Failed to handle unknown subcommand"))
+ }
},
}
} else {
let start = ::chrono::offset::Local::today().naive_local().and_hms(0, 0, 0);
let end = ::chrono::offset::Local::today().naive_local().and_hms(23, 59, 59);
list_impl(&rt, Some(start), Some(end), false, false)
- };
-
- ::std::process::exit(retval);
+ }
}
fn build_cli<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
diff --git a/bin/domain/imag-timetrack/src/list.rs b/bin/domain/imag-timetrack/src/list.rs
index c323cf29..b44f7ed0 100644
--- a/bin/domain/imag-timetrack/src/list.rs
+++ b/bin/domain/imag-timetrack/src/list.rs
@@ -18,7 +18,6 @@
//
use chrono::NaiveDateTime;
-use filters::filter::Filter;
use prettytable::Table;
use prettytable::Row;
use prettytable::Cell;
@@ -27,60 +26,44 @@ use kairos::parser::parse as kairos_parse;
use clap::ArgMatches;
use failure::Fallible as Result;
use failure::ResultExt;
-use failure::err_msg;
use failure::Error;
+use resiter::Filter;
+use resiter::AndThen;
+use resiter::Map;
-use libimagerror::trace::trace_error;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::exit::ExitUnwrap;
use libimagstore::store::FileLockEntry;
-use libimagtimetrack::store::TimeTrackStore;
use libimagtimetrack::timetracking::TimeTracking;
+use libimagtimetrack::store::TimeTrackStore;
use libimagrt::runtime::Runtime;
-pub fn list(rt: &Runtime) -> i32 {
+pub fn list(rt: &Runtime) -> Result<()> {
let (_, cmd) = rt.cli().subcommand();
let cmd = cmd.unwrap(); // checked in main()
let gettime = |cmd: &ArgMatches, name| {
match cmd.value_of(name).map(kairos_parse) {
- Some(Ok(Parsed::TimeType(tt))) => match tt.calculate() {
- Ok(tt) => {
- let dt = tt.get_moment().unwrap_or_else(|| {
- error!("Failed to get date from '{}'", cmd.value_of(name).unwrap());
- ::std::process::exit(1)
- });
-
- Some(*dt)
- },
- Err(e) => {
- error!("Failed to calculate date from '{}': {:?}",
- cmd.value_of(name).unwrap(), e);
- ::std::process::exit(1)
- },
+ Some(Ok(Parsed::TimeType(tt))) => {
+ let tt = tt
+ .calculate()
+ .context(format_err!("Failed to calculate date from '{}'", cmd.value_of(name).unwrap()))?;
+ Ok(tt.get_moment().cloned())
},
Some(Ok(Parsed::Iterator(_))) => {
- error!("Expected single point in time, got '{}', which yields a list of dates", cmd.value_of(name).unwrap());
- ::std::process::exit(1)
+ Err(format_err!("Expected single point in time, got '{}', which yields a list of dates", cmd.value_of(name).unwrap()))
},
- Some(Err(e)) => {
- let e = e;
- trace_error(&e);
- ::std::process::exit(1)
- }
- None => None,
+ Some(Err(e)) => Err(e),
+ None => Ok(None),
}
};
- let start = gettime(&cmd, "start-time");
- let end = gettime(&cmd, "end-time");
+ let start = gettime(&cmd, "start-time")?;
+ let end = gettime(&cmd, "end-time")?;
let list_not_ended = cmd.is_present("list-not-ended");
let show_duration = cmd.is_present("show-duration");
- list_impl(rt, start, end, list_not_ended, show_duration)
+ list_impl(rt, start.clone(), end.clone(), list_not_ended, show_duration)
}
pub fn list_impl(rt: &Runtime,
@@ -88,34 +71,27 @@ pub fn list_impl(rt: &Runtime,
end: Option<NaiveDateTime>,
list_not_ended: bool,
show_duration: bool)
- -> i32
+ -> Result<()>
{
+ use filters::failable::filter::FailableFilter;
- let start_time_filter = |timetracking: &FileLockEntry| {
- start.map(|s| match timetracking.get_start_datetime() {
- Ok(Some(dt)) => dt >= s,
- Ok(None) => {
+ let start_time_filter = |timetracking: &FileLockEntry| -> Result<bool> {
+ start.map(|s| match timetracking.get_start_datetime()? {
+ Some(dt) => Ok(dt >= s),
+ None => {
warn!("Funny things are happening: Timetracking has no start time");
- false
- }
- Err(e) => {
- trace_error(&e);
- false
+ Ok(false)
}
})
- .unwrap_or(true)
+ .unwrap_or(Ok(true))
};
- let end_time_filter = |timetracking: &FileLockEntry| {
- end.map(|s| match timetracking.get_end_datetime() {
- Ok(Some(dt)) => dt <= s,
- Ok(None) => list_not_ended,
- Err(e) => {
- trace_error(&e);
- false
- }
+ let end_time_filter = |timetracking: &FileLockEntry| -> Result<bool> {
+ end.map(|s| match timetracking.get_end_datetime()? {
+ Some(dt) => Ok(dt <= s),
+ None => Ok(list_not_ended),
})
- .unwrap_or(true)
+ .unwrap_or(Ok(true))
};
let filter = start_time_filter.and(end_time_filter);
@@ -128,92 +104,83 @@ pub fn list_impl(rt: &Runtime,
};
table.set_titles(title_row);
- let mut table_empty = true;
-
- let table = rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| filter.filter(e))
- .fold(Ok(table), |acc: Result<_>, e| {
- acc.and_then(|mut tab: Table| {
- debug!("Processing {:?}", e.get_location());
-
- let tag = e.get_timetrack_tag()?;
- debug!(" -> tag = {:?}", tag);
-
- let start = e.get_start_datetime()?;
- debug!(" -> start = {:?}", start);
-
- let end = e.get_end_datetime()?;
- debug!(" -> end = {:?}", end);
-
- let v = match (start, end) {
- (None, _) => {
- let mut v = vec![String::from(tag.as_str()), String::from(""), String::from("")];
- if show_duration {
- v.push(String::from(""));
- }
- v
- },
- (Some(s), None) => {
- let mut v = vec![
- String::from(tag.as_str()),
- format!("{}", s),
- String::from(""),
- ];
-
- if show_duration {
- v.push(String::from(""));
- }
-
- v
- },
- (Some(s), Some(e)) => {
- let mut v = vec![
- String::from(tag.as_str()),
- format!("{}", s),
- format!("{}", e),
- ];
-
- if show_duration {
- let duration = e - s;
- let dur = format!("{days} Days, {hours} Hours, {minutes} Minutes, {seconds} Seconds",
- days = duration.num_days(),
- hours = duration.num_hours(),
- minutes = duration.num_minutes(),
- seconds = duration.num_seconds());
-
- v.push(dur);
- }
-
- v
- },
- };
-
- let cells : Vec<Cell> = v
- .into_iter()
- .map(|s| Cell::new(&s))
- .collect();
- tab.add_row(Row::new(cells));
-
- rt.report_touched(e.get_location()).unwrap_or_exit();
-
- table_empty = false;
- Ok(tab)
- })
+ let table_empty = rt.store()
+ .get_timetrackings()?
+ .and_then_ok(|e| filter.filter(&e).map(|b| (b, e)))
+ .filter_ok(|tpl| tpl.0)
+ .map_ok(|tpl| tpl.1)
+ .and_then_ok(|e| {
+ debug!("Processing {:?}", e.get_location());
+
+ let tag = e.get_timetrack_tag()?;
+ debug!(" -> tag = {:?}", tag);
+
+ let start = e.get_start_datetime()?;
+ debug!(" -> start = {:?}", start);
+
+ let end = e.get_end_datetime()?;
+ debug!(" -> end = {:?}", end);
+
+ let v = match (start, end) {
+ (None, _) => {
+ let mut v = vec![String::from(tag.as_str()), String::from(""), String::from("")];
+ if show_duration {
+ v.push(String::from(""));
+ }
+ v
+ },
+ (Some(s), None) => {
+ let mut v = vec![
+ String::from(tag.as_str()),
+ format!("{}", s),
+ String::from(""),
+ ];
+
+ if show_duration {
+ v.push(String::from(""));
+ }
+
+ v
+ },
+ (Some(s), Some(e)) => {
+ let mut v = vec![
+ String::from(tag.as_str()),
+ format!("{}", s),
+ format!("{}", e),
+ ];
+
+ if show_duration {
+ let duration = e - s;
+ let dur = format!("{days} Days, {hours} Hours, {minutes} Minutes, {seconds} Seconds",
+ days = duration.num_days(),
+ hours = duration.num_hours(),
+ minutes = duration.num_minutes(),
+ seconds = duration.num_seconds());
+
+ v.push(dur);
+ }
+
+ v
+ },
+ };
+
+ let cells : Vec<Cell> = v.iter().map(|s| Cell::new(s)).collect();
+ table.add_row(Row::new(cells));
+
+ rt.report_touched(e.get_location())?;
+ Ok(false)
})
- .map_err_trace_exit_unwrap();
+ .collect::<Result<Vec<bool>>>()?
+ .iter()
+ .any(|b| !b);
if !table_empty {
table.print(&mut rt.stdout())
- .context(err_msg("Failed to print table"))
+ .context("Failed to print table")
.map_err(Error::from)
- .map(|_| 0)
- .map_err_trace()
- .unwrap_or(1)
+ .map(|_| ())
} else {
- 0
+ Ok(())
}
}
diff --git a/bin/domain/imag-timetrack/src/month.rs b/bin/domain/imag-timetrack/src/month.rs
index 19d12ebe..4d4c7e65 100644
--- a/bin/domain/imag-timetrack/src/month.rs
+++ b/bin/domain/imag-timetrack/src/month.rs
@@ -23,21 +23,19 @@ use std::str::FromStr;
use filters::filter::Filter;
use chrono::NaiveDateTime;
use failure::Error;
+use failure::Fallible as Result;
+use resiter::AndThen;
+use resiter::Filter as RFilter;
-use libimagerror::trace::trace_error;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::io::ToExitCode;
-use libimagerror::iter::TraceIterator;
-use libimagerror::exit::ExitUnwrap;
use libimagstore::store::FileLockEntry;
use libimagtimetrack::store::TimeTrackStore;
-use libimagtimetrack::timetracking::TimeTracking;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::iter::filter::*;
+use libimagtimetrack::timetracking::TimeTracking;
use libimagrt::runtime::Runtime;
-pub fn month(rt: &Runtime) -> i32 {
+pub fn month(rt: &Runtime) -> Result<()> {
let cmd = rt.cli().subcommand().1.unwrap(); // checked in main
let filter = {
@@ -49,13 +47,7 @@ pub fn month(rt: &Runtime) -> i32 {
let start = match cmd.value_of("start").map(::chrono::naive::NaiveDateTime::from_str) {
None => NaiveDate::from_ymd(now.year(), now.month(), 1).and_hms(0, 0, 0),
- Some(s) => match s.map_err(Error::from) {
- Ok(dt) => dt,
- Err(e) => {
- trace_error(&e);
- return 1
- }
- }
+ Some(s) => s?,
};
let end = match cmd.value_of("end").map(::chrono::naive::NaiveDateTime::from_str) {
@@ -71,13 +63,7 @@ pub fn month(rt: &Runtime) -> i32 {
NaiveDate::from_ymd(year, month, 1).and_hms(0, 0, 0)
},
- Some(s) => match s.map_err(Error::from) {
- Ok(dt) => dt,
- Err(e) => {
- trace_error(&e);
- return 1
- }
- }
+ Some(s) => s?,
};
let tags = cmd
@@ -103,11 +89,9 @@ pub fn month(rt: &Runtime) -> i32 {
};
rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| filter.filter(e))
- .map(|e| -> Result<_, Error> {
+ .get_timetrackings()?
+ .filter_ok(|e| filter.filter(e))
+ .and_then_ok(|e| -> Result<_> {
debug!("Processing {:?}", e.get_location());
let tag = e.get_timetrack_tag()?;
@@ -119,21 +103,18 @@ pub fn month(rt: &Runtime) -> i32 {
let end = e.get_end_datetime()?;
debug!(" -> end = {:?}", end);
- rt.report_touched(e.get_location()).unwrap_or_exit();
-
- Ok((tag, start, end))
+ rt.report_touched(e.get_location())
+ .map_err(Error::from)
+ .map(|_| (tag, start, end))
})
- .trace_unwrap_exit()
- .map(|(tag, start, end)| {
+ .and_then_ok(|(tag, start, end)| {
match (start, end) {
(None, _) => writeln!(rt.stdout(), "{} has no start time.", tag),
(Some(s), None) => writeln!(rt.stdout(), "{} | {} - ...", tag, s),
(Some(s), Some(e)) => writeln!(rt.stdout(), "{} | {} - {}", tag, s, e),
- }
- .to_exit_code()
+ }.map_err(Error::from)
})
- .collect::<Result<Vec<()>, _>>()
- .map(|_| 0)
- .unwrap_or_else(|e| e.code())
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/shell.rs b/bin/domain/imag-timetrack/src/shell.rs
index c66bfe13..30693438 100644
--- a/bin/domain/imag-timetrack/src/shell.rs
+++ b/bin/domain/imag-timetrack/src/shell.rs
@@ -21,19 +21,19 @@ use std::env;
use std::process::Command;
use filters::filter::Filter;
+use failure::Fallible as Result;
+use failure::err_msg;
+use failure::Error;
+use resiter::Filter as RFilter;
+use resiter::AndThen;
-use libimagerror::exit::ExitUnwrap;
-use libimagerror::iter::TraceIterator;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::trace::trace_error;
use libimagrt::runtime::Runtime;
use libimagtimetrack::iter::filter::has_one_of_tags;
use libimagtimetrack::store::TimeTrackStore;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::timetracking::TimeTracking;
-use libimagutil::warn_result::*;
-pub fn shell(rt: &Runtime) -> i32 {
+pub fn shell(rt: &Runtime) -> Result<()> {
let (_, cmd) = rt.cli().subcommand();
let cmd = cmd.unwrap(); // checked in main()
@@ -54,57 +54,42 @@ pub fn shell(rt: &Runtime) -> i32 {
};
if let Some(s) = cmd.value_of("shell") {
- mkshell(s.to_owned())
+ Ok(mkshell(s.to_owned()))
} else {
env::var("SHELL")
.map(mkshell)
.map_err(|e| match e {
env::VarError::NotPresent => {
- error!("No $SHELL variable in environment, cannot work!");
- ::std::process::exit(1)
+ err_msg("No $SHELL variable in environment, cannot work!")
},
env::VarError::NotUnicode(_) => {
- error!("$SHELL variable is not unicode, cannot work!");
- ::std::process::exit(1)
+ err_msg("SHELL variable is not unicode, cannot work!")
}
})
- .unwrap()
}
- };
+ }?;
for tag in tags.iter() {
- match rt.store().create_timetracking_at(&start, tag) {
- Err(e) => trace_error(&e),
- Ok(entry) => {
- rt.report_touched(entry.get_location()).unwrap_or_exit();
- }
- }
+ let entry = rt.store().create_timetracking_at(&start, tag)?;
+ rt.report_touched(entry.get_location())?;
}
- let exit_code = match shellcmd.status() {
- Ok(estat) => estat.code().unwrap_or(0),
- Err(e) => {
- error!("Error starting shell: {:?}", e);
- ::std::process::exit(2)
- },
- };
+ if !shellcmd.status()?.success() {
+ return Err(format_err!("Failed to execute {:?}", shellcmd))
+ }
+ let stop = ::chrono::offset::Local::now().naive_local();
+ let filter = has_one_of_tags(&tags);
- let stop = ::chrono::offset::Local::now().naive_local();
- let filter = has_one_of_tags(&tags);
rt.store()
- .get_timetrackings()
- .map_warn_err_str("Getting timetrackings failed")
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| filter.filter(e))
- .for_each(|mut elem| if let Err(e) = elem.set_end_datetime(stop.clone()) {
- trace_error(&e)
- } else {
+ .get_timetrackings()?
+ .filter_ok(|e| filter.filter(e))
+ .and_then_ok(|mut elem| {
+ let _ = elem.set_end_datetime(stop.clone())?;
debug!("Setting end time worked: {:?}", elem);
- rt.report_touched(elem.get_location()).unwrap_or_exit();
- });
-
- ::std::process::exit(exit_code)
+ rt.report_touched(elem.get_location()).map_err(Error::from)
+ })
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/start.rs b/bin/domain/imag-timetrack/src/start.rs
index a4f99e91..e3d10f01 100644
--- a/bin/domain/imag-timetrack/src/start.rs
+++ b/bin/domain/imag-timetrack/src/start.rs
@@ -21,49 +21,34 @@ use std::str::FromStr;
use chrono::naive::NaiveDateTime;
use failure::Error;
+use failure::Fallible as Result;
use libimagrt::runtime::Runtime;
-use libimagerror::trace::trace_error;
-use libimagerror::exit::ExitUnwrap;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::store::TimeTrackStore;
-pub fn start(rt: &Runtime) -> i32 {
+pub fn start(rt: &Runtime) -> Result<()> {
let (_, cmd) = rt.cli().subcommand();
let cmd = cmd.unwrap(); // checked in main()
let start = {
let startstr = cmd.value_of("start-time").unwrap(); // safe by clap
if startstr == "now" {
- ::chrono::offset::Local::now().naive_local()
+ Ok(::chrono::offset::Local::now().naive_local())
} else {
- match NaiveDateTime::from_str(startstr).map_err(Error::from) {
- Ok(ndt) => ndt,
- Err(e) => {
- trace_error(&e);
- error!("Cannot continue, not having start time");
- return 1
- },
- }
+ NaiveDateTime::from_str(startstr)
}
- };
+ }?;
cmd.values_of("tags")
.unwrap() // enforced by clap
.map(String::from)
.map(TimeTrackingTag::from)
- .fold(0, |acc, ttt| {
- match rt.store().create_timetracking_at(&start, &ttt) {
- Err(e) => {
- trace_error(&e);
- 1
- },
- Ok(entry) => {
- rt.report_touched(entry.get_location()).unwrap_or_exit();
-
- acc
- }
- }
+ .map(|ttt| {
+ let entry = rt.store().create_timetracking_at(&start, &ttt)?;
+ rt.report_touched(entry.get_location()).map_err(Error::from)
})
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/stop.rs b/bin/domain/imag-timetrack/src/stop.rs
index 5a7f76a3..a4e8c466 100644
--- a/bin/domain/imag-timetrack/src/stop.rs
+++ b/bin/domain/imag-timetrack/src/stop.rs
@@ -21,82 +21,65 @@ use std::str::FromStr;
use filters::filter::Filter;
use chrono::NaiveDateTime;
+use failure::Fallible as Result;
use failure::Error;
+use resiter::Filter as RFilter;
+use resiter::Map;
+use resiter::AndThen;
-use libimagerror::trace::trace_error;
-use libimagerror::iter::TraceIterator;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::exit::ExitUnwrap;
use libimagrt::runtime::Runtime;
-
-use libimagtimetrack::timetracking::TimeTracking;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::store::*;
use libimagtimetrack::iter::filter::has_end_time;
use libimagtimetrack::iter::filter::has_one_of_tags;
-use libimagutil::warn_result::*;
+use libimagtimetrack::timetracking::TimeTracking;
-pub fn stop(rt: &Runtime) -> i32 {
+pub fn stop(rt: &Runtime) -> Result<()> {
let (_, cmd) = rt.cli().subcommand();
let cmd = cmd.unwrap(); // checked in main()
let stop_time = match cmd.value_of("stop-time") {
- None | Some("now") => ::chrono::offset::Local::now().naive_local(),
- Some(ndt) => match NaiveDateTime::from_str(ndt).map_err(Error::from) {
- Ok(ndt) => ndt,
- Err(e) => {
- trace_error(&e);
- error!("Cannot continue, not having start time");
- return 1
- },
- }
- };
+ None | Some("now") => Ok(::chrono::offset::Local::now().naive_local()),
+ Some(ndt) => NaiveDateTime::from_str(ndt).map_err(Error::from),
+ }?;
+
+ let tags = cmd.values_of("tags").map(|tags| {
+ tags.map(String::from)
+ .map(TimeTrackingTag::from)
+ .collect()
+ });
- let tags : Vec<TimeTrackingTag> = cmd.values_of("tags")
- .map(|tags| tags.map(String::from).map(TimeTrackingTag::from).collect())
- .unwrap_or_else(|| {
+ let tags : Vec<TimeTrackingTag> = match tags {
+ Some(s) => s,
+ None => {
// Get all timetrackings which do not have an end datetime.
rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|tracking| {
- tracking
- .get_end_datetime()
- .map_err_trace_exit_unwrap()
- .is_none()
- })
- .map(|t| t.get_timetrack_tag())
- .map(|r| r.map_err_trace_exit_unwrap())
- .collect()
- });
+ .get_timetrackings()?
+ .and_then_ok(|t| Ok((t.get_end_datetime()?.is_none(), t)))
+ .filter_ok(|tpl| (*tpl).0)
+ .map_ok(|tpl| tpl.1)
+ .and_then_ok(|t| t.get_timetrack_tag())
+ .collect::<Result<Vec<_>>>()?
+ }
+ };
let filter = has_end_time.not().and(has_one_of_tags(&tags));
rt
.store()
- .get_timetrackings()
- .map_warn_err_str("Getting timetrackings failed")
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
+ .get_timetrackings()?
// Filter all timetrackings for the ones that are not yet ended.
- .filter(|e| filter.filter(e))
+ .filter_ok(|e| filter.filter(e))
// for each of these timetrackings, end them
// for each result, print the backtrace (if any)
- .fold(0, |acc, mut elem| {
- match elem.set_end_datetime(stop_time.clone()) {
- Err(e) => {
- trace_error(&e);
- 1
- }
- Ok(_) => {
- debug!("Setting end time worked: {:?}", elem);
- rt.report_touched(elem.get_location()).unwrap_or_exit();
- acc
- }
- }
+ .and_then_ok(|mut elem| {
+ elem.set_end_datetime(stop_time.clone())?;
+ debug!("Setting end time worked: {:?}", elem);
+ rt.report_touched(elem.get_location()).map_err(Error::from)
})
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/track.rs b/bin/domain/imag-timetrack/src/track.rs
index 0668f3f6..6c97f6cc 100644
--- a/bin/domain/imag-timetrack/src/track.rs
+++ b/bin/domain/imag-timetrack/src/track.rs
@@ -17,79 +17,49 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
-use std::process::exit;
-
use clap::ArgMatches;
use chrono::naive::NaiveDate;
use chrono::naive::NaiveDateTime;
use failure::Error;
+use failure::Fallible as Result;
+use failure::err_msg;
use libimagrt::runtime::Runtime;
-use libimagerror::trace::trace_error;
-use libimagerror::exit::ExitUnwrap;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::store::TimeTrackStore;
const DATE_TIME_PARSE_FMT : &str = "%Y-%m-%dT%H:%M:%S";
const DATE_PARSE_FMT : &str = "%Y-%m-%d";
-pub fn track(rt: &Runtime) -> i32 {
+pub fn track(rt: &Runtime) -> Result<()> {
let (_, cmd) = rt.cli().subcommand();
let cmd = cmd.unwrap(); // checked in main()
// Gets the appropriate time from the commandline or None on error (errors already logged, so
// callee can directly return in case of error
- fn get_time(cmd: &ArgMatches, clap_name: &str, errname: &str) -> Option<NaiveDateTime> {
+ fn get_time(cmd: &ArgMatches, clap_name: &str) -> Result<Option<NaiveDateTime>> {
match cmd.value_of(clap_name) {
- Some("now") => Some(::chrono::offset::Local::now().naive_local()),
- Some(els) => {
- match NaiveDateTime::parse_from_str(els, DATE_TIME_PARSE_FMT).map_err(Error::from) {
- Ok(ndt) => Some(ndt),
- Err(e_ndt) => {
- match NaiveDate::parse_from_str(els, DATE_PARSE_FMT).map_err(Error::from) {
- Ok(ndt) => Some(ndt.and_hms(0, 0, 0)),
- Err(e_nd) => {
- error!("Cannot parse date {}:", errname);
- trace_error(&e_nd);
-
- error!("Cannot parse date-time {}:", errname);
- trace_error(&e_ndt);
- exit(1)
- }
- }
- }
- }
- }
- None => {
- error!("Not specified in commandline: {}", clap_name);
- exit(1)
+ None => bail!("Not specified in commandline: {}", clap_name),
+ Some("now") => Ok(Some(::chrono::offset::Local::now().naive_local())),
+ Some(els) => match NaiveDateTime::parse_from_str(els, DATE_TIME_PARSE_FMT) {
+ Ok(ndt) => Ok(Some(ndt)),
+ Err(_) => Ok(Some(NaiveDate::parse_from_str(els, DATE_PARSE_FMT)?.and_hms(0, 0, 0))),
}
}
}
- let start = match get_time(&cmd, "start-time", "start") {
- Some(t) => t,
- None => return 1,
- };
-
- let stop = match get_time(&cmd, "end-time", "stop") {
- Some(t) => t,
- None => return 1,
- };
+ let start = get_time(&cmd, "start-time")?.ok_or_else(|| err_msg("No start-time"))?;
+ let stop = get_time(&cmd, "end-time")?.ok_or_else(|| err_msg("No end-time"))?;
cmd.values_of("tags")
.unwrap() // enforced by clap
.map(String::from)
.map(TimeTrackingTag::from)
- .fold(0, |acc, ttt| match rt.store().create_timetracking(&start, &stop, &ttt) {
- Err(e) => {
- trace_error(&e);
- 1
- },
- Ok(entry) => {
- rt.report_touched(entry.get_location()).unwrap_or_exit();
- acc
- }
+ .map(|ttt| {
+ let entry = rt.store().create_timetracking(&start, &stop, &ttt)?;
+ rt.report_touched(entry.get_location()).map_err(Error::from)
})
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/week.rs b/bin/domain/imag-timetrack/src/week.rs
index fe9a4d4d..f3ec56a8 100644
--- a/bin/domain/imag-timetrack/src/week.rs
+++ b/bin/domain/imag-timetrack/src/week.rs
@@ -23,21 +23,19 @@ use std::str::FromStr;
use filters::filter::Filter;
use chrono::NaiveDateTime;
use failure::Error;
+use failure::Fallible as Result;
+use resiter::AndThen;
+use resiter::Filter as RFilter;
-use libimagerror::trace::trace_error;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::io::ToExitCode;
-use libimagerror::exit::ExitUnwrap;
use libimagstore::store::FileLockEntry;
use libimagtimetrack::store::TimeTrackStore;
-use libimagtimetrack::timetracking::TimeTracking;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::iter::filter::*;
+use libimagtimetrack::timetracking::TimeTracking;
use libimagrt::runtime::Runtime;
-pub fn week(rt: &Runtime) -> i32 {
+pub fn week(rt: &Runtime) -> Result<()> {
let cmd = rt.cli().subcommand().1.unwrap(); // checked in main
let filter = {
@@ -48,35 +46,21 @@ pub fn week(rt: &Runtime) -> i32 {
let this_week = Local::now().iso_week();
- let start = match cmd
- .value_of("start")
- .map(|s| {
- ::chrono::naive::NaiveDateTime::from_str(s).map_err(Error::from)
- })
- {
- None => NaiveDate::from_isoywd(this_week.year(), this_week.week(), Weekday::Mon)
- .and_hms(0, 0, 0),
- Some(Ok(dt)) => dt,
- Some(Err(e)) => {
- trace_error(&e);
- return 1
- }
- };
-
- let end = match cmd
- .value_of("end")
- .map(|s| {
- ::chrono::naive::NaiveDateTime::from_str(s).map_err(Error::from)
- })
- {
- None => NaiveDate::from_isoywd(this_week.year(), this_week.week(), Weekday::Sun)
- .and_hms(23, 59, 59),
- Some(Ok(dt)) => dt,
- Some(Err(e)) => {
- trace_error(&e);
- return 1
- }
- };
+ let start = match cmd.value_of("start") {
+ Some(s) => ::chrono::naive::NaiveDateTime::from_str(s).map_err(Error::from),
+ None => Ok({
+ NaiveDate::from_isoywd(this_week.year(), this_week.week(), Weekday::Mon)
+ .and_hms(0, 0, 0)
+ }),
+ }?;
+
+ let end = match cmd.value_of("end") {
+ Some(s) => ::chrono::naive::NaiveDateTime::from_str(s).map_err(Error::from),
+ None => Ok({
+ NaiveDate::from_isoywd(this_week.year(), this_week.week(), Weekday::Sun)
+ .and_hms(23, 59, 59)
+ }),
+ }?;
let tags = cmd
.values_of("tags")
@@ -101,11 +85,9 @@ pub fn week(rt: &Runtime) -> i32 {
};
rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| filter.filter(e))
- .map(|e| -> Result<_, Error> {
+ .get_timetrackings()?
+ .filter_ok(|e| filter.filter(e))
+ .and_then_ok(|e| -> Result<_> {
debug!("Processing {:?}", e.get_location());
let tag = e.get_timetrack_tag()?;
@@ -117,21 +99,17 @@ pub fn week(rt: &Runtime) -> i32 {
let end = e.get_end_datetime()?;
debug!(" -> end = {:?}", end);
- rt.report_touched(e.get_location()).unwrap_or_exit();
-
+ rt.report_touched(e.get_location())?;
Ok((tag, start, end))
})
- .trace_unwrap_exit()
- .map(|(tag, start, end)| {
+ .and_then_ok(|(tag, start, end)| {
match (start, end) {
(None, _) => writeln!(rt.stdout(), "{} has no start time.", tag),
(Some(s), None) => writeln!(rt.stdout(), "{} | {} - ...", tag, s),
(Some(s), Some(e)) => writeln!(rt.stdout(), "{} | {} - {}", tag, s, e),
- }
- .to_exit_code()
+ }.map_err(Error::from)
})
- .collect::<Result<Vec<()>, _>>()
- .map(|_| 0)
- .unwrap_or_else(|e| e.code())
+ .collect::<Result<Vec<_>>>()
+ .map(|_| ())
}
diff --git a/bin/domain/imag-timetrack/src/year.rs b/bin/domain/imag-timetrack/src/year.rs
index d1efaf93..d862a9c3 100644
--- a/bin/domain/imag-timetrack/src/year.rs
+++ b/bin/domain/imag-timetrack/src/year.rs
@@ -23,21 +23,19 @@ use std::str::FromStr;
use filters::filter::Filter;
use chrono::NaiveDateTime;
use failure::Error;
+use failure::Fallible as Result;
+use resiter::AndThen;
+use resiter::Filter as RFilter;
-use libimagerror::trace::trace_error;
-use libimagerror::trace::MapErrTrace;
-use libimagerror::iter::TraceIterator;
-use libimagerror::io::ToExitCode;
-use libimagerror::exit::ExitUnwrap;
use libimagstore::store::FileLockEntry;
use libimagtimetrack::store::TimeTrackStore;
-use libimagtimetrack::timetracking::TimeTracking;
use libimagtimetrack::tag::TimeTrackingTag;
use libimagtimetrack::iter::filter::*;
+use libimagtimetrack::timetracking::TimeTracking;
use libimagrt::runtime::Runtime;
-pub fn year(rt: &Runtime) -> i32 {
+pub fn year(rt: &Runtime) -> Result<()> {
let cmd = rt.cli().subcommand().1.unwrap(); // checked in main
let filter = {
@@ -47,35 +45,15 @@ pub fn year(rt: &Runtime) -> i32 {
let now = Local::now();
- let start = match cmd
- .value_of("start")
- .map(|s| {
- ::chrono::naive::NaiveDateTime::from_str(s).map_err(Error::from)
- })
- {
- None => NaiveDate::from_ymd(now.year(), 1, 1).and_hms(0, 0, 0),
- Some(Ok(dt)) => dt,
- Some(Err(e)) => {
- trace_error(&e);
- return 1
- }
- };
+ let start = match cmd.value_of("start") {
+ Some(s) => ::chrono::naive::NaiveDateTime::from_str(s),
+ None => Ok(NaiveDate::from_ymd(now.year(), 1, 1).and_hms(0, 0, 0)),
+ }?;
- let end = match cmd
- .value_of("end")
- .map(|s| {
- ::chrono::naive::NaiveDateTime::from_str(s).map_err(Error::from)
- })
- {
- None => {
- NaiveDate::from_ymd(now.year() + 1, 1, 1).and_hms(0, 0, 0)
- },
- Some(Ok(dt)) => dt,
- Some(Err(e)) => {
- trace_error(&e);
- return 1
- }
- };
+ let end = match cmd.value_of("end") {
+ Some(s) => ::chrono::naive::NaiveDateTime::from_str(s),
+ None => Ok(NaiveDate::from_ymd(now.year() + 1, 1, 1).and_hms(0, 0, 0)),
+ }?;
let tags = cmd
.values_of("tags")
@@ -101,11 +79,9 @@ pub fn year(rt: &Runtime) -> i32 {
let mut out = rt.stdout();
rt.store()
- .get_timetrackings()
- .map_err_trace_exit_unwrap()
- .trace_unwrap()
- .filter(|e| filter.filter(e))
- .map(|e| -> Result<_, Error> {
+ .get_timetrackings()?
+ .filter_ok(|e| filter.filter(e))
+ .and_then_ok(|e| -> Result<_> {
debug!("Processing {:?}", e.get_location());
let tag = e.get_timetrack_tag()?;
@@ -117,21 +93,18 @@ pub fn year(rt: &Runtime) -> i32 {
let end = e.get_end_datetime()?;
debug!(" -> end = {:?}", end);
- rt.report_touched(e.get_location()).unwrap_or_exit();
+ rt.report_touched(e.get_location())?;
Ok((tag, start, end))
})
- .trace_unwrap_exit()
- .map(|(tag, start, end)| {
+ .and_then_ok(|(tag, start, end)| {
match (start, end) {
(None, _) => writeln!(out, "{} has no start time.", tag),
(Some(s), None) => writeln!(out, "{} | {} - ...", tag, s),
(Some(s), Some(e)) => writeln!(out, "{} | {} - {}", tag, s, e),
- }
- .to_exit_code()
+ }.map_err(Error::from)
})
- .collect::<Result<Vec<()>, _>>()
- .map(|_| 0)
- .unwrap_or_else(|e| e.code())
+ .collect::<Result<Vec<()>>>()
+ .map(|_| ())
}