sql_cli/widgets/
editor_widget.rs

1use crate::buffer::{AppMode, BufferAPI};
2use crate::key_dispatcher::KeyDispatcher;
3use anyhow::Result;
4use crossterm::event::KeyEvent;
5use ratatui::{
6    layout::Rect,
7    style::{Color, Style},
8    widgets::{Block, Borders, Paragraph, Wrap},
9    Frame,
10};
11use tracing::{debug, trace};
12
13/// Represents the result of handling a key event in the editor
14#[derive(Debug, Clone)]
15pub enum EditorAction {
16    /// No special action, just continue
17    Continue,
18    /// Request to quit the application
19    Quit,
20    /// Request to execute the current query
21    ExecuteQuery,
22    /// Request to switch modes
23    SwitchMode(AppMode),
24    /// Request buffer operations
25    BufferAction(BufferAction),
26    /// Request to expand asterisk
27    ExpandAsterisk,
28    /// Request to show help
29    ShowHelp,
30    /// Request to show debug
31    ShowDebug,
32    /// Request to show pretty query
33    ShowPrettyQuery,
34    /// Pass key to main app for handling
35    PassToMainApp(KeyEvent),
36}
37
38/// Buffer-related actions that the main TUI should handle
39#[derive(Debug, Clone)]
40pub enum BufferAction {
41    NextBuffer,
42    PreviousBuffer,
43    QuickSwitch,
44    NewBuffer,
45    CloseBuffer,
46    ListBuffers,
47    SwitchToBuffer(usize),
48}
49
50/// A self-contained editor widget that manages command input
51pub struct EditorWidget {
52    // For now, this is mostly a placeholder that will delegate back to the main app
53    // This establishes the architecture pattern that we can fill in later
54}
55
56impl EditorWidget {
57    #[must_use]
58    pub fn new() -> Self {
59        Self {}
60    }
61
62    /// Handle key input and return the appropriate action
63    pub fn handle_key(
64        &mut self,
65        key: KeyEvent,
66        key_dispatcher: &KeyDispatcher,
67        _buffer: &mut dyn BufferAPI,
68    ) -> Result<EditorAction> {
69        // Log the key event
70        trace!(target: "input", "Key: {:?} Modifiers: {:?}", key.code, key.modifiers);
71
72        // The basic editing operations are now handled by the action system
73        // EditorWidget now focuses on higher-level operations that require special handling
74
75        // Note: Basic cursor movement, text editing (backspace, delete, character insert),
76        // and undo/redo are now handled through the action system in enhanced_tui.rs
77
78        // Try dispatcher for high-level actions
79        if let Some(action) = key_dispatcher.get_command_action(&key) {
80            match action {
81                "quit" => return Ok(EditorAction::Quit),
82                "next_buffer" => return Ok(EditorAction::BufferAction(BufferAction::NextBuffer)),
83                "previous_buffer" => {
84                    return Ok(EditorAction::BufferAction(BufferAction::PreviousBuffer))
85                }
86                "quick_switch_buffer" => {
87                    return Ok(EditorAction::BufferAction(BufferAction::QuickSwitch))
88                }
89                "new_buffer" => return Ok(EditorAction::BufferAction(BufferAction::NewBuffer)),
90                "close_buffer" => return Ok(EditorAction::BufferAction(BufferAction::CloseBuffer)),
91                "list_buffers" => return Ok(EditorAction::BufferAction(BufferAction::ListBuffers)),
92                "expand_asterisk" => return Ok(EditorAction::ExpandAsterisk),
93                "execute_query" => return Ok(EditorAction::ExecuteQuery),
94                "toggle_help" => return Ok(EditorAction::ShowHelp),
95                "toggle_debug" => {
96                    // Pass F5 debug to main app to use original working implementation
97                    return Ok(EditorAction::PassToMainApp(key));
98                }
99                "show_pretty_query" => return Ok(EditorAction::ShowPrettyQuery),
100                "search_history" => return Ok(EditorAction::SwitchMode(AppMode::History)),
101                "enter_results_mode" => return Ok(EditorAction::SwitchMode(AppMode::Results)),
102                action if action.starts_with("switch_to_buffer_") => {
103                    if let Some(buffer_num_str) = action.strip_prefix("switch_to_buffer_") {
104                        if let Ok(buffer_num) = buffer_num_str.parse::<usize>() {
105                            return Ok(EditorAction::BufferAction(BufferAction::SwitchToBuffer(
106                                buffer_num - 1,
107                            )));
108                        }
109                    }
110                    return Ok(EditorAction::Continue);
111                }
112                _ => {
113                    debug!("Passing unhandled action to main app: {}", action);
114                    return Ok(EditorAction::PassToMainApp(key));
115                }
116            }
117        }
118
119        // For all other keys, pass to main app for now
120        Ok(EditorAction::PassToMainApp(key))
121    }
122
123    /// Render the editor widget
124    /// For now, this is a placeholder that the main app will override
125    pub fn render(&self, f: &mut Frame, area: Rect) {
126        // Simple placeholder rendering
127        let placeholder = Paragraph::new("Editor Widget Placeholder")
128            .block(
129                Block::default()
130                    .borders(Borders::ALL)
131                    .title("Command Input")
132                    .border_style(Style::default().fg(Color::Blue)),
133            )
134            .wrap(Wrap { trim: false });
135
136        f.render_widget(placeholder, area);
137    }
138}
139
140impl Default for EditorWidget {
141    fn default() -> Self {
142        Self::new()
143    }
144}