aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/keymap.rs
diff options
context:
space:
mode:
authorBlaž Hrastnik2022-03-20 06:50:48 +0000
committerBlaž Hrastnik2022-03-20 07:03:13 +0000
commit7909d6f05e4d651d904886aa53ec4bd250294e73 (patch)
tree915d6196e9e091bf2a997507c7d5d770ac02bb82 /helix-term/src/keymap.rs
parentcfd992b1511655fc2116af4ddd1cd0dbb3bcb85e (diff)
keymap: Store pending/sticky on the root level
Diffstat (limited to 'helix-term/src/keymap.rs')
-rw-r--r--helix-term/src/keymap.rs148
1 files changed, 68 insertions, 80 deletions
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<KeyEvent>,
- /// Stores the sticky node if one is activated.
- #[serde(skip)]
- sticky: Option<KeyTrieNode>,
}
impl Keymap {
pub fn new(root: KeyTrie) -> Self {
- Keymap {
- root,
- state: Vec::new(),
- sticky: None,
- }
+ Keymap { root }
}
pub fn reverse_map(&self) -> HashMap<String, Vec<Vec<KeyEvent>>> {
@@ -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<Mode, Keymap>,
+
+ /// Stores pending keys waiting for the next key. This is relative to a
+ /// sticky node if one is in use.
+ #[serde(skip)]
+ state: Vec<KeyEvent>,
+
+ /// Stores the sticky node if one is activated.
+ #[serde(skip)]
+ pub sticky: Option<KeyTrieNode>,
+}
+
+impl Keymaps {
+ pub fn new(map: HashMap<Mode, Keymap>) -> 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<Mode, Keymap>);
-
-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<Mode, Keymap>;
-
- 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::<KeyEvent>().unwrap()]).unwrap(),