diff mbox series

[v3,3/5] add -p: insert space in colored hunk header as needed

Message ID 7a9f0b107e636ed57e511d2c145fc63596c1c69b.1661785916.git.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series built-in add -p: support diff-so-fancy better | expand

Commit Message

Johannes Schindelin Aug. 29, 2022, 3:11 p.m. UTC
From: Johannes Schindelin <johannes.schindelin@gmx.de>

We are about to teach `git add -p` to show the entire hunk header if the
`@@ ... @@` line range cannot be parsed. Previously, we showed only the
remainder of that hunk header as an "colored_extra" part.

To prepare for that, detect if that "colored_extra" part starts with any
non-whitespace character (ignoring ANSI escape sequences) and insert a
space, to make the output much more pleasant.

Note that this has an effect already before we make `git add -p` more
lenient when parsing the hunk headers: diff filters could already remove
the space after the line range, which is precisely what we do in the
regression test introduced by this commit.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 add-patch.c                | 22 ++++++++++++++++++++++
 t/t3701-add-interactive.sh | 10 +++++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/add-patch.c b/add-patch.c
index f2fffe1af02..9d575d30ed0 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -8,6 +8,7 @@ 
 #include "diff.h"
 #include "compat/terminal.h"
 #include "prompt.h"
+#include "utf8.h"
 
 enum prompt_mode_type {
 	PROMPT_MODE_CHANGE = 0, PROMPT_DELETION, PROMPT_ADDITION, PROMPT_HUNK,
@@ -635,6 +636,23 @@  static size_t find_next_line(struct strbuf *sb, size_t offset)
 	return eol - sb->buf + 1;
 }
 
+static int starts_with_non_ws(const char *p, size_t len)
+{
+	for (;;) {
+		size_t skip;
+
+		if (!len || isspace(*p))
+			return 0;
+		skip = display_mode_esc_sequence_len(p);
+		if (!skip)
+			return 1;
+		if (skip > len)
+			return 0;
+		p += skip;
+		len -= skip;
+	}
+}
+
 static void render_hunk(struct add_p_state *s, struct hunk *hunk,
 			ssize_t delta, int colored, struct strbuf *out)
 {
@@ -649,6 +667,7 @@  static void render_hunk(struct add_p_state *s, struct hunk *hunk,
 		size_t len;
 		unsigned long old_offset = header->old_offset;
 		unsigned long new_offset = header->new_offset;
+		int needs_extra_space = 0;
 
 		if (!colored) {
 			p = s->plain.buf + header->extra_start;
@@ -658,6 +677,7 @@  static void render_hunk(struct add_p_state *s, struct hunk *hunk,
 			p = s->colored.buf + header->colored_extra_start;
 			len = header->colored_extra_end
 				- header->colored_extra_start;
+			needs_extra_space = starts_with_non_ws(p, len);
 		}
 
 		if (s->mode->is_reverse)
@@ -673,6 +693,8 @@  static void render_hunk(struct add_p_state *s, struct hunk *hunk,
 			strbuf_addf(out, ",%lu", header->new_count);
 		strbuf_addstr(out, " @@");
 
+		if (needs_extra_space)
+			strbuf_addch(out, ' ');
 		if (len)
 			strbuf_add(out, p, len);
 		else if (colored)
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index c2187f9cec8..49200b7df68 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -772,7 +772,15 @@  test_expect_success 'handle iffy colored hunk headers' '
 	echo content >test &&
 	printf n >n &&
 	force_color git -c interactive.diffFilter="sed s/@@/XX/g" \
-		add -p <n
+		add -p <n &&
+	force_color git -c interactive.diffFilter="sed \"s/\(.*@@\).*/\1FN/\"" \
+		add -p >output 2>&1 <n &&
+	if test_have_prereq ADD_I_USE_BUILTIN
+	then
+		grep "@ FN\$" output
+	else
+		grep "@FN\$" output
+	fi
 '
 
 test_expect_success 'handle very large filtered diff' '