Skip to content

Commit f533cec

Browse files
slavicaDjgitster
authored andcommitted
built-in add -i: show unique prefixes of the commands
Just like in the Perl script `git-add--interactive.perl`, for each command a unique prefix is determined (if there exists any within the given parameters), and shown in the list, and accepted as a shortcut for the command. We use the prefix map implementation that we just added in the previous commit for that purpose. Signed-off-by: Slavica Djukic <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ebd386a commit f533cec

File tree

1 file changed

+56
-13
lines changed

1 file changed

+56
-13
lines changed

add-interactive.c

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "diffcore.h"
66
#include "revision.h"
77
#include "refs.h"
8+
#include "prefix-map.h"
89

910
struct 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

5367
struct 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;
@@ -100,13 +115,15 @@ struct list_and_choose_options {
100115
* If an error occurred, returns `LIST_AND_CHOOSE_ERROR`. Upon EOF,
101116
* `LIST_AND_CHOOSE_QUIT` is returned.
102117
*/
103-
static ssize_t list_and_choose(struct item **items, size_t nr,
118+
static ssize_t list_and_choose(struct prefix_item **items, size_t nr,
104119
struct add_i_state *s,
105120
struct list_and_choose_options *opts)
106121
{
107122
struct strbuf input = STRBUF_INIT;
108123
ssize_t res = LIST_AND_CHOOSE_ERROR;
109124

125+
find_unique_prefixes(items, nr, 1, 4);
126+
110127
for (;;) {
111128
char *p, *endp;
112129

@@ -146,6 +163,9 @@ static ssize_t list_and_choose(struct item **items, size_t nr,
146163
}
147164

148165
p[sep] = '\0';
166+
if (index < 0)
167+
index = find_unique(p, items, nr);
168+
149169
if (index < 0 || index >= nr)
150170
printf(_("Huh (%s)?\n"), p);
151171
else {
@@ -171,7 +191,7 @@ struct adddel {
171191

172192
struct file_list {
173193
struct file_item {
174-
struct item item;
194+
struct prefix_item item;
175195
struct adddel index, worktree;
176196
} **file;
177197
size_t nr, alloc;
@@ -338,12 +358,29 @@ static void populate_wi_changes(struct strbuf *buf,
338358
strbuf_addstr(buf, no_changes);
339359
}
340360

361+
/* filters out prefixes which have special meaning to list_and_choose() */
362+
static int is_valid_prefix(const char *prefix, size_t prefix_len)
363+
{
364+
return prefix_len && prefix &&
365+
/*
366+
* We expect `prefix` to be NUL terminated, therefore this
367+
* `strcspn()` call is okay, even if it might do much more
368+
* work than strictly necessary.
369+
*/
370+
strcspn(prefix, " \t\r\n,") >= prefix_len && /* separators */
371+
*prefix != '-' && /* deselection */
372+
!isdigit(*prefix) && /* selection */
373+
(prefix_len != 1 ||
374+
(*prefix != '*' && /* "all" wildcard */
375+
*prefix != '?')); /* prompt help */
376+
}
377+
341378
struct print_file_item_data {
342379
const char *modified_fmt;
343380
struct strbuf buf, index, worktree;
344381
};
345382

346-
static void print_file_item(int i, struct item *item,
383+
static void print_file_item(int i, struct prefix_item *item,
347384
void *print_file_item_data)
348385
{
349386
struct file_item *c = (struct file_item *)item;
@@ -370,20 +407,26 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
370407
return -1;
371408

372409
if (files->nr)
373-
list((struct item **)files->file, files->nr, s, opts);
410+
list((struct prefix_item **)files->file, files->nr, s, opts);
374411
putchar('\n');
375412

376413
return 0;
377414
}
378415

379-
static void print_command_item(int i, struct item *item,
416+
static void print_command_item(int i, struct prefix_item *item,
380417
void *print_command_item_data)
381418
{
382-
printf(" %2d: %s", i + 1, item->name);
419+
if (!item->prefix_length ||
420+
!is_valid_prefix(item->name, item->prefix_length))
421+
printf(" %2d: %s", i + 1, item->name);
422+
else
423+
printf(" %3d: [%.*s]%s", i + 1,
424+
(int)item->prefix_length, item->name,
425+
item->name + item->prefix_length);
383426
}
384427

385428
struct command_item {
386-
struct item item;
429+
struct prefix_item item;
387430
int (*command)(struct add_i_state *s, const struct pathspec *ps,
388431
struct file_list *files, struct list_options *opts);
389432
};
@@ -425,7 +468,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
425468
res = -1;
426469

427470
for (;;) {
428-
i = list_and_choose((struct item **)commands,
471+
i = list_and_choose((struct prefix_item **)commands,
429472
ARRAY_SIZE(commands), &s, &main_loop_opts);
430473
if (i == LIST_AND_CHOOSE_QUIT) {
431474
printf(_("Bye.\n"));

0 commit comments

Comments
 (0)