Compare commits
No commits in common. "8d2cf29b830cc46e89be96e41cc13f9e86f931e4" and "14575813c78b5407015684dec96e0d55d38b4bb9" have entirely different histories.
8d2cf29b83
...
14575813c7
4 changed files with 20 additions and 39 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -681,15 +681,6 @@ version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -774,7 +765,6 @@ dependencies = [
|
||||||
name = "mostr"
|
name = "mostr"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
|
||||||
"nostr-sdk",
|
"nostr-sdk",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
@ -16,4 +16,3 @@ nostr-sdk = "0.30"
|
||||||
tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] }
|
tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] }
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
xdg = "2.5.2"
|
xdg = "2.5.2"
|
||||||
itertools = "0.12.1"
|
|
31
src/task.rs
31
src/task.rs
|
@ -2,8 +2,6 @@ use std::collections::{BTreeSet, HashSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Div;
|
use std::ops::Div;
|
||||||
|
|
||||||
use itertools::Either::{Left, Right};
|
|
||||||
use itertools::Itertools;
|
|
||||||
use nostr_sdk::{Alphabet, Event, EventBuilder, EventId, Kind, Tag, Timestamp};
|
use nostr_sdk::{Alphabet, Event, EventBuilder, EventId, Kind, Tag, Timestamp};
|
||||||
|
|
||||||
use crate::EventSender;
|
use crate::EventSender;
|
||||||
|
@ -15,22 +13,18 @@ pub(crate) struct Task {
|
||||||
pub(crate) props: BTreeSet<Event>,
|
pub(crate) props: BTreeSet<Event>,
|
||||||
/// Cached sorted tags of the event
|
/// Cached sorted tags of the event
|
||||||
pub(crate) tags: Option<BTreeSet<Tag>>,
|
pub(crate) tags: Option<BTreeSet<Tag>>,
|
||||||
parents: Vec<EventId>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Task {
|
impl Task {
|
||||||
pub(crate) fn new(event: Event) -> Task {
|
pub(crate) fn new(event: Event) -> Task {
|
||||||
let (parents, tags) = event.tags.iter().partition_map(|tag| {
|
|
||||||
match tag {
|
|
||||||
Tag::Event { event_id, .. } => return Left(event_id),
|
|
||||||
_ => Right(tag.clone())
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Task {
|
Task {
|
||||||
children: Default::default(),
|
children: Default::default(),
|
||||||
props: Default::default(),
|
props: Default::default(),
|
||||||
tags: Some(tags).filter(|t: &BTreeSet<Tag>| !t.is_empty()),
|
tags: if event.tags.is_empty() {
|
||||||
parents,
|
None
|
||||||
|
} else {
|
||||||
|
Some(event.tags.iter().cloned().collect())
|
||||||
|
},
|
||||||
event,
|
event,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +34,13 @@ impl Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parent_id(&self) -> Option<EventId> {
|
pub(crate) fn parent_id(&self) -> Option<EventId> {
|
||||||
self.parents.first().cloned()
|
for tag in self.event.tags.iter() {
|
||||||
|
match tag {
|
||||||
|
Tag::Event { event_id, .. } => return Some(*event_id),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_title(&self) -> String {
|
pub(crate) fn get_title(&self) -> String {
|
||||||
|
@ -127,8 +127,8 @@ impl Task {
|
||||||
}
|
}
|
||||||
total
|
total
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_tags<P>(&self, predicate: P) -> Option<String>
|
fn filter_tags<P>(&self, predicate: P) -> Option<String>
|
||||||
where P: FnMut(&&Tag) -> bool{
|
where P: FnMut(&&Tag) -> bool{
|
||||||
self.tags.as_ref().map(|tags| {
|
self.tags.as_ref().map(|tags| {
|
||||||
tags.into_iter()
|
tags.into_iter()
|
||||||
|
@ -147,8 +147,7 @@ impl Task {
|
||||||
"name" => Some(self.event.content.clone()),
|
"name" => Some(self.event.content.clone()),
|
||||||
"time" => Some(format!("{}m", self.time_tracked().div(60))),
|
"time" => Some(format!("{}m", self.time_tracked().div(60))),
|
||||||
"hashtags" => self.filter_tags(|tag| tag.single_letter_tag().is_some_and(|sltag| sltag.character == Alphabet::T)),
|
"hashtags" => self.filter_tags(|tag| tag.single_letter_tag().is_some_and(|sltag| sltag.character == Alphabet::T)),
|
||||||
"tags" => self.filter_tags(|_| true),
|
"tags" => self.filter_tags(|tag| !tag.single_letter_tag().is_some_and(|sltag| sltag.character == Alphabet::E)),
|
||||||
"alltags" => Some(format!("{:?}", self.tags)),
|
|
||||||
"props" => Some(format!(
|
"props" => Some(format!(
|
||||||
"{:?}",
|
"{:?}",
|
||||||
self.props
|
self.props
|
||||||
|
|
17
src/tasks.rs
17
src/tasks.rs
|
@ -194,8 +194,7 @@ impl Tasks {
|
||||||
"rpath" => join_tasks(
|
"rpath" => join_tasks(
|
||||||
self.traverse_up_from(Some(task.event.id))
|
self.traverse_up_from(Some(task.event.id))
|
||||||
.take_while(|t| Some(t.event.id) != self.position)
|
.take_while(|t| Some(t.event.id) != self.position)
|
||||||
)
|
).unwrap_or(task.event.id.to_string()),
|
||||||
.unwrap_or(task.event.id.to_string()),
|
|
||||||
"rtime" => {
|
"rtime" => {
|
||||||
let time = self.total_time_tracked(&task.event.id);
|
let time = self.total_time_tracked(&task.event.id);
|
||||||
format!("{:02}:{:02}", time / 3600, time / 60 % 60)
|
format!("{:02}:{:02}", time / 3600, time / 60 % 60)
|
||||||
|
@ -203,7 +202,7 @@ impl Tasks {
|
||||||
prop => task.get(prop).unwrap_or(String::new()),
|
prop => task.get(prop).unwrap_or(String::new()),
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(" \t")
|
.join("\t")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
|
@ -259,22 +258,20 @@ impl Tasks {
|
||||||
|
|
||||||
// Updates
|
// Updates
|
||||||
|
|
||||||
/// Expects sanitized input
|
|
||||||
pub(crate) fn build_task(&self, input: &str) -> EventBuilder {
|
pub(crate) fn build_task(&self, input: &str) -> EventBuilder {
|
||||||
let mut tags: Vec<Tag> = self.tags.iter().cloned().collect();
|
let mut tags: Vec<Tag> = self.tags.iter().cloned().collect();
|
||||||
self.position.inspect(|p| tags.push(Tag::event(*p)));
|
self.position.inspect(|p| tags.push(Tag::event(*p)));
|
||||||
return match input.split_once(": ") {
|
return match input.split_once(": ") {
|
||||||
None => EventBuilder::new(Kind::from(TASK_KIND), input, tags),
|
None => EventBuilder::new(Kind::from(TASK_KIND), input, tags),
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
tags.append(&mut s.1.split_ascii_whitespace().map(|t| Hashtag(t.to_string())).collect());
|
tags.append(&mut s.1.split(" ").map(|t| Hashtag(t.to_string())).collect());
|
||||||
EventBuilder::new(Kind::from(TASK_KIND), s.0, tags)
|
EventBuilder::new(Kind::from(TASK_KIND), s.0, tags)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sanitizes input
|
|
||||||
pub(crate) fn make_task(&mut self, input: &str) -> Option<EventId> {
|
pub(crate) fn make_task(&mut self, input: &str) -> Option<EventId> {
|
||||||
self.sender.submit(self.build_task(input.trim())).map(|e| {
|
self.sender.submit(self.build_task(input)).map(|e| {
|
||||||
let id = e.id;
|
let id = e.id;
|
||||||
self.add_task(e);
|
self.add_task(e);
|
||||||
let state = self.state.clone().unwrap_or("Open".to_string());
|
let state = self.state.clone().unwrap_or("Open".to_string());
|
||||||
|
@ -461,11 +458,7 @@ fn test_depth() {
|
||||||
let empty_id = empty_task.event.id.to_string();
|
let empty_id = empty_task.event.id.to_string();
|
||||||
assert_eq!(empty_task.get_title(), empty_id);
|
assert_eq!(empty_task.get_title(), empty_id);
|
||||||
assert_eq!(tasks.get_task_path(empty), empty_id);
|
assert_eq!(tasks.get_task_path(empty), empty_id);
|
||||||
|
|
||||||
let zero = EventId::all_zeros();
|
let zero = EventId::all_zeros();
|
||||||
assert_eq!(tasks.get_task_path(Some(zero)), zero.to_string());
|
assert_eq!(tasks.get_task_path(Some(zero)), zero.to_string());
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
assert_eq!("test toast".split(' ').collect_vec().len(), 3);
|
|
||||||
assert_eq!("test toast".split_ascii_whitespace().collect_vec().len(), 2);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue