sql_cli/ui/behaviors/
status_behavior.rs

1// Status and error message handling behavior
2// Manages all status bar updates and error display
3
4use anyhow::Result;
5
6/// Trait for managing status and error messages in the UI
7pub trait StatusBehavior {
8    // Required methods - provide access to TUI internals
9    fn buffer_mut(&mut self) -> &mut dyn crate::buffer::BufferAPI;
10
11    /// Set a status message
12    fn set_status(&mut self, message: impl Into<String>) {
13        let msg = message.into();
14        tracing::debug!("Status: {}", msg);
15        self.buffer_mut().set_status_message(msg);
16    }
17
18    /// Set an error message with context
19    fn set_error(&mut self, context: &str, error: impl std::fmt::Display) {
20        let msg = format!("{context}: {error}");
21        tracing::error!("Error status: {}", msg);
22        self.buffer_mut().set_status_message(msg);
23    }
24
25    /// Set a success message
26    fn set_success(&mut self, message: impl Into<String>) {
27        let msg = message.into();
28        tracing::info!("Success: {}", msg);
29        self.buffer_mut().set_status_message(msg);
30    }
31
32    /// Clear the current status message
33    fn clear_status(&mut self) {
34        self.buffer_mut().set_status_message(String::new());
35    }
36
37    /// Set a temporary status message that auto-clears after a duration
38    fn set_temporary_status(&mut self, message: impl Into<String>, _duration_ms: u64) {
39        // For now, just set the status - timer functionality can be added later
40        self.set_status(message);
41    }
42
43    /// Format and set a query execution status
44    fn set_query_status(&mut self, rows: usize, columns: usize, elapsed_ms: u64) {
45        self.set_status(format!(
46            "Query executed: {rows} rows, {columns} columns ({elapsed_ms} ms)"
47        ));
48    }
49
50    /// Set a search status with match count
51    fn set_search_status(&mut self, pattern: &str, current: usize, total: usize) {
52        if total == 0 {
53            self.set_status(format!("/{pattern} - no matches"));
54        } else {
55            self.set_status(format!("Match {current}/{total} for '{pattern}'"));
56        }
57    }
58
59    /// Set a filter status
60    fn set_filter_status(&mut self, active: bool, matches: usize) {
61        if active {
62            self.set_status(format!("Filter active: {matches} matches"));
63        } else {
64            self.set_status("Filter cleared");
65        }
66    }
67
68    /// Set a column operation status
69    fn set_column_status(&mut self, operation: &str, column_name: &str) {
70        self.set_status(format!("{operation}: {column_name}"));
71    }
72
73    /// Set a navigation status
74    fn set_navigation_status(&mut self, description: &str) {
75        self.set_status(description);
76    }
77
78    /// Set a mode change status
79    fn set_mode_status(&mut self, new_mode: &str) {
80        self.set_status(format!("{new_mode} mode"));
81    }
82
83    /// Set a yank operation status
84    fn set_yank_status(&mut self, target: &str, size: usize) {
85        self.set_status(format!("Yanked {target} ({size} items)"));
86    }
87
88    /// Set a chord mode status
89    fn set_chord_status(&mut self, chord: &str, completions: &[String]) {
90        if completions.is_empty() {
91            self.set_status(format!("Chord: {chord} (no completions)"));
92        } else {
93            let completion_str = completions.join(", ");
94            self.set_status(format!("Chord: {chord} - available: {completion_str}"));
95        }
96    }
97
98    /// Set a history search status
99    fn set_history_status(&mut self, matches: usize) {
100        self.set_status(format!("History search: {matches} matches"));
101    }
102
103    /// Handle status from a result type
104    fn handle_result_status<T>(
105        &mut self,
106        result: Result<T>,
107        success_msg: &str,
108        error_context: &str,
109    ) -> Option<T> {
110        match result {
111            Ok(value) => {
112                self.set_success(success_msg);
113                Some(value)
114            }
115            Err(e) => {
116                self.set_error(error_context, e);
117                None
118            }
119        }
120    }
121}