11#![ no_std]
22
3- type MenuCallbackFn < T > = fn ( menu : & Menu < T > ) ;
4- type ItemCallbackFn < T > = fn ( menu : & Menu < T > , item : & Item < T > , args : & str , context : & mut T ) ;
3+ type MenuCallbackFn < T > = fn ( menu : & Menu < T > , context : & mut T ) ;
4+ type ItemCallbackFn < T > = fn ( menu : & Menu < T > , item : & Item < T > , args : & [ & str ] , context : & mut T ) ;
55
6+ #[ derive( Debug ) ]
67/// Describes a parameter to the command
78pub enum Parameter < ' a > {
89 Mandatory ( & ' a str ) ,
2425 parameters : & ' a [ Parameter < ' a > ] ,
2526 } ,
2627 Menu ( & ' a Menu < ' a , T > ) ,
28+ _Dummy,
2729}
2830
2931/// Menu Item
7173{
7274 pub fn new ( menu : & ' a Menu < ' a , T > , buffer : & ' a mut [ u8 ] , context : & ' a mut T ) -> Runner < ' a , T > {
7375 if let Some ( cb_fn) = menu. entry {
74- cb_fn ( menu) ;
76+ cb_fn ( menu, context ) ;
7577 }
7678 let mut r = Runner {
7779 menus : [ Some ( menu) , None , None , None ] ,
@@ -156,9 +158,19 @@ where
156158 self . print_help ( & item) ;
157159 }
158160 if self . depth != 0 {
159- writeln ! ( self . context, "* exit - leave this menu." ) . unwrap ( ) ;
161+ let item = Item {
162+ command : "exit" ,
163+ help : Some ( "leave this menu" ) ,
164+ item_type : ItemType :: _Dummy,
165+ } ;
166+ self . print_help ( & item) ;
160167 }
161- writeln ! ( self . context, "* help - print this help text" ) . unwrap ( ) ;
168+ let item = Item {
169+ command : "help" ,
170+ help : Some ( "show this help" ) ,
171+ item_type : ItemType :: _Dummy,
172+ } ;
173+ self . print_help ( & item) ;
162174 Outcome :: CommandProcessed
163175 } else if command_line == "exit" && self . depth != 0 {
164176 if self . depth == self . menus . len ( ) {
@@ -179,7 +191,8 @@ where
179191 ItemType :: Callback {
180192 function,
181193 parameters,
182- } => self . call_function (
194+ } => Self :: call_function (
195+ self . context ,
183196 function,
184197 parameters,
185198 menu,
@@ -190,6 +203,9 @@ where
190203 self . depth += 1 ;
191204 self . menus [ self . depth ] = Some ( m) ;
192205 }
206+ ItemType :: _Dummy => {
207+ unreachable ! ( ) ;
208+ }
193209 }
194210 found = true ;
195211 break ;
@@ -214,7 +230,7 @@ where
214230 match item. item_type {
215231 ItemType :: Callback { parameters, .. } => {
216232 if !parameters. is_empty ( ) {
217- write ! ( self . context, "* {}" , item. command) . unwrap ( ) ;
233+ write ! ( self . context, "{}" , item. command) . unwrap ( ) ;
218234 for param in parameters. iter ( ) {
219235 match param {
220236 Parameter :: Mandatory ( name) => {
@@ -233,11 +249,14 @@ where
233249 }
234250 }
235251 } else {
236- write ! ( self . context, "* {}" , item. command) . unwrap ( ) ;
252+ write ! ( self . context, "{}" , item. command) . unwrap ( ) ;
237253 }
238254 }
239255 ItemType :: Menu ( _menu) => {
240- write ! ( self . context, "* {}" , item. command) . unwrap ( ) ;
256+ write ! ( self . context, "{}" , item. command) . unwrap ( ) ;
257+ }
258+ ItemType :: _Dummy => {
259+ write ! ( self . context, "{}" , item. command) . unwrap ( ) ;
241260 }
242261 }
243262 if let Some ( help) = item. help {
@@ -247,14 +266,53 @@ where
247266 }
248267
249268 fn call_function (
250- & self ,
251- _function : ItemCallbackFn < T > ,
252- _parameters : & [ Parameter ] ,
253- _parent_menu : & Menu < T > ,
254- _item : & Item < T > ,
255- _command : & str ,
269+ context : & mut T ,
270+ callback_function : ItemCallbackFn < T > ,
271+ parameters : & [ Parameter ] ,
272+ parent_menu : & Menu < T > ,
273+ item : & Item < T > ,
274+ command : & str ,
256275 ) {
257-
276+ let mandatory_parameter_count = parameters
277+ . iter ( )
278+ . filter ( |p| match p {
279+ Parameter :: Mandatory ( _) => true ,
280+ _ => false ,
281+ } )
282+ . count ( ) ;
283+ if command. len ( ) >= item. command . len ( ) {
284+ // Maybe arguments
285+ let mut argument_buffer: [ & str ; 16 ] = [ "" ; 16 ] ;
286+ let mut argument_count = 0 ;
287+ let mut positional_arguments = 0 ;
288+ for ( slot, arg) in argument_buffer
289+ . iter_mut ( )
290+ . zip ( command[ item. command . len ( ) ..] . split_whitespace ( ) )
291+ {
292+ * slot = arg;
293+ argument_count += 1 ;
294+ if !arg. starts_with ( "--" ) {
295+ positional_arguments += 1 ;
296+ }
297+ }
298+ if positional_arguments >= mandatory_parameter_count {
299+ callback_function (
300+ parent_menu,
301+ item,
302+ & argument_buffer[ 0 ..argument_count] ,
303+ context,
304+ ) ;
305+ } else {
306+ writeln ! ( context, "Error: Insufficient arguments given" ) . unwrap ( ) ;
307+ }
308+ } else {
309+ // Definitely no arguments
310+ if mandatory_parameter_count == 0 {
311+ callback_function ( parent_menu, item, & [ ] , context) ;
312+ } else {
313+ writeln ! ( context, "Error: Insufficient arguments given" ) . unwrap ( ) ;
314+ }
315+ }
258316 }
259317}
260318
0 commit comments