From: "René Scharfe" <l.s.r@web•de>
To: "git@vger•kernel.org" <git@vger•kernel.org>
Cc: "Windl, Ulrich" <u.windl@ukr•de>,
Junio C Hamano <gitster@pobox•com>,
Phillip Wood <phillip.wood@dunelm•org.uk>
Subject: [PATCH v2 4/5] add-patch: let options k and K roll over like j and J
Date: Sun, 5 Oct 2025 17:55:46 +0200 [thread overview]
Message-ID: <f99b93d5-3de2-4077-8818-9272e812c289@web.de> (raw)
In-Reply-To: <17ef29a7-5214-4729-82eb-92a2af33e465@web.de>
Options j and J roll over at the bottom and go to the first undecided
hunk and hunk 1, respectively. Let options k and K do the same when
they reach the top of the hunk array, so let them go to the last
undecided hunk and the last hunk, respectively, for consistency.
Signed-off-by: René Scharfe <l.s.r@web•de>
---
Documentation/git-add.adoc | 4 ++--
add-patch.c | 18 ++++++++++++-----
t/t3701-add-interactive.sh | 40 +++++++++++++++++++-------------------
3 files changed, 35 insertions(+), 27 deletions(-)
diff --git a/Documentation/git-add.adoc b/Documentation/git-add.adoc
index 596cdeff93..3116a2cac5 100644
--- a/Documentation/git-add.adoc
+++ b/Documentation/git-add.adoc
@@ -344,8 +344,8 @@ patch::
/ - search for a hunk matching the given regex
j - go to the next undecided hunk, roll over at the bottom
J - go to the next hunk, roll over at the bottom
- k - go to the previous undecided hunk
- K - go to the previous hunk
+ k - go to the previous undecided hunk, roll over at the top
+ K - go to the previous hunk, roll over at the top
s - split the current hunk into smaller hunks
e - manually edit the current hunk
p - print the current hunk
diff --git a/add-patch.c b/add-patch.c
index da75618dcb..52e881d3b0 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1399,8 +1399,8 @@ static size_t display_hunks(struct add_p_state *s,
static const char help_patch_remainder[] =
N_("j - go to the next undecided hunk, roll over at the bottom\n"
"J - go to the next hunk, roll over at the bottom\n"
- "k - go to the previous undecided hunk\n"
- "K - go to the previous hunk\n"
+ "k - go to the previous undecided hunk, roll over at the top\n"
+ "K - go to the previous hunk, roll over at the top\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"
@@ -1408,6 +1408,11 @@ N_("j - go to the next undecided hunk, roll over at the bottom\n"
"p - print the current hunk, 'P' to use the pager\n"
"? - print help\n");
+static size_t dec_mod(size_t a, size_t m)
+{
+ return a > 0 ? a - 1 : m - 1;
+}
+
static size_t inc_mod(size_t a, size_t m)
{
return a < m - 1 ? a + 1 : 0;
@@ -1450,7 +1455,9 @@ static int patch_update_file(struct add_p_state *s,
undecided_next = -1;
if (file_diff->hunk_nr) {
- for (i = hunk_index - 1; i >= 0; i--)
+ for (i = dec_mod(hunk_index, file_diff->hunk_nr);
+ i != hunk_index;
+ i = dec_mod(i, file_diff->hunk_nr))
if (file_diff->hunk[i].use == UNDECIDED_HUNK) {
undecided_previous = i;
break;
@@ -1492,7 +1499,7 @@ static int patch_update_file(struct add_p_state *s,
permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK;
strbuf_addstr(&s->buf, ",k");
}
- if (hunk_index) {
+ if (file_diff->hunk_nr > 1) {
permitted |= ALLOW_GOTO_PREVIOUS_HUNK;
strbuf_addstr(&s->buf, ",K");
}
@@ -1584,7 +1591,8 @@ static int patch_update_file(struct add_p_state *s,
}
} else if (s->answer.buf[0] == 'K') {
if (permitted & ALLOW_GOTO_PREVIOUS_HUNK)
- hunk_index--;
+ hunk_index = dec_mod(hunk_index,
+ file_diff->hunk_nr);
else
err(s, _("No previous hunk"));
} else if (s->answer.buf[0] == 'J') {
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 8086d3da71..385e55c783 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -333,7 +333,7 @@ test_expect_success 'different prompts for mode change/deleted' '
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,?]?
+ (1/2) Stage mode change [y,n,q,a,d,k,K,j,J,g,/,p,?]?
(2/2) Stage this hunk [y,n,q,a,d,K,J,g,/,e,p,?]?
EOF
test_cmp expect actual.filtered
@@ -527,7 +527,7 @@ test_expect_success 'goto hunk 1 with "g 1"' '
_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,k,K,j,J,g,/,e,p,?]?_
EOF
test_write_lines s y g 1 | git add -p >actual &&
tail -n 7 <actual >actual.trimmed &&
@@ -540,7 +540,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,k,K,j,J,g,/,e,p,?]?_
EOF
test_write_lines s y g1 | git add -p >actual &&
tail -n 4 <actual >actual.trimmed &&
@@ -554,7 +554,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,k,K,j,J,g,/,e,p,?]?_
EOF
test_write_lines s y /1,2 | git add -p >actual &&
tail -n 5 <actual >actual.trimmed &&
@@ -567,7 +567,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,k,K,j,J,g,/,e,p,?]?_
EOF
test_write_lines s y / 1,2 | git add -p >actual &&
tail -n 4 <actual >actual.trimmed &&
@@ -579,11 +579,11 @@ 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,k,K,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,k,K,j,J,g,/,e,p,?]?_
EOF
test_write_lines s y g 1 p | git add -p >actual &&
tail -n 7 <actual >actual.trimmed &&
@@ -595,11 +595,11 @@ test_expect_success TTY 'print again the hunk (PAGER)' '
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>
+ <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,k,K,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>
+ <BOLD;BLUE>(1/2) Stage this hunk [y,n,q,a,d,k,K,j,J,g,/,e,p,?]? <RESET>
EOF
test_write_lines s y g 1 P |
(
@@ -802,7 +802,7 @@ test_expect_success 'colors can be overridden' '
<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,k,K,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,J,g,/,e,p,?]? <RESET><MAGENTA>@@ -1,3 +1,3 @@<RESET>
@@ -810,7 +810,7 @@ test_expect_success 'colors can be overridden' '
<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,k,K,j,J,g,/,e,p,?]? <RESET>
EOF
test_cmp expect actual
'
@@ -1354,34 +1354,34 @@ do
'
done
-test_expect_success 'option J rolls over' '
+test_expect_success 'options J, K roll over' '
test_write_lines a b c d e f g h i >file &&
git add file &&
test_write_lines X b c d e f g h X >file &&
- test_write_lines J J q | git add -p >out &&
- test_write_lines 1 2 1 >expect &&
+ test_write_lines J J K q | git add -p >out &&
+ test_write_lines 1 2 1 2 >expect &&
sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
test_cmp expect actual
'
-test_expect_success 'options y, n, j, e roll over to next undecided (1)' '
+test_expect_success 'options y, n, j, k, e roll over to next undecided (1)' '
test_write_lines a b c d e f g h i j k l m n o p q >file &&
git add file &&
test_write_lines X b c d e f g h X j k l m n o p X >file &&
test_set_editor : &&
- test_write_lines g3 y g3 n g3 j g3 e q | git add -p >out &&
- test_write_lines 1 3 1 3 1 3 1 3 1 >expect &&
+ test_write_lines g3 y g3 n g3 j g3 e k q | git add -p >out &&
+ test_write_lines 1 3 1 3 1 3 1 3 1 2 >expect &&
sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
test_cmp expect actual
'
-test_expect_success 'options y, n, j, e roll over to next undecided (2)' '
+test_expect_success 'options y, n, j, k, e roll over to next undecided (2)' '
test_write_lines a b c d e f g h i j k l m n o p q >file &&
git add file &&
test_write_lines X b c d e f g h X j k l m n o p X >file &&
test_set_editor : &&
- test_write_lines y g3 y g3 n g3 j g3 e q | git add -p >out &&
- test_write_lines 1 2 3 2 3 2 3 2 3 2 >expect &&
+ test_write_lines y g3 y g3 n g3 j g3 e g1 k q | git add -p >out &&
+ test_write_lines 1 2 3 2 3 2 3 2 3 2 1 2 >expect &&
sed -n -e "s-/.*--" -e "s/^(//p" <out >actual &&
test_cmp expect actual
'
--
2.51.0
next prev parent reply other threads:[~2025-10-05 15:55 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-02 9:23 Broken handling of "J" hunks for "add --interactive"? Windl, Ulrich
2025-10-03 12:16 ` [PATCH] add-patch: roll over to next undecided hunk René Scharfe
2025-10-03 13:41 ` Phillip Wood
2025-10-03 14:10 ` René Scharfe
2025-10-08 13:47 ` Phillip Wood
2025-10-03 16:11 ` Junio C Hamano
2025-10-03 19:53 ` René Scharfe
2025-10-03 20:39 ` Junio C Hamano
2025-10-03 20:42 ` Junio C Hamano
2025-10-03 21:18 ` Junio C Hamano
2025-10-05 15:45 ` [PATCH v2 0/5] " René Scharfe
2025-10-05 15:55 ` [PATCH v2 1/5] add-patch: improve help for options j, J, k, and K René Scharfe
2025-10-05 21:30 ` Junio C Hamano
2025-10-06 17:17 ` René Scharfe
2025-10-06 17:58 ` Junio C Hamano
2025-10-31 10:08 ` [EXT] " Windl, Ulrich
2025-11-01 8:18 ` Junio C Hamano
2025-11-03 12:43 ` [EXT] " Windl, Ulrich
2025-10-05 15:55 ` [PATCH v2 2/5] add-patch: document that option J rolls over René Scharfe
2025-10-05 21:30 ` Junio C Hamano
2025-10-05 15:55 ` [PATCH v2 3/5] add-patch: let options y, n, j, and e roll over to next undecided René Scharfe
2025-10-05 15:55 ` René Scharfe [this message]
2025-10-05 20:55 ` [PATCH v2 4/5] add-patch: let options k and K roll over like j and J Junio C Hamano
2025-10-06 17:18 ` René Scharfe
2025-10-05 15:55 ` [PATCH v2 5/5] add-patch: reset "permitted" at loop start René Scharfe
2025-10-06 17:18 ` [PATCH v3 0/6] add-patch: roll over to next undecided hunk René Scharfe
2025-10-06 17:19 ` [PATCH v3 1/6] add-patch: improve help for options j, J, k, and K René Scharfe
2025-10-06 17:20 ` [PATCH v3 2/6] add-patch: document that option J rolls over René Scharfe
2025-10-06 17:21 ` [PATCH v3 3/6] add-patch: let options y, n, j, and e roll over to next undecided René Scharfe
2025-10-06 17:22 ` [PATCH v3 4/6] add-patch: let options k and K roll over like j and J René Scharfe
2025-10-06 17:23 ` [PATCH v3 5/6] add-patch: let options a and d roll over like y and n René Scharfe
2025-10-06 17:24 ` [PATCH v3 6/6] add-patch: reset "permitted" at loop start René Scharfe
2025-10-31 10:28 ` [EXT] " Windl, Ulrich
2025-10-31 15:16 ` Junio C Hamano
2025-10-06 18:00 ` [PATCH v3 0/6] add-patch: roll over to next undecided hunk Junio C Hamano
2025-10-06 20:05 ` René Scharfe
2025-10-06 22:01 ` 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=f99b93d5-3de2-4077-8818-9272e812c289@web.de \
--to=l.s.r@web$(echo .)de \
--cc=git@vger$(echo .)kernel.org \
--cc=gitster@pobox$(echo .)com \
--cc=phillip.wood@dunelm$(echo .)org.uk \
--cc=u.windl@ukr$(echo .)de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox