> (For the Git project itself, we long ago realized that putting raw color
> codes into the source is a big pain when working with diffs, and we
> instead use tools like t/test-lib-functions.sh's test_decode_color).
And also we hid the colors behind #defines and such.
> > * Context lines do not begin with reset code, but do end with a reset
> > code. It would be preferable in my opinion if they had both (like
> > every other line), or none at all.
>
> Context lines do have both. It's just that the default color for context
> lines is empty. ;)
The content itself can contain color codes.
Instead of unconditionally resetting each line, we could parse each
content line to determine if we actually have to reset the colors.
>
> But yes, I think it might be reasonable to recognize when an opening
> color is empty, and turn the closing reset into a noop in that case (or
> I guess you are also advocating the opposite: turn an empty color into a
> noop \x1b[m or similar).
>
> I think most of the coloring, including context lines, is coming from
> diff.c:emit_diff_symbol_from_struct(). Instead of unconditionally
> calling:
>
> context = diff_get_color_opt(o, DIFF_CONTEXT);
> reset = diff_get_color_opt(o, DIFF_RESET);
>
> I suspect we could have a helper like this:
>
> static const char *diff_get_reset(const char *color)
> {
> if (!color || !*color)
> return "";
> return diff_colors[DIFF_RESET];
> }
> ...
> context = diff_get_color_opt(o, DIFF_CONTEXT);
> reset = diff_get_reset(context);
Another easier way to do so would be to drop
the line
needs_reset = 1; /* 'line' may contain color codes. */
in diff.c::emit_line_0
I run the test suite and it passes (I thought we had a test
enforcing we'd reset any user provided coloring).
> > * Added lines have excess codes after the plus sign. The entire prefix
> > is, `\x1b[32m+\x1b[m\x1b[32m` translating to GREEN PLUS RESET GREEN.
> > Emitting codes after the plus sign makes the parsing more complex and
> > idiosyncratic.
Then we have broken code in diff.c::emit_line_ws_markup
in the last case ("else {") which first emits the sign via
emit_line_0 and then the rest via ws_check_emit.
It sounds like we'd want to replace `reset` in the call
of emit_line_0 with
set == set_sign ? NULL : reset
and set in the call to ws_check_emit with
set == set_sign ? NULL : set
Manually looking at some diff output of said diff we'd get
<RED>- emit_line_0(o, set_sign ? set_sign : set, NULL, !!set_sign,
reset,<RESET>
<GREEN>+<RESET> <GREEN>emit_line_0(o, set_sign ? set_sign : set,
NULL, !!set_sign, set == set_sign ? NULL : reset,<RESET>
and the issue is that we do not color the beginning white space
of the emission from ws_check_emit but maybe we should.
Another idea would be to allow Git to output its output
as if it was run through test_decode_color, slightly related:
https://public-inbox.org/git/[email protected]/
i.e. we'd markup the output instead of coloring it.