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 theVirtualTerminalLevel
DWORD value to1
- 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
- From PowerShell, you can do this programmatically as follows:
- Open a new console window for changes to take effect.
- See caveats below.
- In short: In registry key
(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]
, theVirtualTerminalLevel
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 theProperties
GUI dialog, as of this writing theVirtualTerminalLevel
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 ofGet-ChildItem
output. However, this setting has no effect on (direct) output from external programs.$PSStyle.OutputRendering
defaults toHost
, 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
Code | Effect | Note |
---|---|---|
0 | Reset / Normal | all attributes off |
1 | Bold or increased intensity | |
2 | Faint (decreased intensity) | Not widely supported. |
3 | Italic | Not widely supported. Sometimes treated as inverse. |
4 | Underline | |
5 | Slow Blink | less than 150 per minute |
6 | Rapid Blink | MS-DOS ANSI.SYS; 150+ per minute; not widely supported |
7 | [[reverse video]] | swap foreground and background colors |
8 | Conceal | Not widely supported. |
9 | Crossed-out | Characters legible, but marked for deletion. Not widely supported. |
10 | Primary(default) font | |
11–19 | Alternate font | Select alternate font n-10 |
20 | Fraktur | hardly ever supported |
21 | Bold off or Double Underline | Bold off not widely supported; double underline hardly ever supported. |
22 | Normal color or intensity | Neither bold nor faint |
23 | Not italic, not Fraktur | |
24 | Underline off | Not singly or doubly underlined |
25 | Blink off | |
27 | Inverse off | |
28 | Reveal | conceal off |
29 | Not crossed out | |
30–37 | Set foreground color | See color table below |
38 | Set foreground color | Next arguments are 5;<n> or 2;<r>;<g>;<b> , see below |
39 | Default foreground color | implementation defined (according to standard) |
40–47 | Set background color | See color table below |
48 | Set background color | Next arguments are 5;<n> or 2;<r>;<g>;<b> , see below |
49 | Default background color | implementation defined (according to standard) |
51 | Framed | |
52 | Encircled | |
53 | Overlined | |
54 | Not framed or encircled | |
55 | Not overlined | |
60 | ideogram underline | hardly ever supported |
61 | ideogram double underline | hardly ever supported |
62 | ideogram overline | hardly ever supported |
63 | ideogram double overline | hardly ever supported |
64 | ideogram stress marking | hardly ever supported |
65 | ideogram attributes off | reset the effects of all of 60-64 |
90–97 | Set bright foreground color | aixterm (not in standard) |
100–107 | Set bright background color | aixterm (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:
Related Topics
How to Write an Agile Pimpl in C++
How to Print Boost::Any to a Stream
Why Do I See 400X Outlier Timings When Calling Clock_Gettime Repeatedly
If Constexpr - Why Is Discarded Statement Fully Checked
Purpose of Struct, Typedef Struct, in C++
Why Do I Need to Include Both the iOStream and Fstream Headers to Open a File
What Is the Size of Float and Double in C and C++
Accessing Parent's Protected Variables
Calling Delete on Null Pointers - C++03 VS C++11
Why Does C++ Allow Private Members to Be Modified Using This Approach
Why Is a C++ Bool Var True by Default
Bitwise Operations on Vector<Bool>
Convert Shared Library to Static Library
Eclipse Mingw C++ Cannot Find -Lpthread
How to Set Error_Code to Asio::Yield_Context
How to Implement "_Mm_Storeu_Epi64" Without Aliasing Problems