summaryrefslogtreecommitdiffstats
path: root/alacritty_terminal/src/input.rs
diff options
context:
space:
mode:
authorChristian Duerr <chrisduerr@users.noreply.github.com>2019-07-15 21:32:48 +0000
committerGitHub <noreply@github.com>2019-07-15 21:32:48 +0000
commit3c3239b1cb4b21ee1dec8ccfbc5ec957b6e66798 (patch)
tree675fcd50d7f33dd6ce7667b3bbf6b99b044b1c1a /alacritty_terminal/src/input.rs
parent1c05b3bb0cfe29ddaa349906a7359f4b65e78f19 (diff)
Override default bindings with subset mode match
Fixes #2641.
Diffstat (limited to 'alacritty_terminal/src/input.rs')
-rw-r--r--alacritty_terminal/src/input.rs142
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,