Compare commits

..

No commits in common. "9f84fd7ef15ed67b92b1b5818a22c896f1f4426c" and "b3d70ab0b7ad2960f2b1290213a2ee29d6ca33b2" have entirely different histories.

3 changed files with 19 additions and 26 deletions

View file

@ -108,9 +108,9 @@ Dots and slashes can be repeated to move to parent tasks.
- `::[PROP]` - Sort by property PROP (multiple space-separated values allowed)
- `([TIME]` - insert timetracking with the specified offset in minutes (empty: list tracked times)
- `)[TIME]` - stop timetracking with the specified offset in minutes - convenience helper to move to root (empty: stop now)
- `>[TEXT]` - complete active task and move up, with optional state description
- `<[TEXT]` - close active task and move up, with optional state description
- `!TEXT` - set state for current task from text and move up
- `>[TEXT]` - complete active task and move to parent, with optional state description
- `<[TEXT]` - close active task and move to parent, with optional state description
- `!TEXT` - set state for current task from text
- `,TEXT` - add text note (comment / description)
- TBI: `*[INT]` - set priority - can also be used in task, with any digit
- `@` - undoes last action (moving in place or upwards or waiting a minute confirms pending actions)

View file

@ -364,7 +364,6 @@ async fn main() {
None => warn!("First select a task to set its state!"),
Some(id) => {
tasks.set_state_for_with(id, arg_default);
tasks.move_up();
}
}

View file

@ -150,25 +150,19 @@ impl Tasks {
#[inline]
pub(crate) fn len(&self) -> usize { self.tasks.len() }
/// Ids of all subtasks recursively found for id, including itself
fn get_task_tree<'a>(&'a self, id: &'a EventId) -> Vec<&'a EventId> {
/// Ids of all subtasks found for id, including itself
fn get_subtasks(&self, id: EventId) -> Vec<EventId> {
let mut children = Vec::with_capacity(32);
let mut index = 0;
children.push(id);
while index < children.len() {
let id = children[index];
if let Some(task) = self.tasks.get(&id) {
children.reserve(task.children.len());
children.extend(task.children.iter());
} else {
// Unknown task, can still find children
for task in self.tasks.values() {
if task.parent_id().is_some_and(|i| i == id) {
children.push(task.get_id());
}
}
self.tasks.get(&children[index]).map(|t| {
children.reserve(t.children.len());
for child in t.children.iter() {
children.push(child.clone());
}
});
index += 1;
}
@ -210,7 +204,7 @@ impl Tasks {
}
}
Some(id) => {
let ids = vec![&id];
let ids = vec![id];
once(format!("Times tracked on {}", self.get_task_title(&id))).chain(
self.history.iter().flat_map(|(key, set)| {
let mut vec = Vec::with_capacity(set.len() / 2);
@ -229,7 +223,7 @@ impl Tasks {
/// Total time in seconds tracked on this task by the current user.
pub(crate) fn time_tracked(&self, id: EventId) -> u64 {
TimesTracked::from(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &vec![&id]).sum::<Duration>().as_secs()
TimesTracked::from(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &vec![id]).sum::<Duration>().as_secs()
}
@ -237,7 +231,7 @@ impl Tasks {
fn total_time_tracked(&self, id: EventId) -> u64 {
let mut total = 0;
let children = self.get_task_tree(&id);
let children = self.get_subtasks(id);
for user in self.history.values() {
total += TimesTracked::from(user, &children).into_iter().sum::<Duration>().as_secs();
}
@ -894,14 +888,14 @@ pub(crate) fn join_tasks<'a>(
})
}
fn matching_tag_id<'a>(event: &'a Event, ids: &'a Vec<&'a EventId>) -> Option<&'a EventId> {
fn matching_tag_id<'a>(event: &'a Event, ids: &'a Vec<EventId>) -> Option<&'a EventId> {
event.tags.iter().find_map(|tag| match tag.as_standardized() {
Some(TagStandard::Event { event_id, .. }) if ids.contains(&event_id) => Some(event_id),
Some(TagStandard::Event { event_id, .. }) if ids.contains(event_id) => Some(event_id),
_ => None
})
}
fn timestamps<'a>(events: impl Iterator<Item=&'a Event>, ids: &'a Vec<&'a EventId>) -> impl Iterator<Item=(&Timestamp, Option<&EventId>)> {
fn timestamps<'a>(events: impl Iterator<Item=&'a Event>, ids: &'a Vec<EventId>) -> impl Iterator<Item=(&Timestamp, Option<&EventId>)> {
events.map(|event| (&event.created_at, matching_tag_id(event, ids)))
.dedup_by(|(_, e1), (_, e2)| e1 == e2)
.skip_while(|element| element.1 == None)
@ -911,11 +905,11 @@ fn timestamps<'a>(events: impl Iterator<Item=&'a Event>, ids: &'a Vec<&'a EventI
/// Expects a sorted iterator
struct TimesTracked<'a> {
events: Box<dyn Iterator<Item=&'a Event> + 'a>,
ids: &'a Vec<&'a EventId>,
ids: &'a Vec<EventId>,
threshold: Option<Timestamp>,
}
impl TimesTracked<'_> {
fn from<'b>(events: impl IntoIterator<Item=&'b Event> + 'b, ids: &'b Vec<&EventId>) -> TimesTracked<'b> {
fn from<'b>(events: impl IntoIterator<Item=&'b Event> + 'b, ids: &'b Vec<EventId>) -> TimesTracked<'b> {
TimesTracked {
events: Box::new(events.into_iter()),
ids,
@ -1012,7 +1006,7 @@ mod tasks_test {
let zero = EventId::all_zeros();
tasks.move_to(Some(zero));
tasks.track_at(Timestamp::from(Timestamp::now().as_u64() + 100));
assert_eq!(timestamps(tasks.history.values().nth(0).unwrap().into_iter(), &vec![&zero]).collect_vec().len(), 2)
assert_eq!(timestamps(tasks.history.values().nth(0).unwrap().into_iter(), &vec![zero]).collect_vec().len(), 2)
// TODO Does not show both future and current tracking properly, need to split by now
}