Subject: Re: bug#15992: 'ls' ignores term capabilities when generating color.

From: Pádraig Brady <[email-masked]>
Date: Fri, 29 Nov 2013 01:36:21 +0000

On 11/28/2013 08:31 PM, Linda Walsh wrote:
> I logged in on a *dumb* terminal
> and did an 'ls'.  Rather than a file list, I got:
> 
> \x1b[00;32mwpad.dat\x1b[0m*
> \x1b[00mwpad_socks.dat\x1b[0m
> \x1b[00mwuredir.xml\x1b[0m
> \x1b[00mx.c\x1b[0m
> \x1b[00mx.c.orig\x1b[0m
> \x1b[00;32mx1\x1b[0m*
> \x1b[00mxaml\x1b[0m
> \x1b[01;35mxmision-web\x1b[0m/
> \x1b[01;35mxrdp\x1b[0m/
> \x1b[00mxrdp-sesadmin.log\x1b[0m
> \x1b[00;32mxtree117.zip\x1b[0m*
> \x1b[00;32mxtree2b-20050606.zip\x1b[0m*
> \x1b[01;35mxx\x1b[0m/
> \x1b[01;35mxxx\x1b[0m/
> \x1b[00;32myast2.txt\x1b[0m*
> \x1b[40;33;01mzero\x1b[0m
> \x1b[01;35mzips\x1b[0m/
> \x1b[01;35mztars\x1b[0m/
> \x1b[01;35mztest\x1b[0m/
> \x1b[00mzyppinst\x1b[0m
> ------------------
> 
> While I do have an alias that says:
> alias ls='ls -CF --show-control-chars --color=always'
> 
> If the terminal HAS NO color capabilities, I would expect
> it not to display anything where color was selected,
> as the mapping for switching colors on a dumb terminal
> is "".
> 
> I tried settings for "TERM":
> of "none", "dumb", and "" (empty)
> 
> All gave the same strings as would be correct
> for a 16-color terminal.
> 
> IMO, "ls" shouldn't print out "bogus" strings for color
> that are not in the listed "TERM"inal's capabilties.
> 
> Wouldn't that be the wisest course of action?  Or is
> there a requirement, "poSomewhereIx" to print garbage strings
> to terminals that don't have specific capabilities?
> 
> ;-)

So this is a fair point.

I see the --color option as controlling color output based
on whether output is a terminal or not.  It would be beneficial
to have more control to disable coloring if output is a terminal,
but can't parse the color codes.

Note that color handling for ls is split into dircolors to generate
the static list of color values to use. ls itself doesn't query the $TERM.

Now dircolors also works off a static list which it converts to the
LS_COLORS env variable if it finds that the current $TERM is tagged
in its config. So if dircolors doesn't find a matching $TERM
it will output an empty LS_COLORS env variable. So far so good.

However ls will default to its builtin ansi color config
with a missing or empty LS_COLORS.  It is debatable as
to whether an empty LS_COLORS should disable colors completely,
but I noticed that an invalid LS_COLORS will disable coloring,
and output a warning. I.E. the following will not colorize the output:

  LS_COLORS='blah' ls --color=always

That's at least inconsistent with an empty LS_COLORS not changing anything.
So what we could do to in ls to address this is:

if $LS_COLORS is unset or empty
  // dircolors not run or is having issues with this terminal
  if ($COLORTERM is set) or ($TERM = any in dircolors.h)
    # go with internal set
  else
    # disable coloring

In that way the $TERM would be honored, but could
be overridden with LS_COLORS.

thanks,
Pádraig.

p.s. dircolors might honor $COLORTERM too,
so that every $TERM in existence doesn't need to be added,
though COLORTERM is not passed to remote ssh sessions
like the TERM variable is for example.

p.p.s a separate point that came to mind is that
dircolors might support being passed a directory
containing color configs to parse, which it continues
doing until it finds one with a matching $TERM