How to Use the Ansi Escape Code for Outputting Colored Text on Console

How to use the ANSI Escape code for outputting colored text on Console

I'm afraid you forgot the ESC character:

#include <cstdio>

int main()
{
printf("%c[%dmHELLO!\n", 0x1B, 32);
}

Unfortunately it will only work on consoles that support ANSI escape sequences (like a linux console using bash, or old Windows consoles that used ansi.sys)

c++ ansi escape codes not displaying color to console

The problem with reading the config.txt files is that the string is read as though it is assigned to be:

std::string str = "\\033[0;31m";

i.e. the \ is treated as a character. What you need in code is "\033", i.e. the character represented by the octal number 033.

You can change the following lines in your code to ignore the "\\033" part of the string and print the octal number.

    cout << x.second << x.first <<endl;

needs to be:

    cout << '\033' << x.second.substr(4) << x.first <<endl;

With that change, I tried your program on my desktop and it works as expected.

Colored text output in PowerShell console using ANSI / VT100 codes

Note:

  • The following applies to regular (legacy) console windows on Windows (provided by conhost.exe), which are used by default, including when a console application is launched from a GUI application.

  • By contrast, the console windows (terminals) provided by Windows Terminal provide support for VT / ANSI escape sequences by default, for all console applications.


While console windows in Windows 10 do support VT (Virtual Terminal) / ANSI escape sequences in principle, support is turned OFF by default.

You have three options:

  • (a) Activate support globally by default, persistently, via the registry, as detailed in this SU answer.

    • In short: In registry key [HKEY_CURRENT_USER\Console], create or set the VirtualTerminalLevel DWORD value to 1
      • From PowerShell, you can do this programmatically as follows:

        Set-ItemProperty HKCU:\Console VirtualTerminalLevel -Type DWORD 1
      • From cmd.exe (also works from PowerShell):

        reg add HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1
    • Open a new console window for changes to take effect.
    • See caveats below.
  • (b) Activate support from inside your program, for that program (process) only, with a call to the SetConsoleMode() Windows API function.

    • See details below.
  • (c) Ad-hoc workaround, from PowerShell: pipe output from external programs to Out-Host; e.g., .\test.exe | Out-Host

    • See details below.


Re (a):

The registry-based approach invariably activates VT support globally, i.e., for all console windows, irrespective of what shell / program runs in them:

  • Individual executables / shells can still deactivate support for themselves, if desired, using method (b).

  • Conversely, however, this means that the output of any program that doesn't explicitly control VT support will be subject to interpretation of VT sequences; while this is generally desirable, hypothetically this could lead to misinterpretation of output from programs that accidentally produce output with VT-like sequences.

Note:

  • While there is a mechanism that allows console-window settings to be scoped by startup executable / window title, via subkeys of [HKEY_CURRENT_USR\Console], the VirtualTerminalLevel value seems not to be supported there.

  • Even if it were, however, it wouldn't be a robust solution, because opening a console window via a shortcut file (*.lnk) (e.g. from the Start Menu or Task Bar) wouldn't respect these settings, because *.lnk files have settings built into them; while you can modify these built-in settings via the Properties GUI dialog, as of this writing the VirtualTerminalLevel setting is not surfaced in that GUI.



Re (b):

Calling the SetConsoleMode() Windows API function from inside the program (process), as shown here, is cumbersome even in C# (due to requiring P/Invoke declarations), and may not be an option:

  • for programs written in languages from which calling the Windows API is not supported.

  • if you have a preexisting executable that you cannot modify.

In that event, option (c) (from PowerShell), discussed next, may work for you.



Re (c):

PowerShell automatically activates VT (virtual terminal) support for itself when it starts (in recent releases of Windows 10 this applies to both Windows PowerShell and PowerShell (Core) 7+) - but that does not extend to external programs called from Windows PowerShell. but does when called from PowerShell (Core) as of at least 7.2.

  • Separately, in v7.2+ there is the $PSStyle.OutputRendering preference variable, which controls whether PowerShell commands produce colored output via the formatting system, such as the colored headers of Get-ChildItem output. However, this setting has no effect on (direct) output from external programs. $PSStyle.OutputRendering defaults to Host, meaning that only formatted output that prints to the terminal (console) is colored. $PSStyle.OutputRendering = 'PlainText' disables coloring, and $PSStyle.OutputRendering = 'Ansi' makes it unconditional; see this answer for more information.

However, as a workaround for Windows PowerShell you can relay an external program's output via a PowerShell command, in which case VT sequences are recognized; using Out-Host is the simplest way to do that (Write-Host would work too):

.\test.exe | Out-Host

Note: Use Out-Host only if you mean to print to the console; if, by contrast, you want to capture the external program's output, use just $capturedOutput = .\test.exe

Alternatively, you can enclose the call in (...), which, however, invariably collects all output first, before relaying it.

(.\test.exe)

Character-encoding caveat: Windows PowerShell by default expects output from external programs to use the OEM code page, as defined by the legacy system locale (e.g., 437 on US-English systems) and as reflected in [console]::OutputEncoding.
.NET console programs respect that setting automatically, but for non-.NET programs (e.g., Python scripts) that use a different encoding (and produce not just pure ASCII output (in the 7-bit range)), you must (at least temporarily) specify that encoding by assigning to [console]::OutputEncoding; e.g., for UTF-8:

[console]::OutputEncoding = [Text.Encoding]::Utf8.

Note that this is not only necessary for the VT-sequences workaround, but generally necessary for PowerShell to interpret non-ASCII characters correctly.

PowerShell Core (v6+), unfortunately, as of v7.3, still defaults to the OEM code page too, but that should be considered a bug, given that it otherwise defaults to UTF-8 without BOM.

List of ANSI color escape sequences

The ANSI escape sequences you're looking for are the Select Graphic Rendition subset. All of these have the form

\033[XXXm

where XXX is a series of semicolon-separated parameters.

To say, make text red, bold, and underlined (we'll discuss many other options below) in C you might write:

printf("\033[31;1;4mHello\033[0m");

In C++ you'd use

std::cout<<"\033[31;1;4mHello\033[0m";

In Python3 you'd use

print("\033[31;1;4mHello\033[0m")

and in Bash you'd use

echo -e "\033[31;1;4mHello\033[0m"

where the first part makes the text red (31), bold (1), underlined (4) and the last part clears all this (0).

As described in the table below, there are a large number of text properties you can set, such as boldness, font, underlining, &c.

Font Effects




















































































































































































































CodeEffectNote
0Reset / Normalall attributes off
1Bold or increased intensity
2Faint (decreased intensity)Not widely supported.
3ItalicNot widely supported. Sometimes treated as inverse.
4Underline
5Slow Blinkless than 150 per minute
6Rapid BlinkMS-DOS ANSI.SYS; 150+ per minute; not widely supported
7[[reverse video]]swap foreground and background colors
8ConcealNot widely supported.
9Crossed-outCharacters legible, but marked for deletion. Not widely supported.
10Primary(default) font
11–19Alternate fontSelect alternate font n-10
20Frakturhardly ever supported
21Bold off or Double UnderlineBold off not widely supported; double underline hardly ever supported.
22Normal color or intensityNeither bold nor faint
23Not italic, not Fraktur
24Underline offNot singly or doubly underlined
25Blink off
27Inverse off
28Revealconceal off
29Not crossed out
30–37Set foreground colorSee color table below
38Set foreground colorNext arguments are 5;<n> or 2;<r>;<g>;<b>, see below
39Default foreground colorimplementation defined (according to standard)
40–47Set background colorSee color table below
48Set background colorNext arguments are 5;<n> or 2;<r>;<g>;<b>, see below
49Default background colorimplementation defined (according to standard)
51Framed
52Encircled
53Overlined
54Not framed or encircled
55Not overlined
60ideogram underlinehardly ever supported
61ideogram double underlinehardly ever supported
62ideogram overlinehardly ever supported
63ideogram double overlinehardly ever supported
64ideogram stress markinghardly ever supported
65ideogram attributes offreset the effects of all of 60-64
90–97Set bright foreground coloraixterm (not in standard)
100–107Set bright background coloraixterm (not in standard)

ANSI-Coloring Console Output with .NET

Your program needs to be compiled for /platform:x64 if you use the AnsiCon x64 environment and with /platform:x86 if you use the AnsiCon x86/32 bits version. The exact reason is a mystery...

Originally I thought you need all this:

You need to grab the StandardOutput and let the Console.WriteLine believe you write to a File instead of to a Console and use an ASCII encoding.

This is how it will work:

 var stdout = Console.OpenStandardOutput();
var con = new StreamWriter(stdout, Encoding.ASCII);
con.AutoFlush = true;
Console.SetOut(con);

Console.WriteLine("\x1b[36mTEST\x1b[0m");

The .Net Console.WriteLine uses an internal __ConsoleStream that checks if the Console.Out is as file handle or a console handle. By default it uses a console handle and therefor writes to the console by calling WriteConsoleW. In the remarks you find:

Although an application can use WriteConsole in ANSI mode to write ANSI characters, consoles do not support ANSI escape sequences. However, some functions provide equivalent functionality. For more information, see SetCursorPos, SetConsoleTextAttribute, and GetConsoleCursorInfo.

To write the bytes directly to the console without WriteConsoleW interfering a simple filehandle/stream will do which is achieved by calling OpenStandardOutput. By wrapping that stream in a StreamWriter so we can set it again with Console.SetOut we are done. The byte sequences are send to the OutputStream and picked up by AnsiCon.

Do notice that this is only useable with an applicable terminal emulator, like AnsiCon, as shown here:

Sample Image



Related Topics



Leave a reply



Submit