@@ -331,6 +331,8 @@ pub type SubCommandInfo = argh_shared::SubCommandInfo<'static>;
331331
332332pub use argh_shared:: { ErrorCodeInfo , FlagInfo , FlagInfoKind , Optionality , PositionalInfo } ;
333333
334+ use rust_fuzzy_search:: fuzzy_search_best_n;
335+
334336/// Structured information about the command line arguments.
335337pub trait ArgsInfo {
336338 /// Returns the argument info.
@@ -972,7 +974,13 @@ impl<'a> ParseStructOptions<'a> {
972974 . arg_to_slot
973975 . iter ( )
974976 . find_map ( |& ( name, pos) | if name == arg { Some ( pos) } else { None } )
975- . ok_or_else ( || unrecognized_argument ( arg) ) ?;
977+ . ok_or_else ( || {
978+ unrecognized_argument (
979+ arg,
980+ self . arg_to_slot ,
981+ & vec ! [ "--help" . to_owned( ) , "help" . to_owned( ) ] ,
982+ )
983+ } ) ?;
976984
977985 match self . slots [ pos] {
978986 ParseStructOption :: Flag ( ref mut b) => b. set_flag ( arg) ,
@@ -992,8 +1000,24 @@ impl<'a> ParseStructOptions<'a> {
9921000 }
9931001}
9941002
995- fn unrecognized_argument ( x : & str ) -> String {
996- [ "Unrecognized argument: " , x, "\n " ] . concat ( )
1003+ fn unrecognized_argument (
1004+ given : & str ,
1005+ arg_to_slot : & [ ( & str , usize ) ] ,
1006+ extra_suggestions : & [ String ] ,
1007+ ) -> String {
1008+ // get the list of available arguments
1009+ let available = arg_to_slot
1010+ . iter ( )
1011+ . map ( |( name, _pos) | * name)
1012+ . chain ( extra_suggestions. iter ( ) . map ( |s| s. as_str ( ) ) )
1013+ . collect :: < Vec < & str > > ( ) ;
1014+
1015+ if available. is_empty ( ) {
1016+ return format ! ( "Unrecognized argument: \" {}\" " , given) ;
1017+ }
1018+
1019+ let suggestions = fuzzy_search_best_n ( given, & available, 1 ) ;
1020+ format ! ( "Unrecognized argument: \" {}\" . Did you mean \" {}\" ?" , given, suggestions[ 0 ] . 0 )
9971021}
9981022
9991023// `--` or `-` options, including a mutable reference to their value.
0 commit comments