1 #![allow(clippy::enum_glob_use)]
2 
3 use std::fmt::{self, Debug, Display};
4 
5 use bitflags::bitflags;
6 use glutin::event::VirtualKeyCode::*;
7 use glutin::event::{ModifiersState, MouseButton, VirtualKeyCode};
8 use serde::de::Error as SerdeError;
9 use serde::de::{self, MapAccess, Unexpected, Visitor};
10 use serde::{Deserialize, Deserializer};
11 use serde_yaml::Value as SerdeValue;
12 
13 use alacritty_config_derive::ConfigDeserialize;
14 
15 use alacritty_terminal::config::Program;
16 use alacritty_terminal::term::TermMode;
17 use alacritty_terminal::vi_mode::ViMotion;
18 
19 use crate::config::ui_config::Hint;
20 
21 /// Describes a state and action to take in that state.
22 ///
23 /// This is the shared component of `MouseBinding` and `KeyBinding`.
default() -> Self24 #[derive(Debug, Clone, PartialEq, Eq)]
25 pub struct Binding<T> {
26     /// Modifier keys required to activate binding.
27     pub mods: ModifiersState,
28 
29     /// String to send to PTY if mods and mode match.
30     pub action: Action,
31 
32     /// Binding mode required to activate binding.
33     pub mode: BindingMode,
34 
35     /// Excluded binding modes where the binding won't be activated.
36     pub notmode: BindingMode,
37 
38     /// This property is used as part of the trigger detection code.
39     ///
40     /// For example, this might be a key like "G", or a mouse button.
41     pub trigger: T,
42 }
43 
44 /// Bindings that are triggered by a keyboard key.
45 pub type KeyBinding = Binding<Key>;
46 
47 /// Bindings that are triggered by a mouse button.
48 pub type MouseBinding = Binding<MouseButton>;
49 
50 impl<T: Eq> Binding<T> {
51     #[inline]
52     pub fn is_triggered_by(&self, mode: BindingMode, mods: ModifiersState, input: &T) -> bool {
53         // Check input first since bindings are stored in one big list. This is
54         // the most likely item to fail so prioritizing it here allows more
55         // checks to be short circuited.
56         self.trigger == *input
57             && self.mods == mods
58             && mode.contains(self.mode)
59             && !mode.intersects(self.notmode)
60     }
61 
62     #[inline]
63     pub fn triggers_match(&self, binding: &Binding<T>) -> bool {
64         // Check the binding's key and modifiers.
65         if self.trigger != binding.trigger || self.mods != binding.mods {
66             return false;
default() -> Self67         }
68 
69         let selfmode = if self.mode.is_empty() { BindingMode::all() } else { self.mode };
70         let bindingmode = if binding.mode.is_empty() { BindingMode::all() } else { binding.mode };
71 
72         if !selfmode.intersects(bindingmode) {
73             return false;
74         }
75 
76         // The bindings are never active at the same time when the required modes of one binding
77         // are part of the forbidden bindings of the other.
78         if self.mode.intersects(binding.notmode) || binding.mode.intersects(self.notmode) {
79             return false;
80         }
81 
82         true
83     }
84 }
85 
86 #[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)]
87 pub enum Action {
88     /// Write an escape sequence.
89     #[config(skip)]
90     Esc(String),
91 
92     /// Run given command.
93     #[config(skip)]
94     Command(Program),
95 
96     /// Regex keyboard hints.
97     #[config(skip)]
98     Hint(Hint),
99 
100     /// Move vi mode cursor.
101     #[config(skip)]
102     ViMotion(ViMotion),
103 
104     /// Perform vi mode action.
105     #[config(skip)]
106     Vi(ViAction),
107 
108     /// Perform search mode action.
109     #[config(skip)]
110     Search(SearchAction),
111 
112     /// Paste contents of system clipboard.
113     Paste,
114 
115     /// Store current selection into clipboard.
116     Copy,
117 
118     #[cfg(not(any(target_os = "macos", windows)))]
119     /// Store current selection into selection buffer.
120     CopySelection,
121 
122     /// Paste contents of selection buffer.
123     PasteSelection,
124 
125     /// Increase font size.
126     IncreaseFontSize,
127 
128     /// Decrease font size.
129     DecreaseFontSize,
130 
131     /// Reset font size to the config value.
132     ResetFontSize,
133 
134     /// Scroll exactly one page up.
135     ScrollPageUp,
136 
137     /// Scroll exactly one page down.
138     ScrollPageDown,
139 
140     /// Scroll half a page up.
141     ScrollHalfPageUp,
142 
143     /// Scroll half a page down.
144     ScrollHalfPageDown,
145 
146     /// Scroll one line up.
147     ScrollLineUp,
148 
149     /// Scroll one line down.
150     ScrollLineDown,
151 
152     /// Scroll all the way to the top.
153     ScrollToTop,
154 
155     /// Scroll all the way to the bottom.
156     ScrollToBottom,
157 
158     /// Clear the display buffer(s) to remove history.
159     ClearHistory,
160 
161     /// Hide the Alacritty window.
162     Hide,
163 
164     /// Hide all windows other than Alacritty on macOS.
165     #[cfg(target_os = "macos")]
166     HideOtherApplications,
167 
168     /// Minimize the Alacritty window.
169     Minimize,
170 
171     /// Quit Alacritty.
172     Quit,
173 
174     /// Clear warning and error notices.
175     ClearLogNotice,
176 
177     /// Spawn a new instance of Alacritty.
178     SpawnNewInstance,
179 
180     /// Toggle fullscreen.
181     ToggleFullscreen,
182 
183     /// Toggle simple fullscreen on macOS.
184     #[cfg(target_os = "macos")]
185     ToggleSimpleFullscreen,
186 
187     /// Clear active selection.
188     ClearSelection,
189 
190     /// Toggle vi mode.
191     ToggleViMode,
192 
193     /// Allow receiving char input.
194     ReceiveChar,
195 
196     /// Start a forward buffer search.
197     SearchForward,
198 
199     /// Start a backward buffer search.
200     SearchBackward,
201 
202     /// No action.
203     None,
204 }
205 
206 impl From<&'static str> for Action {
207     fn from(s: &'static str) -> Action {
208         Action::Esc(s.into())
209     }
210 }
211 
212 impl From<ViAction> for Action {
213     fn from(action: ViAction) -> Self {
214         Self::Vi(action)
215     }
216 }
217 
218 impl From<ViMotion> for Action {
219     fn from(motion: ViMotion) -> Self {
220         Self::ViMotion(motion)
221     }
222 }
223 
224 impl From<SearchAction> for Action {
225     fn from(action: SearchAction) -> Self {
226         Self::Search(action)
227     }
228 }
229 
230 /// Display trait used for error logging.
231 impl Display for Action {
232     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233         match self {
234             Action::ViMotion(motion) => motion.fmt(f),
235             Action::Vi(action) => action.fmt(f),
236             _ => write!(f, "{:?}", self),
237         }
238     }
239 }
240 
241 /// Vi mode specific actions.
242 #[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
243 pub enum ViAction {
244     /// Toggle normal vi selection.
245     ToggleNormalSelection,
246     /// Toggle line vi selection.
247     ToggleLineSelection,
248     /// Toggle block vi selection.
249     ToggleBlockSelection,
250     /// Toggle semantic vi selection.
251     ToggleSemanticSelection,
252     /// Jump to the beginning of the next match.
253     SearchNext,
254     /// Jump to the beginning of the previous match.
255     SearchPrevious,
256     /// Jump to the next start of a match to the left of the origin.
257     SearchStart,
258     /// Jump to the next end of a match to the right of the origin.
259     SearchEnd,
260     /// Launch the URL below the vi mode cursor.
261     Open,
262 }
263 
264 /// Search mode specific actions.
265 #[allow(clippy::enum_variant_names)]
266 #[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
267 pub enum SearchAction {
268     /// Move the focus to the next search match.
269     SearchFocusNext,
270     /// Move the focus to the previous search match.
271     SearchFocusPrevious,
272     /// Confirm the active search.
273     SearchConfirm,
274     /// Cancel the active search.
275     SearchCancel,
276     /// Reset the search regex.
277     SearchClear,
278     /// Delete the last word in the search regex.
279     SearchDeleteWord,
280     /// Go to the previous regex in the search history.
281     SearchHistoryPrevious,
282     /// Go to the next regex in the search history.
283     SearchHistoryNext,
284 }
285 
286 macro_rules! bindings {
287     (
288         KeyBinding;
289         $(
290             $key:ident
291             $(,$mods:expr)*
292             $(,+$mode:expr)*
293             $(,~$notmode:expr)*
294             ;$action:expr
295         );*
296         $(;)*
297     ) => {{
298         bindings!(
299             KeyBinding;
300             $(
301                 Key::Keycode($key)
302                 $(,$mods)*
303                 $(,+$mode)*
304                 $(,~$notmode)*
305                 ;$action
306             );*
307         )
308     }};
309     (
310         $ty:ident;
311         $(
312             $key:expr
313             $(,$mods:expr)*
314             $(,+$mode:expr)*
315             $(,~$notmode:expr)*
316             ;$action:expr
317         );*
318         $(;)*
319     ) => {{
320         let mut v = Vec::new();
321 
322         $(
323             let mut _mods = ModifiersState::empty();
324             $(_mods = $mods;)*
325             let mut _mode = BindingMode::empty();
326             $(_mode.insert($mode);)*
327             let mut _notmode = BindingMode::empty();
328             $(_notmode.insert($notmode);)*
329 
330             v.push($ty {
331                 trigger: $key,
332                 mods: _mods,
333                 mode: _mode,
334                 notmode: _notmode,
335                 action: $action.into(),
336             });
337         )*
338 
339         v
340     }};
341 }
342 
343 pub fn default_mouse_bindings() -> Vec<MouseBinding> {
344     bindings!(
345         MouseBinding;
346         MouseButton::Middle, ~BindingMode::VI; Action::PasteSelection;
347     )
348 }
349 
350 pub fn default_key_bindings() -> Vec<KeyBinding> {
351     let mut bindings = bindings!(
352         KeyBinding;
353         Copy;  Action::Copy;
354         Copy,  +BindingMode::VI; Action::ClearSelection;
355         Paste, ~BindingMode::VI; Action::Paste;
356         L, ModifiersState::CTRL; Action::ClearLogNotice;
357         L,    ModifiersState::CTRL,  ~BindingMode::VI, ~BindingMode::SEARCH;
358             Action::Esc("\x0c".into());
359         Tab,  ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH;
360             Action::Esc("\x1b[Z".into());
361         Back, ModifiersState::ALT,   ~BindingMode::VI, ~BindingMode::SEARCH;
362             Action::Esc("\x1b\x7f".into());
363         Back, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH;
364             Action::Esc("\x7f".into());
365         Home,     ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollToTop;
366         End,      ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollToBottom;
367         PageUp,   ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollPageUp;
368         PageDown, ModifiersState::SHIFT, ~BindingMode::ALT_SCREEN; Action::ScrollPageDown;
369         Home,     ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
370             ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[1;2H".into());
371         End,      ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
372             ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[1;2F".into());
373         PageUp,   ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
374             ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[5;2~".into());
375         PageDown, ModifiersState::SHIFT, +BindingMode::ALT_SCREEN,
376             ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[6;2~".into());
377         Home,  +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
378             Action::Esc("\x1bOH".into());
379         Home,  ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
380             Action::Esc("\x1b[H".into());
381         End,   +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
382             Action::Esc("\x1bOF".into());
383         End,   ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
384             Action::Esc("\x1b[F".into());
385         Up,    +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
386             Action::Esc("\x1bOA".into());
387         Up,    ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
388             Action::Esc("\x1b[A".into());
389         Down,  +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
390             Action::Esc("\x1bOB".into());
391         Down,  ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
392             Action::Esc("\x1b[B".into());
393         Right, +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
394             Action::Esc("\x1bOC".into());
395         Right, ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
396             Action::Esc("\x1b[C".into());
397         Left,  +BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
398             Action::Esc("\x1bOD".into());
399         Left,  ~BindingMode::APP_CURSOR, ~BindingMode::VI, ~BindingMode::SEARCH;
400             Action::Esc("\x1b[D".into());
401         Back,        ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x7f".into());
402         Insert,      ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[2~".into());
403         Delete,      ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[3~".into());
404         PageUp,      ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[5~".into());
405         PageDown,    ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[6~".into());
406         F1,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOP".into());
407         F2,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOQ".into());
408         F3,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOR".into());
409         F4,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1bOS".into());
410         F5,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[15~".into());
411         F6,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[17~".into());
412         F7,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[18~".into());
413         F8,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[19~".into());
414         F9,          ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[20~".into());
415         F10,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[21~".into());
416         F11,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[23~".into());
417         F12,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[24~".into());
418         F13,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[25~".into());
419         F14,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[26~".into());
420         F15,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[28~".into());
421         F16,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[29~".into());
422         F17,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[31~".into());
423         F18,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[32~".into());
424         F19,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[33~".into());
425         F20,         ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\x1b[34~".into());
426         NumpadEnter, ~BindingMode::VI, ~BindingMode::SEARCH; Action::Esc("\n".into());
427         Space, ModifiersState::SHIFT | ModifiersState::CTRL, ~BindingMode::SEARCH;
428             Action::ToggleViMode;
429         Space, ModifiersState::SHIFT | ModifiersState::CTRL, +BindingMode::VI, ~BindingMode::SEARCH;
430             Action::ScrollToBottom;
431         Escape,                        +BindingMode::VI, ~BindingMode::SEARCH;
432             Action::ClearSelection;
433         I,                             +BindingMode::VI, ~BindingMode::SEARCH;
434             Action::ToggleViMode;
435         I,                             +BindingMode::VI, ~BindingMode::SEARCH;
436             Action::ScrollToBottom;
437         C,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
438             Action::ToggleViMode;
439         Y,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
440             Action::ScrollLineUp;
441         E,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
442             Action::ScrollLineDown;
443         G,                             +BindingMode::VI, ~BindingMode::SEARCH;
444             Action::ScrollToTop;
445         G,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
446             Action::ScrollToBottom;
447         B,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
448             Action::ScrollPageUp;
449         F,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
450             Action::ScrollPageDown;
451         U,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
452             Action::ScrollHalfPageUp;
453         D,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
454             Action::ScrollHalfPageDown;
455         Y,                             +BindingMode::VI, ~BindingMode::SEARCH; Action::Copy;
456         Y,                             +BindingMode::VI, ~BindingMode::SEARCH;
457             Action::ClearSelection;
458         Slash,                         +BindingMode::VI, ~BindingMode::SEARCH;
459             Action::SearchForward;
460         Slash,  ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
461             Action::SearchBackward;
462         V,                             +BindingMode::VI, ~BindingMode::SEARCH;
463             ViAction::ToggleNormalSelection;
464         V,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
465             ViAction::ToggleLineSelection;
466         V,      ModifiersState::CTRL,  +BindingMode::VI, ~BindingMode::SEARCH;
467             ViAction::ToggleBlockSelection;
468         V,      ModifiersState::ALT,   +BindingMode::VI, ~BindingMode::SEARCH;
469             ViAction::ToggleSemanticSelection;
470         N,                             +BindingMode::VI, ~BindingMode::SEARCH;
471             ViAction::SearchNext;
472         N,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
473             ViAction::SearchPrevious;
474         Return,                        +BindingMode::VI, ~BindingMode::SEARCH;
475             ViAction::Open;
476         K,                             +BindingMode::VI, ~BindingMode::SEARCH;
477             ViMotion::Up;
478         J,                             +BindingMode::VI, ~BindingMode::SEARCH;
479             ViMotion::Down;
480         H,                             +BindingMode::VI, ~BindingMode::SEARCH;
481             ViMotion::Left;
482         L,                             +BindingMode::VI, ~BindingMode::SEARCH;
483             ViMotion::Right;
484         Up,                            +BindingMode::VI, ~BindingMode::SEARCH;
485             ViMotion::Up;
486         Down,                          +BindingMode::VI, ~BindingMode::SEARCH;
487             ViMotion::Down;
488         Left,                          +BindingMode::VI, ~BindingMode::SEARCH;
489             ViMotion::Left;
490         Right,                         +BindingMode::VI, ~BindingMode::SEARCH;
491             ViMotion::Right;
492         Key0,                          +BindingMode::VI, ~BindingMode::SEARCH;
493             ViMotion::First;
494         Key4,   ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
495             ViMotion::Last;
496         Key6,   ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
497             ViMotion::FirstOccupied;
498         H,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
499             ViMotion::High;
500         M,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
501             ViMotion::Middle;
502         L,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
503             ViMotion::Low;
504         B,                             +BindingMode::VI, ~BindingMode::SEARCH;
505             ViMotion::SemanticLeft;
506         W,                             +BindingMode::VI, ~BindingMode::SEARCH;
507             ViMotion::SemanticRight;
508         E,                             +BindingMode::VI, ~BindingMode::SEARCH;
509             ViMotion::SemanticRightEnd;
510         B,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
511             ViMotion::WordLeft;
512         W,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
513             ViMotion::WordRight;
514         E,      ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
515             ViMotion::WordRightEnd;
516         Key5,   ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH;
517             ViMotion::Bracket;
518         Return,                        +BindingMode::SEARCH, +BindingMode::VI;
519             SearchAction::SearchConfirm;
520         Escape,                        +BindingMode::SEARCH; SearchAction::SearchCancel;
521         C,      ModifiersState::CTRL,  +BindingMode::SEARCH; SearchAction::SearchCancel;
522         U,      ModifiersState::CTRL,  +BindingMode::SEARCH; SearchAction::SearchClear;
523         W,      ModifiersState::CTRL,  +BindingMode::SEARCH; SearchAction::SearchDeleteWord;
524         P,      ModifiersState::CTRL,  +BindingMode::SEARCH; SearchAction::SearchHistoryPrevious;
525         N,      ModifiersState::CTRL,  +BindingMode::SEARCH; SearchAction::SearchHistoryNext;
526         Up,                            +BindingMode::SEARCH; SearchAction::SearchHistoryPrevious;
527         Down,                          +BindingMode::SEARCH; SearchAction::SearchHistoryNext;
528         Return,                        +BindingMode::SEARCH, ~BindingMode::VI;
529             SearchAction::SearchFocusNext;
530         Return, ModifiersState::SHIFT, +BindingMode::SEARCH, ~BindingMode::VI;
531             SearchAction::SearchFocusPrevious;
532     );
533 
534     //   Code     Modifiers
535     // ---------+---------------------------
536     //    2     | Shift
537     //    3     | Alt
538     //    4     | Shift + Alt
539     //    5     | Control
540     //    6     | Shift + Control
541     //    7     | Alt + Control
542     //    8     | Shift + Alt + Control
543     // ---------+---------------------------
544     //
545     // from: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-PC-Style-Function-Keys
546     let mut modifiers = vec![
547         ModifiersState::SHIFT,
548         ModifiersState::ALT,
549         ModifiersState::SHIFT | ModifiersState::ALT,
550         ModifiersState::CTRL,
551         ModifiersState::SHIFT | ModifiersState::CTRL,
552         ModifiersState::ALT | ModifiersState::CTRL,
553         ModifiersState::SHIFT | ModifiersState::ALT | ModifiersState::CTRL,
554     ];
555 
556     for (index, mods) in modifiers.drain(..).enumerate() {
557         let modifiers_code = index + 2;
558         bindings.extend(bindings!(
559             KeyBinding;
560             Delete, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
561                 Action::Esc(format!("\x1b[3;{}~", modifiers_code));
562             Up,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
563                 Action::Esc(format!("\x1b[1;{}A", modifiers_code));
564             Down,   mods, ~BindingMode::VI, ~BindingMode::SEARCH;
565                 Action::Esc(format!("\x1b[1;{}B", modifiers_code));
566             Right,  mods, ~BindingMode::VI, ~BindingMode::SEARCH;
567                 Action::Esc(format!("\x1b[1;{}C", modifiers_code));
568             Left,   mods, ~BindingMode::VI, ~BindingMode::SEARCH;
569                 Action::Esc(format!("\x1b[1;{}D", modifiers_code));
570             F1,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
571                 Action::Esc(format!("\x1b[1;{}P", modifiers_code));
572             F2,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
573                 Action::Esc(format!("\x1b[1;{}Q", modifiers_code));
574             F3,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
575                 Action::Esc(format!("\x1b[1;{}R", modifiers_code));
576             F4,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
577                 Action::Esc(format!("\x1b[1;{}S", modifiers_code));
578             F5,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
579                 Action::Esc(format!("\x1b[15;{}~", modifiers_code));
580             F6,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
581                 Action::Esc(format!("\x1b[17;{}~", modifiers_code));
582             F7,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
583                 Action::Esc(format!("\x1b[18;{}~", modifiers_code));
584             F8,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
585                 Action::Esc(format!("\x1b[19;{}~", modifiers_code));
586             F9,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
587                 Action::Esc(format!("\x1b[20;{}~", modifiers_code));
588             F10,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
589                 Action::Esc(format!("\x1b[21;{}~", modifiers_code));
590             F11,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
591                 Action::Esc(format!("\x1b[23;{}~", modifiers_code));
592             F12,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
593                 Action::Esc(format!("\x1b[24;{}~", modifiers_code));
594             F13,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
595                 Action::Esc(format!("\x1b[25;{}~", modifiers_code));
596             F14,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
597                 Action::Esc(format!("\x1b[26;{}~", modifiers_code));
598             F15,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
599                 Action::Esc(format!("\x1b[28;{}~", modifiers_code));
600             F16,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
601                 Action::Esc(format!("\x1b[29;{}~", modifiers_code));
602             F17,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
603                 Action::Esc(format!("\x1b[31;{}~", modifiers_code));
604             F18,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
605                 Action::Esc(format!("\x1b[32;{}~", modifiers_code));
606             F19,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
607                 Action::Esc(format!("\x1b[33;{}~", modifiers_code));
608             F20,    mods, ~BindingMode::VI, ~BindingMode::SEARCH;
609                 Action::Esc(format!("\x1b[34;{}~", modifiers_code));
610         ));
611 
612         // We're adding the following bindings with `Shift` manually above, so skipping them here.
613         if modifiers_code != 2 {
614             bindings.extend(bindings!(
615                 KeyBinding;
616                 Insert,   mods, ~BindingMode::VI, ~BindingMode::SEARCH;
617                     Action::Esc(format!("\x1b[2;{}~", modifiers_code));
618                 PageUp,   mods, ~BindingMode::VI, ~BindingMode::SEARCH;
619                     Action::Esc(format!("\x1b[5;{}~", modifiers_code));
620                 PageDown, mods, ~BindingMode::VI, ~BindingMode::SEARCH;
621                     Action::Esc(format!("\x1b[6;{}~", modifiers_code));
622                 End,      mods, ~BindingMode::VI, ~BindingMode::SEARCH;
623                     Action::Esc(format!("\x1b[1;{}F", modifiers_code));
624                 Home,     mods, ~BindingMode::VI, ~BindingMode::SEARCH;
625                     Action::Esc(format!("\x1b[1;{}H", modifiers_code));
626             ));
627         }
628     }
629 
630     bindings.extend(platform_key_bindings());
631 
632     bindings
633 }
634 
635 #[cfg(not(any(target_os = "macos", test)))]
636 fn common_keybindings() -> Vec<KeyBinding> {
637     bindings!(
638         KeyBinding;
639         V,        ModifiersState::CTRL | ModifiersState::SHIFT, ~BindingMode::VI; Action::Paste;
640         C,        ModifiersState::CTRL | ModifiersState::SHIFT; Action::Copy;
641         F,        ModifiersState::CTRL | ModifiersState::SHIFT, ~BindingMode::SEARCH;
642             Action::SearchForward;
643         B,        ModifiersState::CTRL | ModifiersState::SHIFT, ~BindingMode::SEARCH;
644             Action::SearchBackward;
645         C,        ModifiersState::CTRL | ModifiersState::SHIFT,
646             +BindingMode::VI, ~BindingMode::SEARCH; Action::ClearSelection;
647         Insert,   ModifiersState::SHIFT, ~BindingMode::VI; Action::PasteSelection;
648         Key0,     ModifiersState::CTRL;  Action::ResetFontSize;
649         Equals,   ModifiersState::CTRL;  Action::IncreaseFontSize;
650         Plus,     ModifiersState::CTRL;  Action::IncreaseFontSize;
651         NumpadAdd,      ModifiersState::CTRL;  Action::IncreaseFontSize;
652         Minus,          ModifiersState::CTRL;  Action::DecreaseFontSize;
653         NumpadSubtract, ModifiersState::CTRL;  Action::DecreaseFontSize;
654     )
655 }
656 
657 #[cfg(not(any(target_os = "macos", target_os = "windows", test)))]
658 pub fn platform_key_bindings() -> Vec<KeyBinding> {
659     common_keybindings()
660 }
661 
662 #[cfg(all(target_os = "windows", not(test)))]
663 pub fn platform_key_bindings() -> Vec<KeyBinding> {
664     let mut bindings = bindings!(
665         KeyBinding;
666         Return, ModifiersState::ALT; Action::ToggleFullscreen;
667     );
668     bindings.extend(common_keybindings());
669     bindings
670 }
671 
672 #[cfg(all(target_os = "macos", not(test)))]
673 pub fn platform_key_bindings() -> Vec<KeyBinding> {
674     bindings!(
675         KeyBinding;
676         Key0,           ModifiersState::LOGO; Action::ResetFontSize;
677         Equals,         ModifiersState::LOGO; Action::IncreaseFontSize;
678         Plus,           ModifiersState::LOGO; Action::IncreaseFontSize;
679         NumpadAdd,      ModifiersState::LOGO; Action::IncreaseFontSize;
680         Minus,          ModifiersState::LOGO; Action::DecreaseFontSize;
681         NumpadSubtract, ModifiersState::LOGO; Action::DecreaseFontSize;
682         Insert, ModifiersState::SHIFT, ~BindingMode::VI, ~BindingMode::SEARCH;
683             Action::Esc("\x1b[2;2~".into());
684         K, ModifiersState::LOGO, ~BindingMode::VI, ~BindingMode::SEARCH;
685             Action::Esc("\x0c".into());
686         K, ModifiersState::LOGO, ~BindingMode::VI, ~BindingMode::SEARCH;  Action::ClearHistory;
687         V, ModifiersState::LOGO, ~BindingMode::VI; Action::Paste;
688         N, ModifiersState::LOGO; Action::SpawnNewInstance;
689         F, ModifiersState::CTRL | ModifiersState::LOGO; Action::ToggleFullscreen;
690         C, ModifiersState::LOGO; Action::Copy;
691         C, ModifiersState::LOGO, +BindingMode::VI, ~BindingMode::SEARCH; Action::ClearSelection;
692         H, ModifiersState::LOGO; Action::Hide;
693         H, ModifiersState::LOGO | ModifiersState::ALT; Action::HideOtherApplications;
694         M, ModifiersState::LOGO; Action::Minimize;
695         Q, ModifiersState::LOGO; Action::Quit;
696         W, ModifiersState::LOGO; Action::Quit;
697         F, ModifiersState::LOGO, ~BindingMode::SEARCH; Action::SearchForward;
698         B, ModifiersState::LOGO, ~BindingMode::SEARCH; Action::SearchBackward;
699     )
700 }
701 
702 // Don't return any bindings for tests since they are commented-out by default.
703 #[cfg(test)]
704 pub fn platform_key_bindings() -> Vec<KeyBinding> {
705     vec![]
706 }
707 
708 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
709 pub enum Key {
710     Scancode(u32),
711     Keycode(VirtualKeyCode),
712 }
713 
714 impl<'a> Deserialize<'a> for Key {
715     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
716     where
717         D: Deserializer<'a>,
718     {
719         let value = SerdeValue::deserialize(deserializer)?;
720         match u32::deserialize(value.clone()) {
721             Ok(scancode) => Ok(Key::Scancode(scancode)),
722             Err(_) => {
723                 let keycode = VirtualKeyCode::deserialize(value).map_err(D::Error::custom)?;
724                 Ok(Key::Keycode(keycode))
725             },
726         }
727     }
728 }
729 
730 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
731 pub struct ModeWrapper {
732     pub mode: BindingMode,
733     pub not_mode: BindingMode,
734 }
735 
736 bitflags! {
737     /// Modes available for key bindings.
738     pub struct BindingMode: u8 {
739         const APP_CURSOR          = 0b0000_0001;
740         const APP_KEYPAD          = 0b0000_0010;
741         const ALT_SCREEN          = 0b0000_0100;
742         const VI                  = 0b0000_1000;
743         const SEARCH              = 0b0001_0000;
744     }
745 }
746 
747 impl BindingMode {
748     pub fn new(mode: &TermMode, search: bool) -> BindingMode {
749         let mut binding_mode = BindingMode::empty();
750         binding_mode.set(BindingMode::APP_CURSOR, mode.contains(TermMode::APP_CURSOR));
751         binding_mode.set(BindingMode::APP_KEYPAD, mode.contains(TermMode::APP_KEYPAD));
752         binding_mode.set(BindingMode::ALT_SCREEN, mode.contains(TermMode::ALT_SCREEN));
753         binding_mode.set(BindingMode::VI, mode.contains(TermMode::VI));
754         binding_mode.set(BindingMode::SEARCH, search);
755         binding_mode
756     }
757 }
758 
759 impl Default for ModeWrapper {
760     fn default() -> Self {
761         Self { mode: BindingMode::empty(), not_mode: BindingMode::empty() }
762     }
763 }
764 
765 impl<'a> Deserialize<'a> for ModeWrapper {
766     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
767     where
768         D: Deserializer<'a>,
769     {
770         struct ModeVisitor;
771 
772         impl<'a> Visitor<'a> for ModeVisitor {
773             type Value = ModeWrapper;
774 
775             fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
776                 f.write_str(
777                     "a combination of AppCursor | AppKeypad | Alt | Vi, possibly with negation (~)",
778                 )
779             }
780 
781             fn visit_str<E>(self, value: &str) -> Result<ModeWrapper, E>
782             where
783                 E: de::Error,
784             {
785                 let mut res =
786                     ModeWrapper { mode: BindingMode::empty(), not_mode: BindingMode::empty() };
787 
788                 for modifier in value.split('|') {
789                     match modifier.trim().to_lowercase().as_str() {
790                         "appcursor" => res.mode |= BindingMode::APP_CURSOR,
791                         "~appcursor" => res.not_mode |= BindingMode::APP_CURSOR,
792                         "appkeypad" => res.mode |= BindingMode::APP_KEYPAD,
793                         "~appkeypad" => res.not_mode |= BindingMode::APP_KEYPAD,
794                         "alt" => res.mode |= BindingMode::ALT_SCREEN,
795                         "~alt" => res.not_mode |= BindingMode::ALT_SCREEN,
796                         "vi" => res.mode |= BindingMode::VI,
797                         "~vi" => res.not_mode |= BindingMode::VI,
798                         "search" => res.mode |= BindingMode::SEARCH,
799                         "~search" => res.not_mode |= BindingMode::SEARCH,
800                         _ => return Err(E::invalid_value(Unexpected::Str(modifier), &self)),
801                     }
802                 }
803 
804                 Ok(res)
805             }
806         }
807         deserializer.deserialize_str(ModeVisitor)
808     }
809 }
810 
811 struct MouseButtonWrapper(MouseButton);
812 
813 impl MouseButtonWrapper {
814     fn into_inner(self) -> MouseButton {
815         self.0
816     }
817 }
818 
819 impl<'a> Deserialize<'a> for MouseButtonWrapper {
820     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
821     where
822         D: Deserializer<'a>,
823     {
824         struct MouseButtonVisitor;
825 
826         impl<'a> Visitor<'a> for MouseButtonVisitor {
827             type Value = MouseButtonWrapper;
828 
829             fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830                 f.write_str("Left, Right, Middle, or a number from 0 to 65536")
831             }
832 
833             fn visit_u64<E>(self, value: u64) -> Result<MouseButtonWrapper, E>
834             where
835                 E: de::Error,
836             {
837                 match value {
838                     0..=65536 => Ok(MouseButtonWrapper(MouseButton::Other(value as u16))),
839                     _ => Err(E::invalid_value(Unexpected::Unsigned(value), &self)),
840                 }
841             }
842 
843             fn visit_str<E>(self, value: &str) -> Result<MouseButtonWrapper, E>
844             where
845                 E: de::Error,
846             {
847                 match value {
848                     "Left" => Ok(MouseButtonWrapper(MouseButton::Left)),
849                     "Right" => Ok(MouseButtonWrapper(MouseButton::Right)),
850                     "Middle" => Ok(MouseButtonWrapper(MouseButton::Middle)),
851                     _ => Err(E::invalid_value(Unexpected::Str(value), &self)),
852                 }
853             }
854         }
855 
856         deserializer.deserialize_any(MouseButtonVisitor)
857     }
858 }
859 
860 /// Bindings are deserialized into a `RawBinding` before being parsed as a
861 /// `KeyBinding` or `MouseBinding`.
862 #[derive(PartialEq, Eq)]
863 struct RawBinding {
864     key: Option<Key>,
865     mouse: Option<MouseButton>,
866     mods: ModifiersState,
867     mode: BindingMode,
868     notmode: BindingMode,
869     action: Action,
870 }
871 
872 impl RawBinding {
873     fn into_mouse_binding(self) -> Result<MouseBinding, Self> {
874         if let Some(mouse) = self.mouse {
875             Ok(Binding {
876                 trigger: mouse,
877                 mods: self.mods,
878                 action: self.action,
879                 mode: self.mode,
880                 notmode: self.notmode,
881             })
882         } else {
883             Err(self)
884         }
885     }
886 
887     fn into_key_binding(self) -> Result<KeyBinding, Self> {
888         if let Some(key) = self.key {
889             Ok(KeyBinding {
890                 trigger: key,
891                 mods: self.mods,
892                 action: self.action,
893                 mode: self.mode,
894                 notmode: self.notmode,
895             })
896         } else {
897             Err(self)
898         }
899     }
900 }
901 
902 impl<'a> Deserialize<'a> for RawBinding {
903     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
904     where
905         D: Deserializer<'a>,
906     {
907         const FIELDS: &[&str] = &["key", "mods", "mode", "action", "chars", "mouse", "command"];
908 
909         enum Field {
910             Key,
911             Mods,
912             Mode,
913             Action,
914             Chars,
915             Mouse,
916             Command,
917         }
918 
919         impl<'a> Deserialize<'a> for Field {
920             fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
921             where
922                 D: Deserializer<'a>,
923             {
924                 struct FieldVisitor;
925 
926                 impl<'a> Visitor<'a> for FieldVisitor {
927                     type Value = Field;
928 
929                     fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
930                         f.write_str("binding fields")
931                     }
932 
933                     fn visit_str<E>(self, value: &str) -> Result<Field, E>
934                     where
935                         E: de::Error,
936                     {
937                         match value.to_ascii_lowercase().as_str() {
938                             "key" => Ok(Field::Key),
939                             "mods" => Ok(Field::Mods),
940                             "mode" => Ok(Field::Mode),
941                             "action" => Ok(Field::Action),
942                             "chars" => Ok(Field::Chars),
943                             "mouse" => Ok(Field::Mouse),
944                             "command" => Ok(Field::Command),
945                             _ => Err(E::unknown_field(value, FIELDS)),
946                         }
947                     }
948                 }
949 
950                 deserializer.deserialize_str(FieldVisitor)
951             }
952         }
953 
954         struct RawBindingVisitor;
955         impl<'a> Visitor<'a> for RawBindingVisitor {
956             type Value = RawBinding;
957 
958             fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959                 f.write_str("binding specification")
960             }
961 
962             fn visit_map<V>(self, mut map: V) -> Result<RawBinding, V::Error>
963             where
964                 V: MapAccess<'a>,
965             {
966                 let mut mods: Option<ModifiersState> = None;
967                 let mut key: Option<Key> = None;
968                 let mut chars: Option<String> = None;
969                 let mut action: Option<Action> = None;
970                 let mut mode: Option<BindingMode> = None;
971                 let mut not_mode: Option<BindingMode> = None;
972                 let mut mouse: Option<MouseButton> = None;
973                 let mut command: Option<Program> = None;
974 
975                 use de::Error;
976 
977                 while let Some(struct_key) = map.next_key::<Field>()? {
978                     match struct_key {
979                         Field::Key => {
980                             if key.is_some() {
981                                 return Err(<V::Error as Error>::duplicate_field("key"));
982                             }
983 
984                             let val = map.next_value::<SerdeValue>()?;
985                             if val.is_u64() {
986                                 let scancode = val.as_u64().unwrap();
987                                 if scancode > u64::from(std::u32::MAX) {
988                                     return Err(<V::Error as Error>::custom(format!(
989                                         "Invalid key binding, scancode too big: {}",
990                                         scancode
991                                     )));
992                                 }
993                                 key = Some(Key::Scancode(scancode as u32));
994                             } else {
995                                 let k = Key::deserialize(val).map_err(V::Error::custom)?;
996                                 key = Some(k);
997                             }
998                         },
999                         Field::Mods => {
1000                             if mods.is_some() {
1001                                 return Err(<V::Error as Error>::duplicate_field("mods"));
1002                             }
1003 
1004                             mods = Some(map.next_value::<ModsWrapper>()?.into_inner());
1005                         },
1006                         Field::Mode => {
1007                             if mode.is_some() {
1008                                 return Err(<V::Error as Error>::duplicate_field("mode"));
1009                             }
1010 
1011                             let mode_deserializer = map.next_value::<ModeWrapper>()?;
1012                             mode = Some(mode_deserializer.mode);
1013                             not_mode = Some(mode_deserializer.not_mode);
1014                         },
1015                         Field::Action => {
1016                             if action.is_some() {
1017                                 return Err(<V::Error as Error>::duplicate_field("action"));
1018                             }
1019 
1020                             let value = map.next_value::<SerdeValue>()?;
1021 
1022                             action = if let Ok(vi_action) = ViAction::deserialize(value.clone()) {
1023                                 Some(vi_action.into())
1024                             } else if let Ok(vi_motion) = ViMotion::deserialize(value.clone()) {
1025                                 Some(vi_motion.into())
1026                             } else if let Ok(search_action) =
1027                                 SearchAction::deserialize(value.clone())
1028                             {
1029                                 Some(search_action.into())
1030                             } else {
1031                                 match Action::deserialize(value.clone()).map_err(V::Error::custom) {
1032                                     Ok(action) => Some(action),
1033                                     Err(err) => {
1034                                         let value = match value {
1035                                             SerdeValue::String(string) => string,
1036                                             SerdeValue::Mapping(map) if map.len() == 1 => {
1037                                                 match map.into_iter().next() {
1038                                                     Some((
1039                                                         SerdeValue::String(string),
1040                                                         SerdeValue::Null,
1041                                                     )) => string,
1042                                                     _ => return Err(err),
1043                                                 }
1044                                             },
1045                                             _ => return Err(err),
1046                                         };
1047                                         return Err(V::Error::custom(format!(
1048                                             "unknown keyboard action `{}`",
1049                                             value
1050                                         )));
1051                                     },
1052                                 }
1053                             };
1054                         },
1055                         Field::Chars => {
1056                             if chars.is_some() {
1057                                 return Err(<V::Error as Error>::duplicate_field("chars"));
1058                             }
1059 
1060                             chars = Some(map.next_value()?);
1061                         },
1062                         Field::Mouse => {
1063                             if chars.is_some() {
1064                                 return Err(<V::Error as Error>::duplicate_field("mouse"));
1065                             }
1066 
1067                             mouse = Some(map.next_value::<MouseButtonWrapper>()?.into_inner());
1068                         },
1069                         Field::Command => {
1070                             if command.is_some() {
1071                                 return Err(<V::Error as Error>::duplicate_field("command"));
1072                             }
1073 
1074                             command = Some(map.next_value::<Program>()?);
1075                         },
1076                     }
1077                 }
1078 
1079                 let mode = mode.unwrap_or_else(BindingMode::empty);
1080                 let not_mode = not_mode.unwrap_or_else(BindingMode::empty);
1081                 let mods = mods.unwrap_or_else(ModifiersState::default);
1082 
1083                 let action = match (action, chars, command) {
1084                     (Some(action @ Action::ViMotion(_)), None, None)
1085                     | (Some(action @ Action::Vi(_)), None, None) => {
1086                         if !mode.intersects(BindingMode::VI) || not_mode.intersects(BindingMode::VI)
1087                         {
1088                             return Err(V::Error::custom(format!(
1089                                 "action `{}` is only available in vi mode, try adding `mode: Vi`",
1090                                 action,
1091                             )));
1092                         }
1093                         action
1094                     },
1095                     (Some(action @ Action::Search(_)), None, None) => {
1096                         if !mode.intersects(BindingMode::SEARCH) {
1097                             return Err(V::Error::custom(format!(
1098                                 "action `{}` is only available in search mode, try adding `mode: \
1099                                  Search`",
1100                                 action,
1101                             )));
1102                         }
1103                         action
1104                     },
1105                     (Some(action), None, None) => action,
1106                     (None, Some(chars), None) => Action::Esc(chars),
1107                     (None, None, Some(cmd)) => Action::Command(cmd),
1108                     _ => {
1109                         return Err(V::Error::custom(
1110                             "must specify exactly one of chars, action or command",
1111                         ))
1112                     },
1113                 };
1114 
1115                 if mouse.is_none() && key.is_none() {
1116                     return Err(V::Error::custom("bindings require mouse button or key"));
1117                 }
1118 
1119                 Ok(RawBinding { mode, notmode: not_mode, action, key, mouse, mods })
1120             }
1121         }
1122 
1123         deserializer.deserialize_struct("RawBinding", FIELDS, RawBindingVisitor)
1124     }
1125 }
1126 
1127 impl<'a> Deserialize<'a> for MouseBinding {
1128     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1129     where
1130         D: Deserializer<'a>,
1131     {
1132         let raw = RawBinding::deserialize(deserializer)?;
1133         raw.into_mouse_binding()
1134             .map_err(|_| D::Error::custom("expected mouse binding, got key binding"))
1135     }
1136 }
1137 
1138 impl<'a> Deserialize<'a> for KeyBinding {
1139     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1140     where
1141         D: Deserializer<'a>,
1142     {
1143         let raw = RawBinding::deserialize(deserializer)?;
1144         raw.into_key_binding()
1145             .map_err(|_| D::Error::custom("expected key binding, got mouse binding"))
1146     }
1147 }
1148 
1149 /// Newtype for implementing deserialize on glutin Mods.
1150 ///
1151 /// Our deserialize impl wouldn't be covered by a derive(Deserialize); see the
1152 /// impl below.
1153 #[derive(Debug, Copy, Clone, Hash, Default, Eq, PartialEq)]
1154 pub struct ModsWrapper(pub ModifiersState);
1155 
1156 impl ModsWrapper {
1157     pub fn into_inner(self) -> ModifiersState {
1158         self.0
1159     }
1160 }
1161 
1162 impl<'a> de::Deserialize<'a> for ModsWrapper {
1163     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1164     where
1165         D: de::Deserializer<'a>,
1166     {
1167         struct ModsVisitor;
1168 
1169         impl<'a> Visitor<'a> for ModsVisitor {
1170             type Value = ModsWrapper;
1171 
1172             fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173                 f.write_str("None or a subset of Shift|Control|Super|Command|Alt|Option")
1174             }
1175 
1176             fn visit_str<E>(self, value: &str) -> Result<ModsWrapper, E>
1177             where
1178                 E: de::Error,
1179             {
1180                 let mut res = ModifiersState::empty();
1181                 for modifier in value.split('|') {
1182                     match modifier.trim().to_lowercase().as_str() {
1183                         "command" | "super" => res.insert(ModifiersState::LOGO),
1184                         "shift" => res.insert(ModifiersState::SHIFT),
1185                         "alt" | "option" => res.insert(ModifiersState::ALT),
1186                         "control" => res.insert(ModifiersState::CTRL),
1187                         "none" => (),
1188                         _ => return Err(E::invalid_value(Unexpected::Str(modifier), &self)),
1189                     }
1190                 }
1191 
1192                 Ok(ModsWrapper(res))
1193             }
1194         }
1195 
1196         deserializer.deserialize_str(ModsVisitor)
1197     }
1198 }
1199 
1200 #[cfg(test)]
1201 mod tests {
1202     use super::*;
1203 
1204     use glutin::event::ModifiersState;
1205 
1206     type MockBinding = Binding<usize>;
1207 
1208     impl Default for MockBinding {
1209         fn default() -> Self {
1210             Self {
1211                 mods: Default::default(),
1212                 action: Action::None,
1213                 mode: BindingMode::empty(),
1214                 notmode: BindingMode::empty(),
1215                 trigger: Default::default(),
1216             }
1217         }
1218     }
1219 
1220     #[test]
1221     fn binding_matches_itself() {
1222         let binding = MockBinding::default();
1223         let identical_binding = MockBinding::default();
1224 
1225         assert!(binding.triggers_match(&identical_binding));
1226         assert!(identical_binding.triggers_match(&binding));
1227     }
1228 
1229     #[test]
1230     fn binding_matches_different_action() {
1231         let binding = MockBinding::default();
1232         let different_action =
1233             MockBinding { action: Action::ClearHistory, ..MockBinding::default() };
1234 
1235         assert!(binding.triggers_match(&different_action));
1236         assert!(different_action.triggers_match(&binding));
1237     }
1238 
1239     #[test]
1240     fn mods_binding_requires_strict_match() {
1241         let superset_mods = MockBinding { mods: ModifiersState::all(), ..MockBinding::default() };
1242         let subset_mods = MockBinding { mods: ModifiersState::ALT, ..MockBinding::default() };
1243 
1244         assert!(!superset_mods.triggers_match(&subset_mods));
1245         assert!(!subset_mods.triggers_match(&superset_mods));
1246     }
1247 
1248     #[test]
1249     fn binding_matches_identical_mode() {
1250         let b1 = MockBinding { mode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1251         let b2 = MockBinding { mode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1252 
1253         assert!(b1.triggers_match(&b2));
1254         assert!(b2.triggers_match(&b1));
1255     }
1256 
1257     #[test]
1258     fn binding_without_mode_matches_any_mode() {
1259         let b1 = MockBinding::default();
1260         let b2 = MockBinding {
1261             mode: BindingMode::APP_KEYPAD,
1262             notmode: BindingMode::ALT_SCREEN,
1263             ..MockBinding::default()
1264         };
1265 
1266         assert!(b1.triggers_match(&b2));
1267     }
1268 
1269     #[test]
1270     fn binding_with_mode_matches_empty_mode() {
1271         let b1 = MockBinding {
1272             mode: BindingMode::APP_KEYPAD,
1273             notmode: BindingMode::ALT_SCREEN,
1274             ..MockBinding::default()
1275         };
1276         let b2 = MockBinding::default();
1277 
1278         assert!(b1.triggers_match(&b2));
1279         assert!(b2.triggers_match(&b1));
1280     }
1281 
1282     #[test]
1283     fn binding_matches_modes() {
1284         let b1 = MockBinding {
1285             mode: BindingMode::ALT_SCREEN | BindingMode::APP_KEYPAD,
1286             ..MockBinding::default()
1287         };
1288         let b2 = MockBinding { mode: BindingMode::APP_KEYPAD, ..MockBinding::default() };
1289 
1290         assert!(b1.triggers_match(&b2));
1291         assert!(b2.triggers_match(&b1));
1292     }
1293 
1294     #[test]
1295     fn binding_matches_partial_intersection() {
1296         let b1 = MockBinding {
1297             mode: BindingMode::ALT_SCREEN | BindingMode::APP_KEYPAD,
1298             ..MockBinding::default()
1299         };
1300         let b2 = MockBinding {
1301             mode: BindingMode::APP_KEYPAD | BindingMode::APP_CURSOR,
1302             ..MockBinding::default()
1303         };
1304 
1305         assert!(b1.triggers_match(&b2));
1306         assert!(b2.triggers_match(&b1));
1307     }
1308 
1309     #[test]
1310     fn binding_mismatches_notmode() {
1311         let b1 = MockBinding { mode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1312         let b2 = MockBinding { notmode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1313 
1314         assert!(!b1.triggers_match(&b2));
1315         assert!(!b2.triggers_match(&b1));
1316     }
1317 
1318     #[test]
1319     fn binding_mismatches_unrelated() {
1320         let b1 = MockBinding { mode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1321         let b2 = MockBinding { mode: BindingMode::APP_KEYPAD, ..MockBinding::default() };
1322 
1323         assert!(!b1.triggers_match(&b2));
1324         assert!(!b2.triggers_match(&b1));
1325     }
1326 
1327     #[test]
1328     fn binding_matches_notmodes() {
1329         let subset_notmodes = MockBinding {
1330             notmode: BindingMode::VI | BindingMode::APP_CURSOR,
1331             ..MockBinding::default()
1332         };
1333         let superset_notmodes =
1334             MockBinding { notmode: BindingMode::APP_CURSOR, ..MockBinding::default() };
1335 
1336         assert!(subset_notmodes.triggers_match(&superset_notmodes));
1337         assert!(superset_notmodes.triggers_match(&subset_notmodes));
1338     }
1339 
1340     #[test]
1341     fn binding_matches_mode_notmode() {
1342         let b1 = MockBinding {
1343             mode: BindingMode::VI,
1344             notmode: BindingMode::APP_CURSOR,
1345             ..MockBinding::default()
1346         };
1347         let b2 = MockBinding { notmode: BindingMode::APP_CURSOR, ..MockBinding::default() };
1348 
1349         assert!(b1.triggers_match(&b2));
1350         assert!(b2.triggers_match(&b1));
1351     }
1352 
1353     #[test]
1354     fn binding_trigger_input() {
1355         let binding = MockBinding { trigger: 13, ..MockBinding::default() };
1356 
1357         let mods = binding.mods;
1358         let mode = binding.mode;
1359 
1360         assert!(binding.is_triggered_by(mode, mods, &13));
1361         assert!(!binding.is_triggered_by(mode, mods, &32));
1362     }
1363 
1364     #[test]
1365     fn binding_trigger_mods() {
1366         let binding = MockBinding {
1367             mods: ModifiersState::ALT | ModifiersState::LOGO,
1368             ..MockBinding::default()
1369         };
1370 
1371         let superset_mods = ModifiersState::all();
1372         let subset_mods = ModifiersState::empty();
1373 
1374         let t = binding.trigger;
1375         let mode = binding.mode;
1376 
1377         assert!(binding.is_triggered_by(mode, binding.mods, &t));
1378         assert!(!binding.is_triggered_by(mode, superset_mods, &t));
1379         assert!(!binding.is_triggered_by(mode, subset_mods, &t));
1380     }
1381 
1382     #[test]
1383     fn binding_trigger_modes() {
1384         let binding = MockBinding { mode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1385 
1386         let t = binding.trigger;
1387         let mods = binding.mods;
1388 
1389         assert!(!binding.is_triggered_by(BindingMode::VI, mods, &t));
1390         assert!(binding.is_triggered_by(BindingMode::ALT_SCREEN, mods, &t));
1391         assert!(binding.is_triggered_by(BindingMode::ALT_SCREEN | BindingMode::VI, mods, &t));
1392     }
1393 
1394     #[test]
1395     fn binding_trigger_notmodes() {
1396         let binding = MockBinding { notmode: BindingMode::ALT_SCREEN, ..MockBinding::default() };
1397 
1398         let t = binding.trigger;
1399         let mods = binding.mods;
1400 
1401         assert!(binding.is_triggered_by(BindingMode::VI, mods, &t));
1402         assert!(!binding.is_triggered_by(BindingMode::ALT_SCREEN, mods, &t));
1403         assert!(!binding.is_triggered_by(BindingMode::ALT_SCREEN | BindingMode::VI, mods, &t));
1404     }
1405 }
1406