55#include "diffcore.h"
66#include "revision.h"
77#include "refs.h"
8+ #include "prefix-map.h"
89
910struct add_i_state {
1011 struct repository * r ;
@@ -46,18 +47,32 @@ static int init_add_i_state(struct repository *r, struct add_i_state *s)
4647 return 0 ;
4748}
4849
49- struct item {
50- const char * name ;
51- };
50+ static ssize_t find_unique (const char * string ,
51+ struct prefix_item * * list , size_t nr )
52+ {
53+ ssize_t found = -1 , i ;
54+
55+ for (i = 0 ; i < nr ; i ++ ) {
56+ struct prefix_item * item = list [i ];
57+ if (!starts_with (item -> name , string ))
58+ continue ;
59+ if (found >= 0 )
60+ return -1 ;
61+ found = i ;
62+ }
63+
64+ return found ;
65+ }
5266
5367struct list_options {
5468 int columns ;
5569 const char * header ;
56- void (* print_item )(int i , struct item * item , void * print_item_data );
70+ void (* print_item )(int i , struct prefix_item * item ,
71+ void * print_item_data );
5772 void * print_item_data ;
5873};
5974
60- static void list (struct item * * list , size_t nr ,
75+ static void list (struct prefix_item * * list , size_t nr ,
6176 struct add_i_state * s , struct list_options * opts )
6277{
6378 int i , last_lf = 0 ;
@@ -94,13 +109,15 @@ struct list_and_choose_options {
94109/*
95110 * Returns the selected index.
96111 */
97- static ssize_t list_and_choose (struct item * * items , size_t nr ,
112+ static ssize_t list_and_choose (struct prefix_item * * items , size_t nr ,
98113 struct add_i_state * s ,
99114 struct list_and_choose_options * opts )
100115{
101116 struct strbuf input = STRBUF_INIT ;
102117 ssize_t res = -1 ;
103118
119+ find_unique_prefixes (items , nr , 1 , 4 );
120+
104121 for (;;) {
105122 char * p , * endp ;
106123
@@ -140,6 +157,9 @@ static ssize_t list_and_choose(struct item **items, size_t nr,
140157 }
141158
142159 p [sep ] = '\0' ;
160+ if (index < 0 )
161+ index = find_unique (p , items , nr );
162+
143163 if (index < 0 || index >= nr )
144164 printf (_ ("Huh (%s)?\n" ), p );
145165 else {
@@ -165,7 +185,7 @@ struct adddel {
165185
166186struct file_list {
167187 struct file_item {
168- struct item item ;
188+ struct prefix_item item ;
169189 struct adddel index , worktree ;
170190 } * * file ;
171191 size_t nr , alloc ;
@@ -331,12 +351,29 @@ static void populate_wi_changes(struct strbuf *buf,
331351 strbuf_addstr (buf , no_changes );
332352}
333353
354+ /* filters out prefixes which have special meaning to list_and_choose() */
355+ static int is_valid_prefix (const char * prefix , size_t prefix_len )
356+ {
357+ return prefix_len && prefix &&
358+ /*
359+ * We expect `prefix` to be NUL terminated, therefore this
360+ * `strcspn()` call is okay, even if it might do much more
361+ * work than strictly necessary.
362+ */
363+ strcspn (prefix , " \t\r\n," ) >= prefix_len && /* separators */
364+ * prefix != '-' && /* deselection */
365+ !isdigit (* prefix ) && /* selection */
366+ (prefix_len != 1 ||
367+ (* prefix != '*' && /* "all" wildcard */
368+ * prefix != '?' )); /* prompt help */
369+ }
370+
334371struct print_file_item_data {
335372 const char * modified_fmt ;
336373 struct strbuf buf , index , worktree ;
337374};
338375
339- static void print_file_item (int i , struct item * item ,
376+ static void print_file_item (int i , struct prefix_item * item ,
340377 void * print_file_item_data )
341378{
342379 struct file_item * c = (struct file_item * )item ;
@@ -363,20 +400,26 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
363400 return -1 ;
364401
365402 if (files -> nr )
366- list ((struct item * * )files -> file , files -> nr , s , opts );
403+ list ((struct prefix_item * * )files -> file , files -> nr , s , opts );
367404 putchar ('\n' );
368405
369406 return 0 ;
370407}
371408
372- static void print_command_item (int i , struct item * item ,
409+ static void print_command_item (int i , struct prefix_item * item ,
373410 void * print_command_item_data )
374411{
375- printf (" %2d: %s" , i + 1 , item -> name );
412+ if (!item -> prefix_length ||
413+ !is_valid_prefix (item -> name , item -> prefix_length ))
414+ printf (" %2d: %s" , i + 1 , item -> name );
415+ else
416+ printf (" %3d: [%.*s]%s" , i + 1 ,
417+ (int )item -> prefix_length , item -> name ,
418+ item -> name + item -> prefix_length );
376419}
377420
378421struct command_item {
379- struct item item ;
422+ struct prefix_item item ;
380423 int (* command )(struct add_i_state * s , const struct pathspec * ps ,
381424 struct file_list * files , struct list_options * opts );
382425};
@@ -418,7 +461,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
418461 res = -1 ;
419462
420463 for (;;) {
421- i = list_and_choose ((struct item * * )commands ,
464+ i = list_and_choose ((struct prefix_item * * )commands ,
422465 ARRAY_SIZE (commands ), & s , & main_loop_opts );
423466 if (i < -1 ) {
424467 printf (_ ("Bye.\n" ));
0 commit comments