@ -85,6 +85,10 @@ macro_rules! keymap {
keymap ! ( { $label $( sticky = $sticky ) ? $( $( $key ) | + = > $value , ) + } )
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 , ) + }
{ $label :literal $( sticky = $sticky :literal ) ? $( $( $key :literal ) | + = > $value :tt , ) + }
) = > {
) = > {
@ -180,6 +184,7 @@ impl KeyTrieNode {
cmd . doc ( )
cmd . doc ( )
}
}
KeyTrie ::Node ( n ) = > n . name ( ) ,
KeyTrie ::Node ( n ) = > n . name ( ) ,
KeyTrie ::Sequence ( _ ) = > "[Multiple commands]" ,
} ;
} ;
match body . iter ( ) . position ( | ( d , _ ) | d = = & desc ) {
match body . iter ( ) . position ( | ( d , _ ) | d = = & desc ) {
Some ( pos ) = > {
Some ( pos ) = > {
@ -240,6 +245,7 @@ impl DerefMut for KeyTrieNode {
#[ serde(untagged) ]
#[ serde(untagged) ]
pub enum KeyTrie {
pub enum KeyTrie {
Leaf ( Command ) ,
Leaf ( Command ) ,
Sequence ( Vec < Command > ) ,
Node ( KeyTrieNode ) ,
Node ( KeyTrieNode ) ,
}
}
@ -247,14 +253,14 @@ impl KeyTrie {
pub fn node ( & self ) -> Option < & KeyTrieNode > {
pub fn node ( & self ) -> Option < & KeyTrieNode > {
match * self {
match * self {
KeyTrie ::Node ( ref node ) = > Some ( node ) ,
KeyTrie ::Node ( ref node ) = > Some ( node ) ,
KeyTrie ::Leaf ( _ ) => None ,
KeyTrie ::Leaf ( _ ) | KeyTrie ::Sequence ( _ ) => None ,
}
}
}
}
pub fn node_mut ( & mut self ) -> Option < & mut KeyTrieNode > {
pub fn node_mut ( & mut self ) -> Option < & mut KeyTrieNode > {
match * self {
match * self {
KeyTrie ::Node ( ref mut node ) = > Some ( node ) ,
KeyTrie ::Node ( ref mut node ) = > Some ( node ) ,
KeyTrie ::Leaf ( _ ) => None ,
KeyTrie ::Leaf ( _ ) | KeyTrie ::Sequence ( _ ) => None ,
}
}
}
}
@ -271,7 +277,7 @@ impl KeyTrie {
trie = match trie {
trie = match trie {
KeyTrie ::Node ( map ) = > map . get ( key ) ,
KeyTrie ::Node ( map ) = > map . get ( key ) ,
// leaf encountered while keys left to process
// leaf encountered while keys left to process
KeyTrie ::Leaf ( _ ) => None ,
KeyTrie ::Leaf ( _ ) | KeyTrie ::Sequence ( _ ) => None ,
} ?
} ?
}
}
Some ( trie )
Some ( trie )
@ -283,6 +289,8 @@ pub enum KeymapResultKind {
/// Needs more keys to execute a command. Contains valid keys for next keystroke.
/// Needs more keys to execute a command. Contains valid keys for next keystroke.
Pending ( KeyTrieNode ) ,
Pending ( KeyTrieNode ) ,
Matched ( Command ) ,
Matched ( Command ) ,
/// Matched a sequence of commands to execute.
MatchedSequence ( Vec < Command > ) ,
/// Key was not found in the root keymap
/// Key was not found in the root keymap
NotFound ,
NotFound ,
/// Key is invalid in combination with previous keys. Contains keys leading upto
/// Key is invalid in combination with previous keys. Contains keys leading upto
@ -365,6 +373,12 @@ impl Keymap {
Some ( & KeyTrie ::Leaf ( cmd ) ) = > {
Some ( & KeyTrie ::Leaf ( cmd ) ) = > {
return KeymapResult ::new ( KeymapResultKind ::Matched ( cmd ) , self . sticky ( ) )
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 ( ) ) ,
None = > return KeymapResult ::new ( KeymapResultKind ::NotFound , self . sticky ( ) ) ,
Some ( t ) = > t ,
Some ( t ) = > t ,
} ;
} ;
@ -382,6 +396,13 @@ impl Keymap {
self . state . clear ( ) ;
self . state . clear ( ) ;
return KeymapResult ::new ( KeymapResultKind ::Matched ( cmd ) , self . sticky ( ) ) ;
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 (
None = > KeymapResult ::new (
KeymapResultKind ::Cancelled ( self . state . drain ( .. ) . collect ( ) ) ,
KeymapResultKind ::Cancelled ( self . state . drain ( .. ) . collect ( ) ) ,
self . sticky ( ) ,
self . sticky ( ) ,