@@ -85,6 +85,10 @@ macro_rules! keymap {
85 keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ })
85 keymap!({ $label $(sticky=$sticky)? $($($key)|+ => $value,)+ })
88+ (@trie [$($cmd:ident),* $(,)?]) => {
89+ $crate::keymap::KeyTrie::Sequence(vec![$($crate::commands::Command::$cmd),*])
89 { $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
93 { $label:literal $(sticky=$sticky:literal)? $($($key:literal)|+ => $value:tt,)+ }
@@ -180,6 +184,7 @@ impl KeyTrieNode {
180 cmd.doc()
184 cmd.doc()
182 KeyTrie::Node(n) => n.name(),
186 KeyTrie::Node(n) => n.name(),
187+ KeyTrie::Sequence(_) => "[Multiple commands]",
184 match body.iter().position(|(d, _)| d == &desc) {
189 match body.iter().position(|(d, _)| d == &desc) {
185 Some(pos) => {
190 Some(pos) => {
@@ -240,6 +245,7 @@ impl DerefMut for KeyTrieNode {
240#[serde(untagged)]
245#[serde(untagged)]
241pub enum KeyTrie {
246pub enum KeyTrie {
242 Leaf(Command),
247 Leaf(Command),
248+ Sequence(Vec<Command>),
243 Node(KeyTrieNode),
249 Node(KeyTrieNode),
@@ -247,14 +253,14 @@ impl KeyTrie {
247 pub fn node(&self) -> Option<&KeyTrieNode> {
253 pub fn node(&self) -> Option<&KeyTrieNode> {
248 match *self {
254 match *self {
249 KeyTrie::Node(ref node) => Some(node),
255 KeyTrie::Node(ref node) => Some(node),
250− KeyTrie::Leaf(_) => None,
256+ KeyTrie::Leaf(_) | KeyTrie::Sequence(_) => None,
254 pub fn node_mut(&mut self) -> Option<&mut KeyTrieNode> {
260 pub fn node_mut(&mut self) -> Option<&mut KeyTrieNode> {
255 match *self {
261 match *self {
256 KeyTrie::Node(ref mut node) => Some(node),
262 KeyTrie::Node(ref mut node) => Some(node),
257− KeyTrie::Leaf(_) => None,
263+ KeyTrie::Leaf(_) | KeyTrie::Sequence(_) => None,
@@ -271,7 +277,7 @@ impl KeyTrie {
271 trie = match trie {
277 trie = match trie {
272 KeyTrie::Node(map) => map.get(key),
278 KeyTrie::Node(map) => map.get(key),
273 // leaf encountered while keys left to process
279 // leaf encountered while keys left to process
274− KeyTrie::Leaf(_) => None,
280+ KeyTrie::Leaf(_) | KeyTrie::Sequence(_) => None,
277 Some(trie)
283 Some(trie)
@@ -283,6 +289,8 @@ pub enum KeymapResultKind {
283 /// Needs more keys to execute a command. Contains valid keys for next keystroke.
289 /// Needs more keys to execute a command. Contains valid keys for next keystroke.
284 Pending(KeyTrieNode),
290 Pending(KeyTrieNode),
285 Matched(Command),
291 Matched(Command),
292+ /// Matched a sequence of commands to execute.
293+ MatchedSequence(Vec<Command>),
286 /// Key was not found in the root keymap
294 /// Key was not found in the root keymap
287 NotFound,
295 NotFound,
288 /// Key is invalid in combination with previous keys. Contains keys leading upto
296 /// Key is invalid in combination with previous keys. Contains keys leading upto
@@ -365,6 +373,12 @@ impl Keymap {
365 Some(&KeyTrie::Leaf(cmd)) => {
373 Some(&KeyTrie::Leaf(cmd)) => {
366 return KeymapResult::new(KeymapResultKind::Matched(cmd), self.sticky())
374 return KeymapResult::new(KeymapResultKind::Matched(cmd), self.sticky())
376+ Some(&KeyTrie::Sequence(ref cmds)) => {
377+ return KeymapResult::new(
378+ KeymapResultKind::MatchedSequence(cmds.clone()),
368 None => return KeymapResult::new(KeymapResultKind::NotFound, self.sticky()),
382 None => return KeymapResult::new(KeymapResultKind::NotFound, self.sticky()),
369 Some(t) => t,
383 Some(t) => t,
@@ -382,6 +396,13 @@ impl Keymap {
382 self.state.clear();
396 self.state.clear();
383 return KeymapResult::new(KeymapResultKind::Matched(cmd), self.sticky());
397 return KeymapResult::new(KeymapResultKind::Matched(cmd), self.sticky());
399+ Some(&KeyTrie::Sequence(ref cmds)) => {
402+ KeymapResultKind::MatchedSequence(cmds.clone()),
385 None => KeymapResult::new(
406 None => KeymapResult::new(
386 KeymapResultKind::Cancelled(self.state.drain(..).collect()),
407 KeymapResultKind::Cancelled(self.state.drain(..).collect()),
387 self.sticky(),
408 self.sticky(),