Merge pull request #468 from a-kenji/partial-unbind-modes

Add more Functionality to Unbind
This commit is contained in:
a-kenji 2021-05-07 15:07:23 +02:00 committed by GitHub
commit c6ec5b22c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 800 additions and 15 deletions

View File

@ -101,6 +101,34 @@ where "normal" stands for a mode name (see MODES section), "action" part
specifies the actions to be executed by Zellij (see ACTIONS section) and "key" specifies the actions to be executed by Zellij (see ACTIONS section) and "key"
is used to list keys or key combinations bound to given actions (see KEYS). is used to list keys or key combinations bound to given actions (see KEYS).
The default keybinds can be unbound either for a specific mode, or for every mode.
It supports either a list of `keybinds`, or a bool indicating that every keybind
should be unbound:
```
keybinds:
unbind: true
```
Will unbind every default binding.
```
keybinds:
unbind: [ Ctrl: 'p']
```
Will unbind every default `^P` binding for each mode.
```
keybinds:
normal:
- unbind: true
```
Will unbind every default keybind for the `normal` mode.
```
keybinds:
normal:
- unbind: [ Alt: 'n', Ctrl: 'g']
```
Will unbind every default keybind for `n` and `^g` for the `normal` mode.
ACTIONS ACTIONS
------- -------

View File

@ -206,7 +206,7 @@ impl Layout {
} }
// It wants to use Path here, but that doesn't compile. // It wants to use Path here, but that doesn't compile.
#[warn(clippy::ptr_arg)] #[allow(clippy::ptr_arg)]
pub fn from_defaults(layout_path: &PathBuf, data_dir: &Path) -> Self { pub fn from_defaults(layout_path: &PathBuf, data_dir: &Path) -> Self {
Self::new( Self::new(
&data_dir &data_dir

View File

@ -29,8 +29,14 @@ pub struct KeybindsFromYaml {
#[serde(untagged)] #[serde(untagged)]
enum KeyActionUnbind { enum KeyActionUnbind {
KeyAction(KeyActionFromYaml), 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 /// Intermediate struct used for deserialisation
@ -41,7 +47,7 @@ pub struct KeyActionFromYaml {
} }
/// Intermediate struct used for deserialisation /// Intermediate struct used for deserialisation
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)] #[derive(Clone, Debug, PartialEq, Deserialize)]
struct UnbindFromYaml { struct UnbindFromYaml {
unbind: Unbind, unbind: Unbind,
} }
@ -51,16 +57,19 @@ struct UnbindFromYaml {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)]
#[serde(untagged)] #[serde(untagged)]
enum Unbind { 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), All(bool),
// TODO@a-kenji: use the enum
//Keys(Vec<Key>),
} }
impl Default for Keybinds { impl Default for Keybinds {
// Use once per codepath
// TODO investigate why
fn default() -> Keybinds { fn default() -> Keybinds {
config::Config::from_default_assets() Self::from_default_assets()
.expect("Keybinds from default assets Error")
.keybinds
} }
} }
@ -69,11 +78,18 @@ impl Keybinds {
Keybinds(HashMap::<InputMode, ModeKeybinds>::new()) 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 { pub fn get_default_keybinds_with_config(from_yaml: Option<KeybindsFromYaml>) -> Keybinds {
let default_keybinds = match from_yaml.clone() { let default_keybinds = match from_yaml.clone() {
Some(keybinds) => match keybinds.unbind { Some(keybinds) => match keybinds.unbind {
Unbind::All(true) => Keybinds::new(), Unbind::All(true) => Keybinds::new(),
Unbind::All(false) => Keybinds::default(), Unbind::All(false) | Unbind::Keys(_) => Keybinds::unbind(keybinds),
}, },
None => Keybinds::default(), 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 /// Merges two Keybinds structs into one Keybinds struct
/// `other` overrides the ModeKeybinds of `self`. /// `other` overrides the ModeKeybinds of `self`.
fn merge_keybinds(&self, other: Keybinds) -> Keybinds { fn merge_keybinds(&self, other: Keybinds) -> Keybinds {
@ -142,6 +223,15 @@ impl ModeKeybinds {
merged.0.extend(other.0); merged.0.extend(other.0);
merged 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 { impl From<KeybindsFromYaml> for Keybinds {
@ -161,30 +251,44 @@ impl From<KeybindsFromYaml> for Keybinds {
} }
} }
/// For each `Key` assigned to `Action`s, /// For each [`Key`] assigned to [`Action`]s,
/// map the `Action`s to the key /// map the [`Action`]s to the [`Key`]
impl From<KeyActionFromYaml> for ModeKeybinds { impl From<KeyActionFromYaml> for ModeKeybinds {
fn from(key_action: KeyActionFromYaml) -> ModeKeybinds { fn from(key_action: KeyActionFromYaml) -> ModeKeybinds {
let keys = key_action.key;
let actions = key_action.action; let actions = key_action.action;
ModeKeybinds( ModeKeybinds(
keys.into_iter() key_action
.key
.into_iter()
.map(|k| (k, actions.clone())) .map(|k| (k, actions.clone()))
.collect::<HashMap<Key, Vec<Action>>>(), .collect::<HashMap<Key, Vec<Action>>>(),
) )
} }
} }
// Currently an enum for future use
impl From<KeyActionUnbind> for ModeKeybinds { impl From<KeyActionUnbind> for ModeKeybinds {
fn from(key_action_unbind: KeyActionUnbind) -> ModeKeybinds { fn from(key_action_unbind: KeyActionUnbind) -> ModeKeybinds {
match key_action_unbind { match key_action_unbind {
KeyActionUnbind::KeyAction(key_action) => ModeKeybinds::from(key_action), 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
}
}
impl Default for Unbind { impl Default for Unbind {
fn default() -> Unbind { fn default() -> Unbind {
Unbind::All(false) Unbind::All(false)

View File

@ -136,6 +136,7 @@ fn toplevel_unbind_unbinds_all() {
assert_eq!(keybinds_from_yaml, Keybinds::new()); assert_eq!(keybinds_from_yaml, Keybinds::new());
} }
#[test]
fn no_unbind_unbinds_none() { fn no_unbind_unbinds_none() {
let from_yaml = KeybindsFromYaml { let from_yaml = KeybindsFromYaml {
unbind: Unbind::All(false), 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)); 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()); 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());
}