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
This commit is contained in:
parent
b14959dacc
commit
e10ba80063
6
UPDATING
6
UPDATING
@ -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
|
||||
|
@ -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;
|
||||
|
49
bin/ls/ls.1
49
bin/ls/ls.1
@ -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.
|
||||
|
67
bin/ls/ls.c
67
bin/ls/ls.c
@ -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 with commas */
|
||||
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) {
|
||||
|
@ -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,12 +562,55 @@ 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
|
||||
colortype(mode_t mode)
|
||||
{
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user