@@ -66,12 +66,14 @@ init(_) ->
66
66
handle_call ({run , Command , Args }, From , State = # state {}) ->
67
67
case ets :lookup (? ETS_TABLE_NAME , Command ) of
68
68
[] ->
69
- {reply , {error , command_not_found }, State };
70
- [{_ , ArgsDef , Fun , _Description }] ->
71
- CommandPid = spawn_run_command (Command , Args , ArgsDef , From , Fun ),
72
- RunningCommands = State # state .running_commands ,
73
- {noreply ,
74
- State # state {running_commands = [{CommandPid , From } | RunningCommands ]}}
69
+ case get_wildcard_command (Command ) of
70
+ [] ->
71
+ {reply , {error , command_not_found }, State };
72
+ Result ->
73
+ evaluate_command_lookup_result (Result , Command , Args , From , State )
74
+ end ;
75
+ Else ->
76
+ evaluate_command_lookup_result (Else , Command , Args , From , State )
75
77
end ;
76
78
handle_call ({get_help , Command }, _From , State = # state {}) ->
77
79
Help = do_get_help (Command ),
@@ -107,6 +109,13 @@ spawn_run_command(Command, Args, ArgsDef, From, Fun) ->
107
109
gen_server :reply (From , CommandResult )
108
110
end ).
109
111
112
+ evaluate_command_lookup_result ([{CommandSpec , ArgsDef , Fun , _Description }],
113
+ Command , Args , From , State ) ->
114
+ NewArgs = extract_command_args (CommandSpec , Command , Args ),
115
+ CommandPid = spawn_run_command (Command , NewArgs , ArgsDef , From , Fun ),
116
+ RunningCommands = State # state .running_commands ,
117
+ {noreply , State # state {running_commands = [{CommandPid , From } | RunningCommands ]}}.
118
+
110
119
run_command (Command , Args , ArgsDef , Fun ) ->
111
120
case convert (ArgsDef , Args ) of
112
121
{ok , NewArgs } ->
@@ -223,7 +232,7 @@ is_numeric(Value) ->
223
232
do_get_help ([]) ->
224
233
ets :foldr (fun ({Command , _ , _ , Desc }, Acc ) ->
225
234
[{Command , Desc } | Acc ]
226
- end , [], cli_commands );
235
+ end , [], ? ETS_TABLE_NAME );
227
236
do_get_help (InCommands ) ->
228
237
case ets :lookup (? ETS_TABLE_NAME , InCommands ) of
229
238
[] ->
@@ -233,9 +242,9 @@ do_get_help(InCommands) ->
233
242
end .
234
243
235
244
do_help_lookup (InCommands ) ->
236
- case ets :select (cli_commands , get_select_matchspec (InCommands , false )) of
245
+ case ets :select (? ETS_TABLE_NAME , get_select_matchspec (InCommands , false )) of
237
246
[] ->
238
- ets :select (cli_commands , get_select_matchspec (InCommands , true ));
247
+ ets :select (? ETS_TABLE_NAME , get_select_matchspec (InCommands , true ));
239
248
Else ->
240
249
Else
241
250
end .
@@ -267,9 +276,15 @@ format_command({Commands, Desc, Args}) ->
267
276
cli_console_formatter :text (" ~n Arguments: " ) |
268
277
[format_arg (Arg ) || Arg <- Args ]];
269
278
format_command ({Commands , Desc }) ->
270
- CommandStr = string :pad (string :join (Commands , " " ), 32 ),
279
+ NewCommands = lists :map (fun format_command_string /1 , Commands ),
280
+ CommandStr = string :pad (string :join (NewCommands , " " ), 32 ),
271
281
cli_console_formatter :text (" ~ts ~ts " , [CommandStr , Desc ]).
272
282
283
+ format_command_string (# argument {name = Name }) ->
284
+ " <" ++ Name ++ " >" ;
285
+ format_command_string (Command ) ->
286
+ Command .
287
+
273
288
format_arg (# argument {name = Name , optional = Optional ,
274
289
default = Default , description = Desc }) ->
275
290
@@ -303,14 +318,31 @@ is_argument_defined(Arg, ArgsDef) ->
303
318
end .
304
319
305
320
register_command (Command , ArgsDef , Fun , Description ) ->
306
- case check_multiple_argdefs (ArgsDef ) of
321
+ CommandArguments = get_command_arguments (Command ),
322
+ case check_multiple_argdefs (ArgsDef ++ CommandArguments ) of
307
323
ok ->
324
+ ets :match_delete (? ETS_TABLE_NAME , {generate_match_head (Command ),
325
+ generate_filter (Command ), []}),
308
326
true = ets :insert (? ETS_TABLE_NAME , {Command , ArgsDef , Fun , Description }),
309
327
ok ;
310
328
Else ->
311
329
Else
312
330
end .
313
331
332
+ get_command_arguments (Command ) ->
333
+ lists :filter (fun (# argument {}) -> true ;
334
+ (_ ) -> false
335
+ end , Command ).
336
+
337
+ get_command_arguments_with_index (Command ) ->
338
+ {_ , Result } =
339
+ lists :foldl (fun (# argument {} = Item , {ItemSeq , Acc }) ->
340
+ {ItemSeq + 1 , [{ItemSeq , Item } | Acc ]};
341
+ (_ , {ItemSeq , Acc }) ->
342
+ {ItemSeq + 1 , Acc }
343
+ end , {1 , []}, Command ),
344
+ Result .
345
+
314
346
check_multiple_argdefs (Argdefs ) ->
315
347
check_multiple_argdefs (Argdefs , []).
316
348
@@ -333,4 +365,40 @@ format_help(HelpCommand, Acc) ->
333
365
lists :foldr (fun (Item , Acc2 ) -> [Item | Acc2 ] end , Acc , Result );
334
366
Item ->
335
367
[Item | Acc ]
336
- end .
368
+ end .
369
+
370
+ get_wildcard_command (Command ) ->
371
+ case ets :select (? ETS_TABLE_NAME , [{generate_match_head (Command ),
372
+ generate_filter (Command ), ['$_' ]}]) of
373
+ [] ->
374
+ [];
375
+ [{Commands , ArgsDef , Fun , Description }] ->
376
+ CommandArguments = get_command_arguments (Commands ),
377
+ [{Commands , ArgsDef ++ CommandArguments , Fun , Description }]
378
+ end .
379
+
380
+ generate_match_head (Command ) ->
381
+ CommandHead = [item_num (ItemNum ) || ItemNum <- lists :seq (1 , length (Command ))],
382
+ {CommandHead , '_' , '_' , '_' }.
383
+
384
+ generate_filter (Command ) ->
385
+ generate_filter (Command , 1 , []).
386
+
387
+ generate_filter ([], _ItemCount , Where ) ->
388
+ lists :reverse (Where );
389
+ generate_filter ([Command | Rest ], ItemCount , Where ) ->
390
+ Item = item_num (ItemCount ),
391
+ Filter = {'orelse' ,
392
+ {'==' , Command , Item },
393
+ {'==' , argument , {element , 1 , Item }}
394
+ },
395
+ generate_filter (Rest , ItemCount + 1 , [Filter | Where ]).
396
+
397
+ item_num (ItemNum ) ->
398
+ list_to_atom (" $" ++ integer_to_list (ItemNum )).
399
+
400
+ extract_command_args (CommandSpec , Command , Args ) ->
401
+ CommandArgWithIndex = get_command_arguments_with_index (CommandSpec ),
402
+ lists :foldl (fun ({Index , # argument {name = Name }}, Acc ) ->
403
+ [{Name , lists :nth (Index , Command )} | Acc ]
404
+ end , Args , CommandArgWithIndex ).
0 commit comments