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
198#[must_use]
200pub fn can_perform_action(action: &Action, context: &ActionContext) -> bool {
201 match action {
202 Action::Navigate(_) => context.mode == AppMode::Results && context.has_results,
204
205 Action::ToggleSelectionMode => context.mode == AppMode::Results,
207 Action::ExitCurrentMode => context.mode != AppMode::Command,
208
209 Action::Yank(_) => context.has_results,
211
212 Action::StartFilter | Action::StartFuzzyFilter => {
214 context.mode == AppMode::Results || context.mode == AppMode::Command
215 }
216 Action::ClearFilter => context.has_filter,
217
218 Action::NextMatch | Action::PreviousMatch => context.has_search,
220
221 _ => true,
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn test_navigation_action_creation() {
232 let action = Action::Navigate(NavigateAction::Down(5));
233 assert_eq!(action, Action::Navigate(NavigateAction::Down(5)));
234 }
235
236 #[test]
237 fn test_action_context() {
238 let context = ActionContext {
239 mode: AppMode::Results,
240 selection_mode: SelectionMode::Row,
241 has_results: true,
242 has_filter: false,
243 has_search: false,
244 row_count: 100,
245 column_count: 10,
246 current_row: 0,
247 current_column: 0,
248 };
249
250 assert!(can_perform_action(
252 &Action::Navigate(NavigateAction::Down(1)),
253 &context
254 ));
255
256 assert!(!can_perform_action(&Action::ClearFilter, &context));
258 }
259}