git-clean: implement partial matching for selection
Document for interactive git-clean says: "You also could say `c` or `clean` above as long as the choice is unique". But it's not true, because only hotkey `c` and full match (`clean`) could work. Implement partial matching via find_unique function to make the document right. Signed-off-by: Jiang Xin <worldhello.net@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
309422e033
commit
6083861305
@ -365,6 +365,56 @@ static void print_highlight_menu_stuff(struct menu_stuff *stuff, int **chosen)
|
||||
string_list_clear(&menu_list, 0);
|
||||
}
|
||||
|
||||
static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
|
||||
{
|
||||
struct menu_item *menu_item;
|
||||
struct string_list_item *string_list_item;
|
||||
int i, len, found = 0;
|
||||
|
||||
len = strlen(choice);
|
||||
switch (menu_stuff->type) {
|
||||
default:
|
||||
die("Bad type of menu_stuff when parse choice");
|
||||
case MENU_STUFF_TYPE_MENU_ITEM:
|
||||
|
||||
menu_item = (struct menu_item *)menu_stuff->stuff;
|
||||
for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
|
||||
if (len == 1 && *choice == menu_item->hotkey) {
|
||||
found = i + 1;
|
||||
break;
|
||||
}
|
||||
if (!strncasecmp(choice, menu_item->title, len)) {
|
||||
if (found) {
|
||||
if (len == 1) {
|
||||
/* continue for hotkey matching */
|
||||
found = -1;
|
||||
} else {
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
found = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_STUFF_TYPE_STRING_LIST:
|
||||
string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
|
||||
for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
|
||||
if (!strncasecmp(choice, string_list_item->string, len)) {
|
||||
if (found) {
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
found = i + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse user input, and return choice(s) for menu (menu_stuff).
|
||||
*
|
||||
@ -392,8 +442,6 @@ static int parse_choice(struct menu_stuff *menu_stuff,
|
||||
int **chosen)
|
||||
{
|
||||
struct strbuf **choice_list, **ptr;
|
||||
struct menu_item *menu_item;
|
||||
struct string_list_item *string_list_item;
|
||||
int nr = 0;
|
||||
int i;
|
||||
|
||||
@ -457,32 +505,8 @@ static int parse_choice(struct menu_stuff *menu_stuff,
|
||||
bottom = 1;
|
||||
top = menu_stuff->nr;
|
||||
} else {
|
||||
switch (menu_stuff->type) {
|
||||
default:
|
||||
die("Bad type of menu_stuff when parse choice");
|
||||
case MENU_STUFF_TYPE_MENU_ITEM:
|
||||
menu_item = (struct menu_item *)menu_stuff->stuff;
|
||||
for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
|
||||
if (((*ptr)->len == 1 &&
|
||||
*(*ptr)->buf == menu_item->hotkey) ||
|
||||
!strcasecmp((*ptr)->buf, menu_item->title)) {
|
||||
bottom = i + 1;
|
||||
top = bottom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MENU_STUFF_TYPE_STRING_LIST:
|
||||
string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
|
||||
for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
|
||||
if (!strcasecmp((*ptr)->buf, string_list_item->string)) {
|
||||
bottom = i + 1;
|
||||
top = bottom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
bottom = find_unique((*ptr)->buf, menu_stuff);
|
||||
top = bottom;
|
||||
}
|
||||
|
||||
if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
|
||||
|
@ -17,7 +17,7 @@ test_expect_success 'setup' '
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'git clean -i (clean)' '
|
||||
test_expect_success 'git clean -i (c: clean hotkey)' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
|
||||
@ -38,12 +38,33 @@ test_expect_success 'git clean -i (clean)' '
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'git clean -i (cl: clean prefix)' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
|
||||
docs/manual.txt obj.o build/lib.so &&
|
||||
echo cl | git clean -i &&
|
||||
test -f Makefile &&
|
||||
test -f README &&
|
||||
test -f src/part1.c &&
|
||||
test -f src/part2.c &&
|
||||
test ! -f a.out &&
|
||||
test -f docs/manual.txt &&
|
||||
test ! -f src/part3.c &&
|
||||
test ! -f src/part3.h &&
|
||||
test ! -f src/part4.c &&
|
||||
test ! -f src/part4.h &&
|
||||
test -f obj.o &&
|
||||
test -f build/lib.so
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'git clean -i (quit)' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
|
||||
docs/manual.txt obj.o build/lib.so &&
|
||||
echo q | git clean -i &&
|
||||
echo quit | git clean -i &&
|
||||
test -f Makefile &&
|
||||
test -f README &&
|
||||
test -f src/part1.c &&
|
||||
@ -256,6 +277,21 @@ test_expect_success 'git clean -id (select - number 3)' '
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'git clean -id (select - filenames)' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
touch a.out foo.txt bar.txt baz.txt &&
|
||||
(echo s; echo a.out fo ba bar; echo; echo c) | \
|
||||
git clean -id &&
|
||||
test -f Makefile &&
|
||||
test ! -f a.out &&
|
||||
test ! -f foo.txt &&
|
||||
test ! -f bar.txt &&
|
||||
test -f baz.txt &&
|
||||
rm baz.txt
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'git clean -id (select - range)' '
|
||||
|
||||
mkdir -p build docs &&
|
||||
|
Loading…
Reference in New Issue
Block a user