aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmnikar2021-11-11 04:44:50 +0000
committerGitHub2021-11-11 04:44:50 +0000
commitd131a9dd0efc5ff271f8b78cd65a8dc30c193af4 (patch)
treed7083b42822d6d37ea04eb291674909d1fb9d3fe
parentbf70cfd050d961ce7b8d5a95fe663dff9eb1e66e (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.md1
-rw-r--r--helix-term/src/keymap.rs27
-rw-r--r--helix-term/src/ui/editor.rs5
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