@@ -12,6 +12,7 @@ use std::{
1212 borrow:: Cow ,
1313 collections:: { BTreeSet , HashMap } ,
1414 ops:: { Deref , DerefMut } ,
15+ str:: FromStr ,
1516 sync:: Arc ,
1617} ;
1718
@@ -83,7 +84,7 @@ impl KeyTrieNode {
8384 cmd. doc ( )
8485 }
8586 KeyTrie :: Node ( n) => & n. name ,
86- KeyTrie :: Sequence ( _ ) => "[Multiple commands]" ,
87+ KeyTrie :: Sequence ( .. ) => KeyTrie :: DEFAULT_SEQUENCE_LABEL ,
8788 } ;
8889 match body. iter ( ) . position ( |( _, d) | d == & desc) {
8990 Some ( pos) => {
@@ -133,10 +134,18 @@ impl DerefMut for KeyTrieNode {
133134#[ derive( Debug , Clone , PartialEq ) ]
134135pub enum KeyTrie {
135136 MappableCommand ( MappableCommand ) ,
136- Sequence ( Vec < MappableCommand > ) ,
137+ Sequence ( String , Vec < MappableCommand > ) ,
137138 Node ( KeyTrieNode ) ,
138139}
139140
141+ impl KeyTrie {
142+ pub const DEFAULT_SEQUENCE_LABEL : & ' static str = "[Multiple commands]" ;
143+
144+ pub fn sequence ( commands : Vec < MappableCommand > ) -> Self {
145+ Self :: Sequence ( Self :: DEFAULT_SEQUENCE_LABEL . to_string ( ) , commands)
146+ }
147+ }
148+
140149impl < ' de > Deserialize < ' de > for KeyTrie {
141150 fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
142151 where
@@ -190,7 +199,10 @@ impl<'de> serde::de::Visitor<'de> for KeyTrieVisitor {
190199 ) ) ;
191200 }
192201
193- Ok ( KeyTrie :: Sequence ( commands) )
202+ Ok ( KeyTrie :: Sequence (
203+ KeyTrie :: DEFAULT_SEQUENCE_LABEL . to_string ( ) ,
204+ commands,
205+ ) )
194206 }
195207
196208 fn visit_map < M > ( self , mut map : M ) -> Result < Self :: Value , M :: Error >
@@ -205,7 +217,35 @@ impl<'de> serde::de::Visitor<'de> for KeyTrieVisitor {
205217 while let Some ( key) = map. next_key :: < String > ( ) ? {
206218 match & key as & str {
207219 "label" => label = map. next_value :: < String > ( ) ?,
208- "command" => command = Some ( map. next_value :: < MappableCommand > ( ) ?) ,
220+ "command" => {
221+ command = Some ( match map. next_value :: < toml:: Value > ( ) ? {
222+ toml:: Value :: String ( s) => {
223+ vec ! [ MappableCommand :: from_str( & s) . map_err( serde:: de:: Error :: custom) ?]
224+ }
225+ toml:: Value :: Array ( arr) => {
226+ let mut vec = Vec :: with_capacity ( arr. len ( ) ) ;
227+ for value in arr {
228+ let toml:: Value :: String ( s) = value else {
229+ return Err ( serde:: de:: Error :: invalid_type (
230+ serde:: de:: Unexpected :: Other ( value. type_str ( ) ) ,
231+ & "string" ,
232+ ) ) ;
233+ } ;
234+ vec. push (
235+ MappableCommand :: from_str ( & s)
236+ . map_err ( serde:: de:: Error :: custom) ?,
237+ ) ;
238+ }
239+ vec
240+ }
241+ value => {
242+ return Err ( serde:: de:: Error :: invalid_type (
243+ serde:: de:: Unexpected :: Other ( value. type_str ( ) ) ,
244+ & "string or array" ,
245+ ) )
246+ }
247+ } ) ;
248+ }
209249 _ => {
210250 let key_event = key. parse :: < KeyEvent > ( ) . map_err ( serde:: de:: Error :: custom) ?;
211251 let key_trie = map. next_value :: < KeyTrie > ( ) ?;
@@ -220,17 +260,28 @@ impl<'de> serde::de::Visitor<'de> for KeyTrieVisitor {
220260 Some ( _command) if !order. is_empty ( ) => {
221261 Err ( serde:: de:: Error :: custom ( "ambiguous mapping: 'command' is only valid with 'label', but I found other keys" ) )
222262 }
223- Some ( MappableCommand :: Static { .. } ) if !label. is_empty ( ) => {
224- Err ( serde:: de:: Error :: custom ( "custom labels are only available for typable commands (the ones starting with ':')" ) )
225- }
226- Some ( MappableCommand :: Typable { name, args, .. } ) if !label. is_empty ( ) => {
227- Ok ( KeyTrie :: MappableCommand ( MappableCommand :: Typable {
228- name,
229- args,
230- doc : label. to_string ( ) ,
231- } ) )
263+ Some ( mut commands) if commands. len ( ) == 1 => match commands. pop ( ) {
264+ None => Err ( serde:: de:: Error :: custom ( "UNREACHABLE!, vec is empty after checking len == 1" ) ) ,
265+ Some ( MappableCommand :: Static { .. } ) if !label. is_empty ( ) => {
266+ Err ( serde:: de:: Error :: custom ( "custom labels are only available for typable commands (the ones starting with ':')" ) )
267+ }
268+ Some ( MappableCommand :: Typable { name, args, .. } ) if !label. is_empty ( ) => {
269+ Ok ( KeyTrie :: MappableCommand ( MappableCommand :: Typable {
270+ name,
271+ args,
272+ doc : label,
273+ } ) )
274+ }
275+ Some ( command) => Ok ( KeyTrie :: MappableCommand ( command) ) ,
232276 }
233- Some ( command) => Ok ( KeyTrie :: MappableCommand ( command) ) ,
277+ Some ( commands) => {
278+ let label = if label. is_empty ( ) {
279+ KeyTrie :: DEFAULT_SEQUENCE_LABEL . to_string ( )
280+ } else {
281+ label
282+ } ;
283+ Ok ( KeyTrie :: Sequence ( label, commands) )
284+ } ,
234285 }
235286 }
236287}
@@ -254,7 +305,7 @@ impl KeyTrie {
254305 keys. pop ( ) ;
255306 }
256307 }
257- KeyTrie :: Sequence ( _ ) => { }
308+ KeyTrie :: Sequence ( .. ) => { }
258309 } ;
259310 }
260311
@@ -266,14 +317,14 @@ impl KeyTrie {
266317 pub fn node ( & self ) -> Option < & KeyTrieNode > {
267318 match * self {
268319 KeyTrie :: Node ( ref node) => Some ( node) ,
269- KeyTrie :: MappableCommand ( _) | KeyTrie :: Sequence ( _ ) => None ,
320+ KeyTrie :: MappableCommand ( _) | KeyTrie :: Sequence ( .. ) => None ,
270321 }
271322 }
272323
273324 pub fn node_mut ( & mut self ) -> Option < & mut KeyTrieNode > {
274325 match * self {
275326 KeyTrie :: Node ( ref mut node) => Some ( node) ,
276- KeyTrie :: MappableCommand ( _) | KeyTrie :: Sequence ( _ ) => None ,
327+ KeyTrie :: MappableCommand ( _) | KeyTrie :: Sequence ( .. ) => None ,
277328 }
278329 }
279330
@@ -290,7 +341,7 @@ impl KeyTrie {
290341 trie = match trie {
291342 KeyTrie :: Node ( map) => map. get ( key) ,
292343 // leaf encountered while keys left to process
293- KeyTrie :: MappableCommand ( _) | KeyTrie :: Sequence ( _ ) => None ,
344+ KeyTrie :: MappableCommand ( _) | KeyTrie :: Sequence ( .. ) => None ,
294345 } ?
295346 }
296347 Some ( trie)
@@ -380,7 +431,7 @@ impl Keymaps {
380431 Some ( KeyTrie :: MappableCommand ( ref cmd) ) => {
381432 return KeymapResult :: Matched ( cmd. clone ( ) ) ;
382433 }
383- Some ( KeyTrie :: Sequence ( ref cmds) ) => {
434+ Some ( KeyTrie :: Sequence ( _ , ref cmds) ) => {
384435 return KeymapResult :: MatchedSequence ( cmds. clone ( ) ) ;
385436 }
386437 None => return KeymapResult :: NotFound ,
@@ -400,7 +451,7 @@ impl Keymaps {
400451 self . state . clear ( ) ;
401452 KeymapResult :: Matched ( cmd. clone ( ) )
402453 }
403- Some ( KeyTrie :: Sequence ( cmds) ) => {
454+ Some ( KeyTrie :: Sequence ( _ , cmds) ) => {
404455 self . state . clear ( ) ;
405456 KeymapResult :: MatchedSequence ( cmds. clone ( ) )
406457 }
@@ -625,7 +676,7 @@ mod tests {
625676 let expectation = KeyTrie :: Node ( KeyTrieNode :: new (
626677 "" ,
627678 hashmap ! {
628- key => KeyTrie :: Sequence ( vec!{
679+ key => KeyTrie :: sequence ( vec!{
629680 MappableCommand :: select_all,
630681 MappableCommand :: Typable {
631682 name: "pipe" . to_string( ) ,
0 commit comments