From 202cf777749be375c85d20612ba74653eb6f2735 Mon Sep 17 00:00:00 2001 From: TimelordUK Date: Sun, 24 Aug 2025 19:54:56 +0100 Subject: [PATCH] move more to the visitor pattern from try_handle_action --- sql-cli/src/ui/action_handlers.rs | 120 ++++++++++++++++++++ sql-cli/src/ui/enhanced_tui.rs | 177 ++++++++++++++---------------- 2 files changed, 201 insertions(+), 96 deletions(-) diff --git a/sql-cli/src/ui/action_handlers.rs b/sql-cli/src/ui/action_handlers.rs index 5fc98aee..14cde2ba 100644 --- a/sql-cli/src/ui/action_handlers.rs +++ b/sql-cli/src/ui/action_handlers.rs @@ -90,6 +90,16 @@ pub trait ActionHandlerContext { // Statistics and display fn show_column_statistics(&mut self); fn cycle_column_packing(&mut self); + + // Input and text editing + fn move_input_cursor_left(&mut self); + fn move_input_cursor_right(&mut self); + fn move_input_cursor_home(&mut self); + fn move_input_cursor_end(&mut self); + fn backspace(&mut self); + fn delete(&mut self); + fn undo(&mut self); + fn redo(&mut self); } /// Handler for navigation actions (Up, Down, Left, Right, PageUp, etc.) @@ -527,6 +537,88 @@ impl ActionHandler for StatisticsActionHandler { } } +/// Handler for cursor movement actions in Command mode +pub struct InputCursorActionHandler; + +impl ActionHandler for InputCursorActionHandler { + fn handle_action( + &self, + action: &Action, + context: &ActionContext, + tui: &mut dyn ActionHandlerContext, + ) -> Option> { + // Only handle in Command mode + if context.mode != AppMode::Command { + return None; + } + + match action { + Action::MoveCursorLeft => { + tui.move_input_cursor_left(); + Some(Ok(ActionResult::Handled)) + } + Action::MoveCursorRight => { + tui.move_input_cursor_right(); + Some(Ok(ActionResult::Handled)) + } + Action::MoveCursorHome => { + tui.move_input_cursor_home(); + Some(Ok(ActionResult::Handled)) + } + Action::MoveCursorEnd => { + tui.move_input_cursor_end(); + Some(Ok(ActionResult::Handled)) + } + _ => None, + } + } + + fn name(&self) -> &'static str { + "InputCursor" + } +} + +/// Handler for text editing actions in Command mode +pub struct TextEditActionHandler; + +impl ActionHandler for TextEditActionHandler { + fn handle_action( + &self, + action: &Action, + context: &ActionContext, + tui: &mut dyn ActionHandlerContext, + ) -> Option> { + // Only handle in Command mode + if context.mode != AppMode::Command { + return None; + } + + match action { + Action::Backspace => { + tui.backspace(); + Some(Ok(ActionResult::Handled)) + } + Action::Delete => { + tui.delete(); + Some(Ok(ActionResult::Handled)) + } + Action::Undo => { + tui.undo(); + Some(Ok(ActionResult::Handled)) + } + Action::Redo => { + tui.redo(); + Some(Ok(ActionResult::Handled)) + } + _ => None, + } + } + + fn name(&self) -> &'static str { + "TextEdit" + } +} + /// Main action dispatcher using visitor pattern pub struct ActionDispatcher { handlers: Vec>, @@ -547,6 +639,8 @@ impl ActionDispatcher { Box::new(ColumnArrangementActionHandler), Box::new(SearchNavigationActionHandler), Box::new(StatisticsActionHandler), + Box::new(InputCursorActionHandler), + Box::new(TextEditActionHandler), ]; Self { handlers } @@ -750,6 +844,32 @@ mod tests { fn cycle_column_packing(&mut self) { self.last_action = "cycle_column_packing".to_string(); } + + // Input and text editing + fn move_input_cursor_left(&mut self) { + self.last_action = "move_input_cursor_left".to_string(); + } + fn move_input_cursor_right(&mut self) { + self.last_action = "move_input_cursor_right".to_string(); + } + fn move_input_cursor_home(&mut self) { + self.last_action = "move_input_cursor_home".to_string(); + } + fn move_input_cursor_end(&mut self) { + self.last_action = "move_input_cursor_end".to_string(); + } + fn backspace(&mut self) { + self.last_action = "backspace".to_string(); + } + fn delete(&mut self) { + self.last_action = "delete".to_string(); + } + fn undo(&mut self) { + self.last_action = "undo".to_string(); + } + fn redo(&mut self) { + self.last_action = "redo".to_string(); + } } #[test] diff --git a/sql-cli/src/ui/enhanced_tui.rs b/sql-cli/src/ui/enhanced_tui.rs index 74fed02a..7a57de15 100644 --- a/sql-cli/src/ui/enhanced_tui.rs +++ b/sql-cli/src/ui/enhanced_tui.rs @@ -666,103 +666,23 @@ impl EnhancedTuiApp { } // Editing actions - only work in Command mode - MoveCursorLeft => { - if context.mode == AppMode::Command { - let buffer = self.buffer_mut(); - let pos = buffer.get_input_cursor_position(); - if pos > 0 { - buffer.set_input_cursor_position(pos - 1); - } - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } - MoveCursorRight => { - if context.mode == AppMode::Command { - let buffer = self.buffer_mut(); - let pos = buffer.get_input_cursor_position(); - let text_len = buffer.get_input_text().chars().count(); - if pos < text_len { - buffer.set_input_cursor_position(pos + 1); - } - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } - MoveCursorHome => { - if context.mode == AppMode::Command { - self.buffer_mut().set_input_cursor_position(0); - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } - MoveCursorEnd => { - if context.mode == AppMode::Command { - let text_len = self.buffer().get_input_text().chars().count(); - self.buffer_mut().set_input_cursor_position(text_len); - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } - Backspace => { - if context.mode == AppMode::Command { - let buffer = self.buffer_mut(); - let pos = buffer.get_input_cursor_position(); - if pos > 0 { - buffer.save_state_for_undo(); - let mut text = buffer.get_input_text(); - let mut chars: Vec = text.chars().collect(); - if pos <= chars.len() { - chars.remove(pos - 1); - text = chars.iter().collect(); - buffer.set_input_text(text); - buffer.set_input_cursor_position(pos - 1); - } - } - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } - Delete => { - if context.mode == AppMode::Command { - let buffer = self.buffer_mut(); - let pos = buffer.get_input_cursor_position(); - let mut text = buffer.get_input_text(); - let chars_len = text.chars().count(); - if pos < chars_len { - buffer.save_state_for_undo(); - let mut chars: Vec = text.chars().collect(); - chars.remove(pos); - text = chars.iter().collect(); - buffer.set_input_text(text); - } - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } + // MoveCursorLeft is now handled by InputCursorActionHandler in visitor pattern + MoveCursorLeft => Ok(ActionResult::NotHandled), + // MoveCursorRight is now handled by InputCursorActionHandler in visitor pattern + MoveCursorRight => Ok(ActionResult::NotHandled), + // MoveCursorHome is now handled by InputCursorActionHandler in visitor pattern + MoveCursorHome => Ok(ActionResult::NotHandled), + // MoveCursorEnd is now handled by InputCursorActionHandler in visitor pattern + MoveCursorEnd => Ok(ActionResult::NotHandled), + // Backspace is now handled by TextEditActionHandler in visitor pattern + Backspace => Ok(ActionResult::NotHandled), + // Delete is now handled by TextEditActionHandler in visitor pattern + Delete => Ok(ActionResult::NotHandled), // ClearLine is now handled by ClearActionHandler in visitor pattern - Undo => { - if context.mode == AppMode::Command { - self.buffer_mut().perform_undo(); - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } - Redo => { - if context.mode == AppMode::Command { - self.buffer_mut().perform_redo(); - Ok(ActionResult::Handled) - } else { - Ok(ActionResult::NotHandled) - } - } + // Undo is now handled by TextEditActionHandler in visitor pattern + Undo => Ok(ActionResult::NotHandled), + // Redo is now handled by TextEditActionHandler in visitor pattern + Redo => Ok(ActionResult::NotHandled), ExecuteQuery => { if context.mode == AppMode::Command { // Delegate to existing execute query logic @@ -7263,6 +7183,71 @@ impl ActionHandlerContext for EnhancedTuiApp { }; self.buffer_mut().set_status_message(message); } + + // Input and text editing methods + fn move_input_cursor_left(&mut self) { + let buffer = self.buffer_mut(); + let pos = buffer.get_input_cursor_position(); + if pos > 0 { + buffer.set_input_cursor_position(pos - 1); + } + } + + fn move_input_cursor_right(&mut self) { + let buffer = self.buffer_mut(); + let pos = buffer.get_input_cursor_position(); + let text_len = buffer.get_input_text().chars().count(); + if pos < text_len { + buffer.set_input_cursor_position(pos + 1); + } + } + + fn move_input_cursor_home(&mut self) { + self.buffer_mut().set_input_cursor_position(0); + } + + fn move_input_cursor_end(&mut self) { + let text_len = self.buffer().get_input_text().chars().count(); + self.buffer_mut().set_input_cursor_position(text_len); + } + + fn backspace(&mut self) { + let buffer = self.buffer_mut(); + let pos = buffer.get_input_cursor_position(); + if pos > 0 { + buffer.save_state_for_undo(); + let mut text = buffer.get_input_text(); + let mut chars: Vec = text.chars().collect(); + if pos <= chars.len() { + chars.remove(pos - 1); + text = chars.iter().collect(); + buffer.set_input_text(text); + buffer.set_input_cursor_position(pos - 1); + } + } + } + + fn delete(&mut self) { + let buffer = self.buffer_mut(); + let pos = buffer.get_input_cursor_position(); + let mut text = buffer.get_input_text(); + let chars_len = text.chars().count(); + if pos < chars_len { + buffer.save_state_for_undo(); + let mut chars: Vec = text.chars().collect(); + chars.remove(pos); + text = chars.iter().collect(); + buffer.set_input_text(text); + } + } + + fn undo(&mut self) { + self.buffer_mut().perform_undo(); + } + + fn redo(&mut self) { + self.buffer_mut().perform_redo(); + } } // Implement NavigationBehavior trait for EnhancedTuiApp