Color and TTYs

Most people are used to being able to send certain color/formatting codes to a terminal. For instance, most terminal emulators support the ANSI color escape codes. In fact, xterm goes beyond this and has supported 256 color output for about ten years now and most other terminal emulators also support this extension.

The reality is that assuming that a terminal supports ANSI color codes is a bad idea for a bunch of reasons.

The most important reason is that the file descriptor you’re printing to might not be a TTY. This commonly happens when stdout is redirected to another program or a file. If you emit ANSI escape codes then the output is no longer “plain text” and it makes a bunch of common operations more difficult. It can break programs like grep if the search term spans escape codes. It also causes weird things to happen when you use programs like less (which will escape the escape codes by default).

Even if the file descriptor you’re printing to is a TTY, not all TTYs support ANSI escape codes. For instance, you could be sitting at an actual 1960s teletype machine that doesn’t support color output. Or you could be on an ancient terminal that does support color output, but doesn’t use the ANSI escape codes.

If you do want to print color at a minimum you should use isatty(3) to check if the file descriptor (typically stdout or stderr) is a TTY. Most other languages have native bindings to this; for instance, in Python you can use os.isatty and in bash you can use test -t. If you do this you’re not actually guaranteed that the terminal supports ANSI escape codes, but most modern terminals (or more likely, terminal emulators) do support them so it’s a fairly safe assumption. If you want to be really pedantic you should actually make a best effort to check the output capabilities of the TTY device; you can do this with termcap/terminfo, which typically would be done for you by a higher level library like ncurses.

tl;dr If you’re going to send ANSI color escape codes to stdout, at the very minimum please check that this is reasonable with isatty first.