1mod bindings;
2pub mod command;
3
4pub use bindings::handle_key_event;
5pub use command::{Command, Direction};
6
7use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
8use std::collections::HashMap;
9
10#[derive(Default)]
12pub struct Keymap {
13 bindings: HashMap<(KeyCode, KeyModifiers), Command>,
14 selection_overrides: HashMap<(KeyCode, KeyModifiers), Command>,
15}
16
17impl Keymap {
18 pub fn bind(&mut self, key: KeyCode, modifiers: KeyModifiers, command: Command) -> &mut Self {
20 self.bindings.insert((key, modifiers), command);
21 self
22 }
23
24 pub fn unbind(&mut self, key: KeyCode, modifiers: KeyModifiers) -> &mut Self {
26 self.bindings.remove(&(key, modifiers));
27 self
28 }
29
30 pub fn bind_selection(
32 &mut self,
33 key: KeyCode,
34 modifiers: KeyModifiers,
35 command: Command,
36 ) -> &mut Self {
37 self.selection_overrides.insert((key, modifiers), command);
38 self
39 }
40
41 pub fn get_command(&self, event: KeyEvent, selection_mode: bool) -> Option<Command> {
43 if selection_mode {
45 if let Some(cmd) = self.selection_overrides.get(&(event.code, event.modifiers)) {
46 return Some(cmd.clone());
47 }
48 }
49
50 if let Some(cmd) = self.bindings.get(&(event.code, event.modifiers)) {
52 return Some(cmd.clone());
53 }
54
55 handle_key_event(event, selection_mode)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_custom_keymap() {
66 let mut keymap = Keymap::default();
67 keymap.bind(KeyCode::Char('s'), KeyModifiers::CONTROL, Command::Save);
68
69 let event = KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL);
70 assert_eq!(keymap.get_command(event, false), Some(Command::Save));
71 }
72
73 #[test]
74 fn test_unbind() {
75 let mut keymap = Keymap::default();
76 keymap.bind(KeyCode::Char('q'), KeyModifiers::CONTROL, Command::Quit);
77 keymap.unbind(KeyCode::Char('q'), KeyModifiers::CONTROL);
78
79 let event = KeyEvent::new(KeyCode::Char('q'), KeyModifiers::CONTROL);
80 assert_eq!(keymap.get_command(event, false), Some(Command::Quit));
82 }
83}