From: Junio C Hamano <gitster@pobox.com>
To: "Rubén Justo" <rjusto@gmail.com>
Cc: Git List <git@vger.kernel.org>,
Dragan Simic <dsimic@manjaro.org>, Jeff King <peff@peff.net>
Subject: Re: [PATCH v4 6/6] add-patch: introduce the command '|'
Date: Tue, 04 Jun 2024 10:12:03 -0700 [thread overview]
Message-ID: <xmqqy17kws2k.fsf@gitster.g> (raw)
In-Reply-To: <75a3cc89-4d23-4eae-b0ad-e52e2c8ba550@gmail.com> ("Rubén Justo"'s message of "Mon, 3 Jun 2024 22:38:41 +0200")
Rubén Justo <rjusto@gmail.com> writes:
> @@ -1389,6 +1390,7 @@ N_("j - leave this hunk undecided, see next undecided hunk\n"
> "s - split the current hunk into smaller hunks\n"
> "e - manually edit the current hunk\n"
> "p - print the current hunk\n"
> + "| - use pager to show the current hunk, or use |<program> to customize\n"
> "? - print help\n");
"to customize" strongly hints that the customization will stick, at
least during this session. Is that what actually happens?
> @@ -1401,6 +1403,7 @@ static int patch_update_file(struct add_p_state *s,
> struct child_process cp = CHILD_PROCESS_INIT;
> int colored = !!s->colored.len, quit = 0;
> enum prompt_mode_type prompt_mode_type;
> + const char* pager = NULL;
The asterisk sticks to "pager", not its type.
> enum {
> ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0,
> ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK = 1 << 1,
> @@ -1449,9 +1452,15 @@ static int patch_update_file(struct add_p_state *s,
> strbuf_reset(&s->buf);
> if (file_diff->hunk_nr) {
> if (rendered_hunk_index != hunk_index) {
> + if (pager)
> + setup_custom_pager(pager);
> render_hunk(s, hunk, 0, colored, &s->buf);
> fputs(s->buf.buf, stdout);
> rendered_hunk_index = hunk_index;
> + if (pager) {
> + wait_for_pager();
> + pager = NULL;
> + }
> }
>
> strbuf_reset(&s->buf);
> @@ -1485,6 +1494,7 @@ static int patch_update_file(struct add_p_state *s,
> strbuf_addstr(&s->buf, ",e");
> }
> strbuf_addstr(&s->buf, ",p");
> + strbuf_addstr(&s->buf, ",|");
> }
> if (file_diff->deleted)
> prompt_mode_type = PROMPT_DELETION;
> @@ -1512,8 +1522,8 @@ static int patch_update_file(struct add_p_state *s,
> continue;
> ch = tolower(s->answer.buf[0]);
>
> - /* 'g' takes a hunk number and '/' takes a regexp */
> - if (s->answer.len != 1 && (ch != 'g' && ch != '/')) {
> + /* 'g' takes a hunk number, '/' takes a regexp and '|' takes a program */
> + if (s->answer.len != 1 && (ch != 'g' && ch != '/' && ch != '|')) {
Not limited to this instance, but a good discipline is to stop and
think twice before adding the third thing to already existing two.
Perhaps
/*
* 'g' takes a hunk number to go to.
* '/' takes a regexp to match.
* '|' takes a program to pipe to.
*/
if (s->answer.len != 1 && !strchr("g/|", ch))
> @@ -1674,6 +1684,17 @@ static int patch_update_file(struct add_p_state *s,
> }
> } else if (s->answer.buf[0] == 'p') {
> rendered_hunk_index = -1;
> + } else if (ch == '|') {
> + strbuf_remove(&s->answer, 0, 1);
> + if (s->s.use_single_key && s->answer.len == 0) {
If you check .use_single_key, you do not need to check answer.len,
do you? Can it ever be anything other than 0 here in the single-key
mode?
> + printf("%s", _("program? "));
> + fflush(stdout);
> + strbuf_getline(&s->answer, stdin);
> + strbuf_trim_trailing_newline(&s->answer);
> + }
> + strbuf_trim(&s->answer);
> + pager = s->answer.buf;
Is it safe to peek into s->answer.buf and expect it to be live until
we have to use the pager like this?
By the way, it should be trivial to make the "custom" pager more sticky.
} else if (ch == '|') {
if (s->s.use_single_key) {
... read into s->answer ...
} else {
strbuf_remove(&s->answer, 0, 1);
}
strbuf_trim_trailing_newline(&s->answer);
/*
* If it is completely empty, use the last
* one, if it is semi-empty, reset to the default.
*/
if (!s->answer.len) {
;
} else {
FREE_AND_NULL(pager);
strbuf_trim(&s->answer);
if (!s->answer.len)
pager = xstrdup(s->answer.buf);
}
Even better, we can lift the scope of "pager" one level up, define
it as an on-stack variable in run_add_p(), add a new parameter of
type "const char **" to patch_update_file(), and use it throughout
patch_update_file(), so that a "custom" pager set here will be
carried across file boundaries.
> + rendered_hunk_index = -1;
> } else if (s->answer.buf[0] == '?') {
> const char *p = _(help_patch_remainder), *eol = p;
>
> diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
> index 6f6d174687..7b3ebb671d 100755
> --- a/t/t3701-add-interactive.sh
> +++ b/t/t3701-add-interactive.sh
> @@ -64,8 +64,8 @@ test_expect_success 'unknown command' '
> git add -N command &&
> git diff command >expect &&
> cat >>expect <<-EOF &&
> - (1/1) Stage addition [y,n,q,a,d,e,p,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
> - (1/1) Stage addition [y,n,q,a,d,e,p,?]?$SP
> + (1/1) Stage addition [y,n,q,a,d,e,p,|,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
> + (1/1) Stage addition [y,n,q,a,d,e,p,|,?]?$SP
> EOF
> git add -p -- command <command >actual 2>&1 &&
> test_cmp expect actual
> @@ -348,9 +348,9 @@ test_expect_success 'different prompts for mode change/deleted' '
> git -c core.filemode=true add -p >actual &&
> sed -n "s/^\(([0-9/]*) Stage .*?\).*/\1/p" actual >actual.filtered &&
> cat >expect <<-\EOF &&
> - (1/1) Stage deletion [y,n,q,a,d,p,?]?
> - (1/2) Stage mode change [y,n,q,a,d,j,J,g,/,p,?]?
> - (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]?
> + (1/1) Stage deletion [y,n,q,a,d,p,|,?]?
> + (1/2) Stage mode change [y,n,q,a,d,j,J,g,/,p,|,?]?
> + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,|,?]?
> EOF
> test_cmp expect actual.filtered
> '
> @@ -537,13 +537,13 @@ test_expect_success 'split hunk setup' '
> test_expect_success 'goto hunk 1 with "g 1"' '
> test_when_finished "git reset" &&
> tr _ " " >expect <<-EOF &&
> - (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? + 1: -1,2 +1,3 +15
> + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,|,?]? + 1: -1,2 +1,3 +15
> _ 2: -2,4 +3,8 +21
> go to which hunk? @@ -1,2 +1,3 @@
> _10
> +15
> _20
> - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
> + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]?_
> EOF
> test_write_lines s y g 1 | git add -p >actual &&
> tail -n 7 <actual >actual.trimmed &&
> @@ -556,7 +556,7 @@ test_expect_success 'goto hunk 1 with "g1"' '
> _10
> +15
> _20
> - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
> + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]?_
> EOF
> test_write_lines s y g1 | git add -p >actual &&
> tail -n 4 <actual >actual.trimmed &&
> @@ -566,11 +566,11 @@ test_expect_success 'goto hunk 1 with "g1"' '
> test_expect_success 'navigate to hunk via regex /pattern' '
> test_when_finished "git reset" &&
> tr _ " " >expect <<-EOF &&
> - (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? @@ -1,2 +1,3 @@
> + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,|,?]? @@ -1,2 +1,3 @@
> _10
> +15
> _20
> - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
> + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]?_
> EOF
> test_write_lines s y /1,2 | git add -p >actual &&
> tail -n 5 <actual >actual.trimmed &&
> @@ -583,7 +583,7 @@ test_expect_success 'navigate to hunk via regex / pattern' '
> _10
> +15
> _20
> - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
> + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]?_
> EOF
> test_write_lines s y / 1,2 | git add -p >actual &&
> tail -n 4 <actual >actual.trimmed &&
> @@ -595,17 +595,38 @@ test_expect_success 'print again the hunk' '
> tr _ " " >expect <<-EOF &&
> +15
> 20
> - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? @@ -1,2 +1,3 @@
> + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]? @@ -1,2 +1,3 @@
> 10
> +15
> 20
> - (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?_
> + (1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]?_
> EOF
> test_write_lines s y g 1 p | git add -p >actual &&
> tail -n 7 <actual >actual.trimmed &&
> test_cmp expect actual.trimmed
> '
>
> +test_expect_success TTY 'print again the hunk (PAGER)' '
> + test_when_finished "git reset" &&
> + cat >expect <<-EOF &&
> + <GREEN>+<RESET><GREEN>15<RESET>
> + 20<RESET>
> + <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]? <RESET>PAGER <CYAN>@@ -1,2 +1,3 @@<RESET>
> + PAGER 10<RESET>
> + PAGER <GREEN>+<RESET><GREEN>15<RESET>
> + PAGER 20<RESET>
> + <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]? <RESET>
> + EOF
> + test_write_lines s y g 1 \| |
> + (
> + GIT_PAGER="sed s/^/PAGER\ /" &&
> + export GIT_PAGER &&
> + test_terminal --no-stdin-pty git add -p >actual
> + ) &&
> + tail -n 7 <actual | test_decode_color >actual.trimmed &&
> + test_cmp expect actual.trimmed
> +'
> +
> test_expect_success 'split hunk "add -p (edit)"' '
> # Split, say Edit and do nothing. Then:
> #
> @@ -780,21 +801,21 @@ test_expect_success 'colors can be overridden' '
> <BLUE>+<RESET><BLUE>new<RESET>
> <CYAN> more-context<RESET>
> <BLUE>+<RESET><BLUE>another-one<RESET>
> - <YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
> + <YELLOW>(1/1) Stage this hunk [y,n,q,a,d,s,e,p,|,?]? <RESET><BOLD>Split into 2 hunks.<RESET>
> <MAGENTA>@@ -1,3 +1,3 @@<RESET>
> <CYAN> context<RESET>
> <BOLD>-old<RESET>
> <BLUE>+<RESET><BLUE>new<RESET>
> <CYAN> more-context<RESET>
> - <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
> + <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]? <RESET><MAGENTA>@@ -3 +3,2 @@<RESET>
> <CYAN> more-context<RESET>
> <BLUE>+<RESET><BLUE>another-one<RESET>
> - <YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
> + <YELLOW>(2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,p,|,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
> <CYAN> context<RESET>
> <BOLD>-old<RESET>
> <BLUE>+new<RESET>
> <CYAN> more-context<RESET>
> - <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]? <RESET>
> + <YELLOW>(1/2) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,|,?]? <RESET>
> EOF
> test_cmp expect actual
> '
next prev parent reply other threads:[~2024-06-04 17:12 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-19 7:06 [PATCH 0/5] use the pager in 'add -p' Rubén Justo
2024-05-19 7:10 ` [PATCH 1/5] add-patch: test for 'p' command Rubén Justo
2024-05-19 7:12 ` [PATCH 2/5] pager: do not close fd 2 unnecessarily Rubén Justo
2024-05-20 19:14 ` Junio C Hamano
2024-05-20 22:33 ` Rubén Justo
2024-05-21 20:57 ` Junio C Hamano
2024-05-21 21:35 ` Rubén Justo
2024-05-21 22:00 ` Junio C Hamano
2024-05-22 17:19 ` Rubén Justo
2024-05-22 17:40 ` Junio C Hamano
2024-05-26 6:48 ` Rubén Justo
2024-05-26 21:26 ` Junio C Hamano
2024-05-19 7:13 ` [PATCH 3/5] pager: introduce wait_for_pager Rubén Justo
2024-05-19 7:14 ` [PATCH 4/5] test-terminal: introduce --no-stdin-pty Rubén Justo
2024-05-19 7:14 ` [PATCH 5/5] add-patch: render hunks through the pager Rubén Justo
2024-05-20 19:30 ` Junio C Hamano
2024-05-20 19:45 ` Dragan Simic
2024-05-20 22:35 ` Rubén Justo
2024-05-20 23:54 ` Dragan Simic
2024-05-21 19:56 ` Rubén Justo
2024-05-21 7:07 ` Jeff King
2024-05-21 19:59 ` Rubén Justo
2024-05-23 9:06 ` Jeff King
2024-05-23 14:00 ` Junio C Hamano
2024-05-23 14:18 ` Dragan Simic
2024-05-23 23:04 ` Junio C Hamano
2024-05-23 23:28 ` Dragan Simic
2024-05-23 23:43 ` Dragan Simic
2024-05-23 23:54 ` Junio C Hamano
2024-05-23 23:57 ` Dragan Simic
2024-05-25 4:54 ` Jeff King
2024-05-23 22:25 ` Rubén Justo
2024-05-23 23:03 ` Dragan Simic
2024-05-20 22:47 ` Rubén Justo
2024-05-20 23:18 ` Junio C Hamano
2024-05-20 23:27 ` Rubén Justo
2024-05-21 20:49 ` [PATCH v2 0/5] use the pager in 'add -p' Rubén Justo
2024-05-21 20:51 ` [PATCH v2 1/5] add-patch: test for 'p' command Rubén Justo
2024-05-21 20:52 ` [PATCH v2 2/5] pager: do not close fd 2 unnecessarily Rubén Justo
2024-05-21 20:52 ` [PATCH v2 3/5] pager: introduce wait_for_pager Rubén Justo
2024-05-21 20:52 ` [PATCH v2 4/5] test-terminal: introduce --no-stdin-pty Rubén Justo
2024-05-21 20:52 ` [PATCH v2 5/5] add-patch: render hunks through the pager Rubén Justo
2024-05-22 8:09 ` Dragan Simic
2024-05-22 18:47 ` Junio C Hamano
2024-05-22 21:23 ` Rubén Justo
2024-05-22 21:27 ` Dragan Simic
2024-06-02 15:38 ` [PATCH v3 0/6] use the pager in 'add -p' Rubén Justo
2024-06-02 15:42 ` [PATCH v3 1/6] add-patch: test for 'p' command Rubén Justo
2024-06-02 15:42 ` [PATCH v3 2/6] pager: do not close fd 2 unnecessarily Rubén Justo
2024-06-02 15:43 ` [PATCH v3 3/6] pager: introduce wait_for_pager Rubén Justo
2024-06-02 15:43 ` [PATCH v3 4/6] pager: introduce setup_custom_pager Rubén Justo
2024-06-02 15:43 ` [PATCH v3 5/6] test-terminal: introduce --no-stdin-pty Rubén Justo
2024-06-02 15:44 ` [PATCH v3 6/6] add-patch: introduce the command '|' Rubén Justo
2024-06-02 16:36 ` [PATCH v3 0/6] use the pager in 'add -p' Junio C Hamano
2024-06-02 17:11 ` Junio C Hamano
2024-06-02 17:33 ` Rubén Justo
2024-06-02 17:13 ` Rubén Justo
2024-06-02 17:46 ` Dragan Simic
2024-06-03 9:03 ` Junio C Hamano
2024-06-03 10:21 ` Dragan Simic
2024-06-03 15:28 ` Junio C Hamano
2024-06-04 17:34 ` Dragan Simic
2024-06-02 17:36 ` Dragan Simic
2024-06-03 16:01 ` Junio C Hamano
2024-06-04 17:41 ` Dragan Simic
2024-06-04 17:42 ` Dragan Simic
2024-06-03 20:19 ` Rubén Justo
2024-06-04 18:13 ` Dragan Simic
2024-06-03 20:35 ` [PATCH v4 " Rubén Justo
2024-06-03 20:38 ` [PATCH v4 1/6] add-patch: test for 'p' command Rubén Justo
2024-06-03 20:38 ` [PATCH v4 2/6] pager: do not close fd 2 unnecessarily Rubén Justo
2024-06-04 15:50 ` Junio C Hamano
2024-06-03 20:38 ` [PATCH v4 3/6] pager: introduce wait_for_pager Rubén Justo
2024-06-04 10:00 ` Phillip Wood
2024-06-04 16:29 ` Junio C Hamano
2024-06-05 22:03 ` Rubén Justo
2024-06-04 16:25 ` Junio C Hamano
2024-06-03 20:38 ` [PATCH v4 4/6] pager: introduce setup_custom_pager Rubén Justo
2024-06-04 16:43 ` Junio C Hamano
2024-06-03 20:38 ` [PATCH v4 5/6] test-terminal: introduce --no-stdin-pty Rubén Justo
2024-06-04 10:05 ` Phillip Wood
2024-06-04 10:33 ` Jeff King
2024-06-05 15:39 ` Junio C Hamano
2024-06-06 8:24 ` Jeff King
2024-06-05 22:50 ` Rubén Justo
2024-06-06 8:27 ` Jeff King
2024-06-09 7:26 ` Rubén Justo
2024-06-03 20:38 ` [PATCH v4 6/6] add-patch: introduce the command '|' Rubén Justo
2024-06-04 17:12 ` Junio C Hamano [this message]
2024-06-04 20:05 ` Dragan Simic
2024-06-05 5:16 ` Junio C Hamano
2024-06-04 10:17 ` [PATCH v3 0/6] use the pager in 'add -p' Jeff King
2024-06-04 15:32 ` Junio C Hamano
2024-06-05 9:09 ` Jeff King
2024-06-05 13:21 ` Phillip Wood
2024-06-08 5:54 ` Dragan Simic
2024-06-09 7:44 ` Rubén Justo
2024-06-09 7:57 ` Dragan Simic
2024-06-10 19:09 ` Rubén Justo
2024-06-10 21:02 ` Dragan Simic
2024-06-10 14:09 ` Phillip Wood
2024-06-10 16:13 ` Junio C Hamano
2024-06-10 19:14 ` Rubén Justo
2024-06-10 19:56 ` Junio C Hamano
2024-06-10 21:08 ` Dragan Simic
2024-06-10 19:28 ` Dragan Simic
2024-06-10 20:08 ` Junio C Hamano
2024-06-10 21:16 ` Dragan Simic
2024-06-09 14:29 ` phillip.wood123
2024-06-09 17:20 ` Dragan Simic
2024-06-10 8:27 ` Phillip Wood
2024-06-10 9:09 ` Dragan Simic
2024-06-05 17:24 ` Junio C Hamano
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqqy17kws2k.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=dsimic@manjaro.org \
--cc=git@vger.kernel.org \
--cc=peff@peff.net \
--cc=rjusto@gmail.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.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.