Skip to content

Commit 6083861

Browse files
jiangxingitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 309422e commit 6083861

File tree

2 files changed

+90
-30
lines changed

2 files changed

+90
-30
lines changed

builtin/clean.c

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,56 @@ static void print_highlight_menu_stuff(struct menu_stuff *stuff, int **chosen)
365365
string_list_clear(&menu_list, 0);
366366
}
367367

368+
static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
369+
{
370+
struct menu_item *menu_item;
371+
struct string_list_item *string_list_item;
372+
int i, len, found = 0;
373+
374+
len = strlen(choice);
375+
switch (menu_stuff->type) {
376+
default:
377+
die("Bad type of menu_stuff when parse choice");
378+
case MENU_STUFF_TYPE_MENU_ITEM:
379+
380+
menu_item = (struct menu_item *)menu_stuff->stuff;
381+
for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
382+
if (len == 1 && *choice == menu_item->hotkey) {
383+
found = i + 1;
384+
break;
385+
}
386+
if (!strncasecmp(choice, menu_item->title, len)) {
387+
if (found) {
388+
if (len == 1) {
389+
/* continue for hotkey matching */
390+
found = -1;
391+
} else {
392+
found = 0;
393+
break;
394+
}
395+
} else {
396+
found = i + 1;
397+
}
398+
}
399+
}
400+
break;
401+
case MENU_STUFF_TYPE_STRING_LIST:
402+
string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
403+
for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
404+
if (!strncasecmp(choice, string_list_item->string, len)) {
405+
if (found) {
406+
found = 0;
407+
break;
408+
}
409+
found = i + 1;
410+
}
411+
}
412+
break;
413+
}
414+
return found;
415+
}
416+
417+
368418
/*
369419
* Parse user input, and return choice(s) for menu (menu_stuff).
370420
*
@@ -392,8 +442,6 @@ static int parse_choice(struct menu_stuff *menu_stuff,
392442
int **chosen)
393443
{
394444
struct strbuf **choice_list, **ptr;
395-
struct menu_item *menu_item;
396-
struct string_list_item *string_list_item;
397445
int nr = 0;
398446
int i;
399447

@@ -457,32 +505,8 @@ static int parse_choice(struct menu_stuff *menu_stuff,
457505
bottom = 1;
458506
top = menu_stuff->nr;
459507
} else {
460-
switch (menu_stuff->type) {
461-
default:
462-
die("Bad type of menu_stuff when parse choice");
463-
case MENU_STUFF_TYPE_MENU_ITEM:
464-
menu_item = (struct menu_item *)menu_stuff->stuff;
465-
for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
466-
if (((*ptr)->len == 1 &&
467-
*(*ptr)->buf == menu_item->hotkey) ||
468-
!strcasecmp((*ptr)->buf, menu_item->title)) {
469-
bottom = i + 1;
470-
top = bottom;
471-
break;
472-
}
473-
}
474-
break;
475-
case MENU_STUFF_TYPE_STRING_LIST:
476-
string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
477-
for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
478-
if (!strcasecmp((*ptr)->buf, string_list_item->string)) {
479-
bottom = i + 1;
480-
top = bottom;
481-
break;
482-
}
483-
}
484-
break;
485-
}
508+
bottom = find_unique((*ptr)->buf, menu_stuff);
509+
top = bottom;
486510
}
487511

488512
if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||

t/t7301-clean-interactive.sh

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ test_expect_success 'setup' '
1717
1818
'
1919

20-
test_expect_success 'git clean -i (clean)' '
20+
test_expect_success 'git clean -i (c: clean hotkey)' '
2121
2222
mkdir -p build docs &&
2323
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)' '
3838
3939
'
4040

41+
test_expect_success 'git clean -i (cl: clean prefix)' '
42+
43+
mkdir -p build docs &&
44+
touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
45+
docs/manual.txt obj.o build/lib.so &&
46+
echo cl | git clean -i &&
47+
test -f Makefile &&
48+
test -f README &&
49+
test -f src/part1.c &&
50+
test -f src/part2.c &&
51+
test ! -f a.out &&
52+
test -f docs/manual.txt &&
53+
test ! -f src/part3.c &&
54+
test ! -f src/part3.h &&
55+
test ! -f src/part4.c &&
56+
test ! -f src/part4.h &&
57+
test -f obj.o &&
58+
test -f build/lib.so
59+
60+
'
61+
4162
test_expect_success 'git clean -i (quit)' '
4263
4364
mkdir -p build docs &&
4465
touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
4566
docs/manual.txt obj.o build/lib.so &&
46-
echo q | git clean -i &&
67+
echo quit | git clean -i &&
4768
test -f Makefile &&
4869
test -f README &&
4970
test -f src/part1.c &&
@@ -256,6 +277,21 @@ test_expect_success 'git clean -id (select - number 3)' '
256277
257278
'
258279

280+
test_expect_success 'git clean -id (select - filenames)' '
281+
282+
mkdir -p build docs &&
283+
touch a.out foo.txt bar.txt baz.txt &&
284+
(echo s; echo a.out fo ba bar; echo; echo c) | \
285+
git clean -id &&
286+
test -f Makefile &&
287+
test ! -f a.out &&
288+
test ! -f foo.txt &&
289+
test ! -f bar.txt &&
290+
test -f baz.txt &&
291+
rm baz.txt
292+
293+
'
294+
259295
test_expect_success 'git clean -id (select - range)' '
260296
261297
mkdir -p build docs &&

0 commit comments

Comments
 (0)