feat: intuitive name navigation and filtering

This commit is contained in:
xeruf 2024-07-19 09:35:03 +03:00
parent 04ff65737a
commit 44ea79bc81
2 changed files with 70 additions and 34 deletions

View File

@ -164,14 +164,32 @@ async fn repl() {
if !slice.is_empty() { if !slice.is_empty() {
pos = EventId::parse(slice).ok().or_else(|| { pos = EventId::parse(slice).ok().or_else(|| {
tasks.move_to(pos); tasks.move_to(pos);
let task = tasks.make_task(slice); let filtered: Vec<EventId> = tasks.current_tasks().iter().filter(|t| t.event.content.starts_with(slice)).map(|t| t.event.id).collect();
let ret = Some(task.id); match filtered.len() {
tasks.add_task(task); 0 => {
ret // No match, new task
let task = tasks.make_task(slice);
let ret = Some(task.id);
tasks.add_task(task);
ret
}
1 => {
// One match, select
Some(filtered.first().unwrap().clone())
}
_ => {
// Multiple match, filter
tasks.set_filter(filtered);
None
}
}
}); });
if pos != None {
tasks.move_to(pos);
}
} else {
tasks.move_to(pos); tasks.move_to(pos);
} }
tasks.move_to(pos);
} }
_ => { _ => {

View File

@ -5,9 +5,14 @@ use std::collections::HashMap;
type TaskMap = HashMap<EventId, Task>; type TaskMap = HashMap<EventId, Task>;
pub(crate) struct Tasks { pub(crate) struct Tasks {
/// The Tasks
pub(crate) tasks: TaskMap, pub(crate) tasks: TaskMap,
/// The task properties currently visible
pub(crate) properties: Vec<String>, pub(crate) properties: Vec<String>,
/// The task currently selected.
position: Option<EventId>, position: Option<EventId>,
/// A filtered view of the current tasks
view: Vec<EventId>,
} }
impl Default for Tasks { impl Default for Tasks {
@ -16,6 +21,7 @@ impl Default for Tasks {
tasks: Default::default(), tasks: Default::default(),
properties: vec!["id".into(), "name".into(), "state".into()], properties: vec!["id".into(), "name".into(), "state".into()],
position: None, position: None,
view: Default::default(),
} }
} }
} }
@ -24,7 +30,47 @@ impl Tasks {
pub(crate) fn get_position(&self) -> Option<EventId> { pub(crate) fn get_position(&self) -> Option<EventId> {
self.position self.position
} }
fn collect_tasks(&self, tasks: &Vec<EventId>) -> Vec<&Task> {
tasks.iter().filter_map(|id| self.tasks.get(id)).collect()
}
pub(crate) fn set_filter(&mut self, view: Vec<EventId>) {
self.view = view
}
pub(crate) fn current_tasks(&self) -> Vec<&Task> {
let res = self.collect_tasks(&self.view);
if res.len() > 0 {
return res;
}
self.position.map_or_else(
|| self.tasks.values().collect(),
|p| {
self.tasks.get(&p).map_or(Vec::new(), |t| {
self.collect_tasks(&t.children)
})
})
}
pub(crate) fn print_current_tasks(&self) {
println!("{}", self.properties.join(" "));
for task in self.current_tasks() {
println!(
"{}",
self.properties
.iter()
.map(|p| match p.as_str() {
"path" => self.taskpath(Some(task.event.id)),
prop => task.get(prop).unwrap_or(String::new()),
})
.collect::<Vec<String>>()
.join(" ")
);
}
println!();
}
pub(crate) fn make_task(&self, input: &str) -> Event { pub(crate) fn make_task(&self, input: &str) -> Event {
let mut tags: Vec<Tag> = Vec::new(); let mut tags: Vec<Tag> = Vec::new();
self.position.inspect(|p| tags.push(Tag::event(*p))); self.position.inspect(|p| tags.push(Tag::event(*p)));
@ -57,35 +103,6 @@ impl Tasks {
self.tasks.insert(event.id, Task::new(event)); self.tasks.insert(event.id, Task::new(event));
} }
pub(crate) fn current_tasks(&self) -> Vec<&Task> {
self.position.map_or(self.tasks.values().collect(), |p| {
self.tasks.get(&p).map_or(Vec::new(), |t| {
t.children
.iter()
.filter_map(|id| self.tasks.get(id))
.collect()
})
})
}
pub(crate) fn print_current_tasks(&self) {
println!("{}", self.properties.join(" "));
for task in self.current_tasks() {
println!(
"{}",
self.properties
.iter()
.map(|p| match p.as_str() {
"path" => self.taskpath(Some(task.event.id)),
prop => task.get(prop).unwrap_or(String::new()),
})
.collect::<Vec<String>>()
.join(" ")
);
}
println!();
}
pub(crate) fn move_up(&mut self) { pub(crate) fn move_up(&mut self) {
self.move_to( self.move_to(
self.position self.position
@ -95,6 +112,7 @@ impl Tasks {
} }
pub(crate) fn move_to(&mut self, id: Option<EventId>) { pub(crate) fn move_to(&mut self, id: Option<EventId>) {
self.view.clear();
if id == self.position { if id == self.position {
return; return;
} }