1use std::{
2 collections::HashMap,
3 fmt::{self, Display, Formatter},
4};
5
6#[derive(Debug)]
8pub enum KeyAction {
9 ShellCommand(String),
11 DoInputFunction(InputFunction),
13}
14
15impl Display for KeyAction {
16 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
17 match self {
18 Self::ShellCommand(command) => write!(f, "shell command: {command}"),
19 Self::DoInputFunction(function) => function.fmt(f),
20 }
21 }
22}
23
24#[derive(Debug, strum_macros::EnumString, strum_macros::Display, strum_macros::EnumIter)]
26#[strum(serialize_all = "kebab-case")]
27#[expect(missing_docs)]
28pub enum InputFunction {
29 Abort,
30 AcceptLine,
31 AliasExpandLine,
32 ArrowKeyPrefix,
33 BackwardByte,
34 BackwardChar,
35 BackwardDeleteChar,
36 BackwardKillLine,
37 BackwardKillWord,
38 BackwardWord,
39 BeginningOfHistory,
40 BeginningOfLine,
41 BracketedPasteBegin,
42 CallLastKbdMacro,
43 CapitalizeWord,
44 CharacterSearch,
45 CharacterSearchBackward,
46 ClearDisplay,
47 ClearScreen,
48 Complete,
49 CompleteCommand,
50 CompleteFilename,
51 CompleteHostname,
52 CompleteIntoBraces,
53 CompleteUsername,
54 CompleteVariable,
55 CopyBackwardWord,
56 CopyForwardWord,
57 CopyRegionAsKill,
58 DabbrevExpand,
59 DeleteChar,
60 DeleteCharOrList,
61 DeleteHorizontalSpace,
62 DigitArgument,
63 DisplayShellVersion,
64 DoLowercaseVersion,
65 DowncaseWord,
66 DumpFunctions,
67 DumpMacros,
68 DumpVariables,
69 DynamicCompleteHistory,
70 EditAndExecuteCommand,
71 EmacsEditingMode,
72 EndKbdMacro,
73 EndOfHistory,
74 EndOfLine,
75 ExchangePointAndMark,
76 ForwardBackwardDeleteChar,
77 ForwardByte,
78 ForwardChar,
79 ForwardSearchHistory,
80 ForwardWord,
81 GlobCompleteWord,
82 GlobExpandWord,
83 GlobListExpansions,
84 HistoryAndAliasExpandLine,
85 HistoryExpandLine,
86 HistorySearchBackward,
87 HistorySearchForward,
88 HistorySubstringSearchBackward,
89 HistorySubstringSearchForward,
90 InsertComment,
91 InsertCompletions,
92 InsertLastArgument,
93 KillLine,
94 KillRegion,
95 KillWholeLine,
96 KillWord,
97 MagicSpace,
98 MenuComplete,
99 MenuCompleteBackward,
100 NextHistory,
101 NextScreenLine,
102 NonIncrementalForwardSearchHistory,
103 NonIncrementalForwardSearchHistoryAgain,
104 NonIncrementalReverseSearchHistory,
105 NonIncrementalReverseSearchHistoryAgain,
106 OldMenuComplete,
107 OperateAndGetNext,
108 OverwriteMode,
109 PossibleCommandCompletions,
110 PossibleCompletions,
111 PossibleFilenameCompletions,
112 PossibleHostnameCompletions,
113 PossibleUsernameCompletions,
114 PossibleVariableCompletions,
115 PreviousHistory,
116 PreviousScreenLine,
117 PrintLastKbdMacro,
118 QuotedInsert,
119 ReReadInitFile,
120 RedrawCurrentLine,
121 ReverseSearchHistory,
122 RevertLine,
123 SelfInsert,
124 SetMark,
125 ShellBackwardKillWord,
126 ShellBackwardWord,
127 ShellExpandLine,
128 ShellForwardWord,
129 ShellKillWord,
130 ShellTransposeWords,
131 SkipCsiSequence,
132 StartKbdMacro,
133 TabInsert,
134 TildeExpand,
135 TransposeChars,
136 TransposeWords,
137 TtyStatus,
138 Undo,
139 UniversalArgument,
140 UnixFilenameRubout,
141 UnixLineDiscard,
142 UnixWordRubout,
143 UpcaseWord,
144 ViAppendEol,
145 ViAppendMode,
146 ViArgDigit,
147 ViBWord,
148 ViBackToIndent,
149 ViBackwardBigword,
150 ViBackwardWord,
151 ViBword,
152 ViChangeCase,
153 ViChangeChar,
154 ViChangeTo,
155 ViCharSearch,
156 ViColumn,
157 ViComplete,
158 ViDelete,
159 ViDeleteTo,
160 ViEWord,
161 ViEditingMode,
162 ViEndBigword,
163 ViEndWord,
164 ViEofMaybe,
165 ViEword,
166 ViFWord,
167 ViFetchHistory,
168 ViFirstPrint,
169 ViForwardBigword,
170 ViForwardWord,
171 ViFword,
172 ViGotoMark,
173 ViInsertBeg,
174 ViInsertionMode,
175 ViMatch,
176 ViMovementMode,
177 ViNextWord,
178 ViOverstrike,
179 ViOverstrikeDelete,
180 ViPrevWord,
181 ViPut,
182 ViRedo,
183 ViReplace,
184 ViRubout,
185 ViSearch,
186 ViSearchAgain,
187 ViSetMark,
188 ViSubst,
189 ViTildeExpand,
190 ViUnixWordRubout,
191 ViYankArg,
192 ViYankPop,
193 ViYankTo,
194 Yank,
195 YankLastArg,
196 YankNthArg,
197 YankPop,
198}
199
200#[derive(Debug, Eq, Hash, PartialEq)]
202pub struct KeySequence {
203 pub strokes: Vec<KeyStroke>,
205}
206
207impl Display for KeySequence {
208 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
209 for stroke in &self.strokes {
210 stroke.fmt(f)?;
211 }
212 Ok(())
213 }
214}
215
216impl From<KeyStroke> for KeySequence {
217 fn from(value: KeyStroke) -> Self {
219 Self {
220 strokes: vec![value],
221 }
222 }
223}
224
225#[derive(Debug, Eq, Hash, PartialEq)]
226pub struct KeyStroke {
228 pub alt: bool,
230 pub control: bool,
232 pub shift: bool,
234 pub key: Key,
236}
237
238impl Display for KeyStroke {
239 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
240 if self.alt {
241 write!(f, "\\e")?;
242 }
243 if self.control {
244 write!(f, "\\C-")?;
245 }
246 if self.shift {
247 }
249 self.key.fmt(f)
250 }
251}
252
253impl From<Key> for KeyStroke {
254 fn from(value: Key) -> Self {
256 Self {
257 alt: false,
258 control: false,
259 shift: false,
260 key: value,
261 }
262 }
263}
264
265#[derive(Clone, Debug, Eq, Hash, PartialEq)]
266pub enum Key {
268 Character(char),
270 Backspace,
272 Enter,
274 Left,
276 Right,
278 Up,
280 Down,
282 Home,
284 End,
286 PageUp,
288 PageDown,
290 Tab,
292 BackTab,
294 Delete,
296 Insert,
298 F(u8),
300 Escape,
302}
303
304impl Display for Key {
305 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
306 match self {
307 Self::Character(c @ ('\\' | '\"' | '\'')) => write!(f, "\\{c}")?,
308 Self::Character(c) => write!(f, "{c}")?,
309 Self::Backspace => write!(f, "Backspace")?,
310 Self::Enter => write!(f, "Enter")?,
311 Self::Left => write!(f, "Left")?,
312 Self::Right => write!(f, "Right")?,
313 Self::Up => write!(f, "Up")?,
314 Self::Down => write!(f, "Down")?,
315 Self::Home => write!(f, "Home")?,
316 Self::End => write!(f, "End")?,
317 Self::PageUp => write!(f, "PageUp")?,
318 Self::PageDown => write!(f, "PageDown")?,
319 Self::Tab => write!(f, "Tab")?,
320 Self::BackTab => write!(f, "BackTab")?,
321 Self::Delete => write!(f, "Delete")?,
322 Self::Insert => write!(f, "Insert")?,
323 Self::F(n) => write!(f, "F{n}")?,
324 Self::Escape => write!(f, "Esc")?,
325 }
326
327 Ok(())
328 }
329}
330
331pub trait KeyBindings: Send {
333 fn get_current(&self) -> HashMap<KeySequence, KeyAction>;
335 fn bind(&mut self, seq: KeySequence, action: KeyAction) -> Result<(), std::io::Error>;
337}