[PATCH 3 of 4] color: automatically define 16 and 256 colors if supported
Gregory Szorc
gregory.szorc at gmail.com
Mon Jul 10 20:26:51 EDT 2017
On Mon, Jul 10, 2017 at 4:32 PM, Kyle Lippincott <spectral at pewpew.net>
wrote:
>
>
> On Sun, Jul 9, 2017 at 4:46 PM, Gregory Szorc <gregory.szorc at gmail.com>
> wrote:
>
>> # HG changeset patch
>> # User Gregory Szorc <gregory.szorc at gmail.com>
>> # Date 1499641339 25200
>> # Sun Jul 09 16:02:19 2017 -0700
>> # Node ID fa6223b9e2a0d9fbfa81329b83c0512417cee713
>> # Parent 98c54db9407a7e0ba94a632aafdbbec3fc76fa8b
>> color: automatically define 16 and 256 colors if supported
>>
>> The "colors" terminfo capability returns the number of colors
>> supported by the terminal profile.
>>
>> But with terminals, nothing is straightforward. The "colors"
>> capability only returns what the current terminal profile (likely
>> defined by $TERM) supports. The current terminal type or its profile
>> may be wrong (most likely the former). So, any consumer of this
>> capability needs to take this scenario into account.
>>
>> This commit adds code for querying the "colors" terminfo capability
>> and for defining additional colors if 16 or 256 color support is
>> present. Because of the aforementioned limitations with capability
>> accuracy, a config option is introduced that allows the color count
>> to be limited. If the extra colors cause any problems, once can simply
>> set this option to restore existing 8 color behavior.
>>
>> As part of this feature, a dictionary containing cherry-picked colors
>> from the 256 color spectrum was created. Choices are very subjective
>> and can and should be adjusted, as appropriate.
>>
>> The help documentation for color support has been significantly
>> overhauled as part of this commit.
>>
>> diff --git a/mercurial/color.py b/mercurial/color.py
>> --- a/mercurial/color.py
>> +++ b/mercurial/color.py
>> @@ -45,10 +45,43 @@ try:
>> 'white': curses.COLOR_WHITE,
>> }
>>
>> + # Bright versions of the built-in colors are colors 8-15, in the
>> same order.
>> + TERMINFO_COLOR_16 = {
>> + 'brightblack': 8,
>> + 'brightred': 9,
>> + 'brightgreen': 10,
>> + 'brightyellow': 11,
>> + 'brightblue': 12,
>> + 'brightmagenta': 13,
>> + 'brightcyan': 14,
>> + 'brightwhite': 15,
>> + }
>> +
>> + # 6x6x6 color cube is 16-231. We define some common ones.
>> + TERMINFO_COLOR_256 = {
>> + 'darkgreen': 28,
>> + 'turquoise': 45,
>> + 'lightgreen': 70,
>> + 'bluegreen': 73,
>> + 'deeppurple': 89,
>> + 'purple': 129,
>> + 'lightpurple': 177,
>> + 'lightorange': 178,
>> + 'lightyellow': 191,
>> + 'pink': 201,
>> + 'darkorange': 208,
>> + }
>> +
>> + # 232-255 is a continuous spectrum of grey.
>> + for i, value in enumerate(range(232, 256)):
>> + TERMINFO_COLOR_256['grey%02d' % (i + 1)] = value
>> +
>> except ImportError:
>> curses = None
>> _baseterminfoparams = {}
>> TERMINFO_COLOR_8 = {}
>> + TERMINFO_COLOR_16 = {}
>> + TERMINFO_COLOR_256 = {}
>>
>> _enabledbydefault = True
>>
>> @@ -146,6 +179,43 @@ def _terminfocolors(ui):
>> for color, value in TERMINFO_COLOR_8.items():
>> colors[color] = (value, False)
>>
>> + # Add 16 and 256 bit colors if supported and allowed by config
>> policy.
>> + #
>> + # There's no reliable way to detect if the extra colors will
>> actually work.
>> + # The terminfo database just reports what the current terminal is
>> + # advertising. Some terminals support querying the value of a color
>> via
>> + # e.g. \e]4;%d;?\a. However, this isn't universally supported. So set
>> + # colors based purely on terminfo and provide users a way to disable
>> in
>> + # case it doesn't work.
>> +
>> + # Will likely return -1 on failure.
>> + termcolors = curses.tigetnum('colors')
>> + if termcolors < 8:
>> + termcolors = 8
>> +
>> + # Default is to allow as many colors as the terminal supports.
>> + colorlimit = ui.configint('color', 'colorlimit', 256)
>> +
>> + if colorlimit not in (8, 16, 256):
>> + ui.warn(_('unsupported color.colorlimit value %d; use 8, 16, '
>> + 'or 256\n') % colorlimit)
>> + colorlimit = 8
>> +
>> + usecolors = min(termcolors, colorlimit)
>>
>
> Considering how often TERM is incorrect and/or terminfo is incorrect or
> minimizing/lowest-common-denominator (great example for both: TERM=xterm
> vs xterm-256color), are we sure we want to min()? Can we have some config
> option to override the colors setting?
>
> Every single terminal I support handles \033[38;5;##m colors where ## is
> max(88) or max(256), regardless of what their terminfo says. I'm fine with
> ignoring the few 88-color rxvt-unicode users and telling them to use the
> 256-color version. It would be nice to be able to put something like:
>
> [color]
> mode=terminfo
> colorlimit=256 # Ignore terminfo's stated limit
>
> into our config file to get this all corrected.
>
>
I was also considering a config option (either the same or a different one)
to force setting color support. After all, inaccurate TERM+terminfo is a
thing. My worry about that is it may need to be conditional depending on
the terminal type. If you e.g. have a shared hgrc that is accessed by
different terminals, a forced setting could be bad. It's definitely safer
to use TERM+terminfo to drive the setting.
Terminals are scary and I'm really hesitant to make *any* change that uses
more powerful terminal features that can't easily be reverted via simple
config file muckery.
> +
>> + if usecolors >= 16:
>> + for color, value in TERMINFO_COLOR_16.items():
>> + colors[color] = (value, False)
>> +
>> + if usecolors >= 256:
>> + for color, value in TERMINFO_COLOR_256.items():
>> + colors[color] = (value, False)
>> +
>> + # TODO consider filtering color values by usecolors. This has 2
>> + # implications: 1) users can't force colors beyond the supported
>> + # color range (this arguably makes sense but is BC) 2) configstyles()
>> + # emits a warning if there is a reference to this discarded color
>> + # (it may be desirable to suppress that warning).
>> for key, value in ui.configitems('color'):
>> if key.startswith('color.'):
>> colors[key[6:]] = (int(value), True)
>> @@ -186,6 +256,7 @@ def _terminfosetup(ui, mode):
>> # noisy and use ui.debug().
>> ui.debug("no terminfo entry for %s\n" % e)
>> del ui._terminfoparams[key]
>> +
>> if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
>> # Only warn about missing terminfo entries if we explicitly
>> asked for
>> # terminfo mode.
>> diff --git a/mercurial/help/color.txt b/mercurial/help/color.txt
>> --- a/mercurial/help/color.txt
>> +++ b/mercurial/help/color.txt
>> @@ -131,19 +131,38 @@ effects may be overridden from your conf
>>
>> histedit.remaining = red bold
>>
>> +Supported Colors
>> +================
>> +
>> +There are 8 standard colors: ``black``, ``red``, ``green``, ``yellow``,
>> +``blue``, ``magenta``, ``cyan``, and ``white``.
>> +
>> +If the ``terminfo`` color mode is being used and the terminfo database
>> +reports that the current terminal supports more colors, additional colors
>> +will be defined.
>> +
>> +If 16 colors are supported, the 8 additional colors are the 8 standard
>> +colors prefixed with "bright". e.g. ``brightred`` and ``brightyellow``.
>> +
>> +If 256 colors are supported, an assortment of additional colors are
>> +available. These include ``darkgreen``, ``turquoise``, ``purple``, and
>> +``pink``. For the list of all defined colors, run :hg:`debugcolor`.
>> +
>> +In some cases, not all colors will render properly. See
>> +:hg:`help config.color.colorlimit` for how to limit Mercurial to a
>> smaller
>> +set of colors.
>> +
>> Custom colors
>> =============
>>
>> -Because there are only eight standard colors, Mercurial allows you
>> -to define color names for other color slots which might be available
>> -for your terminal type, assuming terminfo mode. For instance::
>> +When using ``terminfo`` mode, Mercurial supports defining colors via
>> +config options. You can either declare new colors or change the value
>> +for a built-in color. e.g.::
>>
>> - color.brightblue = 12
>> + [color]
>> + color.mydarkblue = 18
>> color.pink = 207
>> color.orange = 202
>>
>> -to set 'brightblue' to color slot 12 (useful for 16 color terminals
>> -that have brighter colors defined in the upper eight) and, 'pink' and
>> -'orange' to colors in 256-color xterm's default color cube. These
>> -defined colors may then be used as any of the pre-defined eight,
>> -including appending '_background' to set the background to that color.
>> +To see what color values are supported and how they render, perform
>> +an Internet search for "xterm color cube."
>> diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
>> --- a/mercurial/help/config.txt
>> +++ b/mercurial/help/config.txt
>> @@ -432,6 +432,22 @@ effect and style see :hg:`help color`.
>> On some systems (such as MSYS in Windows), the terminal may support
>> a different color mode than the pager program.
>>
>> +``colorlimit``
>> + Limits how many colors will be defined and used.
>> +
>> + Most terminals support 8 standard colors. Mercurial will detect
>> + and use additional colors if the terminal indicates support for them.
>> +
>> + In some cases, the terminal advertises support for additional colors
>> + but doesn't actually support them. This can lead to poor formatting
>> + or even gibberish being printed.
>> +
>> + Setting this option to a value of ``8``, ``16``, or ``256`` will
>> + explicitly limit Mercurial to a maximum of that many colors.
>> +
>> + This option has no effect unless the ``terminfo`` color mode is being
>> + used.
>> +
>> ``commands``
>> ------------
>>
>> diff --git a/tests/hgterm.ti b/tests/hgterm16.ti
>> copy from tests/hgterm.ti
>> copy to tests/hgterm16.ti
>> --- a/tests/hgterm.ti
>> +++ b/tests/hgterm16.ti
>> @@ -1,6 +1,6 @@
>> -hgterm,
>> +hgterm-16color,
>> am, km, mir, msgr, xenl,
>> - colors#8, cols#80, it#8, lines#24, pairs#64,
>> + colors#16, cols#80, it#8, lines#24, pairs#64,
>> acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
>> bel=^G, bold=\E[1m, clear=\E[H\E[2J, cr=\r,
>> csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=\b,
>> diff --git a/tests/hgterm.ti b/tests/hgterm256.ti
>> copy from tests/hgterm.ti
>> copy to tests/hgterm256.ti
>> --- a/tests/hgterm.ti
>> +++ b/tests/hgterm256.ti
>> @@ -1,6 +1,6 @@
>> -hgterm,
>> +hgterm-256color,
>> am, km, mir, msgr, xenl,
>> - colors#8, cols#80, it#8, lines#24, pairs#64,
>> + colors#256, cols#80, it#8, lines#24, pairs#64,
>> acsc=``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
>> bel=^G, bold=\E[1m, clear=\E[H\E[2J, cr=\r,
>> csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=\b,
>> diff --git a/tests/test-status-color.t b/tests/test-status-color.t
>> --- a/tests/test-status-color.t
>> +++ b/tests/test-status-color.t
>> @@ -226,6 +226,9 @@ hg status -A (with terminfo color):
>>
>> $ mkdir "$TESTTMP/terminfo"
>> $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm.ti"
>> + $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm16.ti"
>> + $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm256.ti"
>> +
>> $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config
>> color.mode=terminfo -A
>> \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1madded\x1b[30m
>> (esc)
>> \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1mcopied\x1b[30m
>> (esc)
>> @@ -256,6 +259,58 @@ The user can define effects with raw ter
>> \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88m.hgignore\x1b[30m (esc)
>> \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88mmodified\x1b[30m (esc)
>>
>> +A 16 and 256 colors won't be used if the terminal doesn't advertise
>> support
>> +
>> + $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status -a --config
>> color.mode=terminfo --config color.status.added=brightred
>> + ignoring unknown color/effect 'brightred' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'brightred' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'brightred' (configured in
>> color.status.added)
>> + A added
>> + A copied
>> +
>> + $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status -a --config
>> color.mode=terminfo --config color.status.added=purple
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + A added
>> + A copied
>> +
>> +A 16 color can be used if terminal advertises 16 color support
>> +
>> + $ TERM=hgterm-16color TERMINFO="$TESTTMP/terminfo" hg status -a
>> --config color.mode=terminfo --config color.status.added=brightred
>> + \x1b[30m\x1b[39mA \x1b[30m\x1b[30m\x1b[39madded\x1b[30m (esc)
>> + \x1b[30m\x1b[39mA \x1b[30m\x1b[30m\x1b[39mcopied\x1b[30m (esc)
>> +
>> +A 256 color can be used if terminal advertises 256 color support
>> +
>> + $ TERM=hgterm-256color TERMINFO="$TESTTMP/terminfo" hg status -a
>> --config color.mode=terminfo --config color.status.added=purple
>> + \x1b[30m\x1b[3129mA \x1b[30m\x1b[30m\x1b[3129madded\x1b[30m (esc)
>> + \x1b[30m\x1b[3129mA \x1b[30m\x1b[30m\x1b[3129mcopied\x1b[30m (esc)
>> +
>> +color.colorlimit can narrow allowed color range
>> +
>> + $ TERM=hgterm-256color TERMINFO="$TESTTMP/terminfo" hg status -a
>> --config color.mode=terminfo --config color.status.added=purple --config
>> color.colorlimit=8
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + A added
>> + A copied
>> + $ TERM=hgterm-256color TERMINFO="$TESTTMP/terminfo" hg status -a
>> --config color.mode=terminfo --config color.status.added=purple --config
>> color.colorlimit=16
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + ignoring unknown color/effect 'purple' (configured in
>> color.status.added)
>> + A added
>> + A copied
>> +
>> +Invalid color.colorlimit is normalized to 8
>> +
>> + $ TERM=hgterm-256color TERMINFO="$TESTTMP/terminfo" hg status -a
>> --config color.mode=terminfo --config color.colorlimit=128
>> + unsupported color.colorlimit value 128; use 8, 16, or 256
>> + unsupported color.colorlimit value 128; use 8, 16, or 256
>> + unsupported color.colorlimit value 128; use 8, 16, or 256
>> + \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2madded\x1b[30m
>> (esc)
>> + \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2mcopied\x1b[30m
>> (esc)
>> +
>> #endif
>>
>>
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at mercurial-scm.org
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20170710/17a7d227/attachment.html>
More information about the Mercurial-devel
mailing list