diff --git a/src/engine.rs b/src/engine.rs index 5297a74d..fc2be8af 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -944,6 +944,7 @@ impl Reedline { | ReedlineEvent::MenuRight | ReedlineEvent::MenuPageNext | ReedlineEvent::MenuPagePrevious + | ReedlineEvent::PartialComplete | ReedlineEvent::ViChangeMode(_) => Ok(EventStatus::Inapplicable), } } @@ -954,6 +955,22 @@ impl Reedline { event: ReedlineEvent, ) -> io::Result { match event { + ReedlineEvent::PartialComplete => { + let Some(menu) = self.menus.iter_mut().find(|menu| menu.is_active()) else { + return Ok(EventStatus::Inapplicable); + }; + if self.partial_completions + && menu.can_partially_complete( + &mut self.editor, + self.completer.as_mut(), + self.history.as_ref(), + ) + { + Ok(EventStatus::Handled) + } else { + Ok(EventStatus::Inapplicable) + } + } ReedlineEvent::Menu(name) => { if self.active_menu().is_none() { if let Some(menu) = self.menus.iter_mut().find(|menu| menu.name() == name) { @@ -973,7 +990,6 @@ impl Reedline { if self.partial_completions && menu.can_partially_complete( - self.quick_completions, &mut self.editor, self.completer.as_mut(), self.history.as_ref(), @@ -987,26 +1003,17 @@ impl Reedline { } Ok(EventStatus::Inapplicable) } - ReedlineEvent::MenuNext => { - if let Some(menu) = self.menus.iter_mut().find(|menu| menu.is_active()) { + ReedlineEvent::MenuNext => match self.active_menu() { + None => Ok(EventStatus::Inapplicable), + Some(menu) => { if menu.get_values().len() == 1 && menu.can_quick_complete() { self.handle_editor_event(prompt, ReedlineEvent::Enter) } else { - if self.partial_completions { - menu.can_partially_complete( - self.quick_completions, - &mut self.editor, - self.completer.as_mut(), - self.history.as_ref(), - ); - } menu.menu_event(MenuEvent::NextElement); Ok(EventStatus::Handled) } - } else { - Ok(EventStatus::Inapplicable) } - } + }, ReedlineEvent::MenuPrevious => { self.active_menu() .map_or(Ok(EventStatus::Inapplicable), |menu| { @@ -1197,7 +1204,6 @@ impl Reedline { .handle_editor_event(prompt, ReedlineEvent::Enter); } else if self.partial_completions && menu.can_partially_complete( - self.quick_completions, &mut self.editor, self.completer.as_mut(), self.history.as_ref(), diff --git a/src/enums.rs b/src/enums.rs index 3f1d9181..83f17b65 100644 --- a/src/enums.rs +++ b/src/enums.rs @@ -833,6 +833,9 @@ pub enum ReedlineEvent { /// Change mode (vi mode only) ViChangeMode(String), + + /// Complete the command given the common prefix of items in current open menu + PartialComplete, } impl Display for ReedlineEvent { @@ -877,6 +880,7 @@ impl Display for ReedlineEvent { ReedlineEvent::ExecuteHostCommand(_) => write!(f, "ExecuteHostCommand"), ReedlineEvent::OpenEditor => write!(f, "OpenEditor"), ReedlineEvent::ViChangeMode(_) => write!(f, "ViChangeMode mode: "), + ReedlineEvent::PartialComplete => write!(f, "PartialComplete"), } } } diff --git a/src/menu/columnar_menu.rs b/src/menu/columnar_menu.rs index 14d7c44a..8d762944 100644 --- a/src/menu/columnar_menu.rs +++ b/src/menu/columnar_menu.rs @@ -501,19 +501,13 @@ impl Menu for ColumnarMenu { /// in the given line buffer fn can_partially_complete( &mut self, - values_updated: bool, editor: &mut Editor, completer: &mut dyn Completer, ) -> bool { - // If the values were already updated (e.g. quick completions are true) - // there is no need to update the values from the menu - if !values_updated { - self.update_values(editor, completer); - } - if can_partially_complete(self.get_values(), editor) { // The values need to be updated because the spans need to be // recalculated for accurate replacement in the string + // TODO: recalculate the spans instead of calling the completer 1 more time self.update_values(editor, completer); true @@ -785,7 +779,8 @@ mod tests { editor.set_buffer(input.to_string(), UndoBehavior::CreateUndoPoint); let mut completer = FakeCompleter::new(&$completions); - menu.can_partially_complete(false, &mut editor, &mut completer); + menu.update_values(&mut editor, &mut completer); + menu.can_partially_complete(&mut editor, &mut completer); assert_eq!(editor.get_buffer(), expected); } diff --git a/src/menu/description_menu.rs b/src/menu/description_menu.rs index d9687206..65fd17ae 100644 --- a/src/menu/description_menu.rs +++ b/src/menu/description_menu.rs @@ -418,7 +418,6 @@ impl Menu for DescriptionMenu { /// The menu does not need to partially complete fn can_partially_complete( &mut self, - _values_updated: bool, _editor: &mut Editor, _completer: &mut dyn Completer, ) -> bool { diff --git a/src/menu/ide_menu.rs b/src/menu/ide_menu.rs index 8587b734..0c10f404 100644 --- a/src/menu/ide_menu.rs +++ b/src/menu/ide_menu.rs @@ -601,19 +601,13 @@ impl Menu for IdeMenu { fn can_partially_complete( &mut self, - values_updated: bool, editor: &mut Editor, completer: &mut dyn Completer, ) -> bool { - // If the values were already updated (e.g. quick completions are true) - // there is no need to update the values from the menu - if !values_updated { - self.update_values(editor, completer); - } - if can_partially_complete(self.get_values(), editor) { // The values need to be updated because the spans need to be // recalculated for accurate replacement in the string + // TODO: recalculate the spans instead of calling the completer 1 more time self.update_values(editor, completer); true @@ -1342,7 +1336,8 @@ mod tests { editor.set_buffer(input.to_string(), UndoBehavior::CreateUndoPoint); let mut completer = FakeCompleter::new(&$completions); - menu.can_partially_complete(false, &mut editor, &mut completer); + menu.update_values(&mut editor, &mut completer); + menu.can_partially_complete(&mut editor, &mut completer); assert_eq!(editor.get_buffer(), expected); } diff --git a/src/menu/list_menu.rs b/src/menu/list_menu.rs index 3ed16f6b..7085e743 100644 --- a/src/menu/list_menu.rs +++ b/src/menu/list_menu.rs @@ -323,7 +323,6 @@ impl Menu for ListMenu { /// all registered values fn can_partially_complete( &mut self, - _values_updated: bool, _editor: &mut Editor, _completer: &mut dyn Completer, ) -> bool { diff --git a/src/menu/mod.rs b/src/menu/mod.rs index 23cfc1bb..ca3e971c 100644 --- a/src/menu/mod.rs +++ b/src/menu/mod.rs @@ -106,7 +106,6 @@ pub trait Menu: Send { /// in the given line buffer fn can_partially_complete( &mut self, - values_updated: bool, editor: &mut Editor, completer: &mut dyn Completer, ) -> bool; @@ -305,23 +304,20 @@ impl ReedlineMenu { pub(crate) fn can_partially_complete( &mut self, - values_updated: bool, editor: &mut Editor, completer: &mut dyn Completer, history: &dyn History, ) -> bool { match self { - Self::EngineCompleter(menu) => { - menu.can_partially_complete(values_updated, editor, completer) - } + Self::EngineCompleter(menu) => menu.can_partially_complete(editor, completer), Self::HistoryMenu(menu) => { let mut history_completer = HistoryCompleter::new(history); - menu.can_partially_complete(values_updated, editor, &mut history_completer) + menu.can_partially_complete(editor, &mut history_completer) } Self::WithCompleter { menu, completer: own_completer, - } => menu.can_partially_complete(values_updated, editor, own_completer.as_mut()), + } => menu.can_partially_complete(editor, own_completer.as_mut()), } } @@ -398,18 +394,17 @@ impl Menu for ReedlineMenu { fn can_partially_complete( &mut self, - values_updated: bool, editor: &mut Editor, completer: &mut dyn Completer, ) -> bool { match self { Self::EngineCompleter(menu) | Self::HistoryMenu(menu) => { - menu.can_partially_complete(values_updated, editor, completer) + menu.can_partially_complete(editor, completer) } Self::WithCompleter { menu, completer: own_completer, - } => menu.can_partially_complete(values_updated, editor, own_completer.as_mut()), + } => menu.can_partially_complete(editor, own_completer.as_mut()), } }