add_cmd_list(&main_cmds, &aliases);
add_cmd_list(&main_cmds, &other_cmds);
qsort(main_cmds.names, main_cmds.cnt,
- sizeof(main_cmds.names), cmdname_compare);
+ sizeof(*main_cmds.names), cmdname_compare);
uniq(&main_cmds);
- /* This reuses cmdname->len for similarity index */
- for (i = 0; i < main_cmds.cnt; ++i)
+ /* This abuses cmdname->len for levenshtein distance */
+ for (i = 0, n = 0; i < main_cmds.cnt; i++) {
+ int cmp = 0; /* avoid compiler stupidity */
+ const char *candidate = main_cmds.names[i]->name;
+
+ /*
+ * An exact match means we have the command, but
+ * for some reason exec'ing it gave us ENOENT; probably
+ * it's a bad interpreter in the #! line.
+ */
+ if (!strcmp(candidate, cmd))
+ die(_(bad_interpreter_advice), cmd, cmd);
+
+ /* Does the candidate appear in common_cmds list? */
+ while (n < ARRAY_SIZE(common_cmds) &&
+ (cmp = strcmp(common_cmds[n].name, candidate)) < 0)
+ n++;
+ if ((n < ARRAY_SIZE(common_cmds)) && !cmp) {
+ /* Yes, this is one of the common commands */
+ n++; /* use the entry from common_cmds[] */
+ if (starts_with(candidate, cmd)) {
+ /* Give prefix match a very good score */
+ main_cmds.names[i]->len = 0;
+ continue;
+ }
+ }
+
main_cmds.names[i]->len =
- levenshtein(cmd, main_cmds.names[i]->name, 0, 2, 1, 4);
+ levenshtein(cmd, candidate, 0, 2, 1, 3) + 1;
+ }
qsort(main_cmds.names, main_cmds.cnt,
sizeof(*main_cmds.names), levenshtein_compare);