From: Johannes Schindelin <johannes.schindelin@xxxxxx> 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@xxxxxx> --- add-patch.c | 22 ++++++++++++++++++++++ t/t3701-add-interactive.sh | 10 +++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) 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' ' -- gitgitgadget