ajalt / mordant

Multiplatform text styling for Kotlin command-line applications
https://ajalt.github.io/mordant/
Apache License 2.0
986 stars 34 forks source link

Problems with MinGW Terminal #38

Open Framstag opened 3 years ago

Framstag commented 3 years ago

Hello :-) I'm the author of https://github.com/Framstag/taskdown

I use mordant (the latest beta) to add colored output in the terminal and (with the new beta) to print nicely formatted Markdown to the terminal.

This works perfectly under Linux and under Windows native, however it does not work under MinGW (under Windows). The problem occurs with the standard installation, but also with the integration inf MinGW in the new Windows terminal (calling bash.exe -l -i from the terminal configuration).

The problem is, that I use MinGW under Windows as preferred working environment.

I'm not sure what exactly the problem is, or if it is even a problem of mordant itself. IF I call my program with TERM=dumb (the problem disappears (unsurprisingly)). I tried to set TERM to other values to trick the autodetection mechanism, but did not find a variant to resulted in working output.

DOS Shell: grafik

MinGW bash: grafik

I obviously need some help, and I'm willing to help you if you give me advice what to do.

ajalt commented 3 years ago

So if I use Windows Terminal to create a console with bash.exe -l -i then use the application plugin to run terminal.println("${blue("Hello")} ${red("world")}!"), colors work correctly:

Capture

My installation may be different than yours, but if not, maybe the problem is in the way you're building or running with your td.sh?

Outputs like ←[31m are the ANSI escape codes / VT codes used to contol terminal colors. Most terminals will process these into color commands, but it seems like your temrinal is printing them instead. I'm not sure why it's happening for you on JVM and not native.

Given that your prompt is colored in the screenshot, the terminal clearly does support VT processing. Something must be getting escaped or a configuration changed in the way your jvm code is running. Sorry I can't be of more help, but maybe you can search for ANSI code issues on MinGW with Java. If you find a solution that doesn't require JNI, I'd love to integrate it.

Framstag commented 3 years ago

Some searching lead me to the following issues:

and the following library: https://github.com/alexarchambault/windows-ansi

Adding WindowsAnsi.setup() at the start of main() did help solve the problem:

grafik

I'm not sure if this is the only solution, I'm even unsure if it is the right solution. It may even be possibly solved in newer Java versions, but it seems to solve the problem. It looks though, that it requires low level JNI "magic", which you possibly do not want to make use of :-/

As I'm interested to build native versions (some day), because startup time is not as good as it should be for a console application, things did become more complicated this way :-/


$ java -version
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment Temurin-11.0.12+7 (build 11.0.12+7)
OpenJDK 64-Bit Server VM Temurin-11.0.12+7 (build 11.0.12+7, mixed mode)```
ajalt commented 3 years ago

Thanks for the research! So to summarize, it looks like the problem is a combination of Windows Terminal allowing apps to disable VT processing, and the process (possibly Java?) disabling it.

It seems like WindowsAnsi.setup() is the best workaround for now. I've been avoiding bundling JNI to prevent issues with graal etc.

sschuberth commented 1 year ago

I believe the issue discussion is mixing up some things: MinGW terminal is not running in the Windows Terminal application usually, but inside mintty (aka Git Bash).

Anyway, I'm also facing the issue that color does not work when running ORT on Windows, no matter what the terminal is.

I've tried the following an none output color:

However, all of these combination theoretically support color, as I see it working when setting the FORCE_COLOR=1 environment variable.

Is the only solution to the problem still calling WindowsAnsi.setup() explicitly from my code when running on Windows?

ajalt commented 1 year ago

@sschuberth I think your problem is unrelated to this issue. If FORCE_COLOR=1 works, then it's not a rendering problem, Mordant just isn't detecting that colors are supported. Are you running through Gradle or something? It redirects stdout so colors are disabled unless you explicitly enable them.

sschuberth commented 1 year ago

Are you running through Gradle or something?

I'm running through the script generated by the Gradle application plugin's distZip task, so it's not running through Gradle, and no redirection should be involved.

I'll amend my post above with conhost as a termnial plus cmd.exe, that also does not work. And if I use FORCE_COLOR=1 here, I see ANSI sequences instead of colored output. In short, I cannot get coloring to work properly on Windows at all.

ajalt commented 1 year ago

I guess I'd need more information to help; Windows Terminal works fine for me, including detection.

sschuberth commented 1 year ago

Ok, let's see: In a Windows terminal, I go to the directory of the "table" sample app and run

ajalt\mordant\samples\table>..\..\gradlew installDist

Then I run the batch file

ajalt\mordant\samples\table>build\install\table\bin\table.bat

And I get

image

ajalt commented 1 year ago

image

Hm, that works without issue on my side on both cygwin and cmd.exe shells, on both Windwos 10 and 11.

What are the values of terminal.info.ansiLevel, terminal.info.outputInteractive, and terminal.info.inputInteractive when you run like that? Can you share the environment variables you're running with (Get-ChildItem env: in poweshell)?

sschuberth commented 1 year ago

Odd.

I'm now using https://github.com/ajalt/mordant/pull/126 to get the numbers:

ajalt\mordant\samples\detection>build\install\detection\bin\detection.bat
TerminalInfo(width=120, height=30, ansiLevel=NONE, ansiHyperLinks=false, outputInteractive=true, inputInteractive=true, crClearsLine=false)

Environment variables (I've XXXed some values):

ALLUSERSPROFILE=C:\ProgramData
ANDROID_HOME=C:\Users\Sebastian\AppData\Local\Android\Sdk
APPDATA=C:\Users\Sebastian\AppData\Roaming
CommonProgramFiles=C:\Program Files\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
COMPUTERNAME=XXX
ComSpec=C:\WINDOWS\system32\cmd.exe
DriverData=C:\Windows\System32\Drivers\DriverData
EFC_11920=1
FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer
FPS_BROWSER_USER_PROFILE_STRING=Default
HOMEDRIVE=C:
HOMEPATH=\Users\Sebastian
JAVA_HOME=C:\Users\Sebastian\.jdks\temurin-17.0.6
LOCALAPPDATA=C:\Users\Sebastian\AppData\Local
LOGONSERVER=\\XXX
NUMBER_OF_PROCESSORS=20
OneDrive=C:\Users\Sebastian\OneDrive
OneDriveConsumer=C:\Users\Sebastian\OneDrive
OS=Windows_NT
Path=XXX
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW;.RB;.RBW
POWERSHELL_DISTRIBUTION_CHANNEL=MSI:Windows 10 Home
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 154 Stepping 3, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=9a03
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PROMPT=$P$G
PSModulePath=C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
PUBLIC=C:\Users\Public
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\WINDOWS
TEMP=C:\Users\SEBAST~1\AppData\Local\Temp
TMP=C:\Users\SEBAST~1\AppData\Local\Temp
USERDOMAIN=XXX
USERDOMAIN_ROAMINGPROFILE=XXX
USERNAME=Sebastian
USERPROFILE=C:\Users\Sebastian
windir=C:\WINDOWS
ZES_ENABLE_SYSMAN=1
ajalt commented 1 year ago

Thanks for the info. So based on your environment it looks like Mordant is behaving correctly. The only way to tell what terminal you're running on is by looking at environment variables like TERM, and for some reason your computer isn't setting any. If there's no info there, we default to the safe choice of not enabling color.

sschuberth commented 1 year ago

If there's no info there, we default to the safe choice of not enabling color.

Oh. I wonder how other tools like Gradle then seemingly properly detect color capabilities of the terminal. I should also check tool like picocli to see how they work in this regard.

Edit: I wonder whether instead a method as described here could be used.

sschuberth commented 1 year ago

Ok, so for mintty as a terminal I was able to solve the problem via https://github.com/ajalt/mordant/pull/127. Regarding the new Windows Terminal application, the problem in my case is that it's set as the default terminal in Windows 11, in which case there's a bug that WT_SESSION is not set, so that's probably nothing that can be solved in Mordant. The remaining case on Windows is ConHost as a terminal; there seem to be no special environment variables set in this case, but I wonder whether we could simply enable 16 colors as a fallback on Windows if no other terminal detection applies, as ConHost has always supported color, and AFAIK every version of Windows ships with it.