1use crate::app_state_container::SelectionMode;
5use crate::buffer::AppMode;
6use anyhow::Result;
7
8#[derive(Debug, Clone, PartialEq)]
10pub enum CursorPosition {
11 Current,
13 End,
15 AfterClause(SqlClause),
17}
18
19#[derive(Debug, Clone, PartialEq)]
21pub enum SqlClause {
22 Select,
23 From,
24 Where,
25 OrderBy,
26 GroupBy,
27 Having,
28 Limit,
29}
30
31#[derive(Debug, Clone, PartialEq)]
33pub enum Action {
34 Navigate(NavigateAction),
36
37 SwitchMode(AppMode),
39 SwitchModeWithCursor(AppMode, CursorPosition),
40 ToggleSelectionMode,
41 ExitCurrentMode,
42
43 InsertChar(char),
45 Backspace,
46 Delete,
47 ClearLine,
48 Undo,
49 Redo,
50
51 MoveCursorLeft,
53 MoveCursorRight,
54 MoveCursorHome,
55 MoveCursorEnd,
56 MoveCursorWordLeft,
57 MoveCursorWordRight,
58
59 DeleteWordBackward,
61 DeleteWordForward,
62 DeleteToLineStart,
63 DeleteToLineEnd,
64
65 Yank(YankTarget),
67 Paste,
68
69 ToggleColumnPin,
71 HideColumn,
72 UnhideAllColumns,
73 HideEmptyColumns,
74 MoveColumnLeft,
75 MoveColumnRight,
76 ClearAllPins,
77 NextColumn,
78 PreviousColumn,
79 ToggleCompactMode,
80 ToggleRowNumbers,
81
82 Sort(Option<usize>), StartFilter,
85 StartFuzzyFilter,
86 ApplyFilter(String),
87 ClearFilter,
88 ExportToCsv,
89 ExportToJson,
90
91 StartSearch,
93 StartColumnSearch,
94 NextMatch,
95 PreviousMatch,
96 NextSearchMatch, PreviousSearchMatch, ExecuteQuery,
101 LoadFromHistory(usize),
102 StartHistorySearch,
103 PreviousHistoryCommand, NextHistoryCommand, RefreshView,
108 ShowHelp,
109 ShowDebugInfo,
110 ShowPrettyQuery,
111 StartJumpToRow,
112 NavigateToViewportTop,
113 NavigateToViewportMiddle,
114 NavigateToViewportBottom,
115 ToggleCursorLock,
116 ToggleViewportLock,
117 ToggleCaseInsensitive,
118 ToggleKeyIndicator,
119 ShowColumnStatistics, CycleColumnPacking, KillLine, KillLineBackward, ExpandAsterisk, ExpandAsteriskVisible, Quit,
130 ForceQuit,
131}
132
133#[derive(Debug, Clone, PartialEq)]
135pub enum NavigateAction {
136 Up(usize),
137 Down(usize),
138 Left(usize),
139 Right(usize),
140 PageUp,
141 PageDown,
142 Home,
143 End,
144 FirstColumn,
145 LastColumn,
146 JumpToRow(usize),
147 JumpToColumn(usize),
148}
149
150#[derive(Debug, Clone, PartialEq)]
152pub enum YankTarget {
153 Cell,
154 Row,
155 Column,
156 All,
157 Query,
158}
159
160#[derive(Debug, Clone)]
162pub struct ActionContext {
163 pub mode: AppMode,
164 pub selection_mode: SelectionMode,
165 pub has_results: bool,
166 pub has_filter: bool,
167 pub has_search: bool,
168 pub row_count: usize,
169 pub column_count: usize,
170 pub current_row: usize,
171 pub current_column: usize,
172}
173
174#[derive(Debug, Clone, PartialEq)]
176pub enum ActionResult {
177 Handled,
179 NotHandled,
181 Exit,
183 SwitchMode(AppMode),
185 Error(String),
187}
188
189pub trait ActionHandler {
191 fn can_handle(&self, action: &Action, context: &ActionContext) -> bool;
193
194 fn handle(&mut self, action: Action, context: &ActionContext) -> Result<ActionResult>;
196}
197
198pub fn can_perform_action(action: &Action, context: &ActionContext) -> bool {
200 match action {
201 Action::Navigate(_) => context.mode == AppMode::Results && context.has_results,
203
204 Action::ToggleSelectionMode => context.mode == AppMode::Results,
206 Action::ExitCurrentMode => context.mode != AppMode::Command,
207
208 Action::Yank(_) => context.has_results,
210
211 Action::StartFilter | Action::StartFuzzyFilter => {
213 context.mode == AppMode::Results || context.mode == AppMode::Command
214 }
215 Action::ClearFilter => context.has_filter,
216
217 Action::NextMatch | Action::PreviousMatch => context.has_search,
219
220 _ => true,
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228
229 #[test]
230 fn test_navigation_action_creation() {
231 let action = Action::Navigate(NavigateAction::Down(5));
232 assert_eq!(action, Action::Navigate(NavigateAction::Down(5)));
233 }
234
235 #[test]
236 fn test_action_context() {
237 let context = ActionContext {
238 mode: AppMode::Results,
239 selection_mode: SelectionMode::Row,
240 has_results: true,
241 has_filter: false,
242 has_search: false,
243 row_count: 100,
244 column_count: 10,
245 current_row: 0,
246 current_column: 0,
247 };
248
249 assert!(can_perform_action(
251 &Action::Navigate(NavigateAction::Down(1)),
252 &context
253 ));
254
255 assert!(!can_perform_action(&Action::ClearFilter, &context));
257 }
258}