1use super::modes::Mode;
4use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
5
6#[derive(Debug, Clone, PartialEq)]
8pub enum KeyAction {
9 EnterNormalMode,
11 EnterInsertMode,
12 EnterVisualMode,
13 EnterCommandMode,
14
15 MoveUp,
17 MoveDown,
18 MoveLeft,
19 MoveRight,
20 MoveToTop,
21 MoveToBottom,
22 MovePageUp,
23 MovePageDown,
24
25 ExpandNode,
27 CollapseNode,
28 ToggleNode,
29
30 DeleteChar,
32 DeleteLine,
33 DeleteNode,
34 InsertChar(char),
35 NewLine,
36 Backspace,
37
38 Save,
40 Quit,
41 SaveAndQuit,
42 ForceQuit,
43 ExecuteCommand(String),
44
45 SelectUp,
47 SelectDown,
48 SelectAll,
49
50 ShowHelp,
52 Refresh,
53 Undo,
54 Redo,
55 Repeat,
56 None,
57}
58
59pub struct KeyHandler;
61
62impl KeyHandler {
63 pub fn handle(key: KeyEvent, mode: Mode) -> KeyAction {
65 match mode {
66 Mode::Normal => Self::handle_normal_mode(key),
67 Mode::Insert => Self::handle_insert_mode(key),
68 Mode::Visual => Self::handle_visual_mode(key),
69 Mode::Command => Self::handle_command_mode(key),
70 }
71 }
72
73 fn handle_normal_mode(key: KeyEvent) -> KeyAction {
75 match (key.code, key.modifiers) {
76 (KeyCode::Char('i'), KeyModifiers::NONE) => KeyAction::EnterInsertMode,
78 (KeyCode::Char('v'), KeyModifiers::NONE) => KeyAction::EnterVisualMode,
79 (KeyCode::Char(':'), KeyModifiers::NONE) => KeyAction::EnterCommandMode,
80
81 (KeyCode::Char('h'), KeyModifiers::NONE) => KeyAction::MoveLeft,
83 (KeyCode::Char('j'), KeyModifiers::NONE) => KeyAction::MoveDown,
84 (KeyCode::Char('k'), KeyModifiers::NONE) => KeyAction::MoveUp,
85 (KeyCode::Char('l'), KeyModifiers::NONE) => KeyAction::MoveRight,
86
87 (KeyCode::Left, _) => KeyAction::MoveLeft,
89 (KeyCode::Down, _) => KeyAction::MoveDown,
90 (KeyCode::Up, _) => KeyAction::MoveUp,
91 (KeyCode::Right, _) => KeyAction::MoveRight,
92
93 (KeyCode::Char('g'), KeyModifiers::NONE) => KeyAction::MoveToTop,
95 (KeyCode::Char('G'), KeyModifiers::SHIFT) => KeyAction::MoveToBottom,
96 (KeyCode::PageUp, _) | (KeyCode::Char('u'), KeyModifiers::CONTROL) => {
97 KeyAction::MovePageUp
98 }
99 (KeyCode::PageDown, _) | (KeyCode::Char('d'), KeyModifiers::CONTROL) => {
100 KeyAction::MovePageDown
101 }
102 (KeyCode::Home, _) => KeyAction::MoveToTop,
103 (KeyCode::End, _) => KeyAction::MoveToBottom,
104
105 (KeyCode::Enter, _) | (KeyCode::Char('o'), KeyModifiers::NONE) => KeyAction::ToggleNode,
107 (KeyCode::Char('O'), KeyModifiers::SHIFT) => KeyAction::ExpandNode,
108 (KeyCode::Char('C'), KeyModifiers::SHIFT) => KeyAction::CollapseNode,
109
110 (KeyCode::Char('d'), KeyModifiers::NONE) => KeyAction::DeleteNode,
112 (KeyCode::Char('x'), KeyModifiers::NONE) => KeyAction::DeleteChar,
113 (KeyCode::Delete, _) => KeyAction::DeleteChar,
114
115 (KeyCode::Char('w'), KeyModifiers::CONTROL) => KeyAction::Save,
117 (KeyCode::Char('q'), KeyModifiers::CONTROL) => KeyAction::Quit,
118 (KeyCode::Char('c'), KeyModifiers::CONTROL) => KeyAction::ForceQuit,
119 (KeyCode::Esc, KeyModifiers::NONE) => KeyAction::Quit,
120
121 (KeyCode::Char('u'), KeyModifiers::NONE) => KeyAction::Undo,
123 (KeyCode::Char('r'), KeyModifiers::CONTROL) => KeyAction::Redo,
124 (KeyCode::Char('.'), KeyModifiers::NONE) => KeyAction::Repeat,
125
126 (KeyCode::Char('?'), KeyModifiers::NONE) => KeyAction::ShowHelp,
128
129 (KeyCode::Char('r'), KeyModifiers::NONE) => KeyAction::Refresh,
131
132 _ => KeyAction::None,
133 }
134 }
135
136 fn handle_insert_mode(key: KeyEvent) -> KeyAction {
138 match (key.code, key.modifiers) {
139 (KeyCode::Esc, _) => KeyAction::EnterNormalMode,
141
142 (KeyCode::Char(c), KeyModifiers::NONE | KeyModifiers::SHIFT) => {
144 KeyAction::InsertChar(c)
145 }
146 (KeyCode::Backspace, _) => KeyAction::Backspace,
147 (KeyCode::Delete, _) => KeyAction::DeleteChar,
148 (KeyCode::Enter, _) => KeyAction::NewLine,
149
150 (KeyCode::Left, _) => KeyAction::MoveLeft,
152 (KeyCode::Right, _) => KeyAction::MoveRight,
153 (KeyCode::Up, _) => KeyAction::MoveUp,
154 (KeyCode::Down, _) => KeyAction::MoveDown,
155
156 _ => KeyAction::None,
157 }
158 }
159
160 fn handle_visual_mode(key: KeyEvent) -> KeyAction {
162 match (key.code, key.modifiers) {
163 (KeyCode::Esc, _) | (KeyCode::Char('v'), KeyModifiers::NONE) => {
165 KeyAction::EnterNormalMode
166 }
167
168 (KeyCode::Char('h'), KeyModifiers::NONE) => KeyAction::MoveLeft,
170 (KeyCode::Char('j'), KeyModifiers::NONE) => KeyAction::SelectDown,
171 (KeyCode::Char('k'), KeyModifiers::NONE) => KeyAction::SelectUp,
172 (KeyCode::Char('l'), KeyModifiers::NONE) => KeyAction::MoveRight,
173
174 (KeyCode::Up, _) => KeyAction::SelectUp,
176 (KeyCode::Down, _) => KeyAction::SelectDown,
177
178 (KeyCode::Char('a'), KeyModifiers::CONTROL) => KeyAction::SelectAll,
180
181 (KeyCode::Char('d'), KeyModifiers::NONE) => KeyAction::DeleteNode,
183 (KeyCode::Delete, _) | (KeyCode::Char('x'), KeyModifiers::NONE) => {
184 KeyAction::DeleteNode
185 }
186
187 _ => KeyAction::None,
188 }
189 }
190
191 fn handle_command_mode(key: KeyEvent) -> KeyAction {
193 match (key.code, key.modifiers) {
194 (KeyCode::Esc, _) => KeyAction::EnterNormalMode,
196
197 (KeyCode::Enter, _) => KeyAction::ExecuteCommand(String::new()), (KeyCode::Char(c), KeyModifiers::NONE | KeyModifiers::SHIFT) => {
202 KeyAction::InsertChar(c)
203 }
204 (KeyCode::Backspace, _) => KeyAction::Backspace,
205
206 _ => KeyAction::None,
207 }
208 }
209
210 pub fn parse_command(cmd: &str) -> KeyAction {
212 let cmd = cmd.trim();
213 match cmd {
214 "w" | "write" => KeyAction::Save,
215 "q" | "quit" => KeyAction::Quit,
216 "wq" | "x" => KeyAction::SaveAndQuit,
217 "q!" | "quit!" => KeyAction::ForceQuit,
218 _ => KeyAction::None,
219 }
220 }
221}