fusesource / jansi

Jansi is a small java library that allows you to use ANSI escape sequences to format your console output which works even on windows.
http://fusesource.github.io/jansi/
Apache License 2.0
1.12k stars 139 forks source link

Does not work with Git CMD on Windows #119

Closed plamentotev closed 6 years ago

plamentotev commented 6 years ago

When I run Maven using Git CMD on Windows I'm seeing the escape characters printed on the console:

Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-24T21:49:05+02:00)
Maven home: C:\Programs\maven\bin\..
Java version: 10, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

I suspect the reason is because MSYSTEM is set to MINGW64. If I unset it the output is fine. I wonder if there is a way to detect that the terminal used is CMD and it does not support ANSI escape character?

hboutemy commented 6 years ago

please run "java -jar jansi-*.jar" and report the result: this is a diagnostic utility to display what is enabled and why

plamentotev commented 6 years ago

Here it is:

Jansi 1.18-SNAPSHOT (Jansi native 1.8, HawtJNI runtime 1.16)

library.jansi.path=
library.jansi.version=
path: C:\Users\user\AppData\Local\Temp\jansi-1.18-SNAPSHOT-9418080949423969191.dll
auto-extracted from: jar:file:/C:/Users/user/jansi/jansi/target/jansi-1.18-SNAPSHOT.jar!/META-INF/native/windows64/jansi.dll

os.name= Windows 10, os.version= 10.0, os.arch= amd64
file.encoding= Cp1252
java.version= 10, java.vendor= Oracle Corporation, java.home= C:\jdk

jansi.passthrough= false
jansi.strip= false
jansi.force= false
org.fusesource.jansi.Ansi.disable= false

IS_WINDOWS= true
IS_CYGWIN= false
IS_MINGW= true

isatty(STDOUT_FILENO)= 1, System.out is a terminal
isatty(STDERR_FILENO)= 1, System.err is a terminal

Jansi System.out mode: RESET_ANSI_AT_CLOSE
Jansi System.err mode: RESET_ANSI_AT_CLOSE
hboutemy commented 6 years ago

looks like ANSI code rendering during the diagnostic utility was enabled: do you confirm?

if it works during diagnostic but not during Maven execution, I'm a little puzzled...

plamentotev commented 6 years ago

Yes, the ANSI code rendering is enabled both when the diagnostic utility and Maven are run. And that is the trouble. Git CMD(not to be confused with Git Bash) uses cmd.exe (the Windows command prompt) and it does not support ANSI escape characters. As a result instead of the artwork the ANSI codes are printed. Here is the full output (with the artwork)

Jansi 1.18-SNAPSHOT (Jansi native 1.8, HawtJNI runtime 1.16)

library.jansi.path=
library.jansi.version=
path: C:\Users\user\AppData\Local\Temp\jansi-1.18-SNAPSHOT-16410366055154229302.dll
auto-extracted from: jar:file:/C:/Users/user/jansi/jansi/target/jansi-1.18-SNAPSHOT.jar!/META-INF/native/windows64/jansi.dll

os.name= Windows 10, os.version= 10.0, os.arch= amd64
file.encoding= Cp1252
java.version= 10, java.vendor= Oracle Corporation, java.home= C:\jdk

jansi.passthrough= false
jansi.strip= false
jansi.force= false
org.fusesource.jansi.Ansi.disable= false

IS_WINDOWS= true
IS_CYGWIN= false
IS_MINGW= true

isatty(STDOUT_FILENO)= 1, System.out is a terminal
isatty(STDERR_FILENO)= 1, System.err is a terminal

Jansi System.out mode: RESET_ANSI_AT_CLOSE
Jansi System.err mode: RESET_ANSI_AT_CLOSE

test on System.out: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
            bright: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
              bold: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
test on System.err: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
            bright: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
              bold: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
[?7h
┌──┐┌─────┐ ┌─────┐ ┌──────┬──┐
│██├┘█████└┬┘█████└┬┘██████│??│
┌──┐ │██│██▄▄▄██│██┌─┐██│██▄▄▄▄ │▄▄│
│▒▒└─┘▒█│▒█┌─┐▒█│▒█│ │▒█│ ▀▀▀▀▒█│▒█│
└┐▓▓▓▓▓┌┤▓▓│ │▓▓│▓▓│ │▓▓│▀▓▓▓▓▓▀│▓▓│
└─────┘└──┘ └──┴──┘ └──┴───────┴──┘


It appears that the problem comes from the code introduced with bb3d538315. The following evaluates to true:

    private static final boolean IS_MINGW = IS_WINDOWS
           && System.getenv("MSYSTEM") != null
           && System.getenv("MSYSTEM").startsWith("MINGW");

because Git CMD sets MSYSTEM to MINGW64, but this does not mean that there is terminal that supports ANSI escape characters. I suppose that this code is added to detect if the terminal that comes with mingw is used (that is mintty or sh.exe) but it appears that only the environment variable is not reliable.

p.s. For reference I'm applying the output of the utility when run on cmd.exe (the regular Windows command prompt without the variables set by Git CMD and indeed without MSYSTEM):

Jansi 1.18-SNAPSHOT (Jansi native 1.8, HawtJNI runtime 1.16)

library.jansi.path=
library.jansi.version=
path: C:\Users\user\AppData\Local\Temp\jansi-1.18-SNAPSHOT-14251320175078730506.dll
auto-extracted from: jar:file:/C:/Users/user/jansi/jansi/target/jansi-1.18-SNAPSHOT.jar!/META-INF/native/windows64/jansi.dll

os.name= Windows 10, os.version= 10.0, os.arch= amd64
file.encoding= Cp1252
java.version= 10, java.vendor= Oracle Corporation, java.home= C:\jdk

jansi.passthrough= false
jansi.strip= false
jansi.force= false
org.fusesource.jansi.Ansi.disable= false

IS_WINDOWS= true
IS_CYGWIN= false
IS_MINGW= false

isatty(STDOUT_FILENO)= 1, System.out is a terminal
isatty(STDERR_FILENO)= 1, System.err is a terminal

Jansi System.out mode: WINDOWS
Jansi System.err mode: WINDOWS

test on System.out: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
            bright: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
              bold: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
test on System.err: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
            bright: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT
              bold: BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE DEFAULT

                      ┌──┐┌─────┐ ┌─────┐ ┌──────┬──┐
                      │██├┘█████└┬┘█████└┬┘██████│??│
                 ┌──┐ │██│██▄▄▄██│██┌─┐██│██▄▄▄▄ │▄▄│
                 │▒▒└─┘▒█│▒█┌─┐▒█│▒█│ │▒█│ ▀▀▀▀▒█│▒█│
                 └┐▓▓▓▓▓┌┤▓▓│ │▓▓│▓▓│ │▓▓│▀▓▓▓▓▓▀│▓▓│
                  └─────┘└──┘ └──┴──┘ └──┴───────┴──┘

When the Jansi System.out mode is set to WINDOWS it does work and the artwork is displayed properly.

hboutemy commented 6 years ago

ok, using this System.getenv("MSYSTEM").startsWith("MINGW") algorithm to know if the current terminal supports natively ANSI codes seems not perfect: does not make the difference between Git CMD (no ANSI native support, Jansi Windows tricks required) and Git bash (ANSI native code support).

Do you see a way to make the difference? How should we code the test? Look for BASH environment variable, which is specific to Git bash but should not be there on Git CMD?

plamentotev commented 6 years ago

I think we can use TERM as additional check for Windows. If it's set (on Windows) then probably the ANSI codes are natively supported, otherwise it is CMD or Powershell. But I wonder if there is more reliable way to detect that. Like some native call if Windows and MSYSTEM are detected.

p.s. TERM is specified for Git Bash and the terminal that comes with MSYS and not set for Git CMD, but not sure if it covers all cases.

hboutemy commented 6 years ago

added a check on BASH env variable, since Git Bash is what we are looking for to disable Windows trickery

plamentotev commented 6 years ago

Now on git bash the ANSI codes are stripped. That is strange because:

$ echo $BASH
/usr/bin/bash

but when I debug JANSI System.getenv("BASH") is null.

hboutemy commented 6 years ago

grrrr... I hate that there is a pseudo env variable... and I didn't check because I'm not on Windows usually... I updated the test to use the TERM=xterm test And this time, I took time to launch my VirtualBox and check cmd.exe, PowerShell, Cygwin, Git bash and Git CMD: I should add a list of these specific conditions that are to be tested

Thanks a lot for your feedback