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    pub fn new() -> Self {
58        Self {}
59    }
60
61    /// Handle key input and return the appropriate action
62    pub fn handle_key(
63        &mut self,
64        key: KeyEvent,
65        key_dispatcher: &KeyDispatcher,
66        buffer: &mut dyn BufferAPI,
67    ) -> Result<EditorAction> {
68        // Log the key event
69        trace!(target: "input", "Key: {:?} Modifiers: {:?}", key.code, key.modifiers);
70
71        // The basic editing operations are now handled by the action system
72        // EditorWidget now focuses on higher-level operations that require special handling
73
74        // Note: Basic cursor movement, text editing (backspace, delete, character insert),
75        // and undo/redo are now handled through the action system in enhanced_tui.rs
76
77        // Try dispatcher for high-level actions
78        if let Some(action) = key_dispatcher.get_command_action(&key) {
79            match action {
80                "quit" => return Ok(EditorAction::Quit),
81                "next_buffer" => return Ok(EditorAction::BufferAction(BufferAction::NextBuffer)),
82                "previous_buffer" => {
83                    return Ok(EditorAction::BufferAction(BufferAction::PreviousBuffer))
84                }
85                "quick_switch_buffer" => {
86                    return Ok(EditorAction::BufferAction(BufferAction::QuickSwitch))
87                }
88                "new_buffer" => return Ok(EditorAction::BufferAction(BufferAction::NewBuffer)),
89                "close_buffer" => return Ok(EditorAction::BufferAction(BufferAction::CloseBuffer)),
90                "list_buffers" => return Ok(EditorAction::BufferAction(BufferAction::ListBuffers)),
91                "expand_asterisk" => return Ok(EditorAction::ExpandAsterisk),
92                "execute_query" => return Ok(EditorAction::ExecuteQuery),
93                "toggle_help" => return Ok(EditorAction::ShowHelp),
94                "toggle_debug" => {
95                    // Pass F5 debug to main app to use original working implementation
96                    return Ok(EditorAction::PassToMainApp(key));
97                }
98                "show_pretty_query" => return Ok(EditorAction::ShowPrettyQuery),
99                "search_history" => return Ok(EditorAction::SwitchMode(AppMode::History)),
100                "enter_results_mode" => return Ok(EditorAction::SwitchMode(AppMode::Results)),
101                action if action.starts_with("switch_to_buffer_") => {
102                    if let Some(buffer_num_str) = action.strip_prefix("switch_to_buffer_") {
103                        if let Ok(buffer_num) = buffer_num_str.parse::<usize>() {
104                            return Ok(EditorAction::BufferAction(BufferAction::SwitchToBuffer(
105                                buffer_num - 1,
106                            )));
107                        }
108                    }
109                    return Ok(EditorAction::Continue);
110                }
111                _ => {
112                    debug!("Passing unhandled action to main app: {}", action);
113                    return Ok(EditorAction::PassToMainApp(key));
114                }
115            }
116        }
117
118        // For all other keys, pass to main app for now
119        Ok(EditorAction::PassToMainApp(key))
120    }
121
122    /// Render the editor widget
123    /// For now, this is a placeholder that the main app will override
124    pub fn render(&self, f: &mut Frame, area: Rect) {
125        // Simple placeholder rendering
126        let placeholder = Paragraph::new("Editor Widget Placeholder")
127            .block(
128                Block::default()
129                    .borders(Borders::ALL)
130                    .title("Command Input")
131                    .border_style(Style::default().fg(Color::Blue)),
132            )
133            .wrap(Wrap { trim: false });
134
135        f.render_widget(placeholder, area);
136    }
137}
138
139impl Default for EditorWidget {
140    fn default() -> Self {
141        Self::new()
142    }
143}