extern crate keymap_dev as keymap;
#[derive(Debug, PartialEq, Eq, keymap_derive::KeyMap, Clone)]
enum Action {
#[key("enter", "ctrl-b n")]
Create,
#[key("d", "delete", "d d", "@lower")]
Delete,
#[key("esc", "q")]
Quit,
#[key("@digit")]
Digit(char),
#[key("@any")]
Jump(char),
}
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq, Clone)]
enum NoDefault {
A,
B,
}
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq, keymap_derive::KeyMap, Clone)]
enum IgnoreTest {
#[key("a")]
Active,
#[key(ignore)]
Ignored,
#[key(ignore)]
IgnoredWithData(NoDefault),
}
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq, keymap_derive::KeyMap, Clone)]
enum CustomSymbolTest {
#[key("ctrl-b", symbol = "^B", help = "jump over obstacles")]
Active,
#[key("ctrl-b", help = "do jump")]
FallbackSymbol,
#[key("ctrl-b")]
NoSymbolOrHelp,
}
#[cfg(test)]
mod tests {
use keymap_dev::{Error, Item, KeyMap, KeyMapConfig, ToKeyMap};
use super::*;
struct Wrapper(keymap_parser::Node);
fn wrap(s: &str) -> Vec<Wrapper> {
keymap_parser::parse_seq(s)
.unwrap()
.into_iter()
.map(Wrapper)
.collect()
}
impl ToKeyMap for Wrapper {
fn to_keymap(&self) -> Result<KeyMap, Error> {
Ok(self.0.clone())
}
}
#[test]
fn test_derive_key() {
let config = Action::keymap_config();
[
(Action::Create, "enter"),
(Action::Delete, "d"),
(Action::Delete, "d d"),
(Action::Delete, "delete"),
]
.iter()
.for_each(|(action, input)| {
let key = keymap_parser::parse_seq(input).unwrap();
assert_eq!(action, config.get_item_by_keymaps(&key).unwrap().0);
});
}
#[test]
fn test_derive_char_group() {
let config = Action::keymap_config();
[
(Action::Delete, "x"), (Action::Digit('\0'), "1"), ]
.iter()
.for_each(|(action, input)| {
let key = keymap_parser::parse_seq(input).unwrap();
assert_eq!(action, config.get_item_by_keymaps(&key).unwrap().0);
});
}
#[test]
fn test_keymap_config() {
let config = Action::keymap_config();
assert_eq!(
config.items,
vec![
(
Action::Create,
Item::new(
["enter", "ctrl-b n"].map(ToString::to_string).to_vec(),
"Create a new file.\nMulti-line support.".to_string()
)
),
(
Action::Delete,
Item::new(
["d", "delete", "d d", "@lower"]
.map(ToString::to_string)
.to_vec(),
"Delete a file".to_string()
)
),
(
Action::Quit,
Item::new(
["esc", "q"].map(ToString::to_string).to_vec(),
"Quit".to_string()
)
),
(
Action::Digit('\0'),
Item::new(
["@digit"].map(ToString::to_string).to_vec(),
"Digit with char argument".to_string()
)
),
(
Action::Jump('\0'),
Item::new(
["@any"].map(ToString::to_string).to_vec(),
"Jump with char argument".to_string()
)
),
]
);
}
#[test]
fn test_bound_payload_extraction() {
let config = Action::keymap_config();
[
("1", Action::Digit('1')),
("A", Action::Jump('A')),
("enter", Action::Create),
]
.into_iter()
.for_each(|(input, expected)| {
assert_eq!(expected, config.get_bound_seq(&wrap(input)).unwrap());
});
let nodes = wrap("Q").into_iter().map(|w| w.0).collect::<Vec<_>>();
let (bound_action, item) = config.get_bound_item_by_keymaps(&nodes).unwrap();
assert_eq!(bound_action, Action::Jump('Q'));
assert_eq!(item.description, "Jump with char argument");
let space = vec![Wrapper(keymap_parser::Node::new(
0,
keymap_parser::node::Key::Space,
))];
assert_eq!(Action::Jump(' '), config.get_bound_seq(&space).unwrap());
}
#[test]
fn test_key_ignore_not_in_config() {
let config = IgnoreTest::keymap_config();
assert_eq!(config.items.len(), 1);
assert_eq!(
config.items[0],
(
IgnoreTest::Active,
Item::new(
["a"].map(ToString::to_string).to_vec(),
"Active variant".to_string()
)
)
);
}
#[test]
fn test_ignored_variant_no_default_required() {
let config = IgnoreTest::keymap_config();
assert!(!config
.items
.iter()
.any(|(v, _)| matches!(v, IgnoreTest::Ignored)));
assert!(!config
.items
.iter()
.any(|(v, _)| matches!(v, IgnoreTest::IgnoredWithData(_))));
}
#[test]
fn test_custom_symbol_and_help() {
let config = CustomSymbolTest::keymap_config();
let (_, item1) = &config.items[0];
assert_eq!(item1.symbol.as_deref(), Some("^B"));
assert_eq!(item1.help.as_deref(), Some("jump over obstacles"));
let (_, item2) = &config.items[1];
assert_eq!(item2.symbol.as_deref(), Some("ctrl-b"));
assert_eq!(item2.help.as_deref(), Some("do jump"));
let (_, item3) = &config.items[2];
assert_eq!(item3.symbol.as_deref(), Some("ctrl-b"));
assert_eq!(item3.help.as_deref(), None);
}
}