[PATCH] git-clean: implement partial matching for selection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 builtin/clean.c              | 80 ++++++++++++++++++++++++++++----------------
 t/t7301-clean-interactive.sh | 41 +++++++++++++++++++++--
 2 files changed, 91 insertions(+), 30 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index dba8387..3c85e15 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -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 ||
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index 4e6055d..71c5c6b 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -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,22 @@ 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 &&
+	find . > /tmp/x &&
+	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 &&
-- 
1.8.3.4.842.g8e6673c

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]