From b4c380ae63ce191bb08ab1e409df0acacbc02e8c Mon Sep 17 00:00:00 2001 From: Ryan C Date: Thu, 6 Jul 2023 16:25:06 +0800 Subject: [PATCH] User completion no longer shows highlight --- src/widget/input.rs | 11 ++++++++- src/widget/input/completion.rs | 43 +++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/widget/input.rs b/src/widget/input.rs index 9fb1bb36c..348a773f7 100644 --- a/src/widget/input.rs +++ b/src/widget/input.rs @@ -119,7 +119,16 @@ where } Event::Tab => { state.completion.tab(); - None + if let Some(entry) = state.completion.select() { + if entry.is_user() { + state.input = entry.complete_input(&state.input); + Some(self.on_completion.clone()) + } else { + None + } + } else { + None + } } Event::Up => { state.completion.reset(); diff --git a/src/widget/input/completion.rs b/src/widget/input/completion.rs index 0265de85b..5db804d31 100644 --- a/src/widget/input/completion.rs +++ b/src/widget/input/completion.rs @@ -219,7 +219,7 @@ impl Completion { } } // Command fully typed & already selected, do nothing - Selection::SelectedCommand(_) => {} + Selection::SelectedCommand(_) | Selection::SelectingUser(_) => {} } } @@ -227,28 +227,23 @@ impl Completion { fn process_users(&mut self, input: &str, users: &[User]) { let (_, rest) = input.rsplit_once(' ').unwrap_or(("", input)); - // Only show user completions if using @ - let Some((_, nick)) = rest.split_once('@') else { - self.reset(); - return; - }; - match self.selection { - Selection::None | Selection::Highlighted(_) => { - self.selection = Selection::None; + Selection::None | Selection::SelectingUser(_) => { + self.selection = Selection::SelectingUser(0); self.filtered_entries = users .iter() .filter_map(|user| { let nickname = user.nickname(); nickname .as_ref() - .starts_with(nick) + .starts_with(rest) .then(|| nickname.to_string()) }) .map(Entry::User) .collect(); } - Selection::SelectedCommand(_) => {} + // No highlighting for user completion + Selection::SelectedCommand(_) | Selection::Highlighted(_) => {} } } @@ -263,15 +258,20 @@ impl Completion { pub fn is_selecting(&self) -> bool { match self.selection { - Selection::None | Selection::Highlighted(_) => !self.filtered_entries.is_empty(), + Selection::None | Selection::Highlighted(_) | Selection::SelectingUser(_) => { + !self.filtered_entries.is_empty() + } Selection::SelectedCommand(_) => false, } } fn is_active(&self) -> bool { match self.selection { - Selection::None | Selection::Highlighted(_) => !self.filtered_entries.is_empty(), + Selection::None | Selection::Highlighted(_) => { + !self.filtered_entries.is_empty() + } Selection::SelectedCommand(_) => true, + Selection::SelectingUser(_) => false } } @@ -280,6 +280,13 @@ impl Completion { Selection::None => { self.filtered_entries = vec![]; } + // When selecting a user, don't clear out the filtered entries so we can continue to + // tab through the available options + Selection::SelectingUser(index) => { + if let Some(entry) = self.filtered_entries.get(index).cloned() { + return Some(entry); + } + } Selection::Highlighted(index) => { if let Some(entry) = self.filtered_entries.get(index).cloned() { self.filtered_entries = vec![]; @@ -297,7 +304,9 @@ impl Completion { } pub fn tab(&mut self) { - if let Selection::Highlighted(index) = &mut self.selection { + if let &mut Selection::Highlighted(ref mut index) + | &mut Selection::SelectingUser(ref mut index) = &mut self.selection + { *index = (*index + 1) % self.filtered_entries.len(); } else if matches!(self.selection, Selection::None) { self.selection = Selection::Highlighted(0); @@ -349,6 +358,7 @@ impl Completion { ) } Selection::SelectedCommand(command) => Some(command.view(input)), + Selection::SelectingUser(_) => None, } } else { None @@ -360,6 +370,7 @@ impl Completion { enum Selection { None, Highlighted(usize), + SelectingUser(usize), SelectedCommand(Command), } @@ -389,6 +400,10 @@ impl Entry { }, } } + + pub fn is_user(&self) -> bool { + matches!(self, Self::User(_)) + } } #[derive(Debug, Clone)]