use keymap_core::{Key, KeyInput, Keymap, LegacyForm, Modifiers, resolve_layered};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Action {
Save,
Quit,
}
fn plain(c: char) -> KeyInput {
KeyInput::new(Key::Char(c), Modifiers::NONE)
}
fn ctrl(c: char) -> KeyInput {
KeyInput::new(Key::Char(c), Modifiers::CTRL)
}
fn esc() -> KeyInput {
KeyInput::new(Key::Esc, Modifiers::NONE)
}
fn would_break_escape<A: Clone + PartialEq>(
layers: &[&Keymap<A>],
target: usize,
proposed: KeyInput,
action: A,
reserved: &[KeyInput],
) -> bool {
if let LegacyForm::CollapsesTo(byte_twin) = proposed.legacy_form() {
if reserved.contains(&byte_twin) {
return true;
}
}
let mut simulated: Vec<Keymap<A>> = layers.iter().map(|l| (*l).clone()).collect();
simulated[target].bind(proposed, action);
reserved.iter().any(|&r| {
resolve_layered(layers.iter().copied(), &r) != resolve_layered(simulated.iter(), &r)
})
}
#[test]
fn direct_theft_of_a_reserved_key_is_refused() {
let global: Keymap<Action> = Keymap::new();
let reserved = [esc()];
assert!(would_break_escape(
&[&global],
0,
esc(),
Action::Save,
&reserved
));
}
#[test]
fn an_upper_layer_shadowing_a_reserved_key_is_refused() {
let mut base = Keymap::new();
base.bind(esc(), Action::Quit); let overlay: Keymap<Action> = Keymap::new();
let reserved = [esc()];
assert!(would_break_escape(
&[&overlay, &base],
0, esc(),
Action::Save,
&reserved
));
}
#[test]
fn rebinding_a_reserved_key_in_a_shadowed_lower_layer_is_allowed() {
let mut overlay = Keymap::new();
overlay.bind(esc(), Action::Quit);
let base: Keymap<Action> = Keymap::new();
let reserved = [esc()];
assert!(!would_break_escape(
&[&overlay, &base],
1, esc(),
Action::Save,
&reserved
));
}
#[test]
fn rebinding_a_reserved_key_to_its_own_current_action_is_allowed() {
let mut global = Keymap::new();
global.bind(esc(), Action::Quit);
let reserved = [esc()];
assert!(!would_break_escape(
&[&global],
0,
esc(),
Action::Quit, &reserved
));
}
#[test]
fn a_legacy_collapse_onto_a_reserved_key_is_refused() {
let global: Keymap<Action> = Keymap::new();
let reserved = [KeyInput::new(Key::Tab, Modifiers::NONE)];
assert!(would_break_escape(
&[&global],
0,
ctrl('i'),
Action::Save,
&reserved
));
}
#[test]
fn an_ordinary_rebind_is_allowed() {
let mut global = Keymap::new();
global.bind(ctrl('s'), Action::Quit);
let reserved = [esc()];
assert!(!would_break_escape(
&[&global],
0,
ctrl('s'),
Action::Save,
&reserved
));
}
#[test]
fn validation_does_not_mutate_the_live_keymap() {
let global: Keymap<Action> = Keymap::new();
let reserved = [esc()];
assert!(would_break_escape(
&[&global],
0,
esc(),
Action::Save,
&reserved
));
assert_eq!(global.get(&esc()), None);
assert!(global.is_empty());
}
#[test]
fn multiple_reserved_keys_are_all_protected() {
let global: Keymap<Action> = Keymap::new();
let reserved = [esc(), ctrl('c'), plain('q')];
assert!(would_break_escape(
&[&global],
0,
plain('q'),
Action::Save,
&reserved
));
}