9

In people's '.*rc' files I see online or in various code, I tend to see a lot of people who manually use ANSI escape sequences instead of using tput.

I had the understanding that tput is more universal/safe, so this makes me wonder:

Is there any objective reason one should use escape sequences in place of tput? (Portability, robustness on errors, unusual terminals...?)

  • On the flip side of the portability question, MobaXterm will work with printf and ANSI escape sequences, but tput fails (at least on my box). – Wildcard May 21 '16 at 0:33
6

tput can handle expressions (for instance in sgr and setaf) which the typical shell-scripter would find less than usable. To get an idea of what is involved, see the output from infocmp with the -f (formatting) option applied. Here is one of examples using those strings from xterm's terminfo descriptions:

xterm-16color|xterm with 16 colors,
        colors#16,
        pairs#256,
        setab=\E[
                %?
                        %p1%{8}%<
                        %t%p1%{40}%+
                %e
                        %p1%{92}%+
                %;%dm,
        setaf=\E[
                %?
                        %p1%{8}%<
                        %t%p1%{30}%+
                %e
                        %p1%{82}%+
                %;%dm,
        setb=
                %p1%{8}%/%{6}%*%{4}%+\E[%d%p1%{8}%m%Pa
                %?%ga%{1}%=
                        %t4
                %e%ga%{3}%=
                        %t6
                %e%ga%{4}%=
                        %t1
                %e%ga%{6}%=
                        %t3
                %e%ga%d
                %;
                m,
        setf=
                %p1%{8}%/%{6}%*%{3}%+\E[%d%p1%{8}%m%Pa
                %?%ga%{1}%=
                        %t4
                %e%ga%{3}%=
                        %t6
                %e%ga%{4}%=
                        %t1
                %e%ga%{6}%=
                        %t3
                %e%ga%d
                %;
                m,
        use=xterm+256color,
        use=xterm-new,

The formatting splits things up - a script or program to do the same would have to follow those twists and turns. Most people give up and just use the easiest strings.

The 16-color feature is borrowed from IBM aixterm, which maps 16 codes each for foreground and background onto two ranges;

  • foreground onto 30-37, and 90-97
  • background onto 40-47, and 100-107

A simple script

#!/bin/sh
TERM=xterm-16color
export TERM
printf '    %12s %12s\n' Foreground Background
for n in $(seq 0 15)
do
    F=$(tput setaf $n | cat -v)
    B=$(tput setab $n | cat -v)
    printf '%2d  %12s %12s\n' $n "$F" "$B"
done

and output show how it works:

      Foreground   Background
 0        ^[[30m       ^[[40m
 1        ^[[31m       ^[[41m
 2        ^[[32m       ^[[42m
 3        ^[[33m       ^[[43m
 4        ^[[34m       ^[[44m
 5        ^[[35m       ^[[45m
 6        ^[[36m       ^[[46m
 7        ^[[37m       ^[[47m
 8        ^[[90m      ^[[100m
 9        ^[[91m      ^[[101m
10        ^[[92m      ^[[102m
11        ^[[93m      ^[[103m
12        ^[[94m      ^[[104m
13        ^[[95m      ^[[105m
14        ^[[96m      ^[[106m
15        ^[[97m      ^[[107m

The numbers are split up because aixterm uses the 30-37 and 40-47 ranges to match ECMA-48 (also known as "ANSI") colors, and uses the 90-107 range for codes not defined in the standard.

Here is a screenshot with xterm using TERM=xterm-16color, where you can see the effect.

enter image description here

Further reading:

  • I may be proving your point, but what is the deal with these expressions? From looking at the manual for infocmp I realize they are if-then-else statements... but I've never seen this and I'm having trouble googling for it, this is all I found, but I'm not sure it's what is happening here. Thanks! – Captain Man Apr 6 '16 at 13:11
2

Coming from a time when UNIX platforms could have a variety of devices attached to them, I still much prefer tput and its friends over literal escape sequences.

I think the real reason is that most people simply don't know about tput and its associated terminfo/termcap files and libraries.

2

One of the reason is that tput is the external command, so may run slower than built-in shell escape codes. Another thing is that one can easily create one liners combining ANSI escape codes with shell specific escaped characters, such as in bash prompt for example:

PS1='\[\033[1;32m\]\u@\h\[\033[1;34m\] \w >\[\033[0m\] '

similarly in zsh:

PS1=$'%{\e[1;32m%}%n@%m%{\e[1;34m%} %3~> %{\e[0m%}'

Here everything is clear and compact. With tput one would need to split it to multiple lines or make it much longer and complex line, executing tput multiple times, etc.

  • 1
    With tput you can still do oneliners, PS1="$(tput setaf 2)\u@\h$(tput reset) > – Captain Man Apr 5 '16 at 19:48
  • 2
    Actually that would be $(tput sgr0) for the ending, but agreeing that tput is an improvement. – Thomas Dickey Apr 5 '16 at 22:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.