diff options
author | Christian Duerr <chrisduerr@users.noreply.github.com> | 2019-07-15 21:32:48 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-15 21:32:48 +0000 |
commit | 3c3239b1cb4b21ee1dec8ccfbc5ec957b6e66798 (patch) | |
tree | 675fcd50d7f33dd6ce7667b3bbf6b99b044b1c1a /alacritty_terminal | |
parent | 1c05b3bb0cfe29ddaa349906a7359f4b65e78f19 (diff) | |
download | alacritty-3c3239b1cb4b21ee1dec8ccfbc5ec957b6e66798.tar.gz alacritty-3c3239b1cb4b21ee1dec8ccfbc5ec957b6e66798.zip |
Override default bindings with subset mode match
Fixes #2641.
Diffstat (limited to 'alacritty_terminal')
-rw-r--r-- | alacritty_terminal/src/input.rs | 142 |
1 files changed, 128 insertions, 14 deletions
diff --git a/alacritty_terminal/src/input.rs b/alacritty_terminal/src/input.rs index f4e38fa1..83ab0261 100644 --- a/alacritty_terminal/src/input.rs +++ b/alacritty_terminal/src/input.rs @@ -152,17 +152,17 @@ impl<T: Eq> Binding<T> { // the most likely item to fail so prioritizing it here allows more // checks to be short circuited. self.trigger == *input - && self.mode_matches(mode) - && self.not_mode_matches(mode) + && mode.contains(self.mode) + && !mode.intersects(self.notmode) && self.mods_match(mods, relaxed) } #[inline] pub fn triggers_match(&self, binding: &Binding<T>) -> bool { self.trigger == binding.trigger - && self.mode == binding.mode - && self.notmode == binding.notmode && self.mods == binding.mods + && (self.mode.contains(binding.mode) || binding.mode.contains(self.mode)) + && (self.notmode.contains(binding.notmode) || binding.notmode.contains(self.notmode)) } } @@ -173,16 +173,6 @@ impl<T> Binding<T> { self.action.execute(ctx, mouse_mode) } - #[inline] - fn mode_matches(&self, mode: TermMode) -> bool { - self.mode.is_empty() || mode.intersects(self.mode) - } - - #[inline] - fn not_mode_matches(&self, mode: TermMode) -> bool { - self.notmode.is_empty() || !mode.intersects(self.notmode) - } - /// Check that two mods descriptions for equivalence #[inline] fn mods_match(&self, mods: ModifiersState, relaxed: bool) -> bool { @@ -996,6 +986,130 @@ mod tests { const KEY: VirtualKeyCode = VirtualKeyCode::Key0; + type MockBinding = Binding<usize>; + + impl Default for MockBinding { + fn default() -> Self { + Self { + mods: Default::default(), + action: Default::default(), + mode: TermMode::empty(), + notmode: TermMode::empty(), + trigger: Default::default(), + } + } + } + + #[test] + fn binding_matches_itself() { + let binding = MockBinding::default(); + let identical_binding = MockBinding::default(); + + assert!(binding.triggers_match(&identical_binding)); + assert!(identical_binding.triggers_match(&binding)); + } + + #[test] + fn binding_matches_different_action() { + let binding = MockBinding::default(); + let mut different_action = MockBinding::default(); + different_action.action = Action::ClearHistory; + + assert!(binding.triggers_match(&different_action)); + assert!(different_action.triggers_match(&binding)); + } + + #[test] + fn subset_mode_binding_matches_superset() { + let mut superset_mode = MockBinding::default(); + superset_mode.mode = TermMode::ALT_SCREEN | TermMode::INSERT | TermMode::ORIGIN; + let mut subset_mode = MockBinding::default(); + subset_mode.mode = TermMode::ALT_SCREEN | TermMode::ORIGIN; + + assert!(superset_mode.triggers_match(&subset_mode)); + assert!(subset_mode.triggers_match(&superset_mode)); + } + + #[test] + fn subset_notmode_binding_matches_superset() { + let mut superset_notmode = MockBinding::default(); + superset_notmode.notmode = TermMode::ALT_SCREEN | TermMode::INSERT | TermMode::ORIGIN; + let mut subset_notmode = MockBinding::default(); + subset_notmode.notmode = TermMode::ALT_SCREEN | TermMode::ORIGIN; + + assert!(superset_notmode.triggers_match(&subset_notmode)); + assert!(subset_notmode.triggers_match(&superset_notmode)); + } + + #[test] + fn mods_binding_requires_strict_match() { + let mut superset_mods = MockBinding::default(); + superset_mods.mods = ModifiersState { alt: true, logo: true, ctrl: true, shift: true }; + let mut subset_mods = MockBinding::default(); + subset_mods.mods = ModifiersState { alt: true, logo: false, ctrl: false, shift: false }; + + assert!(!superset_mods.triggers_match(&subset_mods)); + assert!(!subset_mods.triggers_match(&superset_mods)); + } + + fn binding_trigger_input() { + let mut binding = MockBinding::default(); + binding.trigger = 13; + + let mods = binding.mods; + let mode = binding.mode; + + assert!(binding.is_triggered_by(mode, mods, &13, true)); + assert!(!binding.is_triggered_by(mode, mods, &32, true)); + } + + #[test] + fn binding_trigger_mods() { + let mut binding = MockBinding::default(); + binding.mods = ModifiersState { alt: true, logo: true, ctrl: false, shift: false }; + + let superset_mods = ModifiersState { alt: true, logo: true, ctrl: true, shift: true }; + let subset_mods = ModifiersState { alt: false, logo: false, ctrl: false, shift: false }; + + let t = binding.trigger; + let mode = binding.mode; + + assert!(binding.is_triggered_by(mode, binding.mods, &t, true)); + assert!(binding.is_triggered_by(mode, binding.mods, &t, false)); + + assert!(binding.is_triggered_by(mode, superset_mods, &t, true)); + assert!(!binding.is_triggered_by(mode, superset_mods, &t, false)); + + assert!(!binding.is_triggered_by(mode, subset_mods, &t, true)); + assert!(!binding.is_triggered_by(mode, subset_mods, &t, false)); + } + + #[test] + fn binding_trigger_modes() { + let mut binding = MockBinding::default(); + binding.mode = TermMode::ALT_SCREEN; + + let t = binding.trigger; + let mods = binding.mods; + + assert!(!binding.is_triggered_by(TermMode::INSERT, mods, &t, true)); + assert!(binding.is_triggered_by(TermMode::ALT_SCREEN, mods, &t, true)); + assert!(binding.is_triggered_by(TermMode::ALT_SCREEN | TermMode::INSERT, mods, &t, true)); + } + + #[test] + fn binding_trigger_notmodes() { + let mut binding = MockBinding::default(); + binding.notmode = TermMode::ALT_SCREEN; + + let t = binding.trigger; + let mods = binding.mods; + + assert!(binding.is_triggered_by(TermMode::INSERT, mods, &t, true)); + assert!(!binding.is_triggered_by(TermMode::ALT_SCREEN, mods, &t, true)); + assert!(!binding.is_triggered_by(TermMode::ALT_SCREEN | TermMode::INSERT, mods, &t, true)); + } + #[derive(PartialEq)] enum MultiClick { DoubleClick, |