1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, ts_rs::TS)]
5#[ts(export)]
6pub enum KeyContext {
7 Global,
9 Normal,
11 Prompt,
13 Popup,
15 FileExplorer,
17 Menu,
19 Terminal,
21 Settings,
23 Mode(String),
25}
26
27impl KeyContext {
28 pub fn allows_text_input(&self) -> bool {
30 matches!(self, Self::Normal | Self::Prompt)
31 }
32
33 pub fn from_when_clause(when: &str) -> Option<Self> {
35 let trimmed = when.trim();
36 if let Some(mode_name) = trimmed.strip_prefix("mode:") {
37 return Some(Self::Mode(mode_name.to_string()));
38 }
39 Some(match trimmed {
40 "global" => Self::Global,
41 "prompt" => Self::Prompt,
42 "popup" => Self::Popup,
43 "fileExplorer" | "file_explorer" => Self::FileExplorer,
44 "normal" => Self::Normal,
45 "menu" => Self::Menu,
46 "terminal" => Self::Terminal,
47 "settings" => Self::Settings,
48 _ => return None,
49 })
50 }
51
52 pub fn to_when_clause(&self) -> String {
54 match self {
55 Self::Global => "global".to_string(),
56 Self::Normal => "normal".to_string(),
57 Self::Prompt => "prompt".to_string(),
58 Self::Popup => "popup".to_string(),
59 Self::FileExplorer => "fileExplorer".to_string(),
60 Self::Menu => "menu".to_string(),
61 Self::Terminal => "terminal".to_string(),
62 Self::Settings => "settings".to_string(),
63 Self::Mode(name) => format!("mode:{}", name),
64 }
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ts_rs::TS)]
70#[ts(export)]
71pub enum Action {
72 InsertChar(char),
74 InsertNewline,
75 InsertTab,
76
77 MoveLeft,
79 MoveRight,
80 MoveUp,
81 MoveDown,
82 MoveWordLeft,
83 MoveWordRight,
84 MoveLineStart,
85 MoveLineEnd,
86 MovePageUp,
87 MovePageDown,
88 MoveDocumentStart,
89 MoveDocumentEnd,
90
91 SelectLeft,
93 SelectRight,
94 SelectUp,
95 SelectDown,
96 SelectWordLeft,
97 SelectWordRight,
98 SelectLineStart,
99 SelectLineEnd,
100 SelectDocumentStart,
101 SelectDocumentEnd,
102 SelectPageUp,
103 SelectPageDown,
104 SelectAll,
105 SelectWord,
106 SelectLine,
107 ExpandSelection,
108
109 BlockSelectLeft,
111 BlockSelectRight,
112 BlockSelectUp,
113 BlockSelectDown,
114
115 DeleteBackward,
117 DeleteForward,
118 DeleteWordBackward,
119 DeleteWordForward,
120 DeleteLine,
121 DeleteToLineEnd,
122 DeleteToLineStart,
123 TransposeChars,
124 OpenLine,
125
126 Recenter,
128
129 SetMark,
131 CancelMark,
132 ClearMark,
133
134 Copy,
136 CopyWithTheme(String),
137 Cut,
138 Paste,
139
140 YankWordForward,
142 YankWordBackward,
143 YankToLineEnd,
144 YankToLineStart,
145
146 AddCursorAbove,
148 AddCursorBelow,
149 AddCursorNextMatch,
150 RemoveSecondaryCursors,
151
152 Save,
154 SaveAs,
155 Open,
156 SwitchProject,
157 New,
158 Close,
159 CloseTab,
160 Quit,
161 Revert,
162 ToggleAutoRevert,
163 FormatBuffer,
164
165 GotoLine,
167 ScanLineIndex,
168 GoToMatchingBracket,
169 JumpToNextError,
170 JumpToPreviousError,
171
172 SmartHome,
174 DedentSelection,
175 ToggleComment,
176 DabbrevExpand,
180
181 SetBookmark(char),
183 JumpToBookmark(char),
184 ClearBookmark(char),
185 ListBookmarks,
186
187 ToggleSearchCaseSensitive,
189 ToggleSearchWholeWord,
190 ToggleSearchRegex,
191 ToggleSearchConfirmEach,
192
193 StartMacroRecording,
195 StopMacroRecording,
196 PlayMacro(char),
197 ToggleMacroRecording(char),
198 ShowMacro(char),
199 ListMacros,
200 PromptRecordMacro,
201 PromptPlayMacro,
202 PlayLastMacro,
203
204 PromptSetBookmark,
206 PromptJumpToBookmark,
207
208 Undo,
210 Redo,
211
212 ScrollUp,
214 ScrollDown,
215 ShowHelp,
216 ShowKeyboardShortcuts,
217 ShowWarnings,
218 ShowLspStatus,
219 ClearWarnings,
220 CommandPalette,
221 ToggleLineWrap,
222 ToggleReadOnly,
223 TogglePageView,
224 SetPageWidth,
225 InspectThemeAtCursor,
226 SelectTheme,
227 SelectKeybindingMap,
228 SelectCursorStyle,
229 SelectLocale,
230
231 NextBuffer,
233 PrevBuffer,
234 SwitchToPreviousTab,
235 SwitchToTabByName,
236
237 ScrollTabsLeft,
239 ScrollTabsRight,
240
241 NavigateBack,
243 NavigateForward,
244
245 SplitHorizontal,
247 SplitVertical,
248 CloseSplit,
249 NextSplit,
250 PrevSplit,
251 IncreaseSplitSize,
252 DecreaseSplitSize,
253 ToggleMaximizeSplit,
254
255 PromptConfirm,
257 PromptConfirmWithText(String),
259 PromptCancel,
260 PromptBackspace,
261 PromptDelete,
262 PromptMoveLeft,
263 PromptMoveRight,
264 PromptMoveStart,
265 PromptMoveEnd,
266 PromptSelectPrev,
267 PromptSelectNext,
268 PromptPageUp,
269 PromptPageDown,
270 PromptAcceptSuggestion,
271 PromptMoveWordLeft,
272 PromptMoveWordRight,
273 PromptDeleteWordForward,
275 PromptDeleteWordBackward,
276 PromptDeleteToLineEnd,
277 PromptCopy,
278 PromptCut,
279 PromptPaste,
280 PromptMoveLeftSelecting,
282 PromptMoveRightSelecting,
283 PromptMoveHomeSelecting,
284 PromptMoveEndSelecting,
285 PromptSelectWordLeft,
286 PromptSelectWordRight,
287 PromptSelectAll,
288
289 FileBrowserToggleHidden,
291
292 PopupSelectNext,
294 PopupSelectPrev,
295 PopupPageUp,
296 PopupPageDown,
297 PopupConfirm,
298 PopupCancel,
299
300 ToggleFileExplorer,
302 ToggleMenuBar,
304 ToggleTabBar,
306 FocusFileExplorer,
307 FocusEditor,
308 FileExplorerUp,
309 FileExplorerDown,
310 FileExplorerPageUp,
311 FileExplorerPageDown,
312 FileExplorerExpand,
313 FileExplorerCollapse,
314 FileExplorerOpen,
315 FileExplorerRefresh,
316 FileExplorerNewFile,
317 FileExplorerNewDirectory,
318 FileExplorerDelete,
319 FileExplorerRename,
320 FileExplorerToggleHidden,
321 FileExplorerToggleGitignored,
322
323 LspCompletion,
325 LspGotoDefinition,
326 LspReferences,
327 LspRename,
328 LspHover,
329 LspSignatureHelp,
330 LspCodeActions,
331 LspRestart,
332 LspStop,
333 ToggleInlayHints,
334 ToggleMouseHover,
335
336 ToggleLineNumbers,
338 ToggleScrollSync,
339 ToggleMouseCapture,
340 ToggleDebugHighlights, SetBackground,
342 SetBackgroundBlend,
343
344 SetTabSize,
346 SetLineEnding,
347 ToggleIndentationStyle,
348 ToggleTabIndicators,
349 ResetBufferSettings,
350
351 DumpConfig,
353
354 Search,
356 FindInSelection,
357 FindNext,
358 FindPrevious,
359 FindSelectionNext, FindSelectionPrevious, Replace,
362 QueryReplace, MenuActivate, MenuClose, MenuLeft, MenuRight, MenuUp, MenuDown, MenuExecute, MenuOpen(String), SwitchKeybindingMap(String), PluginAction(String),
379
380 LoadPluginFromBuffer,
382
383 OpenSettings, CloseSettings, SettingsSave, SettingsReset, SettingsToggleFocus, SettingsActivate, SettingsSearch, SettingsHelp, SettingsIncrement, SettingsDecrement, OpenTerminal, CloseTerminal, FocusTerminal, TerminalEscape, ToggleKeyboardCapture, TerminalPaste, ShellCommand, ShellCommandReplace, ToUpperCase, ToLowerCase, CalibrateInput, None,
416}
417
418#[cfg(test)]
419mod tests {
420 use super::*;
421
422 #[test]
425 fn when_clause_is_a_roundtrip_for_every_variant() {
426 let variants = [
427 KeyContext::Global,
428 KeyContext::Normal,
429 KeyContext::Prompt,
430 KeyContext::Popup,
431 KeyContext::FileExplorer,
432 KeyContext::Menu,
433 KeyContext::Terminal,
434 KeyContext::Settings,
435 KeyContext::Mode("search-replace-list".into()),
436 KeyContext::Mode(String::new()),
437 ];
438 for ctx in &variants {
439 let clause = ctx.to_when_clause();
440 assert_eq!(
441 KeyContext::from_when_clause(&clause).as_ref(),
442 Some(ctx),
443 "roundtrip failed: {:?} → {:?}",
444 ctx,
445 clause
446 );
447 }
448 }
449
450 #[test]
454 fn from_when_clause_handles_aliases_whitespace_and_rejects_unknown() {
455 assert_eq!(
457 KeyContext::from_when_clause("file_explorer"),
458 Some(KeyContext::FileExplorer)
459 );
460 assert_eq!(
462 KeyContext::from_when_clause(" prompt "),
463 Some(KeyContext::Prompt)
464 );
465 assert_eq!(KeyContext::from_when_clause("nonsense"), None);
467 assert_eq!(KeyContext::from_when_clause("GLOBAL"), None);
468 assert_eq!(KeyContext::from_when_clause(""), None);
469 }
470
471 #[test]
473 fn allows_text_input_iff_normal_or_prompt() {
474 for ctx in [
475 KeyContext::Global,
476 KeyContext::Normal,
477 KeyContext::Prompt,
478 KeyContext::Popup,
479 KeyContext::FileExplorer,
480 KeyContext::Menu,
481 KeyContext::Terminal,
482 KeyContext::Settings,
483 KeyContext::Mode("foo".into()),
484 ] {
485 let expected = matches!(ctx, KeyContext::Normal | KeyContext::Prompt);
486 assert_eq!(
487 ctx.allows_text_input(),
488 expected,
489 "{:?} text-input expectation violated",
490 ctx
491 );
492 }
493 }
494}