diff --git a/Cargo.toml b/Cargo.toml index 8473af5..fe3ae71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,8 @@ edition = "2018" tui = "0.8.0" termion = "1.5" serde_json = "1" -itertools = "0.9" +itertools = "0.9.0" serde = { version = "1", features = ["derive"] } time = { version = "0.2.9", features = ["serde"] } -#cmd_lib = "0.7.8" +regex = "1.3.7" +lazy_static = "1.4.0" diff --git a/src/main.rs b/src/main.rs index 8bfe647..2ea43ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,8 @@ mod timesheet; mod todolist; mod tracc; use tracc::Tracc; +#[macro_use] +extern crate lazy_static; fn main() -> Result<(), io::Error> { let stdout = io::stdout().into_raw_mode()?; diff --git a/src/timesheet.rs b/src/timesheet.rs index 425ff62..505131a 100644 --- a/src/timesheet.rs +++ b/src/timesheet.rs @@ -13,6 +13,9 @@ pub struct TimeSheet { } const PAUSE_TEXTS: [&str; 3] = ["lunch", "mittag", "pause"]; +lazy_static! { + static ref OVERRIDE_REGEX: regex::Regex = regex::Regex::new("\\[(.*)\\]").unwrap(); +} #[derive(Serialize, Deserialize, Clone, Debug)] pub struct TimePoint { @@ -48,6 +51,20 @@ fn read_times(path: &str) -> Option> { .and_then(|r| from_reader(r).ok()) } +/** + * If a time text contains "[something]", + * only use the message inside the brackets. + */ +fn effective_text(s: String) -> String { + OVERRIDE_REGEX + .captures(&s) + // index 0 is the entire string + .and_then(|caps| caps.get(1)) + .map(|m| m.as_str()) + .unwrap_or(&s) + .to_string() +} + impl TimeSheet { pub fn open_or_create(path: &str) -> Self { Self { @@ -76,7 +93,8 @@ impl TimeSheet { // I use a BTreeMap because I need a stable output order for the iterator // (otherwise the summary list will jump around on every input). .fold(collections::BTreeMap::new(), |mut map, (text, duration)| { - *map.entry(text).or_insert_with(Duration::zero) += duration; + *map.entry(effective_text(text)) + .or_insert_with(Duration::zero) += duration; map }) .into_iter()