diff options
| author | a-kenji <aks.kenji@protonmail.com> | 2021-05-07 15:07:23 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-07 15:07:23 +0200 |
| commit | c6ec5b22c9bdbc877d8ccd2c90f927b0e17c9b87 (patch) | |
| tree | be3c795d96d836e290ac39ab0bf8731c1d1d20df /src/common/input | |
| parent | chore(version): bump development version (diff) | |
| parent | !fixup Add more Functionality to Unbind (diff) | |
| download | sl0ppij-c6ec5b22c9bdbc877d8ccd2c90f927b0e17c9b87.tar.gz sl0ppij-c6ec5b22c9bdbc877d8ccd2c90f927b0e17c9b87.tar.xz sl0ppij-c6ec5b22c9bdbc877d8ccd2c90f927b0e17c9b87.zip | |
Merge pull request #468 from a-kenji/partial-unbind-modes
Add more Functionality to Unbind
Diffstat (limited to 'src/common/input')
| -rw-r--r-- | src/common/input/keybinds.rs | 132 | ||||
| -rw-r--r-- | src/common/input/unit/keybinds_test.rs | 653 |
2 files changed, 771 insertions, 14 deletions
diff --git a/src/common/input/keybinds.rs b/src/common/input/keybinds.rs index 9842fbe2..823ca264 100644 --- a/src/common/input/keybinds.rs +++ b/src/common/input/keybinds.rs @@ -29,8 +29,14 @@ pub struct KeybindsFromYaml { #[serde(untagged)] enum KeyActionUnbind { KeyAction(KeyActionFromYaml), - // TODO: use the enum - //Unbind(UnbindFromYaml), + Unbind(UnbindFromYaml), +} + +/// Intermediate struct used for deserialisation +#[derive(Clone, Debug, PartialEq, Deserialize)] +struct KeyActionUnbindFromYaml { + keybinds: Vec<KeyActionFromYaml>, + unbind: Unbind, } /// Intermediate struct used for deserialisation @@ -41,7 +47,7 @@ pub struct KeyActionFromYaml { } /// Intermediate struct used for deserialisation -#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)] +#[derive(Clone, Debug, PartialEq, Deserialize)] struct UnbindFromYaml { unbind: Unbind, } @@ -51,16 +57,19 @@ struct UnbindFromYaml { #[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)] #[serde(untagged)] enum Unbind { + // This is the correct order, don't rearrange! + // Suspected Bug in the untagged macro. + // 1. Keys + Keys(Vec<Key>), + // 2. All All(bool), - // TODO@a-kenji: use the enum - //Keys(Vec<Key>), } impl Default for Keybinds { + // Use once per codepath + // TODO investigate why fn default() -> Keybinds { - config::Config::from_default_assets() - .expect("Keybinds from default assets Error") - .keybinds + Self::from_default_assets() } } @@ -69,11 +78,18 @@ impl Keybinds { Keybinds(HashMap::<InputMode, ModeKeybinds>::new()) } + fn from_default_assets() -> Keybinds { + config::Config::from_default_assets() + .expect("Keybinds from default assets Error!") + .keybinds + } + + /// Entrypoint from the config module pub fn get_default_keybinds_with_config(from_yaml: Option<KeybindsFromYaml>) -> Keybinds { let default_keybinds = match from_yaml.clone() { Some(keybinds) => match keybinds.unbind { Unbind::All(true) => Keybinds::new(), - Unbind::All(false) => Keybinds::default(), + Unbind::All(false) | Unbind::Keys(_) => Keybinds::unbind(keybinds), }, None => Keybinds::default(), }; @@ -85,6 +101,71 @@ impl Keybinds { } } + /// Unbinds the default keybindings in relation to their mode + fn unbind(from_yaml: KeybindsFromYaml) -> Keybinds { + let mut keybind_config = Self::new(); + let mut unbind_config: HashMap<InputMode, Unbind> = HashMap::new(); + let keybinds_from_yaml = from_yaml.keybinds; + + for mode in InputMode::iter() { + if let Some(keybinds) = keybinds_from_yaml.get(&mode) { + for keybind in keybinds.iter() { + match keybind { + KeyActionUnbind::Unbind(unbind) => { + unbind_config.insert(mode, unbind.unbind.clone()); + } + KeyActionUnbind::KeyAction(key_action_from_yaml) => { + keybind_config + .0 + .insert(mode, ModeKeybinds::from(key_action_from_yaml.clone())); + } + } + } + } + } + + let mut default = Self::default().unbind_mode(unbind_config); + + // Toplevel Unbinds + if let Unbind::Keys(_) = from_yaml.unbind { + let mut unbind_config: HashMap<InputMode, Unbind> = HashMap::new(); + for mode in InputMode::iter() { + unbind_config.insert(mode, from_yaml.unbind.clone()); + } + default = default.unbind_mode(unbind_config); + }; + + default.merge_keybinds(keybind_config) + } + + /// Unbind [`Key`] bindings respective to their mode + fn unbind_mode(&self, unbind: HashMap<InputMode, Unbind>) -> Keybinds { + let mut keybinds = Keybinds::new(); + + for mode in InputMode::iter() { + if let Some(unbind) = unbind.get(&mode) { + match unbind { + Unbind::All(true) => {} + Unbind::Keys(keys) => { + if let Some(defaults) = self.0.get(&mode) { + keybinds + .0 + .insert(mode, defaults.clone().unbind_keys(keys.to_vec())); + } + } + Unbind::All(false) => { + if let Some(defaults) = self.0.get(&mode) { + keybinds.0.insert(mode, defaults.clone()); + } + } + } + } else if let Some(defaults) = self.0.get(&mode) { + keybinds.0.insert(mode, defaults.clone()); + } + } + keybinds + } + /// Merges two Keybinds structs into one Keybinds struct /// `other` overrides the ModeKeybinds of `self`. fn merge_keybinds(&self, other: Keybinds) -> Keybinds { @@ -142,6 +223,15 @@ impl ModeKeybinds { merged.0.extend(other.0); merged } + + /// Remove [`Key`]'s from [`ModeKeybinds`] + fn unbind_keys(self, unbind: Vec<Key>) -> Self { + let mut keymap = self; + for key in unbind { + keymap.0.remove(&key); + } + keymap + } } impl From<KeybindsFromYaml> for Keybinds { @@ -161,27 +251,41 @@ impl From<KeybindsFromYaml> for Keybinds { } } -/// For each `Key` assigned to `Action`s, -/// map the `Action`s to the key +/// For each [`Key`] assigned to [`Action`]s, +/// map the [`Action`]s to the [`Key`] impl From<KeyActionFromYaml> for ModeKeybinds { fn from(key_action: KeyActionFromYaml) -> ModeKeybinds { - let keys = key_action.key; let actions = key_action.action; ModeKeybinds( - keys.into_iter() + key_action + .key + .into_iter() .map(|k| (k, actions.clone())) .collect::<HashMap<Key, Vec<Action>>>(), ) } } -// Currently an enum for future use impl From<KeyActionUnbind> for ModeKeybinds { fn from(key_action_unbind: KeyActionUnbind) -> ModeKeybinds { match key_action_unbind { KeyActionUnbind::KeyAction(key_action) => ModeKeybinds::from(key_action), + KeyActionUnbind::Unbind(_) => ModeKeybinds::new(), + } + } +} + +impl From<Vec<KeyActionFromYaml>> for ModeKeybinds { + fn from(key_action_from_yaml: Vec<KeyActionFromYaml>) -> ModeKeybinds { + let mut mode_keybinds = ModeKeybinds::new(); + + for keybind in key_action_from_yaml { + for key in keybind.key { + mode_keybinds.0.insert(key, keybind.action.clone()); + } } + mode_keybinds } } diff --git a/src/common/input/unit/keybinds_test.rs b/src/common/input/unit/keybinds_test.rs index e0d78b62..4767fc15 100644 --- a/src/common/input/unit/keybinds_test.rs +++ b/src/common/input/unit/keybinds_test.rs @@ -136,6 +136,7 @@ fn toplevel_unbind_unbinds_all() { assert_eq!(keybinds_from_yaml, Keybinds::new()); } +#[test] fn no_unbind_unbinds_none() { let from_yaml = KeybindsFromYaml { unbind: Unbind::All(false), @@ -144,5 +145,657 @@ fn no_unbind_unbinds_none() { let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + assert_eq!(keybinds_from_yaml, Keybinds::default()); +} + +#[test] +fn last_keybind_is_taken() { + let actions_1 = vec![Action::NoOp, Action::NewTab]; + let keyaction_1 = KeyActionFromYaml { + action: actions_1.clone(), + key: vec![Key::F(1), Key::Backspace, Key::Char('t')], + }; + let actions_2 = vec![Action::GoToTab(1)]; + let keyaction_2 = KeyActionFromYaml { + action: actions_2.clone(), + key: vec![Key::F(1), Key::Backspace, Key::Char('t')], + }; + + let mut expected = ModeKeybinds::new(); + expected.0.insert(Key::F(1), actions_2.clone()); + expected.0.insert(Key::Backspace, actions_2.clone()); + expected.0.insert(Key::Char('t'), actions_2); + + assert_eq!(expected, ModeKeybinds::from(vec![keyaction_1, keyaction_2])); +} + +#[test] +fn last_keybind_overwrites() { + let actions_1 = vec![Action::NoOp, Action::NewTab]; + let keyaction_1 = KeyActionFromYaml { + action: actions_1.clone(), + key: vec![Key::F(1), Key::Backspace, Key::Char('t')], + }; + let actions_2 = vec![Action::GoToTab(1)]; + let keyaction_2 = KeyActionFromYaml { + action: actions_2.clone(), + key: vec![Key::F(1), Key::Char('t')], + }; + + let mut expected = ModeKeybinds::new(); + expected.0.insert(Key::F(1), actions_2.clone()); + expected.0.insert(Key::Backspace, actions_1.clone()); + expected.0.insert(Key::Char('t'), actions_2); + + assert_eq!(expected, ModeKeybinds::from(vec![keyaction_1, keyaction_2])); +} + +#[test] +fn unbind_single_mode() { + let unbind = Unbind::All(true); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbinds = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds); + + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let result = keybinds.0.get(&InputMode::Normal); + assert!(result.is_none()); +} + +#[test] +fn unbind_multiple_modes() { + let unbind = Unbind::All(true); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbinds = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds.clone()); + keys.insert(InputMode::Pane, key_action_unbinds); + + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let normal = keybinds.0.get(&InputMode::Normal); + let pane = keybinds.0.get(&InputMode::Pane); + assert!(normal.is_none()); + assert!(pane.is_none()); +} + +#[test] +fn unbind_single_keybind_single_mode() { + let unbind = Unbind::Keys(vec![Key::Alt('n')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbinds = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds); + + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let mode_keybinds = keybinds.0.get(&InputMode::Normal); + let result = mode_keybinds + .expect("Mode shouldn't be empty") + .0 + .get(&Key::Alt('n')); + assert!(result.is_none()); +} + +#[test] +fn unbind_single_keybind_multiple_modes() { + let unbind_n = Unbind::Keys(vec![Key::Alt('n')]); + let unbind_h = Unbind::Keys(vec![Key::Alt('h')]); + let unbind_from_yaml_n = UnbindFromYaml { unbind: unbind_n }; + let unbind_from_yaml_h = UnbindFromYaml { unbind: unbind_h }; + let key_action_unbinds_n = vec![KeyActionUnbind::Unbind(unbind_from_yaml_n)]; + let key_action_unbinds_h = vec![KeyActionUnbind::Unbind(unbind_from_yaml_h)]; + + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds_n); + keys.insert(InputMode::Pane, key_action_unbinds_h); + + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let normal = keybinds.0.get(&InputMode::Normal); + let pane = keybinds.0.get(&InputMode::Pane); + let result_normal = normal + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_pane = pane.expect("Mode shouldn't be empty").0.get(&Key::Alt('h')); + assert!(result_normal.is_none()); + assert!(result_pane.is_none()); +} + +#[test] +fn unbind_multiple_keybinds_single_mode() { + let unbind = Unbind::Keys(vec![Key::Alt('n'), Key::Ctrl('p')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbinds = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds); + + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let mode_keybinds = keybinds.0.get(&InputMode::Normal); + let result_n = mode_keybinds + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_p = mode_keybinds + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('p')); + assert!(result_n.is_none()); + assert!(result_p.is_none()); +} + +#[test] +fn unbind_multiple_keybinds_multiple_modes() { + let unbind_normal = Unbind::Keys(vec![Key::Alt('n'), Key::Ctrl('p')]); + let unbind_resize = Unbind::Keys(vec![Key::Char('h'), Key::Ctrl('r')]); + let unbind_from_yaml_normal = UnbindFromYaml { + unbind: unbind_normal, + }; + let unbind_from_yaml_resize = UnbindFromYaml { + unbind: unbind_resize, + }; + let key_action_unbinds_normal = vec![KeyActionUnbind::Unbind(unbind_from_yaml_normal)]; + let key_action_unbinds_resize = vec![KeyActionUnbind::Unbind(unbind_from_yaml_resize)]; + + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds_normal); + keys.insert(InputMode::Resize, key_action_unbinds_resize); + + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let mode_keybinds_normal = keybinds.0.get(&InputMode::Normal); + let mode_keybinds_resize = keybinds.0.get(&InputMode::Resize); + let result_normal_1 = mode_keybinds_normal + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_normal_2 = mode_keybinds_normal + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('p')); + let result_resize_1 = mode_keybinds_resize + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Char('h')); + let result_resize_2 = mode_keybinds_resize + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('r')); + assert!(result_normal_1.is_none()); + assert!(result_resize_1.is_none()); + assert!(result_normal_2.is_none()); + assert!(result_resize_2.is_none()); +} + +#[test] +fn unbind_multiple_keybinds_all_modes() { + let unbind = Unbind::Keys(vec![Key::Alt('n'), Key::Alt('h')]); + let keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + let keybinds_from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind, + }; + + let keybinds = Keybinds::unbind(keybinds_from_yaml); + let mode_keybinds_normal = keybinds.0.get(&InputMode::Normal); + let mode_keybinds_resize = keybinds.0.get(&InputMode::Resize); + let result_normal_1 = mode_keybinds_normal + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_normal_2 = mode_keybinds_normal + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('h')); + let result_resize_1 = mode_keybinds_resize + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Char('n')); + let result_resize_2 = mode_keybinds_resize + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('h')); + assert!(result_normal_1.is_none()); + assert!(result_resize_1.is_none()); + assert!(result_normal_2.is_none()); + assert!(result_resize_2.is_none()); +} + +#[test] +fn unbind_all_toplevel_single_key_single_mode() { + let unbind = Unbind::Keys(vec![Key::Alt('h')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbinds_normal = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds_normal); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(true), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + assert_eq!(keybinds_from_yaml, Keybinds::new()); +} + +#[test] +fn unbind_all_toplevel_single_key_multiple_modes() { + let unbind_n = Unbind::Keys(vec![Key::Alt('n')]); + let unbind_h = Unbind::Keys(vec![Key::Alt('h')]); + let unbind_from_yaml_n = UnbindFromYaml { unbind: unbind_n }; + let unbind_from_yaml_h = UnbindFromYaml { unbind: unbind_h }; + let key_action_unbinds_normal = vec![KeyActionUnbind::Unbind(unbind_from_yaml_n)]; + let key_action_unbinds_pane = vec![KeyActionUnbind::Unbind(unbind_from_yaml_h)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds_normal); + keys.insert(InputMode::Pane, key_action_unbinds_pane); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(true), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + assert_eq!(keybinds_from_yaml, Keybinds::new()); +} + +#[test] +fn unbind_all_toplevel_multiple_key_multiple_modes() { + let unbind_n = Unbind::Keys(vec![Key::Alt('n'), Key::Ctrl('p')]); + let unbind_h = Unbind::Keys(vec![Key::Alt('h'), Key::Ctrl('t')]); + let unbind_from_yaml_n = UnbindFromYaml { unbind: unbind_n }; + let unbind_from_yaml_h = UnbindFromYaml { unbind: unbind_h }; + let key_action_unbinds_normal = vec![KeyActionUnbind::Unbind(unbind_from_yaml_n)]; + let key_action_unbinds_pane = vec![KeyActionUnbind::Unbind(unbind_from_yaml_h)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds_normal); + keys.insert(InputMode::Pane, key_action_unbinds_pane); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(true), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); assert_eq!(keybinds_from_yaml, Keybinds::new()); } + +#[test] +fn unbind_all_toplevel_all_key_multiple_modes() { + let unbind = Unbind::All(true); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbinds_normal = vec![KeyActionUnbind::Unbind(unbind_from_yaml.clone())]; + let key_action_unbinds_pane = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbinds_normal); + keys.insert(InputMode::Pane, key_action_unbinds_pane); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(true), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + assert_eq!(keybinds_from_yaml, Keybinds::new()); +} + +#[test] +fn unbind_single_keybind_all_modes() { + let keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::Keys(vec![Key::Alt('n')]), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + + let result_normal = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_pane = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_resize = keybinds_from_yaml + .0 + .get(&InputMode::Resize) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_tab = keybinds_from_yaml + .0 + .get(&InputMode::Tab) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + + assert!(result_normal.is_none()); + assert!(result_pane.is_none()); + assert!(result_resize.is_none()); + assert!(result_tab.is_none()); +} + +#[test] +fn unbind_single_toplevel_single_key_single_mode_identical() { + let unbind = Unbind::Keys(vec![Key::Alt('n')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbind = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbind); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::Keys(vec![Key::Alt('n')]), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + + let result_normal = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_pane = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_resize = keybinds_from_yaml + .0 + .get(&InputMode::Resize) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_tab = keybinds_from_yaml + .0 + .get(&InputMode::Tab) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + + assert!(result_normal.is_none()); + assert!(result_pane.is_none()); + assert!(result_resize.is_none()); + assert!(result_tab.is_none()); +} + +#[test] +fn unbind_single_toplevel_single_key_single_mode_differing() { + let unbind = Unbind::Keys(vec![Key::Alt('l')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbind = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbind); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::Keys(vec![Key::Alt('n')]), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + + let result_normal_n = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_normal_l = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + let result_resize_n = keybinds_from_yaml + .0 + .get(&InputMode::Resize) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_resize_l = keybinds_from_yaml + .0 + .get(&InputMode::Resize) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + + assert!(result_normal_n.is_none()); + assert!(result_normal_l.is_none()); + assert!(result_resize_n.is_none()); + assert!(result_resize_l.is_some()); +} + +#[test] +fn unbind_single_toplevel_single_key_multiple_modes() { + let unbind = Unbind::Keys(vec![Key::Alt('l')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbind = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbind.clone()); + keys.insert(InputMode::Pane, key_action_unbind); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::Keys(vec![Key::Alt('n')]), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + + let result_normal_n = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_normal_l = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + let result_pane_n = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_pane_l = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + + assert!(result_normal_n.is_none()); + assert!(result_normal_l.is_none()); + assert!(result_pane_n.is_none()); + assert!(result_pane_l.is_none()); +} + +#[test] +fn unbind_single_toplevel_multiple_keys_single_mode() { + let unbind = Unbind::Keys(vec![ + Key::Alt('l'), + Key::Alt('h'), + Key::Alt('j'), + Key::Alt('k'), + ]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbind = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbind.clone()); + keys.insert(InputMode::Pane, key_action_unbind); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::Keys(vec![Key::Alt('n')]), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + + let result_normal_n = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_normal_l = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + let result_normal_k = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('k')); + let result_normal_h = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('h')); + + assert!(result_normal_n.is_none()); + assert!(result_normal_l.is_none()); + assert!(result_normal_h.is_none()); + assert!(result_normal_k.is_none()); +} + +#[test] +fn unbind_single_toplevel_multiple_keys_multiple_modes() { + let unbind_normal = Unbind::Keys(vec![Key::Alt('l'), Key::Ctrl('p')]); + let unbind_from_yaml_normal = UnbindFromYaml { + unbind: unbind_normal, + }; + let key_action_unbind_normal = vec![KeyActionUnbind::Unbind(unbind_from_yaml_normal)]; + let unbind = Unbind::Keys(vec![Key::Alt('l'), Key::Alt('k')]); + let unbind_from_yaml = UnbindFromYaml { unbind }; + let key_action_unbind = vec![KeyActionUnbind::Unbind(unbind_from_yaml)]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbind_normal); + keys.insert(InputMode::Pane, key_action_unbind); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::Keys(vec![Key::Alt('n')]), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + + let result_normal_n = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_normal_p = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('p')); + let result_normal_l = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + let result_pane_p = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Ctrl('p')); + let result_pane_n = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('n')); + let result_pane_l = keybinds_from_yaml + .0 + .get(&InputMode::Pane) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Alt('l')); + + assert!(result_normal_n.is_none()); + assert!(result_normal_l.is_none()); + assert!(result_normal_p.is_none()); + assert!(result_pane_n.is_none()); + assert!(result_pane_p.is_some()); + assert!(result_pane_l.is_none()); +} + +#[test] +fn uppercase_and_lowercase_are_distinct() { + let key_action_n = KeyActionFromYaml { + key: vec![Key::Char('n')], + action: vec![Action::NewTab], + }; + let key_action_large_n = KeyActionFromYaml { + key: vec![Key::Char('N')], + action: vec![Action::NewPane(None)], + }; + + let key_action_unbind = vec![ + KeyActionUnbind::KeyAction(key_action_n), + KeyActionUnbind::KeyAction(key_action_large_n), + ]; + let mut keys = HashMap::<InputMode, Vec<KeyActionUnbind>>::new(); + keys.insert(InputMode::Normal, key_action_unbind); + let from_yaml = KeybindsFromYaml { + keybinds: keys, + unbind: Unbind::All(false), + }; + + let keybinds_from_yaml = Keybinds::get_default_keybinds_with_config(Some(from_yaml)); + let result_n = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Char('n')); + let result_large_n = keybinds_from_yaml + .0 + .get(&InputMode::Normal) + .expect("ModeKeybinds shouldn't be empty") + .0 + .get(&Key::Char('N')); + + assert!(result_n.is_some()); + assert!(result_large_n.is_some()); +} |
