Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TERM and NO_COLOR envirnoment vars still not respected #21160

Open
5 tasks done
ghost opened this issue Jan 30, 2024 · 73 comments
Open
5 tasks done

TERM and NO_COLOR envirnoment vars still not respected #21160

ghost opened this issue Jan 30, 2024 · 73 comments
Labels
Needs-Triage The issue is new and needs to be triaged by a work group.

Comments

@ghost
Copy link

ghost commented Jan 30, 2024

Prerequisites

Steps to reproduce

As per "Enable use of TERM and NO_COLOR env var plaintext #14969" the TERM and NO_COLOR variables should disable coloring of errors in pwsh. But executing the showbug.bat in command.exe in the root directory of pwsh version 7 4 1 with this content:

pwsh.exe -ExecutionPolicy Unrestricted ^
   -Command "$host.version ; " ^
   "Get-Item  Env:TERM ; " ^
   "Get-Item  Env:NO_COLOR ; " ^
   "Get-It1"

Shows:

 Major  Minor  Build  Revision
 -----  -----  -----  --------
 7      4      1      -1
 
 PSPath        : Microsoft.PowerShell.Core\Environment::TERM
 PSDrive       : Env
 PSProvider    : Microsoft.PowerShell.Core\Environment
 PSIsContainer : False
 Key           : TERM
 Value         : xterm-mono
 Name          : TERM
 
 
 PSPath        : Microsoft.PowerShell.Core\Environment::NO_COLOR
 PSDrive       : Env
 PSProvider    : Microsoft.PowerShell.Core\Environment
 PSIsContainer : False
 Key           : NO_COLOR
 Value         : True
 Name          : NO_COLOR
 
 Get-It1: The term 'Get-It1' is not recognized as a name of a cmdlet, function, script file, or executable program.
 Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

Here, the error message, triggered intentionally to demonstrate the bug, is RED colored.

Expected behavior

The error message should be printed without the colors.

Actual behavior

The error is RED colored, in spite of the environment variables requesting no colors and being clearly readable by the pwsh.exe.

Error details

The error in the above example is triggered intentionally to show that the error message is colored RED.
The error here is that the error message itself is displayed using colors, which is not what is supposed to happen according to the #14969

Environment data

PS C:\tmp\pwsh741> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.4.1
PSEdition                      Core
GitCommitId                    7.4.1
OS                             Microsoft Windows 6.3.9600
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

pwsh74bug

@ghost ghost added the Needs-Triage The issue is new and needs to be triaged by a work group. label Jan 30, 2024
@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Jan 30, 2024

NO_COLOR does get recognized and affects $PSStyle.OutputRending

$ NO_COLOR=true pwsh -c '$PSStyle.OutputRendering'
PlainText
$ pwsh -c '$PSStyle.OutputRendering'
Host

According to about ANSI terminals

OutputRendering only applies to rendering in the Host, Out-File, and Out-String. Output from native executables isn't affected.

So I question if the error channel is included in that handling.

Regarding the TERM, it does not make sense to send ANSI colour escape sequences to terminals that don't understand them. (eg should refer to terminfo and not populate all the PSStyle colours if the terminal cannot deal with colour)

@ghost
Copy link
Author

ghost commented Jan 30, 2024

The rationale is simple: if the colors are enforced by default, they will make the output for some users completely unreadable. There should be a way for users set a variable to prevent colors from being used:

https://no-color.org/

At the moment not only the error output is always colored, the same happens for the PS prompt input: on a gray background the input is yellow or light green both of which are unreadable.

NO_COLOR is not recognized and not respected for errors and for prompts.

@rhubarb-geek-nz
Copy link

the input is yellow or light green both of which are unreadable.

Agreed!

PowerShell on osx how to force to be completely monochrome

@237dmitry
Copy link

237dmitry commented Jan 30, 2024

You can set monochrome pwsh:

ss

[console]::Write("`e]12;#ffffff`a")     # set white cursor

$PSStyle.OutputRendering = "PlainText"
Set-PSReadlineOption -Colors @{
    Command = "`e[37m"
    Comment = "`e[37m"
    ContinuationPrompt  = "`e[37m"
    Default = "`e[37m"
    Emphasis = "`e[37m"
    Error = "`e[37m"
    InlinePrediction  = "`e[37m"
    Keyword = "`e[37m"
    ListPrediction = "`e[37m"
    ListPredictionSelected  = "`e[37m"
    ListPredictionTooltip  = "`e[37m"
    Member = "`e[37m"
    Number  = "`e[37m"
    Operator  = "`e[37m"
    Parameter  = "`e[37m"
    Selection =  "`e[7m"
    String  = "`e[37m"
    Type =  "`e[37m"
    Variable  = "`e[37m" 
}

@rhubarb-geek-nz
Copy link

You can set monochrome pwsh:

Without seeing the contents of your "mono.ps1" I don't know what you are trying to demonstrate.

Wanting to use monochrome and NO_COLORs does not mean setting the colours to black and white. It means not using any colour escape codes in any output.

@237dmitry
Copy link

It means not using any colour escape codes in any output.

NO_COLOR also set colors with escape sequences, just reduce base 16 console colors to 2

@rhubarb-geek-nz
Copy link

escape 37 m sets the foreground colour to white, it does not mean 'no colour'. So if the background is white or yellow it becomes hard to read.

@237dmitry
Copy link

escape 37 m sets the foreground colour to white

No! This is 8th color of terminal color palette.

@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Jan 30, 2024

It means not using any colour escape codes in any output.

NO_COLOR also set colors with escape sequences, just reduce base 16 console colors to 2

From no-color.org

Command-line software which adds ANSI color to its output by default should check for a NO_COLOR environment variable that, when present and not an empty string (regardless of its value), prevents the addition of ANSI color.

The goal is not have any ANSI colour code escape sequences in the output.

@237dmitry
Copy link

prevents the addition of ANSI color.

How when terminal does understand what color it has to output? Any symbol, any color and any hotkey are esc-sequences

@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Jan 30, 2024

How when terminal does understand what color it has to output? Any symbol, any color and any hotkey are esc-sequences

A true monochrome terminal does not have that problem, there are no colours to choose from, It may be white on black, green on black or amber on black, some monochrome terminals allow you to have reversed characters. In the same manner it is completely legitimate to have black on white. The application does not deal with any colours at all, it just prints text and it is displayed how the terminal sees fit.

Look ma, no colours

VT100

@237dmitry
Copy link

A true monochrome terminal does not have that problem

What does it mean "true"? Kernel console 80x25?

@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Jan 30, 2024

A true monochrome terminal does not have that problem

What does it mean "true"? Kernel console 80x25?

VT102, VT52, 3270, 5250 were all monochrome terminals. The original xterm was monochrome as not everyone could afford colour. Lisa and the first Macintosh were monochrome, they did not get colour until Macintosh II and Color QuickDraw

@237dmitry
Copy link

237dmitry commented Jan 30, 2024

VT102, VT52 were all monochrome terminals

These are hardware terminals, let's get closer to life.

The original xterm was monochrome as not everyone could afford colour.

I do not remember "original" xterm. But I do remember that xterm configured with ~/.Xresources

XTerm Control Sequences

@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Jan 30, 2024

These are hardware terminals, let's get closer to life.

Modern Macintosh Terminal Console offers many themes, including black on yellow. But PowerShell uses Yellow on Yellow, It also offers black and white. PowerShell gives you yellow on white. The terminals also work on according to the light/dark mode and will change colours during the day. So more than 50% of the time the PowerShell colour configuration is wrong, if you reconfigure it, then it will be wrong again when the dark/light mode changes. It will be wrong if you have multiple terminals open using different themes. So the solution is we want, when asked, is for PowerShell to not do any colours at all.

@237dmitry
Copy link

237dmitry commented Jan 30, 2024

But PowerShell uses Yellow on Yellow

Just test two commands, there is difference in order of colors:

0..8 | % { Write-Host $([consoleColor] $_) -f $_ }
30..37 | % { "`e[$($_)mTEST" }

The .Net...

@ghost
Copy link
Author

ghost commented Jan 30, 2024

How when terminal does understand what color it has to output? Any symbol, any color and any hotkey are esc-sequences

For a programmer, the correct answer is to see how it's implemented elsewhere.

And example of using https://github.com/termcolor/termcolor

demo

where demo-termcolor.py is:

import termcolor
termcolor.cprint( "hello", color="red" )

demo-temcolor-nocolor.zip

GitHub
ANSI color formatting for output in terminal. Contribute to termcolor/termcolor development by creating an account on GitHub.

@237dmitry
Copy link

demo-termcolor.py

Python 3.11.6:

ModuleNotFoundError: No module named 'termcolor'

@ghost
Copy link
Author

ghost commented Jan 30, 2024

ModuleNotFoundError: No module named 'termcolor'

On windows:

py -m pip install termcolor

But I already gave the picture of the output. NO_COLOR results in no ANSI color sequences at all, showing that they aren't supposed to be present if NO_COLOR is set.

There's also a huge list of other libraries already implementing NO_COLOR on https://no-color.org/ pwsh is there too but this entry is to show that what's implemented is still insufficient.

@237dmitry
Copy link

pwsh is there too but this entry is to show that what's implemented is still insufficient.

Start pwsh with -NoProfile

$env:NO_COLOR=1; pwsh -NoProfile

And unload PSReadline Module:

Remove-Module PSReadline

@ghost
Copy link
Author

ghost commented Jan 30, 2024

Adding -NoProfile doesn't change the bug reported in this entry. The error output is still colored and it shouldn't be. Everything else is a tangential discussion.

demo2

@237dmitry
Copy link

237dmitry commented Jan 30, 2024

The error output is still colored and it shouldn't be.

ss

On Windows:
ss

@ghost
Copy link
Author

ghost commented Jan 30, 2024

Not here:

demo3

Note: removing PSReadLine disabled the yellow thing, but not the red error.

@237dmitry
Copy link

I do not know what to say. I tried in conhost, WT and alacritty and results are the same.

Win 11 Home
PowerShell 7.4.1 installed with MSI package.

@ghost
Copy link
Author

ghost commented Jan 30, 2024

I haven't seen in your outputs that you ever see red errors? What's the step when the red errors stop being red in your case, and how does it look before that step? I think PSReadLine is completely irrelevant for that.

@237dmitry
Copy link

and how does it look before that step? I think PSReadLine is completely irrelevant for that

ss

@ghost
Copy link
Author

ghost commented Jan 30, 2024

In your example the NO_COLOR is ignored without the "-nop", which I don't think is how it's supposed to behave. In my case I also use your -nop to no effect.

I'm not doing any msi, I'm simply extracting

https://github.com/PowerShell/PowerShell/releases/download/v7.4.1/PowerShell-7.4.1-win-x64.zip

to C:\tmp\pwsh741

and running my tests in that directory.

@237dmitry
Copy link

I'm simply extracting

I do the same on Linux and there is not red error. What terminal emulator are you using? And I set in registry:

$ (Get-ItemProperty HKCU:\Console).VirtualTerminalLevel
1

@ghost
Copy link
Author

ghost commented Jan 30, 2024

I'm opening a %windir%\system32\cmd.exe and I haven't created any profile.ps1 myself and the only ones I see are something like in C:\Windows\System32\WindowsPowerShell\v1.0\Examples\profile.ps1 and these have only comments inside and should not be seen by the pwsh at all. And as you see adding -nop changes nothing.

I also don't have VirtualTerminalLevel anywhere in registry. Can you try to remove your entry and see what happens?

@jhoneill
Copy link

BUT PSReadline (IIRC) does not use ansi sequences

If you type Get-PSReadlineOption you can see that it uses them. This is by default:

CommandColor                           : "`e[93m"
CommentColor                           : "`e[32m"

Yes but I have something in my memory which says that's not what actually goes to the console. PSR knows how to translate "blue" to an ansi sequence, and I wish I could find where I got the idea that it does the equivalent of a write-host -foreground and not write-output "ANSI_seq"
But that is what this the screen shot below suggests
image
Note the colour goes from the battery-life bars in my prompt as well, it is only PSR which seems able to emit colour.

@237dmitry
Copy link

what actually goes to the console

The "blue" is 94m ))

ss

You can test color palette:

0..15 | % { Write-Host $([consoleColor] $_) -f $_ }

@jhoneill
Copy link

jhoneill commented Jan 31, 2024

what actually goes to the console

The "blue" is 94m ))

You can test color palette:

OK I've done some more tests and I think wherever the idea that psreadline gets round things by interpreting ANSI colours came from it's wrong.
image

@237dmitry
Copy link

This behavior is strange. $env:NO_COLOR = 1 sets $PSStyle.OutputRendering = "PlainText", but this has no effect on Write-Host with System.ConsoleColor enum in parameters.

But if I entirely set mono for terminal then Write-Host is also monochrome:

# mono.ps1


param ( [Parameter()] [string] $color = "black" )

if ($color -eq "white") { $bg, $fg = "#ccc", "#000" }
else { $bg, $fg = "#111", "#ddd" }

[console]::Write("`e]12;$fg`a")

$PSStyle.OutputRendering = "PlainText"
Set-PSReadlineOption -Colors @{
    Command = "`e[37m"
    Comment = "`e[37m"
    ContinuationPrompt  = "`e[37m"
    Default = "`e[37m"
    Emphasis = "`e[37m"
    Error = "`e[37m"
    InlinePrediction  = "`e[37m"
    Keyword = "`e[37m"
    ListPrediction = "`e[37m"
    ListPredictionSelected  = "`e[37m"
    ListPredictionTooltip  = "`e[37m"
    Member = "`e[37m"
    Number  = "`e[37m"
    Operator  = "`e[37m"
    Parameter  = "`e[37m"
    Selection =  "`e[7m"
    String  = "`e[37m"
    Type =  "`e[37m"
    Variable  = "`e[37m" 
}

$col = (1..15 | Foreach-Object { '{0};{1}' -f $_, $fg }) -join ';'
[console]::Write("`e]4;0;$bg;$col`a")

Works in conhost and it can work in terminals without living config reloading:

PS > mono white  # or black

@mklement0
Copy link
Contributor

@237dmitry, the Write-Host behavior seems to be an (actual) bug - or at least a baffling cross-platform inconsistency; see:

@jhoneill
Copy link

jhoneill commented Feb 1, 2024

This behavior is strange. $env:NO_COLOR = 1 sets $PSStyle.OutputRendering = "PlainText", but this has no effect on Write-Host with System.ConsoleColor enum in parameters.

But if I entirely set mono for terminal then Write-Host is also monochrome:

# mono.ps1


param ( [Parameter()] [string] $color = "black" )

if ($color -eq "white") { $bg, $fg = "#ccc", "#000" }
else { $bg, $fg = "#111", "#ddd" }

[console]::Write("`e]12;$fg`a")

$PSStyle.OutputRendering = "PlainText"
Set-PSReadlineOption -Colors @{
    Command = "`e[37m"
    Comment = "`e[37m"
    ContinuationPrompt  = "`e[37m"
    Default = "`e[37m"
    Emphasis = "`e[37m"
    Error = "`e[37m"
    InlinePrediction  = "`e[37m"
    Keyword = "`e[37m"
    ListPrediction = "`e[37m"
    ListPredictionSelected  = "`e[37m"
    ListPredictionTooltip  = "`e[37m"
    Member = "`e[37m"
    Number  = "`e[37m"
    Operator  = "`e[37m"
    Parameter  = "`e[37m"
    Selection =  "`e[7m"
    String  = "`e[37m"
    Type =  "`e[37m"
    Variable  = "`e[37m" 
}

$col = (1..15 | Foreach-Object { '{0};{1}' -f $_, $fg }) -join ';'
[console]::Write("`e]4;0;$bg;$col`a")

Works in conhost and it can work in terminals without living config reloading:

PS > mono white  # or black

Write-host is not selecting (e.g) RGB of 0,0,255 for blue it's selecting terminal colour 9
What your code does is set all the terminal colours to the same thing
image

Note also (1)
image
Write-host strips ansi when No_color is true, but -Foreground is not affected.
(2) What in one place is called blue is either "BrightBlue" or "DarkBlue" in the the other
(3) These changes affect the console even after the process which applied them exits.

@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Feb 1, 2024

Write-host strips ansi when No_color is true, but -Foreground is not affected.

Rather than "stripping ansi", I suggest code should not be writing ANSI colour escape sequences to the output in the first place when NO_COLOR is present or OutputRendering = PlainText.

@237dmitry
Copy link

What your code does is set all the terminal colours to the same thing

Yes. What does it do to reset color palette to two colors (background and foreground)? Monochrome is two colors 37m and 40m and their values are taken from the terminal settings, where the 1st is background and the 8tn is foreground.

@rhubarb-geek-nz
Copy link

rhubarb-geek-nz commented Feb 1, 2024

Monochrome is two colors 37m and 40m and their values are taken from the terminal settings, where the 1st is background and the 8tn is foreground.

If the terminal is monochrome terminal and does not handle ANSI colour escape sequences then it will just print out the text the best it can, so your output would be littered with the literals "37m" and "40m" in the content.

@mklement0
Copy link
Contributor

mklement0 commented Feb 1, 2024

@rhubarb-geek-nz, regarding Write-Host stripping vs. not writing VT escape sequences:

  • I agree that it should not write them to begin with when -ForegroundColor / -BackgroundColor are used - that's the subject of Write-Host -ForegroundColor / -BackgroundColor don't respect in-session $PSStyle.OutputRendering = 'PlainText', respect it via NO_COLOR only on Unix #21168; the fact that it always writes them on Windows (whereas on Unix only with NO_COLOR it does not) is probably due to the fact that the legacy WriteConsoleOutput WinAPI function is used there, whose color support is unrelated to and predates VT support.

  • Separately, active escape-sequence stripping is performed in a command-independent manner when $PSStyle.OutputRendering = 'PlainText' is in effect, as follows:

    • When PowerShell performs to-terminal output, as opposed to an external program call's output being passed through to the terminal.
    • Intra-session, this only affects the display of data, but an outside caller actually receives the stripped text.

Here's a Unix example; run from bash:

# "green" prints in green, because the external printf utility prints directly to the terminal
# (and itself doesn't honor NO_COLOR)
NO_COLOR=1 pwsh -nop -c "printf 'It ain''t easy being \033[32mgreen\033[m.\n'"

# "green" does NOT print in green, because the use of (...) means that PowerShell captures and relays
# the output, and performs active VT-sequence stripping due to NO_COLOR -> $PSStyle.OutputRendering = 'PlainText'
NO_COLOR=1 pwsh -nop -c "(printf 'It ain''t easy being \033[32mgreen\033[m.\n')"

@rhubarb-geek-nz
Copy link

@mklement0, thanks for mentioning the Win32 console virtual terminal support flags, in many ways the equivalent of this in the UNIX world is the struct termios from tcgetattr and terminfo derived from the TERM environment variable.

@237dmitry

This comment was marked as resolved.

@rhubarb-geek-nz
Copy link

If you explicitly print any escape sequence then that is what should be output because that is what you said to do.

With NO_COLOR there should be no need for any filtering, it is up to the code to abide by the request to not output any colour.

@mklement0
Copy link
Contributor

mklement0 commented Feb 1, 2024

My bad, @237dmitry - I forgot to add the (...) enclosure in the second command, which is what triggers PowerShell's VT-sequence stripping (I've updated my comment):

# From Bash
NO_COLOR=1 pwsh -nop -c "(printf 'It ain''t easy being \033[32mgreen\033[m.\n')"

Now the word "green" is NOT colored.


@rhubarb-geek-nz

If you explicitly print any escape sequence then that is what should be output

I don't disagree, but - unlike the buggy, inconsistent Write-Host -Fore/BackgroundColor behavior - this stripping is by intentional design.

That said, you could argue that outside callers, specifically, then see actively modified data is a buggy (possibly accidental implementation) aspect of this design.
(Intra-session, the problem doesn't arise: the data itself isn't modified during further processing, only the display is impacted).

In other words: it may be worth opening a separate issue to question the CLI behavior when stripping is in effect.

@237dmitry
Copy link

237dmitry commented Feb 1, 2024

If the terminal is monochrome terminal and does not handle ANSI colour escape sequences

Try to see rgb value of background (for example):

"`e]4;0;?`a"

All colors are escape sequences. Why do they not handle? I think they write directly into the host.

@rhubarb-geek-nz
Copy link

All colors are escape sequences. Why do they not handle? I think they write directly into the host.

All colours are escape sequences, and monochrome terminals do not deal with colours.

@237dmitry
Copy link

and monochrome terminals do not deal with colours.

Where does your yellow-black terminal get the colors?

@rhubarb-geek-nz
Copy link

Where does your yellow-black terminal get the colors?

I don't know and I don't care because that is internal to the terminal implementation. What I want is my terminals to work with their existing themes.

Years ago I wrote a nice simple terminal, WishStream, this was Windows Mobile/Windows 8 Store app. The foreground and background colours were defined by the user through the XAML Theme, if they wanted it dark it would be light on dark, if they wanted light, they got dark on light.

As it was a monochrome terminal it implemented the VT100 escape sequences, which do not include colour. So this terminal ignored all colour escape sequences because they were meaningless, and as it set TERM=vt100, no application should have been sending any colour escape sequences. So vi etc all worked happily because they abided by the terminfo regarding what a vt100 terminal could do.

@237dmitry
Copy link

What I want is my terminals to work with their existing themes.

Сonfigure pwsh and terminal yourself. This is the easiest way in the current situation. Or wait for the PSReadline developers to listen to our wishes.

@rhubarb-geek-nz
Copy link

Сonfigure pwsh and terminal yourself. This is the easiest way in the current situation. Or wait for the PSReadline developers to listen to our wishes.

The other option is to not use PowerShell. It is a silly situation where, out of the box, with no configuration, PowerShell is unusable on a Mac with the default terminal theme of black on white because it gives you yellow on white. I have to open a new session explicitly different to use PowerShell.

@237dmitry
Copy link

I could not launch bash in monochrome mode, all of TERM=mono|vt100, NO_COLOR=1|true do not work at all. only for one-line syntax and not for all applications and utilities. Even in TTY (TERM=linux).

@rhubarb-geek-nz
Copy link

On Ubuntu, it has this in .bashrc

set a fancy prompt (non-color, unless we know we "want" color)

case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac

So it should not use colour in the prompt unless the terminal matches the case statement. If I set TERM=dtterm I don't get a colour prompt.

Unfortunately the aliases play by a completely different set of rules

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    #alias grep='grep --color=auto'
    #alias fgrep='fgrep --color=auto'
    #alias egrep='egrep --color=auto'
fi

I find standard Linux directory colours hard to read when directories are blue on black.

@237dmitry
Copy link

If I launched bash:

bash --noprofile --norc

It still started with full set of configurations from ~/.profile and ~/.bashrc

@jhoneill
Copy link

jhoneill commented Feb 1, 2024

Write-host strips ansi when No_color is true, but -Foreground is not affected.

Rather than "stripping ansi", I suggest code should not be writing ANSI colour escape sequences to the output in the first place when NO_COLOR is present or OutputRendering = PlainText.

I would suggest that authors need to think REALLY hard about use of any kind of colour, and a lot harder than any actually do.
I think the chance of getting authors to write if no_color around their not terrible well thought out colours isn't great.

If a script that doesn't check the users preference usesWrite-host "$($PSStyle.Foreground.Yellow) Something $($PSStyle.Reset)" in place of the frankly easier and longer established Write-host "Something" -Foreground yellow then PowerShell will apply NO_COLOR as the user wishes.

What I want is my terminals to work with their existing themes

There is always the scope to create terminal themes which become nonsensical . Terminal themes are a set of "slots" which represent colours by convention, and we can set exactly what R,G,B values are used for "Red-on-this-terminal" VS Code's default red and / Windows Terminal default Red are not automatically the same or something simple like 255,0,0. Windows PowerShell re-defined Dark Magenta in the default terminal settings for PowerShell.exe so that it isn't any kind of magenta but a dark blue and then set the background not to black but dark magenta.

Absolutely any assumption that an application theme makes about the terminal has in each slot can be wrong footed:
what you or I set for winterm / vs code - because of taste or address an eyesight issue we have - can result in PSReadline displaying unhelpfully.

I think there is an argument that at start-up PSreadline should look at No_color and if found set all it's colours to the default foreground colour. That's a different branch from this though.

@SteveL-MSFT
Copy link
Member

I'm a bit lost in this thread. The original problem doesn't repro for me:

$env:NO_COLOR=1
pwsh -noprofile -command '$psversiontable;get-it'

image

@mklement0
Copy link
Contributor

@SteveL-MSFT, I don't think there's anything actionable here, as I've tried to express in my previous summary:

  • We have no repro for the original problem, except on a no longer supported Windows version, 8.1, which makes it a moot point. (Also, the OP appears to have deleted their account.)

  • The conceptually related, but separate question of PSReadLine's behavior with respect to coloring of interactive user input at the command prompt should be discussed in:

ProjectSynchro added a commit to ProjectSynchro/powershell-wrapper-for-wine that referenced this issue Apr 4, 2024
We can workaround bug 49780 by disabling colour outputs entirely, and removing the PSReadLine module.

See: PowerShell/PSReadLine#3918 and PowerShell/PowerShell#21160 for context.
@bitbound
Copy link

bitbound commented May 16, 2024

Landed here while searching the same issue. My use case is that I'm starting pwsh with redirected stdin, stdout, and stderr. With NO_COLOR environment variable set, I'd expect there to be no color escape sequences in neither stdout nor stderr.

Maybe I'm wrong to assume this, but it seems like a logical conclusion based on the docs here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_ansi_terminals?view=powershell-7.4#disabling-ansi-output

Here's a quick repro:

using System.Diagnostics;

var psi = new ProcessStartInfo
{
    FileName = "pwsh.exe",
    RedirectStandardError = true,
    RedirectStandardOutput = true,
    RedirectStandardInput = true,
};
psi.Environment.Add("NO_COLOR", "1");

var process = Process.Start(psi)!;
process.OutputDataReceived += (sender, e) =>
{
    Console.WriteLine(e.Data);
};
process.ErrorDataReceived += (sender, e) =>
{
    Console.WriteLine(e.Data);
};

process.BeginOutputReadLine();
process.BeginErrorReadLine();

await process.StandardInput.WriteLineAsync("$env:NO_COLOR;$psversiontable;get-it;exit;");
await process.WaitForExitAsync();

image

image

Describes the features of PowerShell that use ANSI escape sequences and the terminal hosts that support them.

@mklement0
Copy link
Contributor

@bitbound: The problem seems to somehow be related to providing commands via stdin and also System.Diagnostics.Process:

In your repro code, if you comment out RedirectStandardInput = true and await process.StandardInput.WriteLineAsync("$env:NO_COLOR;$psversiontable;get-it;exit;");, and then type get-it interactively, you'll see that the error message is monochrome.

By contrast, from the command line providing commands via stdin does seem to honor NO_COLOR (ditto from Bash and cmd.exe):

# OK - monochrome error message.
$env:NO_COLOR=1; 'get-it' | pwsh -NoProfile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs-Triage The issue is new and needs to be triaged by a work group.
Projects
None yet
Development

No branches or pull requests

6 participants