git: 4e859e67dde2 - main - libdiff: Implement diff coloring.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 02 Oct 2024 15:55:55 UTC
The branch main has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=4e859e67dde2cb4a583d340b27793a255f62f53e
commit 4e859e67dde2cb4a583d340b27793a255f62f53e
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-10-02 15:54:48 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-10-02 15:55:06 +0000
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
---
contrib/libdiff/include/diff_output.h | 4 ++
contrib/libdiff/lib/diff_output.c | 69 ++++++++++++++++++++++++++++-------
usr.bin/diff/diffreg_new.c | 2 +
3 files changed, 62 insertions(+), 13 deletions(-)
diff --git a/contrib/libdiff/include/diff_output.h b/contrib/libdiff/include/diff_output.h
index d2568c5a2b50..500ee6427574 100644
--- a/contrib/libdiff/include/diff_output.h
+++ b/contrib/libdiff/include/diff_output.h
@@ -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);
diff --git a/contrib/libdiff/lib/diff_output.c b/contrib/libdiff/lib/diff_output.c
index 3b84608882f6..2a0d95896e1a 100644
--- a/contrib/libdiff/lib/diff_output.c
+++ b/contrib/libdiff/lib/diff_output.c
@@ -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
diff --git a/usr.bin/diff/diffreg_new.c b/usr.bin/diff/diffreg_new.c
index a7a40ec12ec9..af9104559986 100644
--- a/usr.bin/diff/diffreg_new.c
+++ b/usr.bin/diff/diffreg_new.c
@@ -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) {