зеркало из https://github.com/microsoft/git.git
help: always suggest common-cmds if prefix of cmd
If someone runs "git st", the command "git status" is not suggested because it's not one of the closest levenshtein-neighbour. Reserve the distance of 0 for common commands where the entered command is a prefixe, as these are often more likely to be what the user meant. This way, "git status" is the first suggestion, while a list of possible typos are still suggested as well. Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
7d43de925b
Коммит
6612b9e471
2
Makefile
2
Makefile
|
@ -1620,6 +1620,8 @@ git$X: git.o $(BUILTIN_OBJS) $(GITLIBS)
|
|||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \
|
||||
$(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
|
||||
|
||||
help.o: common-cmds.h
|
||||
|
||||
builtin/help.o: common-cmds.h
|
||||
builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
|
||||
'-DGIT_HTML_PATH="$(htmldir_SQ)"' \
|
||||
|
|
47
help.c
47
help.c
|
@ -3,6 +3,7 @@
|
|||
#include "exec_cmd.h"
|
||||
#include "levenshtein.h"
|
||||
#include "help.h"
|
||||
#include "common-cmds.h"
|
||||
|
||||
/* most GUI terminals set COLUMNS (although some don't export it) */
|
||||
static int term_columns(void)
|
||||
|
@ -298,7 +299,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
|
|||
}
|
||||
|
||||
/* An empirically derived magic number */
|
||||
#define SIMILAR_ENOUGH(x) ((x) < 6)
|
||||
#define SIMILARITY_FLOOR 7
|
||||
#define SIMILAR_ENOUGH(x) ((x) < SIMILARITY_FLOOR)
|
||||
|
||||
const char *help_unknown_cmd(const char *cmd)
|
||||
{
|
||||
|
@ -319,10 +321,28 @@ const char *help_unknown_cmd(const char *cmd)
|
|||
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;
|
||||
|
||||
/* 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 (!prefixcmp(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, 4) + 1;
|
||||
}
|
||||
|
||||
qsort(main_cmds.names, main_cmds.cnt,
|
||||
sizeof(*main_cmds.names), levenshtein_compare);
|
||||
|
@ -330,10 +350,21 @@ const char *help_unknown_cmd(const char *cmd)
|
|||
if (!main_cmds.cnt)
|
||||
die ("Uh oh. Your system reports no Git commands at all.");
|
||||
|
||||
best_similarity = main_cmds.names[0]->len;
|
||||
n = 1;
|
||||
while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len)
|
||||
++n;
|
||||
/* skip and count prefix matches */
|
||||
for (n = 0; n < main_cmds.cnt && !main_cmds.names[n]->len; n++)
|
||||
; /* still counting */
|
||||
|
||||
if (main_cmds.cnt <= n) {
|
||||
/* prefix matches with everything? that is too ambiguous */
|
||||
best_similarity = SIMILARITY_FLOOR + 1;
|
||||
} else {
|
||||
/* count all the most similar ones */
|
||||
for (best_similarity = main_cmds.names[n++]->len;
|
||||
(n < main_cmds.cnt &&
|
||||
best_similarity == main_cmds.names[n]->len);
|
||||
n++)
|
||||
; /* still counting */
|
||||
}
|
||||
if (autocorrect && n == 1 && SIMILAR_ENOUGH(best_similarity)) {
|
||||
const char *assumed = main_cmds.names[0]->name;
|
||||
main_cmds.names[0] = NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче