Skip to content

Commit c2dc365

Browse files
committed
Create our own ANSI codes for colours instead of passing through --color
Fixed: #119 Assisted-by: Cursor
1 parent 5a56bea commit c2dc365

2 files changed

Lines changed: 155 additions & 28 deletions

File tree

Makefile.am

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,7 @@ TESTS = tests/newline1/run-test \
305305
# Feel free to send me patches. :-)
306306
XFAIL_TESTS = \
307307
tests/delhunk5/run-test \
308-
tests/delhunk6/run-test \
309-
tests/interdiff-color-context/run-test
308+
tests/delhunk6/run-test
310309

311310
test-perms: src/combinediff$(EXEEXT) src/flipdiff$(EXEEXT) \
312311
src/lsdiff$(EXEEXT) src/grepdiff$(EXEEXT) src/patchview$(EXEEXT) \

src/interdiff.c

Lines changed: 154 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@
5858
#define PATCH "patch"
5959
#endif
6060

61+
/* ANSI color codes for diff output */
62+
#define COLOR_RESET "\033[0m"
63+
#define COLOR_HEADER "\033[1m" /* Bold for headers */
64+
#define COLOR_FILE "\033[1m" /* Bold for filenames */
65+
#define COLOR_HUNK "\033[36m" /* Cyan for hunk headers */
66+
#define COLOR_ADDED "\033[32m" /* Green for added lines */
67+
#define COLOR_REMOVED "\033[31m" /* Red for removed lines */
68+
#define COLOR_CONTEXT "" /* No color for context lines */
69+
70+
/* Line type for coloring */
71+
enum line_type {
72+
LINE_CONTEXT,
73+
LINE_ADDED,
74+
LINE_REMOVED,
75+
LINE_HEADER,
76+
LINE_FILE,
77+
LINE_HUNK
78+
};
79+
6180
/* This can be invoked as interdiff, combinediff, or flipdiff. */
6281
static enum {
6382
mode_inter,
@@ -98,11 +117,62 @@ static int ignore_components = 0;
98117
static int ignore_components_specified = 0;
99118
static int unzip = 0;
100119
static int no_revert_omitted = 0;
120+
static int use_colors = 0;
121+
static int color_option_specified = 0;
101122
static int debug = 0;
102123

103124
static struct patlist *pat_drop_context = NULL;
104125

105126
static struct file_list *files_done = NULL;
127+
128+
/*
129+
* Colorize a line based on its type and whether colors are enabled.
130+
* Returns a newly allocated string that must be freed by the caller.
131+
* Only colorizes when outputting to a terminal (stdout is a TTY).
132+
*/
133+
static char *
134+
colorize_line (const char *line, enum line_type type, FILE *output_file)
135+
{
136+
const char *color_start = "";
137+
const char *color_end = "";
138+
char *result;
139+
140+
/* Only colorize if colors are enabled AND we're outputting to stdout */
141+
if (!use_colors || output_file != stdout) {
142+
return xstrdup (line);
143+
}
144+
145+
switch (type) {
146+
case LINE_CONTEXT:
147+
color_start = COLOR_CONTEXT;
148+
break;
149+
case LINE_ADDED:
150+
color_start = COLOR_ADDED;
151+
break;
152+
case LINE_REMOVED:
153+
color_start = COLOR_REMOVED;
154+
break;
155+
case LINE_HEADER:
156+
color_start = COLOR_HEADER;
157+
break;
158+
case LINE_FILE:
159+
color_start = COLOR_FILE;
160+
break;
161+
case LINE_HUNK:
162+
color_start = COLOR_HUNK;
163+
break;
164+
}
165+
166+
if (color_start[0] != '\0') {
167+
color_end = COLOR_RESET;
168+
}
169+
170+
if (asprintf (&result, "%s%s%s", color_start, line, color_end) < 0) {
171+
error (EXIT_FAILURE, errno, "Memory allocation failed");
172+
}
173+
174+
return result;
175+
}
106176
static struct file_list *files_in_patch2 = NULL;
107177
static struct file_list *files_in_patch1 = NULL;
108178

@@ -982,7 +1052,9 @@ trim_context (FILE *f /* positioned at start of @@ line */,
9821052

9831053
if (line[0] == '\\') {
9841054
/* Pass '\' lines through unaltered. */
985-
fputs (line, out);
1055+
char *colored_line = colorize_line (line, LINE_CONTEXT, out);
1056+
fputs (colored_line, out);
1057+
free (colored_line);
9861058
continue;
9871059
}
9881060

@@ -1050,13 +1122,35 @@ trim_context (FILE *f /* positioned at start of @@ line */,
10501122
printf ("Trim: %lu,%lu\n", strip_pre, strip_post);
10511123

10521124
fsetpos (f, &pos);
1053-
fprintf (out, "@@ -%lu", orig_offset);
1054-
if (new_orig_count != 1)
1055-
fprintf (out, ",%lu", new_orig_count);
1056-
fprintf (out, " +%lu", new_offset);
1057-
if (new_new_count != 1)
1058-
fprintf (out, ",%lu", new_new_count);
1059-
fprintf (out, " @@\n");
1125+
{
1126+
char *hunk_header;
1127+
char *colored_hunk;
1128+
if (new_orig_count != 1 && new_new_count != 1) {
1129+
if (asprintf (&hunk_header, "@@ -%lu,%lu +%lu,%lu @@\n",
1130+
orig_offset, new_orig_count, new_offset, new_new_count) < 0) {
1131+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1132+
}
1133+
} else if (new_orig_count != 1) {
1134+
if (asprintf (&hunk_header, "@@ -%lu,%lu +%lu @@\n",
1135+
orig_offset, new_orig_count, new_offset) < 0) {
1136+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1137+
}
1138+
} else if (new_new_count != 1) {
1139+
if (asprintf (&hunk_header, "@@ -%lu +%lu,%lu @@\n",
1140+
orig_offset, new_offset, new_new_count) < 0) {
1141+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1142+
}
1143+
} else {
1144+
if (asprintf (&hunk_header, "@@ -%lu +%lu @@\n",
1145+
orig_offset, new_offset) < 0) {
1146+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1147+
}
1148+
}
1149+
colored_hunk = colorize_line (hunk_header, LINE_HUNK, out);
1150+
fputs (colored_hunk, out);
1151+
free (hunk_header);
1152+
free (colored_hunk);
1153+
}
10601154

10611155
while (total_count--) {
10621156
ssize_t got = getline (&line, &linelen, f);
@@ -1070,7 +1164,25 @@ trim_context (FILE *f /* positioned at start of @@ line */,
10701164
if (total_count < strip_post)
10711165
continue;
10721166

1073-
fwrite (line, (size_t) got, 1, out);
1167+
{
1168+
enum line_type type;
1169+
switch (line[0]) {
1170+
case '+':
1171+
type = LINE_ADDED;
1172+
break;
1173+
case '-':
1174+
type = LINE_REMOVED;
1175+
break;
1176+
case ' ':
1177+
case '\n':
1178+
default:
1179+
type = LINE_CONTEXT;
1180+
break;
1181+
}
1182+
char *colored_line = colorize_line (line, type, out);
1183+
fputs (colored_line, out);
1184+
free (colored_line);
1185+
}
10741186
}
10751187
}
10761188

@@ -1253,6 +1365,7 @@ output_delta (FILE *p1, FILE *p2, FILE *out)
12531365
/* First character */
12541366
if (human_readable) {
12551367
char *p, *q, c, d;
1368+
char *header_line;
12561369
c = d = '\0'; /* shut gcc up */
12571370
p = strchr (oldname + 4, '\t');
12581371
if (p) {
@@ -1264,13 +1377,35 @@ output_delta (FILE *p1, FILE *p2, FILE *out)
12641377
d = *q;
12651378
*q = '\0';
12661379
}
1267-
fprintf (out, DIFF " %s %s %s\n", options, oldname + 4,
1268-
newname + 4);
1380+
if (asprintf (&header_line, DIFF " %s %s %s\n", options, oldname + 4,
1381+
newname + 4) < 0) {
1382+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1383+
}
1384+
char *colored_header = colorize_line (header_line, LINE_HEADER, out);
1385+
fputs (colored_header, out);
1386+
free (header_line);
1387+
free (colored_header);
12691388
if (p) *p = c;
12701389
if (q) *q = d;
12711390
}
1272-
fprintf (out, "--- %s\n", oldname + 4);
1273-
fprintf (out, "+++ %s\n", newname + 4);
1391+
{
1392+
char *old_line, *new_line;
1393+
char *colored_old, *colored_new;
1394+
if (asprintf (&old_line, "--- %s\n", oldname + 4) < 0) {
1395+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1396+
}
1397+
if (asprintf (&new_line, "+++ %s\n", newname + 4) < 0) {
1398+
error (EXIT_FAILURE, errno, "Memory allocation failed");
1399+
}
1400+
colored_old = colorize_line (old_line, LINE_FILE, out);
1401+
colored_new = colorize_line (new_line, LINE_FILE, out);
1402+
fputs (colored_old, out);
1403+
fputs (colored_new, out);
1404+
free (old_line);
1405+
free (new_line);
1406+
free (colored_old);
1407+
free (colored_new);
1408+
}
12741409
rewind (tmpdiff);
12751410
trim_context (tmpdiff, file.unline, out);
12761411
fclose (tmpdiff);
@@ -2284,8 +2419,9 @@ main (int argc, char *argv[])
22842419
color_mode = isatty(STDOUT_FILENO) ? "always" : "never";
22852420
}
22862421

2287-
if (asprintf (diff_opts + num_diff_opts++, "--color=%s", color_mode) < 0)
2288-
error (EXIT_FAILURE, errno, "Memory allocation failed");
2422+
/* Set our internal color flag instead of passing to diff */
2423+
use_colors = (strcmp(color_mode, "always") == 0);
2424+
color_option_specified = 1;
22892425
break;
22902426
}
22912427
case 1000 + 'I':
@@ -2317,17 +2453,9 @@ main (int argc, char *argv[])
23172453
error (EXIT_FAILURE, 0,
23182454
"-z and --in-place are mutually exclusive.");
23192455

2320-
/* Add default color=always if no color option was specified and we're in a terminal */
2321-
int has_color_option = 0;
2322-
for (int i = 0; i < num_diff_opts; i++) {
2323-
if (strncmp(diff_opts[i], "--color", 7) == 0) {
2324-
has_color_option = 1;
2325-
break;
2326-
}
2327-
}
2328-
if (!has_color_option && isatty(STDOUT_FILENO)) {
2329-
if (asprintf (diff_opts + num_diff_opts++, "--color=always") < 0)
2330-
error (EXIT_FAILURE, errno, "Memory allocation failed");
2456+
/* Set default color behavior if no color option was specified */
2457+
if (!color_option_specified && isatty(STDOUT_FILENO)) {
2458+
use_colors = 1;
23312459
}
23322460

23332461
if (optind + 2 != argc)

0 commit comments

Comments
 (0)