2
\$\begingroup\$

My goal with the below piece of POSIX shell code was to address the more platforms the better with shell tput colors. With this code, I now start all of my scripts, and so it's time to review it for some things I overlooked, did not think of too well, and such. Note: I start my scripts with set -u, which is why I set all empty in unspecified cases. Thanks.


#!/bin/sh

set -u

if tput setaf > /dev/null 2>&1; then
    # Linux-like
    tput_number_of_colors=$(tput colors 2> /dev/null)
    tput_bold=$(tput bold 2> /dev/null)
    tput_reset=$(tput sgr0 2> /dev/null)
    tput_cmd_set_fg_color='tput setaf'
elif tput AF > /dev/null 2>&1; then
    # BSD-like
    tput_number_of_colors=$(tput Co 2> /dev/null)
    tput_bold=$(tput md 2> /dev/null)
    tput_reset=$(tput me 2> /dev/null)
    tput_cmd_set_fg_color='tput AF'
else
    # Console-like
    tput_number_of_colors=2
    tput_cmd_set_fg_color=
    tput_bold=
    tput_reset=
fi

tput_test ()
{
    [ -n "$tput_number_of_colors" ] && [ -n "$tput_bold" ] && [ -n "$tput_reset" ] &&
    { [ "$tput_number_of_colors" -ge 8 ] && printf '%s' "$tput_bold" && $tput_cmd_set_fg_color 1; } > /dev/null 2>&1
}

if tput_test; then
    color_red=$tput_bold$($tput_cmd_set_fg_color 1)
    color_green=$tput_bold$($tput_cmd_set_fg_color 2)
    color_yellow=$tput_bold$($tput_cmd_set_fg_color 3)
    color_blue=$tput_bold$($tput_cmd_set_fg_color 4)
    color_magenta=$tput_bold$($tput_cmd_set_fg_color 5)
    color_cyan=$tput_bold$($tput_cmd_set_fg_color 6)
    color_white=$tput_bold$($tput_cmd_set_fg_color 7)
else
    color_red=; color_green=; color_yellow=; color_blue=; color_magenta=; color_cyan=; color_white=
fi
\$\endgroup\$
1
\$\begingroup\$

Self-review

Since no one replied thus far, I decided to re-think and re-write the code myself this morning.


terminfo (*nix) vs termcap (*bsd)

I never really thought about how important to make note of this actually is. For searching info online, one needs to know these keywords. So, I added them as comments.

Structure into functions

I believe this code should be structured into suitable functions where available.

Find a way for an exit code from those functions

It's needed to simply chain (&&) the commands like tput_bold=$(tput bold 2> /dev/null) && tput_reset=$(tput sgr0 2> /dev/null) in order for the imagined functions to return a reliable exit code.

The most basic test missing

command -v tput was missing in my code, which is remedied now.

No unset variables

Since I use set -u in my scripts, it's necessary to set variables empty in case of failure. This feature has been enhanced.


Modified code

#!/bin/sh

set -u

tput_setup_nix ()
{
    # terminfo
    tput_cmd_set_fg_color='tput setaf'
    tput_number_of_colors=$(tput colors 2> /dev/null) &&
    tput_bold=$(tput bold 2> /dev/null) &&
    tput_reset=$(tput sgr0 2> /dev/null)
}

tput_setup_bsd ()
{
    # termcap
    tput_cmd_set_fg_color='tput AF'
    tput_number_of_colors=$(tput Co 2> /dev/null) &&
    tput_bold=$(tput md 2> /dev/null) &&
    tput_reset=$(tput me 2> /dev/null)
}

tput_setup_none ()
{
    # no unset variables
    tput_cmd_set_fg_color=
    tput_number_of_colors=
    tput_bold=
    tput_reset=
}

if command -v tput > /dev/null 2>&1; then

    if tput setaf > /dev/null 2>&1; then

        if ! tput_setup_nix; then tput_setup_none; fi

    elif tput AF > /dev/null 2>&1; then

        if ! tput_setup_bsd; then tput_setup_none; fi

    else
        tput_setup_none
    fi

else
    tput_setup_none
fi

tput_capability_test ()
{
    [ -n "$tput_cmd_set_fg_color" ] && [ -n "$tput_number_of_colors" ] && [ -n "$tput_bold" ] && [ -n "$tput_reset" ] &&
    [ "$tput_number_of_colors" -ge 8 ] && { $tput_cmd_set_fg_color 1 && printf '%s' "$tput_bold$tput_reset"; } > /dev/null 2>&1

}

if tput_capability_test; then
    color_red=$tput_bold$($tput_cmd_set_fg_color 1)
    color_green=$tput_bold$($tput_cmd_set_fg_color 2)
    color_yellow=$tput_bold$($tput_cmd_set_fg_color 3)
    color_blue=$tput_bold$($tput_cmd_set_fg_color 4)
    color_magenta=$tput_bold$($tput_cmd_set_fg_color 5)
    color_cyan=$tput_bold$($tput_cmd_set_fg_color 6)
    color_white=$tput_bold$($tput_cmd_set_fg_color 7)
else
    color_red=
    color_green=
    color_yellow=
    color_blue=
    color_magenta=
    color_cyan=
    color_white=
fi
\$\endgroup\$

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.