How to color System.out.println output?

Davide Aversa picture Davide Aversa · Sep 19, 2009 · Viewed 220.8k times · Source

How can I color Java output?

For example in C and other languages I can use ANSI-escape like \033[0m to do this. But in Java it doesn't work.

public static void main(String[] x) {
    System.out.println("\033[0m BLABLA \033[0m\n");
}

Answer

dylnmc picture dylnmc · Jun 25, 2014

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'
  • 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
  • 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

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.)

ANSI Escape Sequences Coloring Text Red

"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 ASCII m—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:

various foreground/background colors using ANSI escapes

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 than 1-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 ASCII m—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:

string attributes together example screenshot

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:

SGR state 1 SGR state 2

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:

8-bit color example screenshot

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 be 0-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):

24-bit color example screenshot

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 be 0-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:

sh raw escape char example screenshot


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:

enter image description here

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 the curses 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:

example with tput

More Info on Tput