diff options
author | Omnikar | 2021-11-11 04:44:50 +0000 |
---|---|---|
committer | GitHub | 2021-11-11 04:44:50 +0000 |
commit | d131a9dd0efc5ff271f8b78cd65a8dc30c193af4 (patch) | |
tree | d7083b42822d6d37ea04eb291674909d1fb9d3fe | |
parent | bf70cfd050d961ce7b8d5a95fe663dff9eb1e66e (diff) |
Allow keys to be mapped to sequences of commands (#589)
* Allow keys to be mapped to sequences of commands
* Handle `Sequence` at the start of `Keymap::get`
* Use `"[Multiple commands]"` as command sequence doc
* Add command sequence example to `remapping.md`
-rw-r--r-- | book/src/remapping.md | 1 | ||||
-rw-r--r-- | helix-term/src/keymap.rs | 27 | ||||
-rw-r--r-- | helix-term/src/ui/editor.rs | 5 |
3 files changed, 30 insertions, 3 deletions
diff --git a/book/src/remapping.md b/book/src/remapping.md index 5ca6cd1b..532f502a 100644 --- a/book/src/remapping.md +++ b/book/src/remapping.md @@ -15,6 +15,7 @@ a = "move_char_left" # Maps the 'a' key to the move_char_left command w = "move_line_up" # Maps the 'w' key move_line_up "C-S-esc" = "extend_line" # Maps Control-Shift-Escape to extend_line g = { a = "code_action" } # Maps `ga` to show possible code actions +"ret" = ["open_below", "normal_mode"] # Maps the enter key to open_below then re-enter normal mode [keys.insert] "A-x" = "normal_mode" # Maps Alt-X to enter normal mode diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index d7040b88..b2b865e4 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -85,6 +85,10 @@ macro_rules! keymap { keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ }) }; + (@trie [$($cmd:ident),* $(,)?]) => { + $crate::keymap::KeyTrie::Sequence(vec![$($crate::commands::Command::$cmd),*]) + }; + ( { $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ } ) => { @@ -180,6 +184,7 @@ impl KeyTrieNode { cmd.doc() } KeyTrie::Node(n) => n.name(), + KeyTrie::Sequence(_) => "[Multiple commands]", }; match body.iter().position(|(d, _)| d == &desc) { Some(pos) => { @@ -240,6 +245,7 @@ impl DerefMut for KeyTrieNode { #[serde(untagged)] pub enum KeyTrie { Leaf(Command), + Sequence(Vec<Command>), Node(KeyTrieNode), } @@ -247,14 +253,14 @@ impl KeyTrie { pub fn node(&self) -> Option<&KeyTrieNode> { match *self { KeyTrie::Node(ref node) => Some(node), - KeyTrie::Leaf(_) => None, + KeyTrie::Leaf(_) | KeyTrie::Sequence(_) => None, } } pub fn node_mut(&mut self) -> Option<&mut KeyTrieNode> { match *self { KeyTrie::Node(ref mut node) => Some(node), - KeyTrie::Leaf(_) => None, + KeyTrie::Leaf(_) | KeyTrie::Sequence(_) => None, } } @@ -271,7 +277,7 @@ impl KeyTrie { trie = match trie { KeyTrie::Node(map) => map.get(key), // leaf encountered while keys left to process - KeyTrie::Leaf(_) => None, + KeyTrie::Leaf(_) | KeyTrie::Sequence(_) => None, }? } Some(trie) @@ -283,6 +289,8 @@ pub enum KeymapResultKind { /// Needs more keys to execute a command. Contains valid keys for next keystroke. Pending(KeyTrieNode), Matched(Command), + /// Matched a sequence of commands to execute. + MatchedSequence(Vec<Command>), /// Key was not found in the root keymap NotFound, /// Key is invalid in combination with previous keys. Contains keys leading upto @@ -365,6 +373,12 @@ impl Keymap { Some(&KeyTrie::Leaf(cmd)) => { return KeymapResult::new(KeymapResultKind::Matched(cmd), self.sticky()) } + Some(&KeyTrie::Sequence(ref cmds)) => { + return KeymapResult::new( + KeymapResultKind::MatchedSequence(cmds.clone()), + self.sticky(), + ) + } None => return KeymapResult::new(KeymapResultKind::NotFound, self.sticky()), Some(t) => t, }; @@ -382,6 +396,13 @@ impl Keymap { self.state.clear(); return KeymapResult::new(KeymapResultKind::Matched(cmd), self.sticky()); } + Some(&KeyTrie::Sequence(ref cmds)) => { + self.state.clear(); + KeymapResult::new( + KeymapResultKind::MatchedSequence(cmds.clone()), + self.sticky(), + ) + } None => KeymapResult::new( KeymapResultKind::Cancelled(self.state.drain(..).collect()), self.sticky(), diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index a7015577..90f09e9c 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -695,6 +695,11 @@ impl EditorView { match &key_result.kind { KeymapResultKind::Matched(command) => command.execute(cxt), KeymapResultKind::Pending(node) => self.autoinfo = Some(node.infobox()), + KeymapResultKind::MatchedSequence(commands) => { + for command in commands { + command.execute(cxt); + } + } KeymapResultKind::NotFound | KeymapResultKind::Cancelled(_) => return Some(key_result), } None |