spectreconsole / spectre.console

A .NET library that makes it easier to create beautiful console applications.
https://spectreconsole.net
MIT License
9.29k stars 479 forks source link

Some components are broken in raw tty #1236

Open harrison314 opened 1 year ago

harrison314 commented 1 year ago

Information

Describe the bug Some components (in my case Rule and Confirm) is broken.

To Reproduce Access the terminal (without Putty or SSH) directly on the linux console. It manifested itself in VirtualBox, HyperV and a physical computer.

Example program to reproduce:

        Console.WriteLine("Encoding : {0}", AnsiConsole.Console.Profile.Encoding);
        Console.WriteLine("Height : {0}", AnsiConsole.Console.Profile.Height);
        Console.WriteLine("Width : {0}", AnsiConsole.Console.Profile.Width);
        Console.WriteLine("Unicode : {0}", AnsiConsole.Console.Profile.Capabilities.Unicode);
        Console.WriteLine("Ansi : {0}", AnsiConsole.Console.Profile.Capabilities.Ansi);
        Console.WriteLine("IsTerminal : {0}", AnsiConsole.Console.Profile.Out.IsTerminal);
        Console.WriteLine("Legacy : {0}", AnsiConsole.Console.Profile.Capabilities.Legacy);
        Console.WriteLine("Links : {0}", AnsiConsole.Console.Profile.Capabilities.Links);

        Console.WriteLine();
        Console.WriteLine();

        Console.WriteLine("AnsiConsole.Write(new Rule());");
        AnsiConsole.Write(new Rule());

        Console.WriteLine();
        Console.WriteLine();

        Console.WriteLine(@"AnsiConsole.Confirm(""Is this prompt OK?"", true);");

       _ = AnsiConsole.Confirm("Is this prompt OK?", true);

Screenshots

Problem with Confirm: image

Sometimes there is also a problem with Rule: image

Context Workaround for AnsiConsole.Confirm:

new ConfirmationPrompt("Is this prompt OK? [lime][[y/n]] (y)[/]")
        {
            DefaultValue = true,
            ShowChoices = false,
            ShowDefaultValue = false
        }
        .Show(AnsiConsole.Console);

If I use the blue text color, the output is broken as well.


Please upvote :+1: this issue if you are interested in it.

nils-a commented 1 year ago

@harrison314 what do you mean by "raw tty"? Are you talking about the virtual console, or do you have a real physical Teletype Terminal hooked up to your system?

harrison314 commented 1 year ago

what do you mean by "raw tty"? Are you talking about the virtual console, or do you have a real physical Teletype Terminal hooked up to your system?

virtual console

nils-a commented 1 year ago

I think I found... "something"

Can you please show me the output of locale, showconsolefont and tput colors? Also, can you try to run your sample program with the NO_COLOR environment variable set?

harrison314 commented 1 year ago

locale:

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

showconsolefont: image

tput colors:

8

When using NO_COLOR, the problem did not appear.

image

nils-a commented 11 months ago

So there are two things going on here:

unicode support

We're determining whether unicode is supported, or not, by "asking" the .NET framework: If the output encoding contains the word unicode, then we're assuming unicode is enabled. The .NET framework, in turn, uses one of LC_ALL, LC_MESSAGES, or LANG and parses the encoding from there.

Whether unicode is really working, has nothing to do with it. Also, keep in mind that the virtual console does never really support unicode, but rather it supports a 255 character wide window of the selected console font. In my tests, unicode in the virtual console was broken more often than not.

I am fairly certain, your error displaying the Rule goes back to whether the unicode characters used to display it are currently working on the console, or not. (Try playing with unicode_start/unicode_stop and the consolefont in use, but I didn't have much luck of getting a consistent result.)

color support

The terminfo-db contains a value of 8 colors for a $TERM of linux. In contrast, we fall back to 256 colors for linux systems. One could call this a bug. However, I feel, the number of terminals that are in use currently and not supporting at least 256 colors is rather limited.

I would suggest setting NO_COLOR to disable the colors completely.

harrison314 commented 11 months ago

Is it not possible to solve at least the display of colors at the Spectre.Console level?

Or provide a code snippet, how to use NO_COLOR automatically in C# code?

nils-a commented 11 months ago

Well, you can always set the environment variables using System.Environment.SetEnvironmentVariable:

System.Environment.SetEnvironmentVariable("NO_COLOR", "1", System.EnvironmentVariableTarget.Process);

However, if you can (and are willing to) modify the code of the program, you could also set the number of colors manually:

AnsiConsole.Profile.Capabilities.ColorSystem = ColorSystem.Legacy;
borrrden commented 17 hours ago

For a bit of further context here, this same behavior for Rule happens when piping output to Out-File on Powershell 7.4.5 on Windows. The weird thing is it does NOT happen when redirecting via > but only with | Out-File or | Out-String.

It also, unfortunately, happens when adding 2>&1 to the command line invocation and then redirecting to a file.