color: enable ANSI support on Windows 10
authorMatt Harbison <matt_harbison@yahoo.com>
Mon, 22 May 2017 22:20:38 -0400
changeset 32665 98c2b44bdf9a
parent 32664 2d56e6d23be7
child 32666 dd0bdeb0feee
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
mercurial/color.py
--- a/mercurial/color.py	Mon May 22 22:00:56 2017 -0400
+++ b/mercurial/color.py	Mon May 22 22:20:38 2017 -0400
@@ -215,24 +215,34 @@
         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
+
+        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. 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:
+        # 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