From: "Slavica Djukic via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Phillip Wood" <phillip.wood@dunelm.org.uk>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
"Junio C Hamano" <gitster@pobox.com>,
"Slavica Djukic" <slawica92@hotmail.com>
Subject: [PATCH v5 07/10] add-interactive.c: add support for list_only option
Date: Wed, 20 Feb 2019 03:41:33 -0800 (PST) [thread overview]
Message-ID: <7912f375170ca266a4ce0f9f755f8d8fecdf3d37.1550662887.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.103.v5.git.gitgitgadget@gmail.com>
From: Slavica Djukic <slawica92@hotmail.com>
If list_only option is not set, (i.e. we want to pick elements
from the list, not just display them), highlight unique prefixes
of list elements and let user make a choice as shown in
prompt_help_cmd and singleton_prompt_help_cmd.
Input that is expected from user is full line.
Although that's also the case with Perl script in this
particular situation, there is also sub prompt_single_character,
which deals with single keystroke.
Ever since f7a4cea25e3ee1c8f27777bc4293dca0210fa573,
we did not use _getch() in our code base's C code, and this would
be the first user. There are portability issues with _getch()
(or getch()) that we would like to avoid.
That said, from now on, every other input will also be expected
to be full line, rather than single keystroke.
Mentored-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
---
add-interactive.c | 378 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 373 insertions(+), 5 deletions(-)
diff --git a/add-interactive.c b/add-interactive.c
index 6bf8a90d9d..3c2e972413 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -70,18 +70,27 @@ struct choices {
};
#define CHOICES_INIT { NULL, 0, 0 }
+struct prefix_entry {
+ struct hashmap_entry e;
+ const char *name;
+ size_t prefix_length;
+ struct choice *item;
+};
+
static int use_color = -1;
enum color_add_i {
COLOR_PROMPT,
COLOR_HEADER,
COLOR_HELP,
- COLOR_ERROR
+ COLOR_ERROR,
+ COLOR_RESET
};
static char colors[][COLOR_MAXLEN] = {
GIT_COLOR_BOLD_BLUE, /* Prompt */
GIT_COLOR_BOLD, /* Header */
GIT_COLOR_BOLD_RED, /* Help */
+ GIT_COLOR_BOLD_RED, /* Error */
GIT_COLOR_RESET /* Reset */
};
@@ -102,6 +111,8 @@ static int parse_color_slot(const char *slot)
return COLOR_HELP;
if (!strcasecmp(slot, "error"))
return COLOR_ERROR;
+ if (!strcasecmp(slot, "reset"))
+ return COLOR_RESET;
return -1;
}
@@ -288,14 +299,248 @@ static struct collection_status *list_modified(struct repository *r, const char
return s;
}
+static int map_cmp(const void *unused_cmp_data,
+ const void *entry,
+ const void *entry_or_key,
+ const void *unused_keydata)
+{
+ const struct choice *a = entry;
+ const struct choice *b = entry_or_key;
+ if((a->prefix_length == b->prefix_length) &&
+ (strncmp(a->name, b->name, a->prefix_length) == 0))
+ return 0;
+ return 1;
+}
+
+static struct prefix_entry *new_prefix_entry(const char *name,
+ size_t prefix_length,
+ struct choice *item)
+{
+ struct prefix_entry *result = xcalloc(1, sizeof(*result));
+ result->name = name;
+ result->prefix_length = prefix_length;
+ result->item = item;
+ hashmap_entry_init(result, memhash(name, prefix_length));
+ return result;
+}
+
+static void find_unique_prefixes(struct choices *data)
+{
+ int soft_limit = 0;
+ int hard_limit = 4;
+ struct hashmap map;
+
+ hashmap_init(&map, map_cmp, NULL, 0);
+
+ for (int i = 0; i < data->nr; i++) {
+ struct prefix_entry *e = xcalloc(1, sizeof(*e));
+ struct prefix_entry *e2;
+ e->name = data->choices[i]->name;
+ e->item = data->choices[i];
+
+ for (int j = soft_limit + 1; j <= hard_limit; j++) {
+ if (!isascii(e->name[j]))
+ break;
+
+ e->prefix_length = j;
+ hashmap_entry_init(e, memhash(e->name, j));
+ e2 = hashmap_get(&map, e, NULL);
+ if (!e2) {
+ e->item->prefix_length = j;
+ hashmap_add(&map, e);
+ e = NULL;
+ break;
+ }
+
+ if (!e2->item) {
+ continue; /* non-unique prefix */
+ }
+
+ if (j != e2->item->prefix_length)
+ BUG("Hashmap entry has unexpected prefix length (%"PRIuMAX"/ != %"PRIuMAX"/)",
+ (uintmax_t)j, (uintmax_t)e2->item->prefix_length);
+
+ /* skip common prefix */
+ for (j++; j <= hard_limit && e->name[j - 1]; j++) {
+ if (e->item->name[j - 1] != e2->item->name[j - 1])
+ break;
+ hashmap_add(&map, new_prefix_entry(e->name, j, NULL));
+ }
+ if (j <= hard_limit && e2->name[j - 1]) {
+ e2->item->prefix_length = j;
+ hashmap_add(&map, new_prefix_entry(e2->name, j, e2->item));
+ }
+ else {
+ e2->item->prefix_length = 0;
+ }
+ e2->item = NULL;
+
+ if (j <= hard_limit && e->name[j - 1]) {
+ e->item->prefix_length = j;
+ hashmap_add(&map, new_prefix_entry(e->name,
+ e->item->prefix_length, e->item));
+ e = NULL;
+ }
+ else
+ e->item->prefix_length = 0;
+ break;
+ }
+
+ free(e);
+ }
+}
+
+static int find_unique(char *string, struct choices *data)
+{
+ int found = 0;
+ int i = 0;
+ int hit = 0;
+
+ for (i = 0; i < data->nr; i++) {
+ struct choice *item = data->choices[i];
+ hit = 0;
+ if (!strcmp(item->name, string))
+ hit = 1;
+ if (hit && found)
+ return 0;
+ if (hit)
+ found = i + 1;
+ }
+
+ return found;
+}
+
+/* filters out prefixes which have special meaning to list_and_choose() */
+static int is_valid_prefix(const char *prefix)
+{
+ regex_t *regex;
+ const char *pattern = "(\\s,)|(^-)|(^[0-9]+)";
+ int is_valid = 0;
+
+ regex = xmalloc(sizeof(*regex));
+ if (regcomp(regex, pattern, REG_EXTENDED))
+ return 0;
+
+ is_valid = prefix &&
+ regexec(regex, prefix, 0, NULL, 0) &&
+ strcmp(prefix, "*") &&
+ strcmp(prefix, "?");
+ free(regex);
+ return is_valid;
+}
+
+/* return a string with the prefix highlighted */
+/* for now use square brackets; later might use ANSI colors (underline, bold) */
+static char *highlight_prefix(struct choice *item)
+{
+ struct strbuf buf;
+ struct strbuf prefix;
+ struct strbuf remainder;
+ const char *prompt_color = get_color(COLOR_PROMPT);
+ const char *reset_color = get_color(COLOR_RESET);
+ int remainder_size = strlen(item->name) - item->prefix_length;
+
+ strbuf_init(&buf, 0);
+
+ strbuf_init(&prefix, 0);
+ strbuf_add(&prefix, item->name, item->prefix_length);
+
+ strbuf_init(&remainder, 0);
+ strbuf_add(&remainder, item->name + item->prefix_length,
+ remainder_size + 1);
+
+ if(!prefix.buf) {
+ strbuf_release(&buf);
+ strbuf_release(&prefix);
+ return remainder.buf;
+ }
+
+ if (!is_valid_prefix(prefix.buf)) {
+ strbuf_addstr(&buf, prefix.buf);
+ strbuf_addstr(&buf, remainder.buf);
+ }
+ else if (!use_color) {
+ strbuf_addstr(&buf, "[");
+ strbuf_addstr(&buf, prefix.buf);
+ strbuf_addstr(&buf, "]");
+ strbuf_addstr(&buf, remainder.buf);
+ }
+ else {
+ strbuf_addstr(&buf, prompt_color);
+ strbuf_addstr(&buf, prefix.buf);
+ strbuf_addstr(&buf, reset_color);
+ strbuf_addstr(&buf, remainder.buf);
+ }
+
+ strbuf_release(&prefix);
+ strbuf_release(&remainder);
+
+ return buf.buf;
+}
+
+static void singleton_prompt_help_cmd(void)
+{
+ const char *help_color = get_color(COLOR_HELP);
+ color_fprintf_ln(stdout, help_color, "%s", _("Prompt help:"));
+ color_fprintf_ln(stdout, help_color, "1 - %s",
+ _("select a numbered item"));
+ color_fprintf_ln(stdout, help_color, "foo - %s",
+ _("select item based on unique prefix"));
+ color_fprintf_ln(stdout, help_color, " - %s",
+ _("(empty) select nothing"));
+}
+
+static void prompt_help_cmd(void)
+{
+ const char *help_color = get_color(COLOR_HELP);
+ color_fprintf_ln(stdout, help_color, "%s",
+ _("Prompt help:"));
+ color_fprintf_ln(stdout, help_color, "1 - %s",
+ _("select a single item"));
+ color_fprintf_ln(stdout, help_color, "3-5 - %s",
+ _("select a range of items"));
+ color_fprintf_ln(stdout, help_color, "2-3,6-9 - %s",
+ _("select multiple ranges"));
+ color_fprintf_ln(stdout, help_color, "foo - %s",
+ _("select item based on unique prefix"));
+ color_fprintf_ln(stdout, help_color, "-... - %s",
+ _("unselect specified items"));
+ color_fprintf_ln(stdout, help_color, "* - %s",
+ _("choose all items"));
+ color_fprintf_ln(stdout, help_color, " - %s",
+ _("(empty) finish selecting"));
+}
+
static struct choices *list_and_choose(struct choices *data,
struct list_and_choose_options *opts)
{
- if (!data)
+ char *chosen_choices = xcalloc(data->nr, sizeof(char *));
+ struct choices *results = xcalloc(1, sizeof(*results));
+ int chosen_size = 0;
+
+ if (!data) {
+ free(chosen_choices);
+ free(results);
return NULL;
+ }
+
+ if (!opts->list_only)
+ find_unique_prefixes(data);
+top:
while (1) {
int last_lf = 0;
+ const char *prompt_color = get_color(COLOR_PROMPT);
+ const char *error_color = get_color(COLOR_ERROR);
+ struct strbuf input = STRBUF_INIT;
+ struct strbuf choice;
+ struct strbuf token;
+ char *token_tmp;
+ regex_t *regex_dash_range;
+ regex_t *regex_number;
+ const char *pattern_dash_range;
+ const char *pattern_number;
+ const char delim[] = " ,";
if (opts->header) {
const char *header_color = get_color(COLOR_HEADER);
@@ -306,13 +551,17 @@ static struct choices *list_and_choose(struct choices *data,
for (int i = 0; i < data->nr; i++) {
struct choice *c = data->choices[i];
+ char chosen = chosen_choices[i]? '*' : ' ';
char *print;
const char *modified_fmt = _("%12s %12s %s");
char worktree_changes[50];
char index_changes[50];
char print_buf[100];
- print = (char *)c->name;
+ if (!opts->list_only)
+ print = highlight_prefix(data->choices[i]);
+ else
+ print = (char *)c->name;
if ((data->choices[i]->type == 'f') && (!opts->list_only_file_names)) {
uintmax_t worktree_added = c->u.file.worktree.added;
@@ -338,7 +587,7 @@ static struct choices *list_and_choose(struct choices *data,
snprintf(print, 100, "%s", print_buf);
}
- printf(" %2d: %s", i + 1, print);
+ printf("%c%2d: %s", chosen, i + 1, print);
if ((opts->list_flat) && ((i + 1) % (opts->column_n))) {
printf("\t");
@@ -354,8 +603,126 @@ static struct choices *list_and_choose(struct choices *data,
if (!last_lf)
printf("\n");
- return NULL;
+ if (opts->list_only)
+ return NULL;
+
+ color_fprintf(stdout, prompt_color, "%s", opts->prompt);
+ if(opts->singleton)
+ printf("> ");
+ else
+ printf(">> ");
+
+ fflush(stdout);
+ strbuf_getline(&input, stdin);
+ strbuf_trim(&input);
+
+ if (!input.buf)
+ break;
+
+ if (!input.buf[0]) {
+ printf("\n");
+ if (opts->on_eof_fn)
+ opts->on_eof_fn();
+ break;
+ }
+
+ if (!strcmp(input.buf, "?")) {
+ opts->singleton? singleton_prompt_help_cmd() : prompt_help_cmd();
+ goto top;
+ }
+
+ token_tmp = strtok(input.buf, delim);
+ strbuf_init(&token, 0);
+ strbuf_add(&token, token_tmp, strlen(token_tmp));
+
+ while (1) {
+ int choose = 1;
+ int bottom = 0, top = 0;
+ strbuf_init(&choice, 0);
+ strbuf_addbuf(&choice, &token);
+
+ /* Input that begins with '-'; unchoose */
+ pattern_dash_range = "^-";
+ regex_dash_range = xmalloc(sizeof(*regex_dash_range));
+
+ if (regcomp(regex_dash_range, pattern_dash_range, REG_EXTENDED))
+ BUG("regex compilation for pattern %s failed",
+ pattern_dash_range);
+ if (!regexec(regex_dash_range, choice.buf, 0, NULL, 0)) {
+ choose = 0;
+ /* remove dash from input */
+ strbuf_remove(&choice, 0, 1);
+ }
+
+ /* A range can be specified like 5-7 or 5-. */
+ pattern_dash_range = "^([0-9]+)-([0-9]*)$";
+ pattern_number = "^[0-9]+$";
+ regex_number = xmalloc(sizeof(*regex_number));
+
+ if (regcomp(regex_dash_range, pattern_dash_range, REG_EXTENDED))
+ BUG("regex compilation for pattern %s failed",
+ pattern_dash_range);
+ if (regcomp(regex_number, pattern_number, REG_EXTENDED))
+ BUG("regex compilation for pattern %s failed", pattern_number);
+
+ if (!regexec(regex_dash_range, choice.buf, 0, NULL, 0)) {
+ const char delim_dash[] = "-";
+ char *num = NULL;
+ num = strtok(choice.buf, delim_dash);
+ bottom = atoi(num);
+ num = strtok(NULL, delim_dash);
+ top = num? atoi(num) : (1 + data->nr);
+ }
+ else if (!regexec(regex_number, choice.buf, 0, NULL, 0))
+ bottom = top = atoi(choice.buf);
+ else if (!strcmp(choice.buf, "*")) {
+ bottom = 1;
+ top = 1 + data->nr;
+ }
+ else {
+ bottom = top = find_unique(choice.buf, data);
+ if (!bottom) {
+ color_fprintf_ln(stdout, error_color, _("Huh (%s)?"), choice.buf);
+ goto top;
+ }
+ }
+
+ if (opts->singleton && bottom != top) {
+ color_fprintf_ln(stdout, error_color, _("Huh (%s)?"), choice.buf);
+ goto top;
+ }
+
+ for (int i = bottom - 1; i <= top - 1; i++) {
+ if (data->nr <= i || i < 0)
+ continue;
+ chosen_choices[i] = choose;
+ if (choose == 1)
+ chosen_size++;
+ }
+
+ strbuf_release(&token);
+ strbuf_release(&choice);
+
+ token_tmp = strtok(NULL, delim);
+ if (!token_tmp)
+ break;
+ strbuf_init(&token, 0);
+ strbuf_add(&token, token_tmp, strlen(token_tmp));
+ }
+
+ if ((opts->immediate) || !(strcmp(choice.buf, "*")))
+ break;
}
+
+ for (int i = 0; i < data->nr; i++) {
+ if (chosen_choices[i]) {
+ ALLOC_GROW(results->choices, results->nr + 1, results->alloc);
+ results->choices[results->nr++] = data->choices[i];
+ }
+ }
+
+ free(chosen_choices);
+ return results;
}
static struct choice *make_choice(const char *name )
@@ -412,6 +779,7 @@ void add_i_status(void)
const char *modified_fmt = _("%12s %12s %s");
const char type = 'f';
+ opts.list_only = 1;
opts.header = xmalloc(sizeof(char) * (HEADER_MAXLEN + 1));
snprintf(opts.header, HEADER_MAXLEN + 1, modified_fmt,
_("staged"), _("unstaged"), _("path"));
--
gitgitgadget
next prev parent reply other threads:[~2019-02-20 11:41 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-20 12:34 [PATCH 0/7] Turn git add-i into built-in Johannes Schindelin
2018-12-20 12:09 ` [PATCH 1/7] diff: export diffstat interface Daniel Ferreira via GitGitGadget
2018-12-20 12:09 ` [PATCH 2/7] add--helper: create builtin helper for interactive add Daniel Ferreira via GitGitGadget
2018-12-20 12:09 ` [PATCH 3/7] add-interactive.c: implement status command Daniel Ferreira via GitGitGadget
2018-12-20 12:09 ` [PATCH 4/7] add--interactive.perl: use add--helper --status for status_cmd Daniel Ferreira via GitGitGadget
2018-12-20 12:09 ` [PATCH 5/7] add-interactive.c: implement show-help command Slavica Djukic via GitGitGadget
2019-01-14 11:12 ` Phillip Wood
2018-12-20 12:09 ` [PATCH 6/7] Git.pm: introduce environment variable GIT_TEST_PRETEND_TTY Slavica Djukic via GitGitGadget
2019-01-14 11:13 ` Phillip Wood
2019-01-15 12:45 ` Slavica Djukic
2019-01-15 13:50 ` Johannes Schindelin
2019-01-15 16:09 ` Phillip Wood
2018-12-20 12:09 ` [PATCH 7/7] add--interactive.perl: use add--helper --show-help for help_cmd Slavica Djukic via GitGitGadget
2019-01-14 11:17 ` Phillip Wood
2018-12-20 12:37 ` [PATCH 0/7] Turn git add-i into built-in Johannes Schindelin
2019-01-11 14:09 ` Slavica Djukic
2019-01-18 7:47 ` [PATCH v2 " Slavica Đukić via GitGitGadget
2019-01-18 7:47 ` [PATCH v2 1/7] diff: export diffstat interface Daniel Ferreira via GitGitGadget
2019-01-18 7:47 ` [PATCH v2 2/7] add--helper: create builtin helper for interactive add Daniel Ferreira via GitGitGadget
2019-01-18 7:47 ` [PATCH v2 3/7] add-interactive.c: implement status command Daniel Ferreira via GitGitGadget
2019-01-18 7:47 ` [PATCH v2 4/7] add--interactive.perl: use add--helper --status for status_cmd Daniel Ferreira via GitGitGadget
2019-01-18 7:47 ` [PATCH v2 5/7] add-interactive.c: implement show-help command Slavica Djukic via GitGitGadget
2019-01-18 11:20 ` Phillip Wood
2019-01-18 12:19 ` Slavica Djukic
[not found] ` <VI1PR05MB577331CCE110D2EAE325927CA69C0@VI1PR05MB5773.eurprd05.prod.outlook.com>
2019-01-18 14:25 ` Phillip Wood
2019-01-18 20:40 ` Johannes Schindelin
2019-01-18 7:47 ` [PATCH v2 6/7] t3701-add-interactive: test add_i_show_help() Slavica Djukic via GitGitGadget
2019-01-18 11:23 ` Phillip Wood
2019-01-18 7:47 ` [PATCH v2 7/7] add--interactive.perl: use add--helper --show-help for help_cmd Slavica Djukic via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 0/7] Turn git add-i into built-in Slavica Đukić via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 1/7] diff: export diffstat interface Daniel Ferreira via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 2/7] add--helper: create builtin helper for interactive add Daniel Ferreira via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 3/7] add-interactive.c: implement status command Daniel Ferreira via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 4/7] add--interactive.perl: use add--helper --status for status_cmd Daniel Ferreira via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 5/7] add-interactive.c: implement show-help command Slavica Djukic via GitGitGadget
2019-01-21 9:13 ` [PATCH v3 6/7] t3701-add-interactive: test add_i_show_help() Slavica Djukic via GitGitGadget
2019-01-25 11:01 ` Phillip Wood
2019-01-25 11:36 ` Slavica Djukic
2019-01-21 9:13 ` [PATCH v3 7/7] add--interactive.perl: use add--helper --show-help for help_cmd Slavica Djukic via GitGitGadget
2019-01-21 9:59 ` Ævar Arnfjörð Bjarmason
2019-01-21 11:59 ` Slavica Djukic
2019-01-25 12:23 ` [PATCH v4 0/7] Turn git add-i into built-in Slavica Đukić via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 1/7] diff: export diffstat interface Daniel Ferreira via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 2/7] add--helper: create builtin helper for interactive add Daniel Ferreira via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 3/7] add-interactive.c: implement status command Daniel Ferreira via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 4/7] add--interactive.perl: use add--helper --status for status_cmd Daniel Ferreira via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 5/7] add-interactive.c: implement show-help command Slavica Djukic via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 6/7] t3701-add-interactive: test add_i_show_help() Slavica Djukic via GitGitGadget
2019-01-25 12:23 ` [PATCH v4 7/7] add--interactive.perl: use add--helper --show-help for help_cmd Slavica Djukic via GitGitGadget
2019-01-25 12:37 ` [PATCH v4 0/7] Turn git add-i into built-in Slavica Djukic
2019-02-01 14:37 ` Phillip Wood
2019-02-20 11:41 ` [PATCH v5 00/10] " Slavica Đukić via GitGitGadget
2019-02-20 11:41 ` [PATCH v5 02/10] add--helper: create builtin helper for interactive add Daniel Ferreira via GitGitGadget
2019-02-21 17:56 ` Junio C Hamano
2019-03-08 20:48 ` Johannes Schindelin
2019-02-20 11:41 ` [PATCH v5 01/10] diff: export diffstat interface Daniel Ferreira via GitGitGadget
2019-02-21 17:53 ` Junio C Hamano
2019-02-22 9:03 ` Slavica Djukic
2019-02-20 11:41 ` [PATCH v5 03/10] add-interactive.c: implement list_modified Slavica Djukic via GitGitGadget
2019-02-21 19:06 ` Junio C Hamano
2019-02-21 20:27 ` Junio C Hamano
2019-02-22 12:18 ` Slavica Djukic
2019-02-22 11:35 ` Slavica Djukic
2019-02-20 11:41 ` [PATCH v5 04/10] add-interactive.c: implement list_and_choose Slavica Djukic via GitGitGadget
2019-02-22 21:46 ` Junio C Hamano
2019-03-01 11:20 ` Slavica Djukic
2019-02-20 11:41 ` [PATCH v5 05/10] add-interactive.c: implement status command Slavica Djukic via GitGitGadget
2019-02-22 22:11 ` Junio C Hamano
2019-03-01 11:08 ` Slavica Djukic
2019-02-20 11:41 ` [PATCH v5 06/10] add--interactive.perl: use add--helper --status for status_cmd Daniel Ferreira via GitGitGadget
2019-02-20 11:41 ` Slavica Djukic via GitGitGadget [this message]
2019-02-20 11:41 ` [PATCH v5 08/10] add-interactive.c: implement show-help command Slavica Djukic via GitGitGadget
2019-02-20 11:41 ` [PATCH v5 09/10] t3701-add-interactive: test add_i_show_help() Slavica Djukic via GitGitGadget
2019-02-20 11:41 ` [PATCH v5 10/10] add--interactive.perl: use add--helper --show-help for help_cmd Slavica Djukic via GitGitGadget
2019-02-22 4:53 ` [PATCH v5 00/10] Turn git add-i into built-in Junio C Hamano
2019-03-04 10:49 ` End of Outreachy internship Slavica Djukic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7912f375170ca266a4ce0f9f755f8d8fecdf3d37.1550662887.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=phillip.wood@dunelm.org.uk \
--cc=slawica92@hotmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).