2

I'm trying to use the built-in PSReadLine (v2) module of Powershell (v5.1) to customize Powershell console text colors.

Previous versions of PSReadLine allowed you to simply specify -Background and -Foreground parameters for any given token type. But that is no longer the case. PSReadLine v2 introduced the use of ANSI escape codes to define color behavior. I gather that this allows for much greater flexibility, but it's extremely complicated for what it's meant to accomplish. Documentation about these codes is all over the place, and highly dependent on the implementation of the host application, which makes it that much harder to find answers.

Simply coloring text foreground is (relatively) easy with something like:

set-psreadlineoption -colors @{
    CommandColor = "`e[93m"
    CommentColor = "`e[32m"
}

However things get more complicated if you want to introduce decoration, such as bold, underline, or of particular interest to me, background color and combinations of these.

The default value for SelectionColor (which highlights selected text with a different background color) is`e[35;43m. But that big hint is still not enough to betray the syntactical secrets I'm searching for.

The doc for Set-PSReadLineOption very matter-of-factly states:

You can specify other escape sequences including:
256 color
24-bit color
Foreground, background, or both
Inverse, bold

... but provides no examples.

How would you go about specifying an escape code that defines both foreground and background color, or any other combination of colors and colored decorations?

Sources I've found helpful in learning about these escape codes are: http://jafrog.com/2013/11/23/colors-in-terminal.html https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters

But I've not been able to fully wrap my head around any of this.

Solved:

Thanks to @LotPings. I was mistakenly assuming that escape codes could only have a set number of options given to them. In truth, I can specify as many as I want (or as many as I need to accomplish my goals). So for example:

$e = [char]0x1b
"$e[38;2;255;128;128;48;2;128;0;255;4mtest$e[0m"

... will result in the word test, which is underlined with a pink foreground and purple background. To break it down:

enter image description here

mmseng
  • 735
  • 9
  • 24

1 Answers1

1
  • Use Get-PSReadLineOption to see current settings
  • Some attributes don't make sense in 256/24bit color modes.
  • Windows console doesn't support inverse (also in WSL)

The code from Jafrog's blog translated to PowerShell

## Q:\Test\2019\06\20\SO_56679782.ps1

Get-PSReadLineOption

$Esc=[char]0x1b 

'The following command should print “hello” in bright red underscore text:'
"$Esc[91;4mHello$Esc[0m"

ForEach($code in 30..37){
"{0}[{1}mEsc[{1}m{0}[0m  {0}[{1};1mEsc[{1};1m{0}[0m  {0}[{1};3mEsc[{1};3m{0}[0m  {0}[{1};4mEsc[{1};4m{0}[0m  {0}[{2}mEsc[{2}m{0}[0m" -f $Esc,$code,($code+60)
}
pause
foreach($code in 0..255){"{0}[38;5;{1}mESC[38;5;{1}m{0}[0m" -f $Esc,$code}

enter image description here

Ansi Esc[ sequence (CSI)
              Foreground     Background
No Color     normal bright  normal bright
0  black       30     90      40    100
1  red         31     91      41    101
2  green       32     92      42    102
3  yellow      33     93      43    103
4  blue        34     94      44    104
5  violet      35     95      45    105
6  turqoise    36     96      46    106
7  grey        37     97      47    107

enter image description here

  • Thank you. I'm afraid I still don't understand the logic behind specifying the foreground color along with the background color though. For example, in your last screenshot, why does `Esc[40;1m` have a yellow foreground color? Is that just because the Powershell console renders bold (`;1`) as yellow and doesn't even render italics (`;3`)? Is there actually a way to specify both foreground and background color? I also haven't been able to decode why the default `SelectionColor` (`Esc[35;43`) is rendered the way it is. – mmseng Jun 20 '19 at 20:58
  • 1
    The yellow color may come from my bicolored powershell prompt function, in pwsh without this function it is normal. To specify fore-/background in one go combine them with a semicolon like the selectioncolor does. For bright red on bright green background `$Esc=[char]0x1b;"$Esc[91;102mEsc[91;102m$Esc[0m"` –  Jun 20 '19 at 21:46
  • I see. I'm trying to test that out, by I've found that part of my confusion lies in the fact that set-psreadlineoption is apparently not working at all. If I load up the console, type `get-psreadlineoption`, then `set-psreadlineoption -colors @{stringcolor='red'}`, and then `get-psreadlineoption` again, the value of `stringcolor` does not change, and strings continue to use the default color. Am I using this wrong? – mmseng Jun 20 '19 at 22:34
  • 1
    FWIW, I understand the syntax now. I was mistakenly assuming that each escape character could only have a set number of options, but I see now that, for example, `$e=[char]0x1b; "$e[91;103;4mtest$e[0m"` would result in the word test with red foreground, green background, and underlined. Now I just need to figure out how to get `set-psreadlineoption` to save my changes. – mmseng Jun 20 '19 at 22:45
  • Aha, I was using `set-psreadlineoption -colors` incorrectly. The `colors` hashtable uses names like `string` and not `stringcolor`, even though `get-psreadlineoption` displays them as `stringcolor`. – mmseng Jun 21 '19 at 00:15