Skip to content

Commit 928e9d0

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 1f3e304 commit 928e9d0

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;
@@ -337,12 +357,29 @@ static void populate_wi_changes(struct strbuf *buf,
337357
strbuf_addstr(buf, no_changes);
338358
}
339359

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

345-
static void print_file_item(int i, struct item *item,
382+
static void print_file_item(int i, struct prefix_item *item,
346383
void *print_file_item_data)
347384
{
348385
struct file_item *c = (struct file_item *)item;
@@ -369,20 +406,26 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
369406
return -1;
370407

371408
if (files->nr)
372-
list((struct item **)files->file, files->nr, s, opts);
409+
list((struct prefix_item **)files->file, files->nr, s, opts);
373410
putchar('\n');
374411

375412
return 0;
376413
}
377414

378-
static void print_command_item(int i, struct item *item,
415+
static void print_command_item(int i, struct prefix_item *item,
379416
void *print_command_item_data)
380417
{
381-
printf(" %2d: %s", i + 1, item->name);
418+
if (!item->prefix_length ||
419+
!is_valid_prefix(item->name, item->prefix_length))
420+
printf(" %2d: %s", i + 1, item->name);
421+
else
422+
printf(" %3d: [%.*s]%s", i + 1,
423+
(int)item->prefix_length, item->name,
424+
item->name + item->prefix_length);
382425
}
383426

384427
struct command_item {
385-
struct item item;
428+
struct prefix_item item;
386429
int (*command)(struct add_i_state *s, const struct pathspec *ps,
387430
struct file_list *files, struct list_options *opts);
388431
};
@@ -424,7 +467,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
424467
res = -1;
425468

426469
for (;;) {
427-
i = list_and_choose((struct item **)commands,
470+
i = list_and_choose((struct prefix_item **)commands,
428471
ARRAY_SIZE(commands), &s, &main_loop_opts);
429472
if (i == LIST_AND_CHOOSE_QUIT) {
430473
printf(_("Bye.\n"));

0 commit comments

Comments
 (0)