color: enable ANSI support on Windows 10

This will display color if "color.mode=ansi", and default to 'ansi' if the mode
is set to 'auto'.  The 'debugcolor' command also reflects this policy.
Previously, "color.mode=ansi" on Windows printed jibberish around the normal
text.  Using ANSI color is better, as it avoids the normal loss of color when
the default pager is enabled on Windows.  See also issue5570.

When the underlying function fails (e.g. when run on older Windows), 'auto'
still falls back to 'win32'.  Apparently, Microsoft originally had this feature
turned on by default, and then made it opt-in[1].  Therefore, not enabling it
unconditionally seems safer.  Instead, only do it after processing the existing
check for support in a Unix-like environment.

[1] https://github.com/symfony/symfony/issues/17499#issuecomment-243481052
This commit is contained in:
Matt Harbison 2017-05-22 22:20:38 -04:00
parent 8487f39227
commit 2671b24110

View File

@ -215,24 +215,34 @@ def _modesetup(ui):
mode = ui.config('color', 'pagermode', mode)
realmode = mode
if mode == 'auto':
if pycompat.osname == 'nt':
term = encoding.environ.get('TERM')
# TERM won't be defined in a vanilla cmd.exe environment.
if pycompat.osname == 'nt':
from . import win32
# UNIX-like environments on Windows such as Cygwin and MSYS will
# set TERM. They appear to make a best effort attempt at setting it
# to something appropriate. However, not all environments with TERM
# defined support ANSI. Since "ansi" could result in terminal
# gibberish, we error on the side of selecting "win32". However, if
# w32effects is not defined, we almost certainly don't support
# "win32", so don't even try.
if (term and 'xterm' in term) or not w32effects:
term = encoding.environ.get('TERM')
# TERM won't be defined in a vanilla cmd.exe environment.
# UNIX-like environments on Windows such as Cygwin and MSYS will
# set TERM. They appear to make a best effort attempt at setting it
# to something appropriate. However, not all environments with TERM
# defined support ANSI.
ansienviron = term and 'xterm' in term
if mode == 'auto':
# Since "ansi" could result in terminal gibberish, we error on the
# side of selecting "win32". However, if w32effects is not defined,
# we almost certainly don't support "win32", so don't even try.
# w32ffects is not populated when stdout is redirected, so checking
# it first avoids win32 calls in a state known to error out.
if ansienviron or not w32effects or win32.enablevtmode():
realmode = 'ansi'
else:
realmode = 'win32'
else:
realmode = 'ansi'
# An empty w32effects is a clue that stdout is redirected, and thus
# cannot enable VT mode.
elif mode == 'ansi' and w32effects and not ansienviron:
win32.enablevtmode()
elif mode == 'auto':
realmode = 'ansi'
def modewarn():
# only warn if color.mode was explicitly set and we're in