The branch main has been updated by pstef:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f38702e5a52e1350b9349bc297ccd0b50b1941c3

commit f38702e5a52e1350b9349bc297ccd0b50b1941c3
Author:     Cameron Katri <m...@cameronkatri.com>
AuthorDate: 2021-09-05 00:10:41 +0000
Commit:     Piotr Pawel Stefaniak <ps...@freebsd.org>
CommitDate: 2021-09-15 23:46:44 +0000

    diff(1): Add --color support
    
    Adds a --color flag to diff(1) that supports the same options as GNU's
    diff(1). The colors are customizable with the env var DIFFCOLORS in
    a format similar to grep(1)'s GREPCOLORS. An example would be 04;36:41
    for additions to be underlined light blue, and deletions have a red
    background.
    
    Differential Revision:  https://reviews.freebsd.org/D30545
---
 usr.bin/diff/diff.1    | 35 ++++++++++++++++++++++++++++++++
 usr.bin/diff/diff.c    | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-
 usr.bin/diff/diff.h    | 10 ++++++++-
 usr.bin/diff/diffreg.c | 21 ++++++++++++++++++-
 4 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/usr.bin/diff/diff.1 b/usr.bin/diff/diff.1
index e0a790f6efb6..6056ddd3ac76 100644
--- a/usr.bin/diff/diff.1
+++ b/usr.bin/diff/diff.1
@@ -44,6 +44,7 @@
 .Fl n | q | u | y
 .Oc
 .Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
 .Op Fl -changed-group-format Ar GFMT
 .Op Fl -ed
 .Op Fl -expand-tabs
@@ -71,6 +72,7 @@
 .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
 .Op Fl L Ar label | Fl -label Ar label
 .Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
 .Op Fl -changed-group-format Ar GFMT
 .Op Fl -ed
 .Op Fl -expand-tabs
@@ -96,6 +98,7 @@
 .Op Fl aBbdiltw
 .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
 .Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
 .Op Fl -changed-group-format Ar GFMT
 .Op Fl -ed
 .Op Fl -expand-tabs
@@ -122,6 +125,7 @@
 .Op Fl I Ar pattern | Fl -ignore-matching-lines Ar pattern
 .Op Fl L Ar label | Fl -label Ar label
 .Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
 .Op Fl -changed-group-format Ar GFMT
 .Op Fl -ed
 .Op Fl -expand-tabs
@@ -150,6 +154,7 @@
 .Fl n | q | u
 .Oc
 .Op Fl -brief
+.Op Fl -color Ns = Ns Ar when
 .Op Fl -changed-group-format Ar GFMT
 .Op Fl -context
 .Op Fl -ed
@@ -184,6 +189,7 @@
 .Ar dir1 dir2
 .Nm diff
 .Op Fl aBbditwW
+.Op Fl -color Ns = Ns Ar when
 .Op Fl -expand-tabs
 .Op Fl -ignore-all-blanks
 .Op Fl -ignore-blank-lines
@@ -332,6 +338,21 @@ Causes chunks that include only blank lines to be ignored.
 .It Fl b -ignore-space-change
 Causes trailing blanks (spaces and tabs) to be ignored, and other
 strings of blanks to compare equal.
+.It Fl -color= Ns Oo Ar when Oc
+Color the additions green, and removals red, or the value in the
+.Ev DIFFCOLORS
+environment variable.
+The possible values of
+.Ar when
+are
+.Dq Cm never ,
+.Dq Cm always
+and
+.Dq Cm auto .
+.Cm auto
+will use color if the output is a tty and the
+.Ev COLORTERM
+environment variable is set to a non-empty string.
 .It Fl d -minimal
 Try very hard to produce a diff as small as possible.
 This may consume a lot of processing power and memory when processing
@@ -592,6 +613,20 @@ As in
 identical
 pairs (where num1 = num2) are abbreviated as a single
 number.
+.Sh ENVIRONMENT
+.Bl -tag -width DIFFCOLORS
+.It Ev DIFFCOLORS
+The value of this variable is the form
+.Ar add Ns : Ns Ar rm ,
+where
+.Ar add
+is the ASCII escape sequence for additions and
+.Ar rm
+is the ASCII escape sequence for deletions.
+If this is unset,
+.Nm
+uses green for additions and red for removals.
+.El
 .Sh FILES
 .Bl -tag -width /tmp/diff.XXXXXXXX -compact
 .It Pa /tmp/diff.XXXXXXXX
diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c
index a5966e74dbcc..4fc3094035d9 100644
--- a/usr.bin/diff/diff.c
+++ b/usr.bin/diff/diff.c
@@ -39,11 +39,13 @@ __FBSDID("$FreeBSD$");
 #include "xmalloc.h"
 
 bool    lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
-bool    ignore_file_case, suppress_common;
+bool    ignore_file_case, suppress_common, color;
 int     diff_format, diff_context, status;
 int     tabsize = 8, width = 130;
+static int     colorflag = COLORFLAG_NEVER;
 char   *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
 char   *group_format = NULL;
+const char     *add_code, *del_code;
 struct stat stb1, stb2;
 struct excludes *excludes_list;
 regex_t         ignore_re;
@@ -58,6 +60,7 @@ enum {
        OPT_HORIZON_LINES,
        OPT_CHANGED_GROUP_FORMAT,
        OPT_SUPPRESS_COMMON,
+       OPT_COLOR,
 };
 
 static struct option longopts[] = {
@@ -98,6 +101,7 @@ static struct option longopts[] = {
        { "tabsize",                    required_argument,      NULL,   
OPT_TSIZE },
        { "changed-group-format",       required_argument,      NULL,   
OPT_CHANGED_GROUP_FORMAT},
        { "suppress-common-lines",      no_argument,            NULL,   
OPT_SUPPRESS_COMMON },
+       { "color",                      optional_argument,      NULL,   
OPT_COLOR },
        { NULL,                         0,                      0,      '\0'}
 };
 
@@ -108,6 +112,7 @@ static void push_ignore_pats(char *);
 static void read_excludes_file(char *file);
 static void set_argstr(char **, char **);
 static char *splice(char *, char *);
+static bool do_color(void);
 
 int
 main(int argc, char **argv)
@@ -301,6 +306,17 @@ main(int argc, char **argv)
                case OPT_SUPPRESS_COMMON:
                        suppress_common = 1;
                        break;
+               case OPT_COLOR:
+                       if (optarg == NULL || strncmp(optarg, "auto", 4) == 0)
+                               colorflag = COLORFLAG_AUTO;
+                       else if (strncmp(optarg, "always", 6) == 0)
+                               colorflag = COLORFLAG_ALWAYS;
+                       else if (strncmp(optarg, "never", 5) == 0)
+                               colorflag = COLORFLAG_NEVER;
+                       else
+                               errx(2, "unsupported --color value '%s' (must 
be always, auto, or never)",
+                                       optarg);
+                       break;
                default:
                        usage();
                        break;
@@ -316,6 +332,22 @@ main(int argc, char **argv)
        argc -= optind;
        argv += optind;
 
+       if (do_color()) {
+               char *p;
+               const char *env;
+
+               color = true;
+               add_code = "32";
+               del_code = "31";
+               env = getenv("DIFFCOLORS");
+               if (env != NULL && *env != '\0' && (p = strdup(env))) {
+                       add_code = p;
+                       strsep(&p, ":");
+                       if (p != NULL)
+                               del_code = p;
+               }
+       }
+
 #ifdef __OpenBSD__
        if (pledge("stdio rpath tmppath", NULL) == -1)
                err(2, "pledge");
@@ -545,6 +577,27 @@ conflicting_format(void)
        usage();
 }
 
+static bool
+do_color(void)
+{
+       const char *p, *p2;
+
+       switch (colorflag) {
+       case COLORFLAG_AUTO:
+               p = getenv("CLICOLOR");
+               p2 = getenv("COLORTERM");
+               if ((p != NULL && *p != '\0') || (p2 != NULL && *p2 != '\0'))
+                       return isatty(STDOUT_FILENO);
+               break;
+       case COLORFLAG_ALWAYS:
+               return (true);
+       case COLORFLAG_NEVER:
+               return (false);
+       }
+
+       return (false);
+}
+
 static char *
 splice(char *dir, char *path)
 {
diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h
index 7ae700810fc6..5164fe22ace4 100644
--- a/usr.bin/diff/diff.h
+++ b/usr.bin/diff/diff.h
@@ -87,17 +87,25 @@
 #define        D_SKIPPED2      6       /* path2 was a special file */
 #define        D_ERROR         7       /* A file access error occurred */
 
+/*
+ * Color options
+ */
+#define COLORFLAG_NEVER                0
+#define COLORFLAG_AUTO         1
+#define COLORFLAG_ALWAYS       2
+
 struct excludes {
        char *pattern;
        struct excludes *next;
 };
 
 extern bool    lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag;
-extern bool    ignore_file_case, suppress_common;
+extern bool    ignore_file_case, suppress_common, color;
 extern int     diff_format, diff_context, status;
 extern int     tabsize, width;
 extern char    *start, *ifdefname, *diffargs, *label[2], *ignore_pats;
 extern char    *group_format;
+extern const char      *add_code, *del_code;
 extern struct  stat stb1, stb2;
 extern struct  excludes *excludes_list;
 extern regex_t ignore_re;
diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c
index c9095ec46e88..47c1934a6a65 100644
--- a/usr.bin/diff/diffreg.c
+++ b/usr.bin/diff/diffreg.c
@@ -1140,13 +1140,23 @@ proceed:
                }
        }
        if (diff_format == D_SIDEBYSIDE) {
+               if (color && a > b)
+                       printf("\033[%sm", add_code);
+               else if (color && c > d)
+                       printf("\033[%sm", del_code);
                if (a > b) {
                        print_space(0, hw + padding , *pflags);
                } else {
                        nc = fetch(ixold, a, b, f1, '\0', 1, *pflags);
                        print_space(nc, hw - nc + padding, *pflags);
                }
+               if (color && a > b)
+                       printf("\033[%sm", add_code);
+               else if (color && c > d)
+                       printf("\033[%sm", del_code);
                printf("%c", (a > b) ? '>' : ((c > d) ? '<' : '|'));
+               if (color && c > d)
+                       printf("\033[m");
                print_space(hw + padding + 1 , padding, *pflags);
                fetch(ixnew, c, d, f2, '\0', 0, *pflags);
                printf("\n");
@@ -1220,6 +1230,10 @@ fetch(long *f, int a, int b, FILE *lb, int ch, int 
oldfile, int flags)
                        nc = hw;
                if (diff_format != D_IFDEF && diff_format != D_GFORMAT &&
                    ch != '\0') {
+                       if (color && (ch == '>' || ch == '+'))
+                               printf("\033[%sm", add_code);
+                       else if (color && (ch == '<' || ch == '-'))
+                               printf("\033[%sm", del_code);
                        printf("%c", ch);
                        if (Tflag && (diff_format == D_NORMAL ||
                            diff_format == D_CONTEXT ||
@@ -1290,12 +1304,17 @@ fetch(long *f, int a, int b, FILE *lb, int ch, int 
oldfile, int flags)
                                }
                                /* when side-by-side, do not print a newline */
                                if (diff_format != D_SIDEBYSIDE || c != '\n') {
-                                       printf("%c", c);
+                                       if (color && c == '\n')
+                                               printf("\033[m%c", c);
+                                       else
+                                               printf("%c", c);
                                        col++;
                                }
                        }
                }
        }
+       if (color && diff_format == D_SIDEBYSIDE)
+               printf("\033[m");
        return (col);
 }
 
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to