mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-26 03:07:18 +02:00
Add tab complete for filter tags
This commit is contained in:
parent
fad1f37a8c
commit
fa6a1370d1
2 changed files with 79 additions and 17 deletions
93
src/app.rs
93
src/app.rs
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue