@@ -75,12 +75,12 @@ static ssize_t find_unique(const char *string,
75
75
struct list_options {
76
76
int columns ;
77
77
const char * header ;
78
- void (* print_item )(int i , struct prefix_item * item ,
78
+ void (* print_item )(int i , int selected , struct prefix_item * item ,
79
79
void * print_item_data );
80
80
void * print_item_data ;
81
81
};
82
82
83
- static void list (struct prefix_item * * list , size_t nr ,
83
+ static void list (struct prefix_item * * list , int * selected , size_t nr ,
84
84
struct add_i_state * s , struct list_options * opts )
85
85
{
86
86
int i , last_lf = 0 ;
@@ -93,7 +93,8 @@ static void list(struct prefix_item **list, size_t nr,
93
93
"%s" , opts -> header );
94
94
95
95
for (i = 0 ; i < nr ; i ++ ) {
96
- opts -> print_item (i , list [i ], opts -> print_item_data );
96
+ opts -> print_item (i , selected ? selected [i ] : 0 , list [i ],
97
+ opts -> print_item_data );
97
98
98
99
if ((opts -> columns ) && ((i + 1 ) % (opts -> columns ))) {
99
100
putchar ('\t' );
@@ -112,18 +113,32 @@ struct list_and_choose_options {
112
113
struct list_options list_opts ;
113
114
114
115
const char * prompt ;
116
+ enum {
117
+ SINGLETON = (1 <<0 ),
118
+ IMMEDIATE = (1 <<1 ),
119
+ } flags ;
115
120
void (* print_help )(struct add_i_state * s );
116
121
};
117
122
118
123
/*
119
- * Returns the selected index.
124
+ * Returns the selected index in singleton mode, the number of selected items
125
+ * otherwise.
120
126
*/
121
- static ssize_t list_and_choose (struct prefix_item * * items , size_t nr ,
122
- struct add_i_state * s ,
127
+ static ssize_t list_and_choose (struct prefix_item * * items , int * selected ,
128
+ size_t nr , struct add_i_state * s ,
123
129
struct list_and_choose_options * opts )
124
130
{
131
+ int singleton = opts -> flags & SINGLETON ;
132
+ int immediate = opts -> flags & IMMEDIATE ;
133
+
125
134
struct strbuf input = STRBUF_INIT ;
126
- ssize_t res = -1 ;
135
+ ssize_t res = singleton ? -1 : 0 ;
136
+
137
+ if (!selected && !singleton )
138
+ BUG ("need a selected array in non-singleton mode" );
139
+
140
+ if (singleton && !immediate )
141
+ BUG ("singleton requires immediate" );
127
142
128
143
find_unique_prefixes (items , nr , 1 , 4 );
129
144
@@ -132,15 +147,16 @@ static ssize_t list_and_choose(struct prefix_item **items, size_t nr,
132
147
133
148
strbuf_reset (& input );
134
149
135
- list (items , nr , s , & opts -> list_opts );
150
+ list (items , selected , nr , s , & opts -> list_opts );
136
151
137
152
color_fprintf (stdout , s -> prompt_color , "%s" , opts -> prompt );
138
- fputs (" > " , stdout );
153
+ fputs (singleton ? "> " : "> > " , stdout );
139
154
fflush (stdout );
140
155
141
156
if (strbuf_getline (& input , stdin ) == EOF ) {
142
157
putchar ('\n' );
143
- res = -2 ;
158
+ if (immediate )
159
+ res = -2 ;
144
160
break ;
145
161
}
146
162
strbuf_trim (& input );
@@ -156,7 +172,9 @@ static ssize_t list_and_choose(struct prefix_item **items, size_t nr,
156
172
p = input .buf ;
157
173
for (;;) {
158
174
size_t sep = strcspn (p , " \t\r\n," );
159
- ssize_t index = -1 ;
175
+ int choose = 1 ;
176
+ /* `from` is inclusive, `to` is exclusive */
177
+ ssize_t from = -1 , to = -1 ;
160
178
161
179
if (!sep ) {
162
180
if (!* p )
@@ -165,28 +183,59 @@ static ssize_t list_and_choose(struct prefix_item **items, size_t nr,
165
183
continue ;
166
184
}
167
185
168
- if (isdigit (* p )) {
169
- index = strtoul (p , & endp , 10 ) - 1 ;
170
- if (endp != p + sep )
171
- index = -1 ;
186
+ /* Input that begins with '-'; unchoose */
187
+ if (* p == '-' ) {
188
+ choose = 0 ;
189
+ p ++ ;
190
+ sep -- ;
191
+ }
192
+
193
+ if (sep == 1 && * p == '*' ) {
194
+ from = 0 ;
195
+ to = nr ;
196
+ } else if (isdigit (* p )) {
197
+ /* A range can be specified like 5-7 or 5-. */
198
+ from = strtoul (p , & endp , 10 ) - 1 ;
199
+ if (endp == p + sep )
200
+ to = from + 1 ;
201
+ else if (* endp == '-' ) {
202
+ to = strtoul (++ endp , & endp , 10 );
203
+ /* extra characters after the range? */
204
+ if (endp != p + sep )
205
+ from = -1 ;
206
+ }
172
207
}
173
208
174
209
p [sep ] = '\0' ;
175
- if (index < 0 )
176
- index = find_unique (p , items , nr );
210
+ if (from < 0 ) {
211
+ from = find_unique (p , items , nr );
212
+ if (from >= 0 )
213
+ to = from + 1 ;
214
+ }
177
215
178
- if (index < 0 || index >= nr )
216
+ if (from < 0 || from >= nr ||
217
+ (singleton && from + 1 != to )) {
179
218
color_fprintf_ln (stdout , s -> error_color ,
180
219
_ ("Huh (%s)?" ), p );
181
- else {
182
- res = index ;
220
+ break ;
221
+ } else if (singleton ) {
222
+ res = from ;
183
223
break ;
184
224
}
185
225
226
+ if (to > nr )
227
+ to = nr ;
228
+
229
+ for (; from < to ; from ++ )
230
+ if (selected [from ] != choose ) {
231
+ selected [from ] = choose ;
232
+ res += choose ? +1 : -1 ;
233
+ }
234
+
186
235
p += sep + 1 ;
187
236
}
188
237
189
- if (res >= 0 )
238
+ if (( immediate && res >= 0 ) || ! strcmp ( input . buf , "*" ) )
190
239
break ;
191
240
}
192
241
@@ -407,7 +456,7 @@ struct print_file_item_data {
407
456
struct strbuf buf , index , worktree ;
408
457
};
409
458
410
- static void print_file_item (int i , struct prefix_item * item ,
459
+ static void print_file_item (int i , int selected , struct prefix_item * item ,
411
460
void * print_file_item_data )
412
461
{
413
462
struct file_item * c = (struct file_item * )item ;
@@ -422,7 +471,7 @@ static void print_file_item(int i, struct prefix_item *item,
422
471
strbuf_addf (& d -> buf , d -> modified_fmt ,
423
472
d -> index .buf , d -> worktree .buf , item -> name );
424
473
425
- printf (" % 2d: %s" , i + 1 , d -> buf .buf );
474
+ printf ("%c% 2d: %s" , selected ? '*' : ' ' , i + 1 , d -> buf .buf );
426
475
}
427
476
428
477
static int run_status (struct add_i_state * s , const struct pathspec * ps ,
@@ -434,7 +483,8 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
434
483
return -1 ;
435
484
436
485
if (files -> nr )
437
- list ((struct prefix_item * * )files -> file , files -> nr , s , opts );
486
+ list ((struct prefix_item * * )files -> file , NULL , files -> nr ,
487
+ s , opts );
438
488
putchar ('\n' );
439
489
440
490
return 0 ;
@@ -465,7 +515,7 @@ struct print_command_item_data {
465
515
const char * color , * reset ;
466
516
};
467
517
468
- static void print_command_item (int i , struct prefix_item * item ,
518
+ static void print_command_item (int i , int selected , struct prefix_item * item ,
469
519
void * print_command_item_data )
470
520
{
471
521
struct print_command_item_data * d = print_command_item_data ;
@@ -503,7 +553,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
503
553
struct print_command_item_data data ;
504
554
struct list_and_choose_options main_loop_opts = {
505
555
{ 4 , N_ ("*** Commands ***" ), print_command_item , & data },
506
- N_ ("What now" ), command_prompt_help
556
+ N_ ("What now" ), SINGLETON | IMMEDIATE , command_prompt_help
507
557
};
508
558
struct command_item
509
559
status = { { "status" }, run_status },
@@ -549,7 +599,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
549
599
res = -1 ;
550
600
551
601
for (;;) {
552
- i = list_and_choose ((struct prefix_item * * )commands ,
602
+ i = list_and_choose ((struct prefix_item * * )commands , NULL ,
553
603
ARRAY_SIZE (commands ), & s , & main_loop_opts );
554
604
if (i < -1 ) {
555
605
printf (_ ("Bye.\n" ));
0 commit comments