From owner-svn-src-head@freebsd.org Fri Aug 17 04:15:53 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9122A10818BE; Fri, 17 Aug 2018 04:15:53 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 3830E8B423; Fri, 17 Aug 2018 04:15:53 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 0C2E623538; Fri, 17 Aug 2018 04:15:53 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w7H4FqBG046780; Fri, 17 Aug 2018 04:15:52 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w7H4Fp7D046775; Fri, 17 Aug 2018 04:15:51 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201808170415.w7H4Fp7D046775@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Fri, 17 Aug 2018 04:15:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r337956 - in head: . bin/ls X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in head: . bin/ls X-SVN-Commit-Revision: 337956 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Aug 2018 04:15:53 -0000 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 + 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 #include #include +#include #include #include #include @@ -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