use crate::{Key, Keymap};
pub struct ScopeBuilder<'a, K: Key, S, A, C> {
keymap: &'a mut Keymap<K, S, A, C>,
scope: S,
}
impl<'a, K: Key, S, A, C> ScopeBuilder<'a, K, S, A, C> {
pub(super) fn new(keymap: &'a mut Keymap<K, S, A, C>, scope: S) -> Self {
Self { keymap, scope }
}
pub fn bind(&mut self, sequence: &str, action: A, category: C) -> &mut Self
where
K: Clone,
S: Clone + PartialEq,
A: Clone + std::fmt::Display,
C: Clone,
{
self.keymap
.bind(sequence, action, category, self.scope.clone());
self
}
pub fn catch_all<F>(&mut self, handler: F) -> &mut Self
where
F: Fn(&K) -> Option<A> + Send + Sync + 'static,
S: Clone + Ord,
C: Clone,
{
self.keymap.register_catch_all(self.scope.clone(), handler);
self
}
}
#[cfg(test)]
mod tests {
#![allow(dead_code)]
use super::*;
use crate::test_utils::{TestAction, TestCategory, TestScope};
use crate::{CrosstermKey, KeyNode};
#[test]
fn bind_with_navigation_category_works_correctly() {
let mut keymap = Keymap::new();
let mut builder = ScopeBuilder::new(&mut keymap, TestScope::Global);
builder.bind("h", TestAction::Open, TestCategory::Navigation);
let node = keymap.get_node_at_path(&[CrosstermKey::Char('h')]);
assert!(node.is_some());
if let Some(KeyNode::Leaf(entries)) = node {
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].category, TestCategory::Navigation);
assert_eq!(entries[0].action, TestAction::Open);
} else {
panic!("Expected leaf node with Navigation category");
}
}
#[test]
fn chaining_binds_first_key() {
let mut keymap = Keymap::new();
let mut builder = ScopeBuilder::new(&mut keymap, TestScope::Global);
builder.bind("q", TestAction::Quit, TestCategory::General);
let node = keymap.get_node_at_path(&[CrosstermKey::Char('q')]);
assert!(node.is_some());
if let Some(KeyNode::Leaf(entries)) = node {
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].action, TestAction::Quit);
} else {
panic!("Expected leaf node for 'q'");
}
}
#[test]
fn chaining_binds_second_key() {
let mut keymap = Keymap::new();
let mut builder = ScopeBuilder::new(&mut keymap, TestScope::Global);
builder.bind("h", TestAction::Open, TestCategory::Navigation);
let node = keymap.get_node_at_path(&[CrosstermKey::Char('h')]);
assert!(node.is_some());
if let Some(KeyNode::Leaf(entries)) = node {
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].action, TestAction::Open);
} else {
panic!("Expected leaf node for 'h'");
}
}
#[test]
fn chaining_binds_third_key() {
let mut keymap = Keymap::new();
let mut builder = ScopeBuilder::new(&mut keymap, TestScope::Global);
builder.bind("s", TestAction::Save, TestCategory::General);
let node = keymap.get_node_at_path(&[CrosstermKey::Char('s')]);
assert!(node.is_some());
if let Some(KeyNode::Leaf(entries)) = node {
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].action, TestAction::Save);
} else {
panic!("Expected leaf node for 's'");
}
}
}