Programmatically detect the ANSI escape code supported by terminal

ansi-termescape-charactersterminal

I am playing around with shell scripts that use ANSI codes and found that for one reason or another different escape codes are supported depending on your terminal/OS.

In some cases I get a dump of unparsed gunk unexpectedly, which I'm assuming means my terminal (on Mac OS) doesn't support that escape code used, despite having read in a number of places that these mean the same thing:

27 = 033 = 0x1b = ^[ = \e

In searching I found this question about detecting slash-escaped support.

The selected answer sniffs the $TERM value to detect

case $TERM in
  (|color(|?))(([Ekx]|dt|(ai|n)x)term|rxvt|screen*)*)
    PS1=$'\e\]0;$GENERATED_WINDOW_TITLE\a'"$PS1"
esac

But I wonder how reliable that is.

Is there a standard way to check for escape code support (primarily for Bash), or is that script pretty much the run of the mill?

  • Alternatively, what escape code can I use to 'guarantee' the most
    wide-spread support?
  • What about echo expansion -e?
  • What are general best practices in terms of portability/availability/distribution for scripts that use or reference control codes?

This is a nice read too for anyone else looking for info.

Best Answer

Have you got specific operations in mind?

Here is an example of using standout mode, which on many terminals will give a strong visible result:

tput smso; echo hello, world; tput rmso

The tput tool uses the value of the $TERM environment variable to determine which escape sequences to output - if any. For example

TERM=xterm
( tput smso; echo hello, world; tput rmso ) | hexdump -C
00000000  1b 5b 37 6d 68 65 6c 6c  6f 2c 20 77 6f 72 6c 64  |.[7mhello, world|
00000010  0a 1b 5b 32 37 6d                                 |..[27m|

TERM=dumb
( tput smso; echo hello, world; tput rmso ) | hexdump -C
00000000  68 65 6c 6c 6f 2c 20 77  6f 72 6c 64 0a           |hello, world.|

Interesting characteristic pairs can be found in man 5 terminfo, some of which are as follows:

  • Standout: smso and rmso
  • Underline: smul and rmul
  • Blink (yes!): blink
  • Doublewide: swidm and rwidm
  • Reverse: rev
  • Cancel all: sgr0

If you want to write bold text, but only if the terminal understands it, then a snippet like this will work

boldOn=$(tput smso)
boldOff=$(tput rmso)
# ...
printf "%s%s%s\n" "$boldOn" 'This message will be in bold, when available' "$boldOff"