From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Junio C Hamano <gitster@pobox.com>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH 16/19] built-in add -p: implement the '/' ("search regex") command
Date: Fri, 13 Dec 2019 08:08:03 +0000 [thread overview]
Message-ID: <e7d218793b506d7e9116d9f3a3fabf220191bc72.1576224486.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.173.git.1576224486.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
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 <johannes.schindelin@gmx.de>
---
add-patch.c | 50 +++++++++++++++++++++++++++++++++++++-
t/t3701-add-interactive.sh | 14 +++++++++++
2 files changed, 63 insertions(+), 1 deletion(-)
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 @@ static int patch_update_file(struct add_p_state *s,
"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)
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 57c656a20c..12ee321707 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -429,6 +429,20 @@ test_expect_success 'goto hunk' '
test_cmp expect actual.trimmed
'
+test_expect_success 'navigate to hunk via regex' '
+ test_when_finished "git reset" &&
+ tr _ " " >expect <<-EOF &&
+ (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? @@ -1,2 +1,3 @@
+ _10
+ +15
+ _20
+ (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]?_
+ EOF
+ test_write_lines s y /1,2 | git add -p >actual &&
+ tail -n 5 <actual >actual.trimmed &&
+ test_cmp expect actual.trimmed
+'
+
test_expect_success 'split hunk "add -p (edit)"' '
# Split, say Edit and do nothing. Then:
#
--
gitgitgadget
next prev parent reply other threads:[~2019-12-13 8:08 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-13 8:07 [PATCH 00/19] Implement the git add --patch backend in C Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 01/19] built-in add -i: start implementing the `patch` functionality " Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 02/19] built-in add -i: wire up the new C code for the `patch` command Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 03/19] built-in add -p: show colored hunks by default Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 04/19] built-in add -p: adjust hunk headers as needed Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 05/19] built-in add -p: color the prompt and the help text Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 06/19] built-in add -p: offer a helpful error message when hunk navigation failed Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 07/19] built-in add -p: support multi-file diffs Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 08/19] built-in add -p: handle deleted empty files Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 09/19] built-in app -p: allow selecting a mode change as a "hunk" Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 10/19] built-in add -p: show different prompts for mode changes and deletions Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 11/19] built-in add -p: implement the hunk splitting feature Johannes Schindelin via GitGitGadget
2019-12-13 8:07 ` [PATCH 12/19] built-in add -p: coalesce hunks after splitting them Johannes Schindelin via GitGitGadget
2019-12-13 8:08 ` [PATCH 13/19] strbuf: add a helper function to call the editor "on an strbuf" Johannes Schindelin via GitGitGadget
2019-12-13 8:08 ` [PATCH 14/19] built-in add -p: implement hunk editing Johannes Schindelin via GitGitGadget
2019-12-13 8:08 ` [PATCH 15/19] built-in add -p: implement the 'g' ("goto") command Johannes Schindelin via GitGitGadget
2019-12-13 8:08 ` Johannes Schindelin via GitGitGadget [this message]
2019-12-13 8:08 ` [PATCH 17/19] built-in add -p: implement the 'q' ("quit") command Johannes Schindelin via GitGitGadget
2019-12-13 8:08 ` [PATCH 18/19] built-in add -p: only show the applicable parts of the help text Johannes Schindelin via GitGitGadget
2019-12-13 8:08 ` [PATCH 19/19] built-in add -p: show helpful hint when nothing can be staged Johannes Schindelin via GitGitGadget
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=e7d218793b506d7e9116d9f3a3fabf220191bc72.1576224486.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=johannes.schindelin@gmx.de \
/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).