How to color System.out.println output? [duplicate]
Solution 1:
Note
You may not be able to color Window's cmd prompt
, but it should work in many unix (or unix-like) terminals.
Also, note that some terminals simply won't support some (if any) ANSI escape sequences and, especially, 24-bit colors.
Usage
Please refer to the section Curses at the bottom for the best solution. For a personal or easy solution (although not as cross-platform solution), refer to the ANSI Escape Sequences section.
TL;DR
java:
System.out.println((char)27 + "[31m" + "ERROR MESSAGE IN RED");
python:
print(chr(27) + "[31m" + "ERROR MESSAGE IN RED")
-
bash or zsh:
printf '\x1b[31mERROR MESSAGE IN RED'
- this may also work for Os X:
printf '\e[31mERROR MESSAGE IN RED'
- this may also work for Os X:
-
sh:
printf '
CTRL+V,CTRL+[[31mERROR MESSAGE IN RED'
- ie, press CTRL+V and then CTRL+[ in order to get a "raw" ESC character when escape interpretation is not available
- If done correctly, you should see a
^[
. Although it looks like two characters, it is really just one, the ESC character. - You can also press CTRL+V,CTRL+[ in vim in any of the programming or sripting langauges because that uses a literal ESC character
- Also, you can replace Ctrl+[ with ESC … eg, you can use CTRL+V,ESC, but I find the former easier, since I am already pressing CTRL and since [ is less out of the way.
ANSI Escape Sequences
Background on Escape Sequences
While it is not the best way to do it, the easiest way to do this in a programming or scripting language is to use escape sequences. From that link:
An escape sequence is a series of characters used to change the state of computers and their attached peripheral devices. These are also known as control sequences, reflecting their use in device control.
Backgound on ANSI Escape Sequences
However, it gets even easier than that in video text terminals, as these terminals use ANSI escape sequences. From that link:
ANSI escape sequences are a standard for in-band signaling to control the cursor location, color, and other options on video text terminals. Certain sequences of bytes, most starting with Esc and '[', are embedded into the text, which the terminal looks for and interprets as commands, not as character codes.
How to Use ANSI Escape Sequences
Generally
- Escape sequences begin with an escape character; for ANSI escape sequences, the sequence always begins with ESC (ASCII:
27
/ hex:0x1B
). - For a list of what you can do, refer to the ANSI Escape Sequence List on Wikipedia
In Programming Languages
Some programming langauges (like Java) will not interpret \e
or \x1b
as the ESC character. However, we know that the ASCII character 27
is the ESC character, so we can simply typecast 27
to a char
and use that to begin the escape sequence.
Here are some ways to do it in common programming languages:
-
Java
System.out.println((char)27 + "[33mYELLOW");
-
Python 3
print(chr(27) + "[34mBLUE");
-
print("\x1b[35mMAGENTA");
- Note that
\x1b
is interpretted correctly in python
- Note that
-
Node JS
- The following will NOT color output in JavaScript in the Web Console
console.log(String.fromCharCode(27) + "[36mCYAN");
-
console.log("\x1b[30;47mBLACK_ON_WHITE");
- Note that
\x1b
also works in node
- Note that
In Shell Prompt OR Scripts
If you are working with bash or zsh, it is quite easy to color the output (in most terminals). In Linux, Os X, and in some Window's terminals, you can check to see if your terminal supports color by doing both of the following:
printf '\e[31mRED'
printf '\x1b[31mRED'
If you see color for both, then that's great! If you see color for only one, then use that sequence. If you do not see color for either of them, then double check to make sure you typed everything correctly and that you are in bash or zsh; if you still do not see any color, then your terminal probably does not support ANSI escape sequences.
If I recall correctly, linux terminals tend to support both \e
and \x1b
escape sequences, while os x terminals only tend to support \e
, but I may be wrong. Nonetheless, if you see something like the following image, then you're all set! (Note that I am using the shell, zsh, and it is coloring my prompt string; also, I am using urxvt as my terminal in linux.)
"How does this work?" you might ask. Bascially, printf
is interpretting the sequence of characters that follows (everything inside of the single-quotes). When printf
encounters \e
or \x1b
, it will convert these characters to the ESC character (ASCII: 27). That's just what we want. Now, printf
sends ESC31m
, and since there is an ESC followed by a valid ANSI escape sequence, we should get colored output (so long as it is supported by the terminal).
You can also use echo -e '\e[32mGREEN'
(for example), to color output. Note that the -e
flag for echo
"[enables] interpretation of backslash escapes" and must be used if you want echo
to appropriately interpret the escape sequence.
More on ANSI Escape Sequences
ANSI escape sequences can do more than just color output, but let's start with that, and see exactly how color works; then, we will see how to manipulate the cursor; finally, we'll take a look and see how to use 8-bit color and also 24-bit color (although it only has tenuous support).
On Wikipedia, they refer to ESC[ as CSI
, so I will do the same.
Color
To color output using ANSI escapes, use the following:
-
CSI
n
m
-
CSI
: escape character—^[[
or ESC[ -
n
: a number—one of the following:-
30
-37
,39
: foreground -
40
-47
,49
: background
-
-
m
: a literal ASCIIm
—terminates the escape sequence
-
I will use bash or zsh to demonstrate all of the possible color combinations. Plop the following in bash or zsh to see for yourself (You may need to replace \e
with \x1b
):
for fg in {30..37} 39; do for bg in {40..47} 49; do printf "\e[${fg};${bg}m~TEST~"; done; printf "\n"; done;
Result:
Quick Reference (Color)
+~~~~~~+~~~~~~+~~~~~~~~~~~+
| fg | bg | color |
+~~~~~~+~~~~~~+~~~~~~~~~~~+
| 30 | 40 | black |
| 31 | 41 | red |
| 32 | 42 | green |
| 33 | 43 | yellow |
| 34 | 44 | blue |
| 35 | 45 | magenta |
| 36 | 46 | cyan |
| 37 | 47 | white |
| 39 | 49 | default |
+~~~~~~+~~~~~~+~~~~~~~~~~~+
Select Graphic Rendition (SGR)
SGR just allows you to change the text. Many of these do not work in certain terminals, so use these sparingly in production-level projects. However, they can be useful for making program output more readable or helping you distinguish between different types of output.
Color actually falls under SGR, so the syntax is the same:
-
CSI
n
m
-
CSI
: escape character—^[[
or ESC[ -
n
: a number—one of the following:-
0
: reset -
1
-9
: turns on various text effects -
21
-29
: turns off various text effects (less supported than1
-9
) -
30
-37
,39
: foreground color -
40
-47
,49
: background color -
38
: 8- or 24-bit foreground color (see 8/24-bit Color below) -
48
: 8- or 24-bit background color (see 8/24-bit Color below)
-
-
m
: a literal ASCIIm
—terminates the escape sequence
-
Although there is only tenuous support for faint (2), italic (3), underline (4), blinking (5,6), reverse video (7), conceal (8), and crossed out (9), some (but rarely all) tend to work on linux and os x terminals.
It's also worthwhile to note that you can separate any of the above attributes with a semi-colon. For example printf '\e[34;47;1;3mCRAZY TEXT\n'
will show CRAZY TEXT
with a blue foreground
on a white background
, and it will be bold
and italic
.
Eg:
Plop the following in your bash or zsh shell to see all of the text effects you can do. (You may need to replace \e
with \x1b
.)
for i in {1..9}; do printf "\e[${i}m~TEST~\e[0m "; done
Result:
You can see that my terminal supports all of the text effects except for faint (2), conceal (8) and cross out (9).
Quick Reference (SGR Attributes 0-9)
+~~~~~+~~~~~~~~~~~~~~~~~~+
| n | effect |
+~~~~~+~~~~~~~~~~~~~~~~~~+
| 0 | reset |
| 1 | bold |
| 2 | faint* |
| 3 | italic** |
| 4 | underline |
| 5 | slow blink |
| 6 | rapid blink* |
| 7 | inverse |
| 8 | conceal* |
| 9 | strikethrough* |
+~~~~~+~~~~~~~~~~~~~~~~~~+
* not widely supported
** not widely supported and sometimes treated as inverse
8-bit Color
While most terminals support this, it is less supported than 0-7
,9
colors.
Syntax:
-
CSI
38;5;
n
m
-
CSI
: escape character—^[[
or ESC[ -
38;5;
: literal string that denotes use of 8-bit colors for foreground -
n
: a number—one of the following:-
0
-255
-
-
If you want to preview all of the colors in your terminal in a nice way, I have a nice script on gist.github.com.
It looks like this:
If you want to change the background using 8-bit colors, just replace the 38
with a 48
:
-
CSI
48;5;
n
m
-
CSI
: escape character—^[[
or ESC[ -
48;5;
: literal string that denotes use of 8-bit colors for background -
n
: a number—one of the following:-
0
-255
-
-
24-bit Color
Also known as true color, 24-bit color provides some really cool functionality. Support for this is definitely growing (as far as I know it works in most modern terminals except urxvt, my terminal [insert angry emoji]).
24-bit color is actually supported in vim (see the vim wiki to see how to enable 24-bit colors). It's really neat because it pulls from the colorscheme defined for gvim; eg, it uses the fg/bg from highlight guibg=#______ guifg=#______
for the 24-bit colors! Neato, huh?
Here is how 24-bit color works:
-
CSI
38;2;
r
;
g
;
b
m
-
CSI
: escape character—^[[
or ESC[ -
38;2;
: literal string that denotes use of 24-bit colors for foreground -
r
,g
,b
: numbers—each should be0
-255
-
To test just a few of the many colors you can have ((2^8)^3
or 2^24
or 16777216
possibilites, I think), you can use this in bash or zsh:
for r in 0 127 255; do for g in 0 127 255; do for b in 0 127 255; do printf "\e[38;2;${r};${g};${b}m($r,$g,$b)\e[0m "; done; printf "\n"; done; done;
Result (this is in gnome-terminal since urxvt DOES NOT SUPPORT 24-bit color ... get it together, urxvt maintainer ... for real):
If you want 24-bit colors for the background ... you guessed it! You just replace 38
with 48
:
-
CSI
48;2;
r
;
g
;
b
m
-
CSI
: escape character—^[[
or ESC[ -
48;2;
: literal string that denotes use of 24-bit colors for background -
r
,g
,b
: numbers—each should be0
-255
-
Inserting Raw Escape Sequences
Sometimes \e
and \x1b
will not work. For example, in the sh shell, sometimes neither works (although it does on my system now, I don't think it used to).
To circumvent this, you can use CTRL+V,CTRL+[ or CTRLV,ESC
This will insert a "raw" ESC character (ASCII: 27). It will look like this ^[
, but do not fret; it is only one character—not two.
Eg:
Curses
Refer to the Curses (Programming Library) page for a full reference on curses. It should be noted that curses only works on unix and unix-like operating systems.
Up and Running with Curses
I won't go into too much detail, for search engines can reveal links to websites that can explain this much better than I can, but I'll discuss it briefly here and give an example.
Why Use Curses Over ANSI Escapes?
If you read the above text, you might recall that \e
or \x1b
will sometimes work with printf
. Well, sometimes \e
and \x1b
will not work at all (this is not standard and I have never worked with a terminal like this, but it is possible). More importantly, more complex escape sequences (think Home and other multi-character keys) are difficult to support for every terminal (unless you are willing to spend a lot of time and effort parsing terminfo and termcap and and figuring out how to handle every terminal).
Curses solves this problem. Basically, it is able to understand what capabilities a terminal has, using these methods (as described by the wikipedia article linked above):
Most implementations of curses use a database that can describe the capabilities of thousands of different terminals. There are a few implementations, such as PDCurses, which use specialized device drivers rather than a terminal database. Most implementations use terminfo; some use termcap. Curses has the advantage of back-portability to character-cell terminals and simplicity. For an application that does not require bit-mapped graphics or multiple fonts, an interface implementation using curses will usually be much simpler and faster than one using an X toolkit.
Most of the time, curses will poll terminfo and will then be able to understand how to manipulate the cursor and text attributes. Then, you, the programmer, use the API provided by curses to manipulate the cursor or change the text color or other attributes if the functionality you seek is desired.
Example with Python
I find python is really easy to use, but if you want to use curses in a different programming language, then simply search it on duckduckgo or any other search engine. :) Here is a quick example in python 3:
import curses
def main(stdscr):
# allow curses to use default foreground/background (39/49)
curses.use_default_colors()
# Clear screen
stdscr.clear()
curses.init_pair(1, curses.COLOR_RED, -1)
curses.init_pair(2, curses.COLOR_GREEN, -1)
stdscr.addstr("ERROR: I like tacos, but I don't have any.\n", curses.color_pair(1))
stdscr.addstr("SUCCESS: I found some tacos.\n", curses.color_pair(2))
stdscr.refresh() # make sure screen is refreshed
stdscr.getkey() # wait for user to press key
if __name__ == '__main__':
curses.wrapper(main)
result:
You might think to yourself that this is a much more round-about way of doing things, but it really is much more cross-platform (really cross-terminal … at least in the unix- and unix-like-platform world). For colors, it is not quite as important, but when it comes to supporting other multi-sequence escape sequences (such as Home, End, Page Up, Page Down, etc), then curses becomes all the more important.
Example with Tput
-
tput
is a command line utility for manipulating cursor and text -
tput
comes with thecurses
package. If you want to use cross-terminal (ish) applications in the terminal, you should use tput, as it parses terminfo or whatever it needs to and uses a set of standardized commands (like curses) and returns the correct escape sequence. - example:
echo "$(tput setaf 1)$(tput bold)ERROR:$(tput sgr0)$(tput setaf 1) My tacos have gone missing"
echo "$(tput setaf 2)$(tput bold)SUCCESS:$(tput sgr0)$(tput setaf 2) Oh good\! I found my tacos\!"
Result:
More Info on Tput
- see: http://linuxcommand.org/lc3_adv_tput.php to see how tput works
- see: http://invisible-island.net/ncurses/man/terminfo.5.html for a list of commands that you can use
Solution 2:
This has worked for me:
System.out.println((char)27 + "[31mThis text would show up red" + (char)27 + "[0m");
You need the ending "[37m" to return the color to white (or whatever you were using). If you don't it may make everything that follows "red".