How To Use ANSI/VT100 Formatting in PowerShell (ooh, pretty colors!)

I’ve been working primarily in bash on CentOS and RHL, and just recently started working on some Windows 10 systems and trying to translate my skills from bash to PowerShell. It’s been… interesting.

ANSI/VT100 formatting might not help you directly automate any tasks, but I’ve found that it can be really helpful to be able to adjust output for readability, and highlight important pieces of information. I wasn’t able to find a good writeup anywhere that explains the basics with regard to PowerShell, so I thought I’d lay it out. I am drawing primarily on the work done here by Fabien.

This has been tested on Windows 10 Enterprise r1803, using PowerShell v5.1 (in native conhost.exe). As far as I can tell, everything should just work if you’re on that revision or higher, with no need to mess with virtual terminal settings as before.

VT100 text formatting sequences follow the general format:

ESC[#mTEXT

To use this, we first need to get the escape character. For PSv5.1, this is not the same as the backtick “`” (grave-accent or backwards apostrophe) used to escape special characters. To get the escape character we need to call the specific ASCII character by number (in this case 27) using “[char]##”, and for ease of use store it in a variable:

PS\> $esc = "$([char]27)"

This will be applied at the beginning of each VT100 sequence.

Text Styling and Resets
The following styles are usable:
[ul]
[li]Bold [pre]$esc[1m[/pre][/li]
[li]Underlined [pre]$esc[4m[/pre][/li]
[li]Inverted [pre]$esc[7m[/pre] there’s no equivalent for this in BBCode - it inverts the foreground and background colors (e.g. white text on black background becomes black text on white background)[/li]
[/ul]
VT100 also has Dim ([3m), Blinking ([5m) and Hidden ([8m), but they don’t seem to be implemented in conhost.

To remove the style, VT100 has the following reset sequences:
[ul]
[li]Bold Reset [pre]$esc[21m[/pre][/li] oddly, this one reset doesn’t seem to be implemented properly in conhost (I assume it’s the terminal emulator and not PowerShell itself)
[li]Underline Reset [pre]$esc[24m[/pre][/li]
[li]Invert Reset [pre]$esc[27m[/pre][/li]
[li]Reset All [pre]$esc[0m[/pre] this one resets all formatting to default, including the color codes we’ll cover next[/li]
[/ul]
There are also reset codes for Dim, Blinking and Hidden but they’re useless at the moment.

Multiple styles can be applied at the same time by separating the numbers with semi-colons, and they can be individually turned off using the above resets. For example:
[pre]$esc[1;4mBold Underlined $esc[24mBold Only $esc[0mNormal Text[/pre]
will produce
Bold Underlined Bold Only Normal Text

16-Color Foreground & Background
The standard 16-color set is assigned to its own numbers for both the text and the background, but the color seems a bit off for some of them. I’ve tried to replicate what they actually look like in conhost.
[ul]
[li]Default [pre]$esc[39m[/pre] forces the terminal default text color, whatever it’s set to[/li]
[li][color=black]Black[/color] [pre]$esc[30m[/pre][/li]
[li][color=darkred]Red[/color] [pre]$esc[31m[/pre][/li]
[li][color=darkgreen]Green[/color] [pre]$esc[32m[/pre][/li]
[li][color=whitesmoke]Yellow[/color] [pre]$esc[33m[/pre] (appears slightly off-white)[/li]
[li][color=darkblue]Blue[/color] [pre]$esc[34m[/pre][/li]
[li][color=darkslategray]Magenta[/color] [pre]$esc[35m[/pre] (this one looks the least like the color it’s supposed to be)[/li]
[li][color=darkcyan]Cyan[/color] [pre]$esc[36m[/pre][/li]
[li][color=lightgray]Light Gray[/color] [pre]$esc[37m[/pre][/li]
[li][color=gray]Dark Gray[/color] [pre]$esc[90m[/pre][/li]
[li][color=red]Light Red[/color] [pre]$esc[91m[/pre][/li]
[li][color=lawngreen]Light Green[/color] [pre]$esc[92m[/pre][/li]
[li][color=yellow]Light Yellow[/color] [pre]$esc[93m[/pre][/li]
[li][color=blue]Light Blue[/color] [pre]$esc[94m[/pre][/li]
[li][color=magenta]Light Magenta[/color] [pre]$esc[95m[/pre][/li]
[li][color=cyan]Light Cyan[/color] [pre]$esc[96m[/pre][/li]
[li][color=white]White[/color] [pre]$esc[97m[/pre][/li]
[/ul]
The background colors are the same set, and appear essentially as text highlighting.

256-Color Foreground & Background
The conhost.exe terminal emulator supports the full 256 color range available with ANSI/VT100. The foreground color is applied using the sequence:

$esc[38;5;###m

Where ### is a number between 0 and 255. To apply the color to the background instead of the foreground, replace the 38 with 48.
To see a chart with all of the colors, you can copy & paste this into your PS prompt:


This code was originally written for bash by Sam Hocevar and falls under his license.
Editing for PowerShell was done by me.

I would really like to improve the way the color boxes in that bit of code are formatted. To reproduce the functionality of Linux’s printf I had to apply PadLeft() to the text being displayed and then handle the display with Write-Host -NoNewLine to prevent the really unnecessary newlines PowerShell wants to add all over the place. For various reasons, I’d love to avoid the use of Write-Host but I haven’t found another option for stripping out the newlines. Is there a better way to get the kind of control that printf offers?