From adcd35967f9a7bc542b099297273ca0d172b2ad2 Mon Sep 17 00:00:00 2001 From: xeruf <27jf@pm.me> Date: Mon, 18 Nov 2024 14:43:49 +0100 Subject: [PATCH] refactor: reformat tasks file --- src/kinds.rs | 14 ++-- src/tasks.rs | 179 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 125 insertions(+), 68 deletions(-) diff --git a/src/kinds.rs b/src/kinds.rs index d9eea88..0f8597d 100644 --- a/src/kinds.rs +++ b/src/kinds.rs @@ -62,7 +62,7 @@ pub struct EventTag { pub(crate) fn match_event_tag(tag: &Tag) -> Option { let mut vec = tag.as_slice().into_iter(); if vec.next() == Some(&"e".to_string()) { - if let Some(id) = vec.next().and_then(|v| EventId::parse(v).ok()) { + if let Some(id) = vec.next().and_then(|v| EventId::parse(v).ok()) { vec.next(); return Some(EventTag { id, marker: vec.next().cloned() }); } @@ -107,15 +107,15 @@ pub(crate) fn extract_tags(input: &str) -> (String, Vec) { if s.starts_with('*') { if s.len() == 1 { prio = Some(HIGH_PRIO); - return false + return false; } return match s[1..].parse::() { Ok(num) => { prio = Some(num * (if s.len() > 2 { 1 } else { 10 })); false - }, + } _ => true, - } + }; } true }).collect_vec(); @@ -136,9 +136,9 @@ pub fn to_hashtag(tag: &str) -> Tag { fn format_tag(tag: &Tag) -> String { if let Some(et) = match_event_tag(tag) { - return format!("{}: {:.8}", - et.marker.as_ref().map(|m| m.to_string()).unwrap_or(MARKER_PARENT.to_string()), - et.id) + return format!("{}: {:.8}", + et.marker.as_ref().map(|m| m.to_string()).unwrap_or(MARKER_PARENT.to_string()), + et.id); } match tag.as_standardized() { Some(TagStandard::PublicKey { diff --git a/src/tasks.rs b/src/tasks.rs index e1eea51..a0901a8 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -197,7 +197,10 @@ impl TasksRelay { } } if elements > 0 { - info!("Reprocessed {elements} updates with {issues} issues{}", self.sender.url.clone().map(|url| format!(" from {url}")).unwrap_or_default()); + info!( + "Reprocessed {elements} updates with {issues} issues{}", + self.sender.url.as_ref().map(|url| format!(" from {url}")).unwrap_or_default() + ); } } @@ -269,14 +272,24 @@ impl TasksRelay { if new != last { // TODO omit intervals <2min - but I think I need threeway for that // TODO alternate color with grey between days - full.push(format!("{} {}", format_timestamp_local(&event.created_at), new.as_ref().unwrap_or(&"---".to_string()))); + full.push(format!( + "{} {}", + format_timestamp_local(&event.created_at), + new.as_ref().unwrap_or(&"---".to_string()) + )); last = new; } } // TODO show history for active tags - ("Your Time-Tracking History:".to_string(), Box::from(full.into_iter())) + ( + "Your Time-Tracking History:".to_string(), + Box::from(full.into_iter()), + ) } else { - ("You have nothing time-tracked yet".to_string(), Box::from(empty())) + ( + "You have nothing time-tracked yet".to_string(), + Box::from(empty()), + ) } } Some(id) => { @@ -289,15 +302,21 @@ impl TasksRelay { while let Some(((start, _), (end, _))) = iter.next() { // Filter out intervals <2 mins if start.as_u64() + 120 < end.as_u64() { - vec.push(format!("{} - {} by {}", - format_timestamp_local(start), - format_timestamp_relative_to(end, start), - self.get_username(key))) + vec.push(format!( + "{} - {} by {}", + format_timestamp_local(start), + format_timestamp_relative_to(end, start), + self.get_username(key) + )) } } - iter.into_buffer() - .for_each(|(stamp, _)| - vec.push(format!("{} started by {}", format_timestamp_local(stamp), self.get_username(key)))); + iter.into_buffer().for_each(|(stamp, _)| { + vec.push(format!( + "{} started by {}", + format_timestamp_local(stamp), + self.get_username(key) + )) + }); vec }).sorted_unstable(); // TODO sorting depends on timestamp format - needed to interleave different people ( @@ -321,7 +340,9 @@ impl TasksRelay { let children = ChildIterator::from(&self, id).get_all(); for user in self.history.values() { - total += Durations::from(user.values(), &children).sum::().as_secs(); + total += Durations::from(user.values(), &children) + .sum::() + .as_secs(); } total } @@ -340,13 +361,7 @@ impl TasksRelay { sum += prog; count += 1; } - Some( - if count > 0 { - sum / (count as f32) - } else { - 0.0 - } - ) + Some(if count > 0 { sum / (count as f32) } else { 0.0 }) } }) } @@ -421,7 +436,8 @@ impl TasksRelay { } } if new_depth > 0 { - let mut children = self.resolve_tasks_rec(self.tasks.children_of(&task), sparse, new_depth); + let mut children = + self.resolve_tasks_rec(self.tasks.children_of(&task), sparse, new_depth); if !children.is_empty() { if !sparse { children.push(task); @@ -430,7 +446,8 @@ impl TasksRelay { } } return if self.filter(task) { vec![task] } else { vec![] }; - }).collect_vec() + }) + .collect_vec() } /// Executes the given function with each task referenced by this event with no or property marker. @@ -477,7 +494,8 @@ impl TasksRelay { sparse: bool, ) -> Vec<&Task> { let roots = self.tasks.children_for(position); - let mut current = self.resolve_tasks_rec(roots, sparse, self.search_depth + self.view_depth); + let mut current = + self.resolve_tasks_rec(roots, sparse, self.search_depth + self.view_depth); if current.is_empty() { if !self.tags.is_empty() { let mut children = self.tasks.children_for(position).peekable(); @@ -512,6 +530,7 @@ impl TasksRelay { } // TODO this is a relict for tests + #[deprecated] fn visible_tasks(&self) -> Vec<&Task> { if self.search_depth == 0 { return vec![]; @@ -546,8 +565,15 @@ impl TasksRelay { } } "state" => { - if let Some(task) = task.get_dependendees().iter().filter_map(|id| self.get_by_id(id)).find(|t| t.pure_state().is_open()) { - return format!("Blocked by \"{}\"", task.get_title()).bright_red().to_string(); + if let Some(task) = task + .get_dependendees() + .iter() + .filter_map(|id| self.get_by_id(id)) + .find(|t| t.pure_state().is_open()) + { + return format!("Blocked by \"{}\"", task.get_title()) + .bright_red() + .to_string(); } let state = task.pure_state(); if state.is_open() && progress.is_some_and(|p| p > 0.1) { @@ -559,11 +585,16 @@ impl TasksRelay { "progress" => prog_string.clone(), "author" | "creator" => format!("{:.6}", self.get_username(&task.event.pubkey)), // FIXME temporary until proper column alignment - "prio" => self.traverse_up_from(Some(*task.get_id())).find_map(Task::priority_raw).map(|p| p.to_string()).unwrap_or_else(|| - if self.priority.is_some() { - DEFAULT_PRIO.to_string().dimmed().to_string() - } else { - "".to_string() + "prio" => self + .traverse_up_from(Some(task.event.id)) + .find_map(Task::priority_raw) + .map(|p| p.to_string()) + .unwrap_or_else(|| { + if self.priority.is_some() { + DEFAULT_PRIO.to_string().dimmed().to_string() + } else { + "".to_string() + } }), "path" => self.get_task_path(Some(task.event.id)), "rpath" => self.relative_path(task.event.id), @@ -602,9 +633,11 @@ impl TasksRelay { false } }; - self.sender.submit( - EventBuilder::new(Kind::Bookmarks, "mostr pins", - self.bookmarks.iter().map(|id| Tag::event(*id))))?; + self.sender.submit(EventBuilder::new( + Kind::Bookmarks, + "mostr pins", + self.bookmarks.iter().map(|id| Tag::event(*id)), + ))?; Ok(added) } @@ -664,7 +697,10 @@ impl TasksRelay { } pub(crate) fn print_hashtags(&self) { - println!("Hashtags of all known tasks:\n{}", self.all_hashtags().join(" ").italic()); + println!( + "Hashtags of all known tasks:\n{}", + self.all_hashtags().join(" ").italic() + ); } /// Returns true if tags have been updated, false if it printed something @@ -698,7 +734,9 @@ impl TasksRelay { pub(crate) fn remove_tag(&mut self, tag: &str) { self.view.clear(); let len = self.tags.len(); - self.tags.retain(|t| !t.content().is_some_and(|value| value.to_string().starts_with(tag))); + self.tags.retain(|t| { + !t.content().is_some_and(|value| value.to_string().starts_with(tag)) + }); if self.tags.len() < len { info!("Removed tag filters starting with {tag}"); } else { @@ -762,7 +800,8 @@ impl TasksRelay { for task in self.tasks.values() { if task.get_filter_title().to_ascii_lowercase() == lowercase_arg && // exclude closed tasks and their subtasks - !self.traverse_up_from(Some(*task.get_id())).any(|t| !t.pure_state().is_open()) { + !self.traverse_up_from(Some(*task.get_id())).any(|t| !t.pure_state().is_open()) + { return vec![task.event.id]; } } @@ -815,9 +854,10 @@ impl TasksRelay { /// Returns all recent events from history until the first event at or before the given timestamp. fn history_from(&self, stamp: Timestamp) -> impl Iterator { - self.history.get(&self.sender.pubkey()).map(|hist| { - hist.values().rev().take_while_inclusive(move |e| e.created_at > stamp) - }).into_iter().flatten() + self.history.get(&self.sender.pubkey()) + .map(|hist| { + hist.values().rev().take_while_inclusive(move |e| e.created_at > stamp) + }).into_iter().flatten() } pub(crate) fn move_to(&mut self, target: Option) { @@ -838,13 +878,16 @@ impl TasksRelay { } let now = Timestamp::now(); - let offset: u64 = self.history_from(now).skip_while(|e| e.created_at.as_u64() > now.as_u64() + MAX_OFFSET).count() as u64; + let offset: u64 = self + .history_from(now) + .skip_while(|e| e.created_at.as_u64() > now.as_u64() + MAX_OFFSET) + .count() as u64; if offset >= MAX_OFFSET { warn!("Whoa you are moving around quickly! Give me a few seconds to process.") } self.submit( build_tracking(target) - .custom_created_at(Timestamp::from(now.as_u64() + offset)) + .custom_created_at(Timestamp::from(now.as_u64() + offset)), ); } @@ -913,9 +956,12 @@ impl TasksRelay { self.move_up(); self.make_task_with( input, - self.get_position().map(|par| self.make_event_tag_from_id(par, MARKER_PARENT)) - .into_iter().chain(once(self.make_event_tag_from_id(pos, MARKER_DEPENDS))), - true); + self.get_position() + .map(|par| self.make_event_tag_from_id(par, MARKER_PARENT)) + .into_iter() + .chain(once(self.make_event_tag_from_id(pos, MARKER_DEPENDS))), + true, + ); return true; } false @@ -944,7 +990,7 @@ impl TasksRelay { } pub(crate) fn get_task_title(&self, id: &EventId) -> String { - self.tasks.get(id).map_or(id.to_string(), |t| t.get_title()) + self.get_by_id(id).map_or(id.to_string(), |t| t.get_title()) } /// Parse relative time string and track for current position @@ -956,7 +1002,11 @@ impl TasksRelay { .is_some() } - pub(crate) fn track_at(&mut self, mut time: Timestamp, target: Option) -> Option { + pub(crate) fn track_at( + &mut self, + mut time: Timestamp, + target: Option, + ) -> Option { if target.is_none() { // Prevent random overlap with tracking started in the same second time = time - 1; @@ -1012,11 +1062,10 @@ impl TasksRelay { pub(crate) fn add(&mut self, event: Event) { match event.kind { Kind::GitIssue => self.add_task(event), - Kind::Metadata => - match Metadata::from_json(event.content.as_str()) { - Ok(metadata) => { self.users.insert(event.pubkey, metadata); } - Err(e) => warn!("Cannot parse metadata: {} from {:?}", e, event) - } + Kind::Metadata => match Metadata::from_json(event.content.as_str()) { + Ok(metadata) => { self.users.insert(event.pubkey, metadata); } + Err(e) => warn!("Cannot parse metadata: {} from {:?}", e, event), + }, Kind::Bookmarks => { if event.pubkey == self.sender.pubkey() { self.bookmarks = referenced_events(&event).collect_vec() @@ -1073,7 +1122,9 @@ impl TasksRelay { } fn get_own_events_history(&self) -> impl DoubleEndedIterator + '_ { - self.history.get(&self.sender.pubkey()).into_iter().flat_map(|t| t.values()) + self.history.get(&self.sender.pubkey()) + .into_iter() + .flat_map(|t| t.values()) } fn history_before_now(&self) -> impl Iterator { @@ -1098,7 +1149,9 @@ impl TasksRelay { } pub(crate) fn move_back_by(&mut self, steps: usize) { - let id = self.history_before_now().nth(steps) + let id = self + .history_before_now() + .nth(steps) .and_then(|e| referenced_event(e)); self.move_to(id) } @@ -1336,7 +1389,10 @@ impl Display for TasksRelay { total_time += self.total_time_tracked(task.event.id) // TODO include parent if it matches } - writeln!(lock, "{} visible tasks{}", count, display_time(" tracked a total of HHhMMm", total_time))?; + writeln!(lock, + "{count} visible tasks{}", + display_time(" tracked a total of HHhMMm", total_time) + )?; Ok(()) } } @@ -1389,7 +1445,7 @@ fn display_time(format: &str, secs: u64) -> String { .map_or(String::new(), |mins| format .replace("MMM", &format!("{:3}", mins)) .replace("HH", &format!("{:02}", mins.div(60))) - .replace("MM", &format!("{:02}", mins.rem(60))), + .replace("MM", &format!("{:02}", mins.rem(60))) ) } @@ -1402,8 +1458,7 @@ pub(crate) fn join_tasks<'a>( .iter() .map(|t| t.get_title()) .chain(if include_last_id { - tasks - .last() + tasks.last() .and_then(|t| t.parent_id()) .map(|id| id.to_string()) .into_iter() @@ -1411,7 +1466,10 @@ pub(crate) fn join_tasks<'a>( None.into_iter() }) .fold(None, |acc, val| { - Some(acc.map_or_else(|| val.clone(), |cur| format!("{}{}{}", val, ">".dimmed(), cur))) + Some(acc.map_or_else( + || val.clone(), + |cur| format!("{}{}{}", val, ">".dimmed(), cur), + )) }) } @@ -1477,7 +1535,8 @@ impl Iterator for Durations<'_> { } } let now = self.threshold.unwrap_or(Timestamp::now()).as_u64(); - start.filter(|t| t < &now).map(|stamp| Duration::from_secs(now.saturating_sub(stamp))) + start.filter(|t| t < &now) + .map(|stamp| Duration::from_secs(now.saturating_sub(stamp))) } } @@ -1635,7 +1694,6 @@ impl<'a> Iterator for ChildIterator<'a> { } } - struct ParentIterator<'a> { tasks: &'a TaskMap, current: Option, @@ -1653,9 +1711,8 @@ impl<'a> Iterator for ParentIterator<'a> { #[cfg(test)] mod tasks_test { - use std::collections::HashSet; - use super::*; + use std::collections::HashSet; fn stub_tasks() -> TasksRelay { use nostr_sdk::Keys;