Patchwork [2,of,3,V3] color: enable ANSI support on Windows 10

login
register
mail settings
Submitter Matt Harbison
Date May 31, 2017, 2:50 a.m.
Message ID <d0dcc7b57bab42b1e799.1496199014@Envy>
Download mbox | patch
Permalink /patch/21087/
State Accepted
Headers show

Comments

Matt Harbison - May 31, 2017, 2:50 a.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1495506038 14400
#      Mon May 22 22:20:38 2017 -0400
# Node ID d0dcc7b57bab42b1e79931ef5cab4ba66a0cc58e
# Parent  79425b258088af20ae520e24bd60ab471dd62ec4
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
Matt Harbison - May 31, 2017, 3 a.m.
On Tue, 30 May 2017 22:50:14 -0400, Matt Harbison <mharbison72@gmail.com>  
wrote:

> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1495506038 14400
> #      Mon May 22 22:20:38 2017 -0400
> # Node ID d0dcc7b57bab42b1e79931ef5cab4ba66a0cc58e
> # Parent  79425b258088af20ae520e24bd60ab471dd62ec4
> color: enable ANSI support on Windows 10

It's not an issue that started with this series, but I just noticed that  
`less` in msys displays '?' files in light blue, whereas normally it is  
pink.

$ PAGER="less -FRX" ../hg st --config color.mode=ansi
# light '?' blue

$ ../hg st --pager=no
# pink '?' files

$ ../hg showconfig | grep color

I don't have access to Windows 10 to see if this series helps fix that  
(with more.com or less.exe).
Katsunori FUJIWARA - May 31, 2017, 3:09 p.m.
At Tue, 30 May 2017 23:00:02 -0400,
Matt Harbison wrote:
> 
> On Tue, 30 May 2017 22:50:14 -0400, Matt Harbison <mharbison72@gmail.com>  
> wrote:
> 
> > # HG changeset patch
> > # User Matt Harbison <matt_harbison@yahoo.com>
> > # Date 1495506038 14400
> > #      Mon May 22 22:20:38 2017 -0400
> > # Node ID d0dcc7b57bab42b1e79931ef5cab4ba66a0cc58e
> > # Parent  79425b258088af20ae520e24bd60ab471dd62ec4
> > color: enable ANSI support on Windows 10
> 
> It's not an issue that started with this series, but I just noticed that  
> `less` in msys displays '?' files in light blue, whereas normally it is  
> pink.
> 
> $ PAGER="less -FRX" ../hg st --config color.mode=ansi
> # light '?' blue
> 
> $ ../hg st --pager=no
> # pink '?' files
> 
> $ ../hg showconfig | grep color
> 
> I don't have access to Windows 10 to see if this series helps fix that  
> (with more.com or less.exe).

This issue can be observed with Cygwin more.exe/less.exe on cmd.exe of
Windows10, too.

AFAIK, with these pagers on cmd.exe, "underline" ANSI effect always
replaces foreground color effects with "cyan", regardless of enabling
VT mode.

  $ hg debugcolor --pager no --color ansi | more.exe
  ("underline" is rendered as "cyan" foreground color)

On the other hand, more.com colorizes output in ANSI mode as expected
at enabling VT mode.

We may have to add note about this issue for third party pagers?
Katsunori FUJIWARA - May 31, 2017, 5:07 p.m.
At Thu, 01 Jun 2017 00:09:04 +0900,
FUJIWARA Katsunori wrote:
> 
> At Tue, 30 May 2017 23:00:02 -0400,
> Matt Harbison wrote:
> > 
> > On Tue, 30 May 2017 22:50:14 -0400, Matt Harbison <mharbison72@gmail.com>  
> > wrote:
> > 
> > > # HG changeset patch
> > > # User Matt Harbison <matt_harbison@yahoo.com>
> > > # Date 1495506038 14400
> > > #      Mon May 22 22:20:38 2017 -0400
> > > # Node ID d0dcc7b57bab42b1e79931ef5cab4ba66a0cc58e
> > > # Parent  79425b258088af20ae520e24bd60ab471dd62ec4
> > > color: enable ANSI support on Windows 10
> > 
> > It's not an issue that started with this series, but I just noticed that  
> > `less` in msys displays '?' files in light blue, whereas normally it is  
> > pink.
> > 
> > $ PAGER="less -FRX" ../hg st --config color.mode=ansi
> > # light '?' blue
> > 
> > $ ../hg st --pager=no
> > # pink '?' files
> > 
> > $ ../hg showconfig | grep color
> > 
> > I don't have access to Windows 10 to see if this series helps fix that  
> > (with more.com or less.exe).
> 
> This issue can be observed with Cygwin more.exe/less.exe on cmd.exe of
> Windows10, too.
> 
> AFAIK, with these pagers on cmd.exe, "underline" ANSI effect always
> replaces foreground color effects with "cyan", regardless of enabling
> VT mode.
> 
>   $ hg debugcolor --pager no --color ansi | more.exe

As you may already guess, "--color ansi" above is mistake of "--color
always --config color.mode=ansi" :-)


>   ("underline" is rendered as "cyan" foreground color)
> 
> On the other hand, more.com colorizes output in ANSI mode as expected
> at enabling VT mode.
> 
> We may have to add note about this issue for third party pagers?
> 
> -- 
> ----------------------------------------------------------------------
> [FUJIWARA Katsunori]                             foozy@lares.dti.ne.jp
>

Patch

diff --git a/mercurial/color.py b/mercurial/color.py
--- a/mercurial/color.py
+++ b/mercurial/color.py
@@ -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