1use std::collections::HashMap;
2
3use thiserror::Error;
4
5use crate::events::Key;
6
7#[derive(Error, Debug, Clone, PartialEq)]
9pub enum KeybindingError {
10 #[error("conflict: {0} is already bound to {1}")]
12 Conflict(String, String),
13}
14
15pub struct KeybindingsManager {
20 bindings: HashMap<String, Key>,
21 reverse: HashMap<Key, String>,
22}
23
24pub fn default_bindings() -> Vec<(String, Key)> {
51 vec![
52 ("editor.cursorLeft".into(), Key::left()),
53 ("editor.cursorRight".into(), Key::right()),
54 ("editor.cursorUp".into(), Key::up()),
55 ("editor.cursorDown".into(), Key::down()),
56 ("editor.wordForward".into(), Key::ctrl('f')),
57 ("editor.wordBackward".into(), Key::ctrl('b')),
58 ("editor.lineStart".into(), Key::home()),
59 ("editor.lineEnd".into(), Key::end()),
60 ("editor.deleteChar".into(), Key::delete()),
61 ("editor.undo".into(), Key::ctrl('-')),
62 ("editor.redo".into(), Key::ctrl_shift('z')),
63 ("editor.yankLine".into(), Key::ctrl('y')),
64 ("editor.paste".into(), Key::ctrl('v')),
65 ("editor.insertMode".into(), Key::char('i')),
66 ("editor.normalMode".into(), Key::esc()),
67 ("input.submit".into(), Key::enter()),
68 ("input.backspace".into(), Key::backspace()),
69 ("input.delete".into(), Key::delete()),
70 ("select.next".into(), Key::down()),
71 ("select.prev".into(), Key::up()),
72 ("select.confirm".into(), Key::enter()),
73 ("select.cancel".into(), Key::esc()),
74 ]
75}
76
77impl Default for KeybindingsManager {
78 fn default() -> Self {
79 let mut mgr = Self {
80 bindings: HashMap::new(),
81 reverse: HashMap::new(),
82 };
83 for (action, key) in default_bindings() {
84 mgr.bindings.insert(action.clone(), key.clone());
85 mgr.reverse.insert(key, action);
86 }
87 mgr
88 }
89}
90
91impl KeybindingsManager {
92 pub fn new() -> Self {
94 Self::default()
95 }
96
97 pub fn get(&self, action: &str) -> Option<&Key> {
99 self.bindings.get(action)
100 }
101
102 pub fn set(&mut self, action: &str, key: Key) -> Result<(), KeybindingError> {
106 if let Some(existing_action) = self.reverse.get(&key) {
107 if existing_action != action {
108 return Err(KeybindingError::Conflict(
109 format!("{:?}", key),
110 existing_action.clone(),
111 ));
112 }
113 }
114 if let Some(old_key) = self.bindings.get(action) {
115 self.reverse.remove(old_key);
116 }
117 self.bindings.insert(action.to_string(), key.clone());
118 self.reverse.insert(key, action.to_string());
119 Ok(())
120 }
121
122 pub fn detect_conflicts(&self) -> Vec<(String, String)> {
126 let mut conflicts = Vec::new();
127 let mut seen: HashMap<&Key, &String> = HashMap::new();
128 for (action, key) in &self.bindings {
129 if let Some(other) = seen.get(key) {
130 conflicts.push((action.clone(), other.to_string()));
131 } else {
132 seen.insert(key, action);
133 }
134 }
135 conflicts
136 }
137}