diff --git a/src/main.rs b/src/main.rs index 44937ef..5a18e06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -164,14 +164,32 @@ async fn repl() { if !slice.is_empty() { pos = EventId::parse(slice).ok().or_else(|| { tasks.move_to(pos); - let task = tasks.make_task(slice); - let ret = Some(task.id); - tasks.add_task(task); - ret + let filtered: Vec = tasks.current_tasks().iter().filter(|t| t.event.content.starts_with(slice)).map(|t| t.event.id).collect(); + match filtered.len() { + 0 => { + // 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); } _ => { diff --git a/src/tasks.rs b/src/tasks.rs index dc76b28..3749cc6 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -5,9 +5,14 @@ use std::collections::HashMap; type TaskMap = HashMap; pub(crate) struct Tasks { + /// The Tasks pub(crate) tasks: TaskMap, + /// The task properties currently visible pub(crate) properties: Vec, + /// The task currently selected. position: Option, + /// A filtered view of the current tasks + view: Vec, } impl Default for Tasks { @@ -16,6 +21,7 @@ impl Default for Tasks { tasks: Default::default(), properties: vec!["id".into(), "name".into(), "state".into()], position: None, + view: Default::default(), } } } @@ -24,7 +30,47 @@ impl Tasks { pub(crate) fn get_position(&self) -> Option { self.position } + + fn collect_tasks(&self, tasks: &Vec) -> Vec<&Task> { + tasks.iter().filter_map(|id| self.tasks.get(id)).collect() + } + + pub(crate) fn set_filter(&mut self, view: Vec) { + 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::>() + .join(" ") + ); + } + println!(); + } + pub(crate) fn make_task(&self, input: &str) -> Event { let mut tags: Vec = Vec::new(); self.position.inspect(|p| tags.push(Tag::event(*p))); @@ -57,35 +103,6 @@ impl Tasks { 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::>() - .join(" ") - ); - } - println!(); - } - pub(crate) fn move_up(&mut self) { self.move_to( self.position @@ -95,6 +112,7 @@ impl Tasks { } pub(crate) fn move_to(&mut self, id: Option) { + self.view.clear(); if id == self.position { return; }