pub use crate::components::keymap::{KeyBinding, KeyType, Modifiers};
#[derive(Debug, Clone)]
pub struct ViewportKeyMap {
pub up: Vec<KeyBinding>,
pub down: Vec<KeyBinding>,
pub page_up: Vec<KeyBinding>,
pub page_down: Vec<KeyBinding>,
pub half_page_up: Vec<KeyBinding>,
pub half_page_down: Vec<KeyBinding>,
pub goto_top: Vec<KeyBinding>,
pub goto_bottom: Vec<KeyBinding>,
pub left: Vec<KeyBinding>,
pub right: Vec<KeyBinding>,
pub goto_left: Vec<KeyBinding>,
pub goto_right: Vec<KeyBinding>,
}
impl Default for ViewportKeyMap {
fn default() -> Self {
Self {
up: vec![KeyBinding::special(KeyType::Up), KeyBinding::char('k')],
down: vec![KeyBinding::special(KeyType::Down), KeyBinding::char('j')],
page_up: vec![KeyBinding::special(KeyType::PageUp), KeyBinding::ctrl('b')],
page_down: vec![
KeyBinding::special(KeyType::PageDown),
KeyBinding::ctrl('f'),
KeyBinding::special(KeyType::Space),
],
half_page_up: vec![KeyBinding::ctrl('u')],
half_page_down: vec![KeyBinding::ctrl('d')],
goto_top: vec![KeyBinding::special(KeyType::Home), KeyBinding::char('g')],
goto_bottom: vec![KeyBinding::special(KeyType::End), KeyBinding::char('G')],
left: vec![KeyBinding::special(KeyType::Left), KeyBinding::char('h')],
right: vec![KeyBinding::special(KeyType::Right), KeyBinding::char('l')],
goto_left: vec![KeyBinding::char('0')],
goto_right: vec![KeyBinding::char('$')],
}
}
}
impl ViewportKeyMap {
pub fn new() -> Self {
Self::default()
}
pub fn arrows_only() -> Self {
Self {
up: vec![KeyBinding::special(KeyType::Up)],
down: vec![KeyBinding::special(KeyType::Down)],
page_up: vec![KeyBinding::special(KeyType::PageUp)],
page_down: vec![KeyBinding::special(KeyType::PageDown)],
half_page_up: vec![],
half_page_down: vec![],
goto_top: vec![KeyBinding::special(KeyType::Home)],
goto_bottom: vec![KeyBinding::special(KeyType::End)],
left: vec![KeyBinding::special(KeyType::Left)],
right: vec![KeyBinding::special(KeyType::Right)],
goto_left: vec![],
goto_right: vec![],
}
}
pub fn vim() -> Self {
Self {
up: vec![KeyBinding::char('k')],
down: vec![KeyBinding::char('j')],
page_up: vec![KeyBinding::ctrl('b')],
page_down: vec![KeyBinding::ctrl('f')],
half_page_up: vec![KeyBinding::ctrl('u')],
half_page_down: vec![KeyBinding::ctrl('d')],
goto_top: vec![KeyBinding::char('g')],
goto_bottom: vec![KeyBinding::char('G')],
left: vec![KeyBinding::char('h')],
right: vec![KeyBinding::char('l')],
goto_left: vec![KeyBinding::char('0')],
goto_right: vec![KeyBinding::char('$')],
}
}
pub fn disabled() -> Self {
Self {
up: vec![],
down: vec![],
page_up: vec![],
page_down: vec![],
half_page_up: vec![],
half_page_down: vec![],
goto_top: vec![],
goto_bottom: vec![],
left: vec![],
right: vec![],
goto_left: vec![],
goto_right: vec![],
}
}
pub fn match_action(&self, input: &str, key: &crate::hooks::Key) -> Option<ViewportAction> {
let checks: &[(&[KeyBinding], ViewportAction)] = &[
(&self.up, ViewportAction::ScrollUp),
(&self.down, ViewportAction::ScrollDown),
(&self.page_up, ViewportAction::PageUp),
(&self.page_down, ViewportAction::PageDown),
(&self.half_page_up, ViewportAction::HalfPageUp),
(&self.half_page_down, ViewportAction::HalfPageDown),
(&self.goto_top, ViewportAction::GotoTop),
(&self.goto_bottom, ViewportAction::GotoBottom),
(&self.left, ViewportAction::ScrollLeft),
(&self.right, ViewportAction::ScrollRight),
(&self.goto_left, ViewportAction::GotoLeft),
(&self.goto_right, ViewportAction::GotoRight),
];
for (bindings, action) in checks {
for binding in *bindings {
if binding.matches(input, key) {
return Some(*action);
}
}
}
None
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViewportAction {
ScrollUp,
ScrollDown,
PageUp,
PageDown,
HalfPageUp,
HalfPageDown,
GotoTop,
GotoBottom,
ScrollLeft,
ScrollRight,
GotoLeft,
GotoRight,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_keymap() {
let keymap = ViewportKeyMap::default();
assert!(!keymap.up.is_empty());
assert!(!keymap.down.is_empty());
}
#[test]
fn test_vim_keymap() {
let keymap = ViewportKeyMap::vim();
assert!(keymap.up.iter().any(|b| b.key == KeyType::Char('k')));
assert!(keymap.down.iter().any(|b| b.key == KeyType::Char('j')));
}
#[test]
fn test_disabled_keymap() {
let keymap = ViewportKeyMap::disabled();
assert!(keymap.up.is_empty());
assert!(keymap.down.is_empty());
}
}