3 command_not_found_handle
()
7 #declare -a args=("$@")
9 echo "$badcmd: command not found. similar commands: " >&2
11 local distance_threshold
12 if [ ${#badcmd} -le 4 ]
18 local startswith_threshold
=3
19 local endswith_threshold
=0
20 local min_suggestions
=20
22 # 1. list every commands in all the PATH directories and bash functions
24 # 2. measure Levenshtein between the typed word and each commands.
25 # 3. find exact matches of typed word in each commands and score them
26 # according to how close is it to the start or end of the command name.
27 # 4. calc the lowest score (the lower the better), ie. overall score.
28 # 5. sort the commands first by the lowest score, then length.
29 # 6. pass through commands, scores of which are below threshold.
30 # 7. worse-score commands are passed through too, in groups, to show at
31 # least a given number of suggestions.
32 # they are groupd by the overall score.
35 find ${PATH//:/ } -maxdepth 1 -type f
-executable -printf '%f\n' 2>/dev
/null
36 declare -p -F | cut
-d' ' -f3-
37 alias -p | cut
-d' ' -f2- | cut
-d= -f1
39 | levenshtein-distance
"$badcmd" \
40 | env badcmd
=$badcmd perl
-ne '
42 use List::Util qw/min/;
51 $spos = index $_, $ENV{badcmd}; $spos = $worst_score if $spos == -1;
52 $rpos = rindex $_, $ENV{badcmd};
53 if($rpos == -1) { $epos = $worst_score; } else { $epos = $len - ($rpos + length($ENV{badcmd})); }
54 print min($spos, $epos, $distance), $spos, $epos, $distance, $len, $_;' \
56 | env min_suggestions
=$min_suggestions startswith_threshold
=$startswith_threshold endswith_threshold
=$endswith_threshold distance_threshold
=$distance_threshold\
59 s/(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s//;
60 ($score, $spos, $epos, $distance, $len) = ($1, $2, $3, $4, $5);
61 if($spos > $ENV{startswith_threshold} and $epos > $ENV{endswith_threshold} and $distance > $ENV{distance_threshold})
63 if($printed >= $ENV{min_suggestions} and $score ne $last_score) { exit; }
67 $last_score = $score;' \