Author: kevans
Date: Fri Aug 17 04:15:51 2018
New Revision: 337956
URL: https://svnweb.freebsd.org/changeset/base/337956

Log:
  ls(1): Add --color=when
  
  --color may be set to one of: 'auto', 'always', and 'never'.
  
  'auto' is the default behavior- output colors only if -G or COLORTERM are
  set, and only if stdout is a tty.
  
  'always' is a new behavior- output colors always. termcap(5) will be
  consulted unless TERM is unset or not a recognized terminal, in which case
  ls(1) will fall back to explicitly outputting ANSI escape sequences.
  
  'never' to turn off any environment variable and -G usage.
  
  Reviewed by:  cem, 0mp (both modulo last-minute manpage changes
  Differential Revision:        https://reviews.freebsd.org/D16741

Modified:
  head/UPDATING
  head/bin/ls/extern.h
  head/bin/ls/ls.1
  head/bin/ls/ls.c
  head/bin/ls/print.c
  head/bin/ls/util.c

Modified: head/UPDATING
==============================================================================
--- head/UPDATING       Fri Aug 17 04:11:10 2018        (r337955)
+++ head/UPDATING       Fri Aug 17 04:15:51 2018        (r337956)
@@ -35,9 +35,9 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
        ls(1) now respects the COLORTERM environment variable used in other
        systems and software to indicate that a colored terminal is both
        supported and desired.  If ls(1) is suddenly emitting colors, they may
-       be disabled again by removing the unwanted COLORTERM from your
-       environment.  The ls(1) specific CLICOLOR may not be observed in a
-       future release.
+       be disabled again by either removing the unwanted COLORTERM from your
+       environment, or using `ls --color=never`.  The ls(1) specific CLICOLOR
+       may not be observed in a future release.
 
 20180808:
        The default pager for most commands has been changed to "less".  To

Modified: head/bin/ls/extern.h
==============================================================================
--- head/bin/ls/extern.h        Fri Aug 17 04:11:10 2018        (r337955)
+++ head/bin/ls/extern.h        Fri Aug 17 04:15:51 2018        (r337956)
@@ -32,6 +32,8 @@
  * $FreeBSD$
  */
 
+#include <stdbool.h>
+
 int     acccmp(const FTSENT *, const FTSENT *);
 int     revacccmp(const FTSENT *, const FTSENT *);
 int     birthcmp(const FTSENT *, const FTSENT *);
@@ -64,5 +66,12 @@ extern       char    *ansi_bgcol;
 extern char    *ansi_coloff;
 extern char    *attrs_off;
 extern char    *enter_bold;
+
+extern int      colorflag;
+extern bool     explicitansi;
+
+#define        COLORFLAG_NEVER         0
+#define        COLORFLAG_AUTO          1
+#define        COLORFLAG_ALWAYS        2
 #endif
 extern int     termwidth;

Modified: head/bin/ls/ls.1
==============================================================================
--- head/bin/ls/ls.1    Fri Aug 17 04:11:10 2018        (r337955)
+++ head/bin/ls/ls.1    Fri Aug 17 04:15:51 2018        (r337956)
@@ -32,7 +32,7 @@
 .\"     @(#)ls.1       8.7 (Berkeley) 7/29/94
 .\" $FreeBSD$
 .\"
-.Dd August 8, 2018
+.Dd August 16, 2018
 .Dt LS 1
 .Os
 .Sh NAME
@@ -41,6 +41,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,
+.Op Fl -color Ns = Ns Ar when
 .Op Fl D Ar format
 .Op Ar
 .Sh DESCRIPTION
@@ -210,6 +211,47 @@ This option is not defined in
 .St -p1003.1-2001 .
 .It Fl c
 Use time when file status was last changed for sorting or printing.
+.It Fl -color Ns = Ns Ar when
+Output colored escape sequences based on
+.Ar when ,
+which may be set to either
+.Cm always ,
+.Cm auto
+(default), or
+.Cm never .
+.Pp
+.Cm always
+will make
+.Nm
+always output color.
+If
+.Ev TERM
+is unset or set to an invalid terminal, then
+.Nm
+will fall back to explicit
+.Tn ANSI
+escape sequences without the help of
+.Xr termcap 5 .
+.Cm always
+is the default if
+.Fl -color
+is specified without an argument.
+.Pp
+.Cm auto
+will make
+.Nm
+output escape sequences based on
+.Xr termcap 5 ,
+but only if
+.Dv stdout
+is a tty and either the
+.Fl G
+flag is specified or the
+.Ev COLORTERM
+environment variable is set and not empty.
+.Pp
+.Cm never
+will disable color regardless of environment variables.
 .It Fl d
 Directories are listed as plain files (not searched recursively).
 .It Fl f
@@ -620,7 +662,10 @@ Colorization
 is silently disabled if the output is not directed to a terminal
 unless the
 .Ev CLICOLOR_FORCE
-variable is defined.
+variable is defined or
+.Fl -color
+is set to
+.Dq always .
 .It Ev CLICOLOR_FORCE
 Color sequences are normally disabled if the output is not directed to
 a terminal.

Modified: head/bin/ls/ls.c
==============================================================================
--- head/bin/ls/ls.c    Fri Aug 17 04:11:10 2018        (r337955)
+++ head/bin/ls/ls.c    Fri Aug 17 04:15:51 2018        (r337956)
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <errno.h>
 #include <fts.h>
+#include <getopt.h>
 #include <grp.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -99,6 +100,16 @@ static void  display(const FTSENT *, FTSENT *, int);
 static int      mastercmp(const FTSENT * const *, const FTSENT * const *);
 static void     traverse(int, char **, int);
 
+#define        COLOR_OPT       (CHAR_MAX + 1)
+
+static const struct option long_opts[] =
+{
+#ifdef COLORLS
+        {"color",       optional_argument,      NULL, COLOR_OPT},
+#endif
+        {NULL,          no_argument,            NULL, 0}
+};
+
 static void (*printfcn)(const DISPLAY *);
 static int (*sortfcn)(const FTSENT *, const FTSENT *);
 
@@ -140,10 +151,10 @@ static int f_stream;              /* stream the output, 
separate w
 static int f_timesort;         /* sort by time vice name */
        int f_type;             /* add type character for non-regular files */
 static int f_whiteout;         /* show whiteout entries */
-
 #ifdef COLORLS
+       int colorflag = COLORFLAG_AUTO;         /* passed in colorflag */
        int f_color;            /* add type in color for non-regular files */
-
+       bool explicitansi;      /* Explicit ANSI sequences, no termcap(5) */
 char *ansi_bgcol;              /* ANSI sequence to set background colour */
 char *ansi_fgcol;              /* ANSI sequence to set foreground colour */
 char *ansi_coloff;             /* ANSI sequence to reset colours */
@@ -176,6 +187,19 @@ do_color_from_env(void)
            (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE")));
 }
 
+static bool
+do_color(void)
+{
+
+#ifdef COLORLS
+       if (colorflag == COLORFLAG_NEVER)
+               return (false);
+       else if (colorflag == COLORFLAG_ALWAYS)
+               return (true);
+#endif
+       return (do_color_from_env());
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -187,7 +211,7 @@ main(int argc, char *argv[])
 #ifdef COLORLS
        char termcapbuf[1024];  /* termcap definition buffer */
        char tcapbuf[512];      /* capability buffer */
-       char *bp = tcapbuf;
+       char *bp = tcapbuf, *term;
 #endif
 
        (void)setlocale(LC_ALL, "");
@@ -215,8 +239,9 @@ main(int argc, char *argv[])
        fts_options = FTS_PHYSICAL;
        if (getenv("LS_SAMESORT"))
                f_samesort = 1;
-       while ((ch = getopt(argc, argv,
-           "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) {
+       while ((ch = getopt_long(argc, argv,
+           "+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,", long_opts,
+           NULL)) != -1) {
                switch (ch) {
                /*
                 * The -1, -C, -x and -l options all override each other so
@@ -379,6 +404,19 @@ main(int argc, char *argv[])
                case 'y':
                        f_samesort = 1;
                        break;
+#ifdef COLORLS
+               case COLOR_OPT:
+                       if (optarg == NULL || strcmp(optarg, "always") == 0)
+                               colorflag = COLORFLAG_ALWAYS;
+                       else if (strcmp(optarg, "auto") == 0)
+                               colorflag = COLORFLAG_AUTO;
+                       else if (strcmp(optarg, "never") == 0)
+                               colorflag = COLORFLAG_NEVER;
+                       else
+                               errx(2, "unsupported --color value '%s' (must 
be always, auto, or never)",
+                                   optarg);
+                       break;
+#endif
                default:
                case '?':
                        usage();
@@ -391,10 +429,14 @@ main(int argc, char *argv[])
        if (!f_listdot && getuid() == (uid_t)0 && !f_noautodot)
                f_listdot = 1;
 
-       /* Enabling of colours is conditional on the environment. */
-       if (do_color_from_env())
+       /*
+        * Enabling of colours is conditional on the environment in conjunction
+        * with the --color and -G arguments, if supplied.
+        */
+       if (do_color()) {
 #ifdef COLORLS
-               if (tgetent(termcapbuf, getenv("TERM")) == 1) {
+               if ((term = getenv("TERM")) != NULL &&
+                   tgetent(termcapbuf, term) == 1) {
                        ansi_fgcol = tgetstr("AF", &bp);
                        ansi_bgcol = tgetstr("AB", &bp);
                        attrs_off = tgetstr("me", &bp);
@@ -408,10 +450,19 @@ main(int argc, char *argv[])
                                ansi_coloff = tgetstr("oc", &bp);
                        if (ansi_fgcol && ansi_bgcol && ansi_coloff)
                                f_color = 1;
+               } else if (colorflag == COLORFLAG_ALWAYS) {
+                       /*
+                        * If we're *always* doing color but we don't have
+                        * a functional TERM supplied, we'll fallback to
+                        * outputting raw ANSI sequences.
+                        */
+                       f_color = 1;
+                       explicitansi = true;
                }
 #else
                warnx("color support not compiled in");
 #endif /*COLORLS*/
+       }
 
 #ifdef COLORLS
        if (f_color) {

Modified: head/bin/ls/print.c
==============================================================================
--- head/bin/ls/print.c Fri Aug 17 04:11:10 2018        (r337955)
+++ head/bin/ls/print.c Fri Aug 17 04:15:51 2018        (r337956)
@@ -73,6 +73,8 @@ static void   printtime(time_t);
 static int     printtype(u_int);
 static void    printsize(size_t, off_t);
 #ifdef COLORLS
+static void    endcolor_termcap(int);
+static void    endcolor_ansi(void);
 static void    endcolor(int);
 static int     colortype(mode_t);
 #endif
@@ -540,7 +542,7 @@ writech(int c)
 }
 
 static void
-printcolor(Colors c)
+printcolor_termcap(Colors c)
 {
        char *ansiseq;
 
@@ -560,10 +562,53 @@ printcolor(Colors c)
 }
 
 static void
-endcolor(int sig)
+printcolor_ansi(Colors c)
 {
+
+       printf("\033[");
+
+       if (colors[c].bold)
+               printf("1");
+       if (colors[c].num[0] != -1)
+               printf(";3%d", colors[c].num[0]);
+       if (colors[c].num[1] != -1)
+               printf(";4%d", colors[c].num[1]);
+       printf("m");
+}
+
+static void
+printcolor(Colors c)
+{
+
+       if (explicitansi)
+               printcolor_ansi(c);
+       else
+               printcolor_termcap(c);
+}
+
+static void
+endcolor_termcap(int sig)
+{
+
        tputs(ansi_coloff, 1, sig ? writech : putch);
        tputs(attrs_off, 1, sig ? writech : putch);
+}
+
+static void
+endcolor_ansi(void)
+{
+
+       printf("\33[m");
+}
+
+static void
+endcolor(int sig)
+{
+
+       if (explicitansi)
+               endcolor_ansi();
+       else
+               endcolor_termcap(sig);
 }
 
 static int

Modified: head/bin/ls/util.c
==============================================================================
--- head/bin/ls/util.c  Fri Aug 17 04:11:10 2018        (r337955)
+++ head/bin/ls/util.c  Fri Aug 17 04:15:51 2018        (r337956)
@@ -227,7 +227,7 @@ usage(void)
 {
        (void)fprintf(stderr,
 #ifdef COLORLS
-       "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
+       "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [--color=when] 
[-D format]"
 #else
        "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
 #endif
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to