From 7909d6f05e4d651d904886aa53ec4bd250294e73 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Sun, 20 Mar 2022 15:50:48 +0900 Subject: keymap: Store pending/sticky on the root level --- helix-term/src/keymap.rs | 148 ++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 80 deletions(-) (limited to 'helix-term/src/keymap.rs') diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 1059feae..e3cbcaad 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -328,26 +328,15 @@ impl<'a> KeymapResult<'a> { } #[derive(Debug, Clone, PartialEq, Deserialize)] +#[serde(transparent)] pub struct Keymap { /// Always a Node - #[serde(flatten)] root: KeyTrie, - /// Stores pending keys waiting for the next key. This is relative to a - /// sticky node if one is in use. - #[serde(skip)] - state: Vec, - /// Stores the sticky node if one is activated. - #[serde(skip)] - sticky: Option, } impl Keymap { pub fn new(root: KeyTrie) -> Self { - Keymap { - root, - state: Vec::new(), - sticky: None, - } + Keymap { root } } pub fn reverse_map(&self) -> HashMap>> { @@ -387,19 +376,65 @@ impl Keymap { &self.root } - pub fn sticky(&self) -> Option<&KeyTrieNode> { - self.sticky.as_ref() + pub fn merge(&mut self, other: Self) { + self.root.merge_nodes(other.root); + } +} + +impl Deref for Keymap { + type Target = KeyTrieNode; + + fn deref(&self) -> &Self::Target { + self.root.node().unwrap() } +} - /// Returns list of keys waiting to be disambiguated. +impl Default for Keymap { + fn default() -> Self { + Self::new(KeyTrie::Node(KeyTrieNode::default())) + } +} + +#[derive(Debug, Clone, PartialEq, Deserialize)] +pub struct Keymaps { + #[serde(flatten)] + pub map: HashMap, + + /// Stores pending keys waiting for the next key. This is relative to a + /// sticky node if one is in use. + #[serde(skip)] + state: Vec, + + /// Stores the sticky node if one is activated. + #[serde(skip)] + pub sticky: Option, +} + +impl Keymaps { + pub fn new(map: HashMap) -> Self { + Self { + map, + state: Vec::new(), + sticky: None, + } + } + + /// Returns list of keys waiting to be disambiguated in current mode. pub fn pending(&self) -> &[KeyEvent] { &self.state } + pub fn sticky(&self) -> Option<&KeyTrieNode> { + self.sticky.as_ref() + } + /// Lookup `key` in the keymap to try and find a command to execute. Escape /// key cancels pending keystrokes. If there are no pending keystrokes but a /// sticky node is in use, it will be cleared. - pub fn get(&mut self, key: KeyEvent) -> KeymapResult { + pub fn get(&mut self, mode: Mode, key: KeyEvent) -> KeymapResult { + // TODO: remove the sticky part and look up manually + let keymap = &self.map[&mode]; + if key!(Esc) == key { if !self.state.is_empty() { return KeymapResult::new( @@ -414,7 +449,7 @@ impl Keymap { let first = self.state.get(0).unwrap_or(&key); let trie_node = match self.sticky { Some(ref trie) => Cow::Owned(KeyTrie::Node(trie.clone())), - None => Cow::Borrowed(&self.root), + None => Cow::Borrowed(&keymap.root), }; let trie = match trie_node.search(&[*first]) { @@ -457,55 +492,6 @@ impl Keymap { ), } } - - pub fn merge(&mut self, other: Self) { - self.root.merge_nodes(other.root); - } -} - -impl Deref for Keymap { - type Target = KeyTrieNode; - - fn deref(&self) -> &Self::Target { - self.root.node().unwrap() - } -} - -impl Default for Keymap { - fn default() -> Self { - Self::new(KeyTrie::Node(KeyTrieNode::default())) - } -} - -#[derive(Debug, Clone, PartialEq, Deserialize)] -#[serde(transparent)] -pub struct Keymaps(pub HashMap); - -impl Keymaps { - /// Returns list of keys waiting to be disambiguated in current mode. - pub fn pending(&self) -> &[KeyEvent] { - self.0 - .values() - .find_map(|keymap| match keymap.pending().is_empty() { - true => None, - false => Some(keymap.pending()), - }) - .unwrap_or_default() - } -} - -impl Deref for Keymaps { - type Target = HashMap; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Keymaps { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } } impl Default for Keymaps { @@ -856,7 +842,7 @@ impl Default for Keymaps { "C-x" => completion, "C-r" => insert_register, }); - Self(hashmap!( + Self::new(hashmap!( Mode::Normal => Keymap::new(normal), Mode::Select => Keymap::new(select), Mode::Insert => Keymap::new(insert), @@ -867,8 +853,8 @@ impl Default for Keymaps { /// Merge default config keys with user overwritten keys for custom user config. pub fn merge_keys(mut config: Config) -> Config { let mut delta = std::mem::take(&mut config.keys); - for (mode, keys) in &mut *config.keys { - keys.merge(delta.remove(mode).unwrap_or_default()) + for (mode, keys) in &mut config.keys.map { + keys.merge(delta.map.remove(mode).unwrap_or_default()) } config } @@ -895,7 +881,7 @@ mod tests { #[test] fn merge_partial_keys() { let config = Config { - keys: Keymaps(hashmap! { + keys: Keymaps::new(hashmap! { Mode::Normal => Keymap::new( keymap!({ "Normal mode" "i" => normal_mode, @@ -913,23 +899,25 @@ mod tests { let mut merged_config = merge_keys(config.clone()); assert_ne!(config, merged_config); - let keymap = merged_config.keys.0.get_mut(&Mode::Normal).unwrap(); + let keymap = &mut merged_config.keys; assert_eq!( - keymap.get(key!('i')).kind, + keymap.get(Mode::Normal, key!('i')).kind, KeymapResultKind::Matched(MappableCommand::normal_mode), "Leaf should replace leaf" ); assert_eq!( - keymap.get(key!('无')).kind, + keymap.get(Mode::Normal, key!('无')).kind, KeymapResultKind::Matched(MappableCommand::insert_mode), "New leaf should be present in merged keymap" ); // Assumes that z is a node in the default keymap assert_eq!( - keymap.get(key!('z')).kind, + keymap.get(Mode::Normal, key!('z')).kind, KeymapResultKind::Matched(MappableCommand::jump_backward), "Leaf should replace node" ); + + let keymap = merged_config.keys.map.get_mut(&Mode::Normal).unwrap(); // Assumes that `g` is a node in default keymap assert_eq!( keymap.root().search(&[key!('g'), key!('$')]).unwrap(), @@ -949,14 +937,14 @@ mod tests { "Old leaves in subnode should be present in merged node" ); - assert!(merged_config.keys.0.get(&Mode::Normal).unwrap().len() > 1); - assert!(merged_config.keys.0.get(&Mode::Insert).unwrap().len() > 0); + assert!(merged_config.keys.map.get(&Mode::Normal).unwrap().len() > 1); + assert!(merged_config.keys.map.get(&Mode::Insert).unwrap().len() > 0); } #[test] fn order_should_be_set() { let config = Config { - keys: Keymaps(hashmap! { + keys: Keymaps::new(hashmap! { Mode::Normal => Keymap::new( keymap!({ "Normal mode" "space" => { "" @@ -972,7 +960,7 @@ mod tests { }; let mut merged_config = merge_keys(config.clone()); assert_ne!(config, merged_config); - let keymap = merged_config.keys.0.get_mut(&Mode::Normal).unwrap(); + let keymap = merged_config.keys.map.get_mut(&Mode::Normal).unwrap(); // Make sure mapping works assert_eq!( keymap @@ -990,7 +978,7 @@ mod tests { #[test] fn aliased_modes_are_same_in_default_keymap() { let keymaps = Keymaps::default(); - let root = keymaps.get(&Mode::Normal).unwrap().root(); + let root = keymaps.map.get(&Mode::Normal).unwrap().root(); assert_eq!( root.search(&[key!(' '), key!('w')]).unwrap(), root.search(&["C-w".parse::().unwrap()]).unwrap(), -- cgit v1.2.3-70-g09d2