From d6cf873340703098f2d7f54be457e4db1b32cf7b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 13 Dec 2019 08:08:03 +0000 Subject: built-in add -p: implement the '/' ("search regex") command This patch implements the hunk searching feature in the C version of `git add -p`. A test is added to verify that this behavior matches the one of the Perl version of `git add -p`. Note that this involves a change of behavior: the Perl version uses (of course) the Perl flavor of regular expressions, while this patch uses the regcomp()/regexec(), i.e. POSIX extended regular expressions. In practice, this behavior change is unlikely to matter. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- add-patch.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'add-patch.c') diff --git a/add-patch.c b/add-patch.c index fdbb1e3e22..fd72850c65 100644 --- a/add-patch.c +++ b/add-patch.c @@ -1013,6 +1013,7 @@ N_("y - stage this hunk\n" "k - leave this hunk undecided, see previous undecided hunk\n" "K - leave this hunk undecided, see previous hunk\n" "g - select a hunk to go to\n" + "/ - search for a hunk matching the given regex\n" "s - split the current hunk into smaller hunks\n" "e - manually edit the current hunk\n" "? - print help\n"); @@ -1072,7 +1073,7 @@ static int patch_update_file(struct add_p_state *s, if (hunk_index + 1 < file_diff->hunk_nr) strbuf_addstr(&s->buf, ",J"); if (file_diff->hunk_nr > 1) - strbuf_addstr(&s->buf, ",g"); + strbuf_addstr(&s->buf, ",g,/"); if (hunk->splittable_into > 1) strbuf_addstr(&s->buf, ",s"); if (hunk_index + 1 > file_diff->mode_change && @@ -1177,6 +1178,53 @@ soft_increment: "Sorry, only %d hunks available.", file_diff->hunk_nr), (int)file_diff->hunk_nr); + } else if (s->answer.buf[0] == '/') { + regex_t regex; + int ret; + + if (file_diff->hunk_nr < 2) { + err(s, _("No other hunks to search")); + continue; + } + strbuf_remove(&s->answer, 0, 1); + strbuf_trim_trailing_newline(&s->answer); + if (s->answer.len == 0) { + printf("%s", _("search for regex? ")); + fflush(stdout); + if (strbuf_getline(&s->answer, + stdin) == EOF) + break; + strbuf_trim_trailing_newline(&s->answer); + if (s->answer.len == 0) + continue; + } + ret = regcomp(®ex, s->answer.buf, + REG_EXTENDED | REG_NOSUB | REG_NEWLINE); + if (ret) { + char errbuf[1024]; + + regerror(ret, ®ex, errbuf, sizeof(errbuf)); + err(s, _("Malformed search regexp %s: %s"), + s->answer.buf, errbuf); + continue; + } + i = hunk_index; + for (;;) { + /* render the hunk into a scratch buffer */ + render_hunk(s, file_diff->hunk + i, 0, 0, + &s->buf); + if (regexec(®ex, s->buf.buf, 0, NULL, 0) + != REG_NOMATCH) + break; + i++; + if (i == file_diff->hunk_nr) + i = 0; + if (i != hunk_index) + continue; + err(s, _("No hunk matches the given pattern")); + break; + } + hunk_index = i; } else if (s->answer.buf[0] == 's') { size_t splittable_into = hunk->splittable_into; if (splittable_into < 2) -- cgit v1.2.3