libdiff: Implement diff coloring.

This patch got accidentally left out when libdiff was imported.  The
rest of the code (command-line option etc.) was present, just not the
part that actually prints ANSI color codes.

Sponsored by:	Klara, Inc.
Reviewed by:	kevans
Differential Revision:	https://reviews.freebsd.org/D46873
This commit is contained in:
Dag-Erling Smørgrav 2024-10-02 17:54:48 +02:00
parent fe55d62ab9
commit 4e859e67dd
3 changed files with 62 additions and 13 deletions

View File

@ -110,3 +110,7 @@ int diff_output_chunk_right_version(struct diff_output_info **output_info,
const char *diff_output_get_label_left(const struct diff_input_info *info);
const char *diff_output_get_label_right(const struct diff_input_info *info);
void diff_output_set_colors(bool _color,
const char *_del_code,
const char *_add_code);

View File

@ -30,6 +30,22 @@
#include "diff_internal.h"
static bool color;
static const char *del_code = "31";
static const char *add_code = "32";
void
diff_output_set_colors(bool _color,
const char *_del_code,
const char *_add_code)
{
color = _color;
if (_del_code)
del_code = _del_code;
if (_add_code)
add_code = _add_code;
}
static int
get_atom_byte(int *ch, struct diff_atom *atom, off_t off)
{
@ -66,12 +82,25 @@ diff_output_lines(struct diff_output_info *outinfo, FILE *dest,
off_t outoff = 0, *offp;
uint8_t *typep;
int rc;
bool colored;
if (outinfo && outinfo->line_offsets.len > 0) {
unsigned int idx = outinfo->line_offsets.len - 1;
outoff = outinfo->line_offsets.head[idx];
}
if (color) {
colored = true;
if (*prefix == '-' || *prefix == '<')
printf("\033[%sm", del_code);
else if (*prefix == '+' || *prefix == '>')
printf("\033[%sm", add_code);
else
colored = false;
} else {
colored = false;
}
foreach_diff_atom(atom, start_atom, count) {
off_t outlen = 0;
int i, ch, nbuf = 0;
@ -80,14 +109,16 @@ diff_output_lines(struct diff_output_info *outinfo, FILE *dest,
size_t n;
n = strlcpy(buf, prefix, sizeof(buf));
if (n >= DIFF_OUTPUT_BUF_SIZE) /* leave room for '\n' */
return ENOBUFS;
if (n >= DIFF_OUTPUT_BUF_SIZE) { /* leave room for '\n' */
rc = ENOBUFS;
goto out;
}
nbuf += n;
if (len) {
rc = get_atom_byte(&ch, atom, len - 1);
if (rc)
return rc;
goto out;
if (ch == '\n')
len--;
}
@ -95,11 +126,13 @@ diff_output_lines(struct diff_output_info *outinfo, FILE *dest,
for (i = 0; i < len; i++) {
rc = get_atom_byte(&ch, atom, i);
if (rc)
return rc;
goto out;
if (nbuf >= DIFF_OUTPUT_BUF_SIZE) {
wlen = fwrite(buf, 1, nbuf, dest);
if (wlen != nbuf)
return errno;
if (wlen != nbuf) {
rc = errno;
goto out;
}
outlen += wlen;
nbuf = 0;
}
@ -107,25 +140,35 @@ diff_output_lines(struct diff_output_info *outinfo, FILE *dest,
}
buf[nbuf++] = '\n';
wlen = fwrite(buf, 1, nbuf, dest);
if (wlen != nbuf)
return errno;
if (wlen != nbuf) {
rc = errno;
goto out;
}
outlen += wlen;
if (outinfo) {
ARRAYLIST_ADD(offp, outinfo->line_offsets);
if (offp == NULL)
return ENOMEM;
if (offp == NULL) {
rc = ENOMEM;
goto out;
}
outoff += outlen;
*offp = outoff;
ARRAYLIST_ADD(typep, outinfo->line_types);
if (typep == NULL)
return ENOMEM;
if (typep == NULL) {
rc = ENOMEM;
goto out;
}
*typep = *prefix == ' ' ? DIFF_LINE_CONTEXT :
*prefix == '-' ? DIFF_LINE_MINUS :
*prefix == '+' ? DIFF_LINE_PLUS : DIFF_LINE_NONE;
}
}
return DIFF_RC_OK;
rc = DIFF_RC_OK;
out:
if (colored)
printf("\033[m");
return rc;
}
int

View File

@ -253,6 +253,8 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum)
goto done;
}
if (color)
diff_output_set_colors(color, del_code, add_code);
if (diff_format == D_NORMAL) {
rc = diff_output_plain(NULL, stdout, &info, result, false);
} else if (diff_format == D_EDIT) {