Add tab complete for filter tags

This commit is contained in:
Dheepak Krishnamurthy 2021-04-06 04:32:48 -06:00
parent fad1f37a8c
commit fa6a1370d1
2 changed files with 79 additions and 17 deletions

View file

@ -255,8 +255,8 @@ impl TaskwarriorTuiApp {
terminal_height: h, terminal_height: h,
filter_history_context: HistoryContext::new("filter.history"), filter_history_context: HistoryContext::new("filter.history"),
command_history_context: HistoryContext::new("command.history"), command_history_context: HistoryContext::new("command.history"),
completion_list: CompletionList::with_items(vec!["hello".to_string(), "word".to_string()]), completion_list: CompletionList::with_items(vec![]),
show_completion_pane: true, show_completion_pane: false,
}; };
for c in app.config.filter.chars() { for c in app.config.filter.chars() {
@ -410,9 +410,6 @@ impl TaskwarriorTuiApp {
} }
} }
}; };
if self.show_completion_pane {
self.draw_completion_pop_up(f, rects[1], 0);
}
match self.mode { match self.mode {
AppMode::TaskReport => self.draw_command( AppMode::TaskReport => self.draw_command(
f, f,
@ -425,6 +422,9 @@ impl TaskwarriorTuiApp {
AppMode::TaskFilter => { AppMode::TaskFilter => {
let position = self.get_position(&self.filter); let position = self.get_position(&self.filter);
if self.show_completion_pane {
self.draw_completion_pop_up(f, rects[1], position);
}
self.draw_command( self.draw_command(
f, f,
rects[1], rects[1],
@ -629,16 +629,22 @@ impl TaskwarriorTuiApp {
// Create a List from all list items and highlight the currently selected one // Create a List from all list items and highlight the currently selected one
let items = List::new(items) let items = List::new(items)
.block(Block::default().borders(Borders::NONE).title("")) .block(Block::default().borders(Borders::NONE).title(""))
.style(Style::default().bg(Color::Rgb(223, 223, 223))); .style(Style::default().bg(Color::Rgb(223, 223, 223)))
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
.highlight_symbol(&self.config.uda_selection_indicator);
let area = f.size(); let area = f.size();
let mut rect = rect.clone();
rect.y = rect let mut rect = rect;
.y rect.height = std::cmp::min(area.height / 4, self.completion_list.items.len() as u16 + 5);
.saturating_sub(self.completion_list.items.len() as u16)
.saturating_sub(5);
rect.height = self.completion_list.items.len() as u16 + 5;
rect.width = std::cmp::min(area.width / 4, 20); rect.width = std::cmp::min(area.width / 4, 20);
rect.y = rect.y.saturating_sub(rect.height);
if cursor_position as u16 + rect.width >= area.width {
rect.x = area.width - rect.width;
} else {
rect.x = cursor_position as u16;
}
// We can now render the item list // We can now render the item list
f.render_widget(Clear, rect); f.render_widget(Clear, rect);
f.render_stateful_widget(items, rect, &mut self.completion_list.state); f.render_stateful_widget(items, rect, &mut self.completion_list.state);
@ -1961,6 +1967,7 @@ impl TaskwarriorTuiApp {
self.mode = AppMode::TaskHelpPopup; self.mode = AppMode::TaskHelpPopup;
} else if input == self.keyconfig.filter { } else if input == self.keyconfig.filter {
self.mode = AppMode::TaskFilter; self.mode = AppMode::TaskFilter;
self.update_completion_list();
} else if input == self.keyconfig.shortcut1 { } else if input == self.keyconfig.shortcut1 {
match self.task_shortcut(1) { match self.task_shortcut(1) {
Ok(_) => self.update(true)?, Ok(_) => self.update(true)?,
@ -2237,10 +2244,32 @@ impl TaskwarriorTuiApp {
} }
}, },
AppMode::TaskFilter => match input { AppMode::TaskFilter => match input {
Key::Char('\n') | Key::Esc => { Key::Esc => {
self.mode = AppMode::TaskReport; if self.show_completion_pane {
self.filter_history_context.add(self.filter.as_str()); self.show_completion_pane = false;
self.update(true)?; self.completion_list.unselect();
} else {
self.mode = AppMode::TaskReport;
self.filter_history_context.add(self.filter.as_str());
self.update(true)?;
}
}
Key::Char('\n') => {
if self.show_completion_pane {
self.show_completion_pane = false;
if let Some(i) = self.completion_list.state.selected() {
if i < self.completion_list.items.len() {
let s = format!("{}{}", self.filter.as_str(), &self.completion_list.items[i]);
self.filter.update(&s, s.graphemes(true).count());
}
}
self.completion_list.unselect();
self.dirty = true;
} else {
self.mode = AppMode::TaskReport;
self.filter_history_context.add(self.filter.as_str());
self.update(true)?;
}
} }
Key::Up => { Key::Up => {
if let Some(s) = self if let Some(s) = self
@ -2264,6 +2293,19 @@ impl TaskwarriorTuiApp {
self.dirty = true; self.dirty = true;
} }
} }
Key::Tab => {
if !self.completion_list.items.is_empty() {
if !self.show_completion_pane {
self.show_completion_pane = true;
}
self.completion_list.next();
}
}
Key::BackTab => {
if !self.completion_list.items.is_empty() {
self.completion_list.previous();
}
}
_ => { _ => {
handle_movement(&mut self.filter, input); handle_movement(&mut self.filter, input);
self.dirty = true; self.dirty = true;
@ -2293,6 +2335,25 @@ impl TaskwarriorTuiApp {
self.update_task_table_state(); self.update_task_table_state();
Ok(()) Ok(())
} }
pub fn update_completion_list(&mut self) {
match self.mode {
AppMode::TaskFilter => {
let virtual_tags = self.task_report_table.virtual_tags.clone();
self.completion_list.items.clear();
for task in self.tasks.iter() {
if let Some(tags) = task.tags() {
for tag in tags {
if !virtual_tags.contains(tag) && !self.completion_list.items.contains(tag) {
self.completion_list.items.push(format!("+{}", &tag));
}
}
}
}
}
_ => {}
}
}
} }
pub fn handle_movement(linebuffer: &mut LineBuffer, input: Key) { pub fn handle_movement(linebuffer: &mut LineBuffer, input: Key) {

View file

@ -37,6 +37,7 @@ pub enum Key {
Ctrl(char), Ctrl(char),
Null, Null,
Esc, Esc,
Tab,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -83,7 +84,7 @@ impl Events {
End => Key::End, End => Key::End,
PageUp => Key::PageUp, PageUp => Key::PageUp,
PageDown => Key::PageDown, PageDown => Key::PageDown,
Tab => Key::Char('\t'), Tab => Key::Tab,
BackTab => Key::BackTab, BackTab => Key::BackTab,
Delete => Key::Delete, Delete => Key::Delete,
Insert => Key::Insert, Insert => Key::Insert,