Как стать автором
Обновить
244.05
FirstVDS
Виртуальные серверы в ДЦ в Москве

Как изменить цвет текста в терминале Linux

Время на прочтение10 мин
Количество просмотров37K
Автор оригинала: Chris Maunder
Небольшое руководство и простой bash скрипт, чтобы сделать вывод вашего кода немного более ярким и красочным

Обычно вывод текста в терминале пользователя выглядит слишком монохромно. Однако добавить больше красок — совсем несложно. В данном скрипте я предлагаю вспомогательные методы для вывода текста, использования заданных цветов и работы с окнами терминала в тёмном и светлом режимах.

⬇️ Скачать color.zip — 2.7 KB (прим. редактора — потребуется регистрация на сайте)

Введение


Текст, выводимый в терминале по умолчанию, является одноцветным и не предоставляет простого способа указать на контекст. Например, вы можете захотеть, чтобы ошибка отображалась красным цветом, успех — зелёным, или чтобы важная информация была выделена жирным шрифтом.

Добавление цвета к выводу текста в терминале — простая задача, которая заключается в выводе правильных управляющих символов перед вашим текстом.

Цвета в терминале


Чтобы вывести цветной текст, вам следует выполнить printf или echo -e управляющих символов для требуемого цвета (-e обеспечивает интерпретацию управляющих символов), далее вывести ваш текст, а затем (просто для аккуратности) сбросить вывод обратно к значениям по умолчанию. В таблице ниже приведены коды:
Цвет Основной Фон
Стандартный \033[39m \033[49m
Чёрный \033[30m \033[40m
Тёмно-красный \033[31m \033[41m
Тёмно-зелёный \033[32m \033[42m
Тёмно-жёлтый «Оранжевый» \033[33m \033[43m
Тёмно-синий \033[34m \033[44m
Темно-пурпурный \033[35m \033[45m
Тёмно-голубой \033[36m \033[46m
Светло-серый \033[37m \033[47m
Тёмно-серый \033[90m \033[100m
Красный \033[91m \033[101m
Зелёный \033[92m \033[101m
Оранжевый \033[93m \033[103m
Синий \033[94m \033[104m
Пурпурный \033[95m \033[105m
Голубой \033[96m \033[106m
Белый \033[97m \033[107m
и код сброса \033[0m

Формат строки для основного цвета:

"\033[" + "<0 or 1, meaning normal or bold>;" + "<color code> + "m"

И для фона:

"\033[" + "<color code>" + "m"

Эти коды могут быть использованы вместе для одновременного изменения основного цвета и фона.

Применяем код


Простой пример красного текста:

printf "\033[91mThis is red text\033[0m"

Пример красного текста на белом фоне:

printf "\033[91m\033[107mThis is red text on a white background\033[0m"

Это выглядит довольно громоздко, так что я создал несколько простых подпрограмм, которые позволят задать цвет текста более изящным способом.

Вспомогательные функции


Следующие вспомогательные функции позволяют вам делать такие вещи, как:

WriteLine "This is red text" "Red"
WriteLine "This is red text on a white background" "Red" "White"

… намного проще.

useColor="true" # Установите значение на false, если вы обнаружите, что ваша среда плохо обрабатывает цвета.

# Возвращает код цвета для заданных цветов переднего/заднего плана
# Этот код передаётся эхом в терминал перед выводом текста
# для создания цветного вывода.
#
# строка foreground (основной цвет) имя_цвета. Необязательна, если не задан фон.
#        По умолчанию "Default", который использует системный цвет по умолчанию
# строка background (фон) имя_цвета. Необязательна. По умолчанию используется $color_background
#        который устанавливается на основе текущего фона терминала.
# возвращает строку
function Color () {

    local foreground=$1
    local background=$2

    if [ "$foreground" == "" ];  then foreground="Default"; fi
    if [ "$background" == "" ]; then background="$color_background"; fi

    local colorString='\033['

    # Основные цвета
    case "$foreground" in
        "Default")      colorString='\033[0;39m';;
        "Black" )       colorString='\033[0;30m';;
        "DarkRed" )     colorString='\033[0;31m';;
        "DarkGreen" )   colorString='\033[0;32m';;
        "DarkYellow" )  colorString='\033[0;33m';;
        "DarkBlue" )    colorString='\033[0;34m';;
        "DarkMagenta" ) colorString='\033[0;35m';;
        "DarkCyan" )    colorString='\033[0;36m';;
        "Gray" )        colorString='\033[0;37m';;
        "DarkGray" )    colorString='\033[1;90m';;
        "Red" )         colorString='\033[1;91m';;
        "Green" )       colorString='\033[1;92m';;
        "Yellow" )      colorString='\033[1;93m';;
        "Blue" )        colorString='\033[1;94m';;
        "Magenta" )     colorString='\033[1;95m';;
        "Cyan" )        colorString='\033[1;96m';;
        "White" )       colorString='\033[1;97m';;
        *)              colorString='\033[0;39m';;
    esac

    # Цвета фона
    case "$background" in
        "Default" )     colorString="${colorString}\033[49m";;
        "Black" )       colorString="${colorString}\033[40m";;
        "DarkRed" )     colorString="${colorString}\033[41m";;
        "DarkGreen" )   colorString="${colorString}\033[42m";;
        "DarkYellow" )  colorString="${colorString}\033[43m";;
        "DarkBlue" )    colorString="${colorString}\033[44m";;
        "DarkMagenta" ) colorString="${colorString}\033[45m";;
        "DarkCyan" )    colorString="${colorString}\033[46m";;
        "Gray" )        colorString="${colorString}\033[47m";;
        "DarkGray" )    colorString="${colorString}\033[100m";;
        "Red" )         colorString="${colorString}\033[101m";;
        "Green" )       colorString="${colorString}\033[102m";;
        "Yellow" )      colorString="${colorString}\033[103m";;
        "Blue" )        colorString="${colorString}\033[104m";;
        "Magenta" )     colorString="${colorString}\033[105m";;
        "Cyan" )        colorString="${colorString}\033[106m";;
        "White" )       colorString="${colorString}\033[107m";;
        *)              colorString="${colorString}\033[49m";;
    esac

    echo "${colorString}"
}


# Выводит строку (включая перевод на строку) на терминал, используя заданные основной или фоновый 
# цвета
#
# строка The text to output (Текст для вывода). Необязательна, если не задан основной цвет. По умолчанию выводится только перевод на строку.
# строка Foreground color name (Имя основного цвета). Необязательна, если не указан фон. По умолчанию "Default", который
#        использует системное значение по умолчанию
# строка Background color name (Имя фонового цвета). Необязательна. По умолчанию используется $color_background, который устанавливается на основе
#        текущего фона терминала
function WriteLine () {

    local resetColor='\033[0m'

    local str=$1
    local forecolor=$2
    local backcolor=$3

    if [ "$str" == "" ]; then
        printf "\n"
        return;
    fi

    # Обратите внимание на использование форматного заполнителя %s. Это позволяет нам передавать "--" в качестве строк без ошибок
    if [ "$useColor" == "true" ]; then
        local colorString=$(Color ${forecolor} ${backcolor})
        printf "${colorString}%s${resetColor}\n" "${str}"
    else
        printf "%s\n" "${str}"
    fi
}

# Выводит строку без перевода на строку в терминал, используя заданные основные / фоновые цвета
#
# строка The text to output (Текст для вывода). Необязательна, если не задан основной цвет. По умолчанию выводится только перевод на строку.
# строка Foreground color name (Имя основного цвета). Необязательна, если не указан фон. По умолчанию "Default", который
#        использует системное значение по умолчанию
# строка Background color name (Имя фонового цвета). Необязательна. По умолчанию используется $color_background, который устанавливается на основе
#        текущего фона терминала
function Write () {
    local resetColor="\033[0m"

    local forecolor=$1
    local backcolor=$2
    local str=$3

    if [ "$str" == "" ];  then
        return;
    fi

    # Обратите внимание на использование форматного заполнителя %s. Это позволяет нам передавать "--" в качестве строк без ошибок
    if [ "$useColor" == "true" ]; then
        local colorString=$(Color ${forecolor} ${backcolor})
        printf "${colorString}%s${resetColor}" "${str}"
    else
        printf "%s" "$str"
    fi
}

Работа с тёмным и светлым режимами


Во многих дистрибутивах Linux и Unix терминал имеет чёрный фон и белый текст. В macOS по умолчанию используется белый фон с чёрным текстом. Конечно, есть способы и средства для смены тёмного/светлого режима, но вам придется проверять и тестировать всё на собственной системе, чтобы найти то, что подходит именно вам.

Я предполагаю, что если мы используем mac, то можем всё протестировать напрямую, в противном случае — мы предполагаем черный фон и белый текст. Я также стараюсь придерживаться цветов по умолчанию, а там, где мне нужно немного цвета, я предпочитаю использование некоторых предопределённых цветов, которые, по моим представлениям, будут хорошо работать везде.

# Получает цвет фона терминала. Это очень наивная догадка
# возвращает триплет RGB, значения от 0 до 64K
function getBackground () {

    if [[ $OSTYPE == 'darwin'* ]]; then
        osascript -e \
        'tell application "Terminal"
            get background color of selected tab of window 1
        end tell'
    else

        # См. https://github.com/rocky/shell-term-background/blob/master/term-background.bash
        # для получения исчерпывающей информации о том, как проверить цвет фона. Сейчас мы просто
        # предположим, что терминалы, не использующие macOS, имеют чёрный фон.

        echo "0,0,0" # здесь мы делаем предположения
    fi
}

# Определяет, находится ли текущий терминал в тёмном режиме (тёмный фон, светлый текст).
# возвращает "true", если работает в тёмном режиме; false в противном случае
function isDarkMode () {

    local bgColor=$(getBackground)
    
    IFS=','; colors=($bgColor); IFS=' ';

    # Фон более или менее тёмный?
    if [ ${colors[0]} -lt 20000 ] && [ ${colors[1]} -lt 20000 ] && [ ${colors[2]} -lt 20000 ]; then
        echo "true"
    else
        echo "false"
    fi
}

Как только мы получим приблизительное представление о том, с чем имеем дело, я выполню код ниже:

darkmode=$(isDarkMode)

# Установим некоторые предопределённые цвета. Обратите внимание, что мы не можем достоверно определить фон
# цвет терминала, поэтому мы избегаем специально устанавливать чёрный или белый цвет в качестве основного цвета
# или фона. Вы всегда можете просто использовать "Белый" и "Чёрный", если вам действительно нужно
# это сочетание, но предварительно тщательно протестируйте
if [ "$darkmode" == "true" ]; then
    color_primary="Blue"
    color_mute="Gray"
    color_info="Yellow"
    color_success="Green"
    color_warn="DarkYellow"
    color_error="Red"
else
    color_primary="DarkBlue"
    color_mute="Gray"
    color_info="Magenta"
    color_success="DarkGreen"
    color_warn="DarkYellow"
    color_error="Red"
fi

и также воспользуюсь этими строками:

WriteLine "Predefined colors on default background"
WriteLine

WriteLine "Default colored text" "Default"
WriteLine "Primary colored text" $color_primary
WriteLine "Mute colored text"    $color_mute
WriteLine "Info colored text"    $color_info
WriteLine "Success colored text" $color_success
WriteLine "Warning colored text" $color_warn
WriteLine "Error colored text"   $color_error

WriteLine
WriteLine "Default color on predefined background"
WriteLine

WriteLine "Default colored background" "Default"
WriteLine "Primary colored background" "Default" $color_primary
WriteLine "Mute colored background"    "Default" $color_mute
WriteLine "Info colored background"    "Default" $color_info
WriteLine "Success colored background" "Default" $color_success
WriteLine "Warning colored background" "Default" $color_warn
WriteLine "Error colored background"   "Default" $color_error

Получаем примерно такую картину в классическом терминале Linux:


И такую в macOS:


Всё немного запутано, поэтому давайте добавим ещё одну функцию, которая обеспечит контрастный передний план на любом выбранном нами фоне:

# Возвращает имя цвета, который будет служить в качестве основного контрастного
# цвета для заданного цвета фона. Эта функция предполагает, что $darkmode был
# установлен глобально.
#
# строка background color name (имя фонового цвета).
# возвращает строку, представляющую имя основного контрастного цвета
function ContrastForeground () {

    local color=$1
    if [ "$color" == "" ]; then color="Default"; fi

    if [ "$darkmode" == "true" ]; then
        case "$color" in
            "Default" )     echo "White";;
            "Black" )       echo "White";;
            "DarkRed" )     echo "White";;
            "DarkGreen" )   echo "White";;
            "DarkYellow" )  echo "White";;
            "DarkBlue" )    echo "White";;
            "DarkMagenta" ) echo "White";;
            "DarkCyan" )    echo "White";;
            "Gray" )        echo "Black";;
            "DarkGray" )    echo "White";;
            "Red" )         echo "White";;
            "Green" )       echo "White";;
            "Yellow" )      echo "Black";;
            "Blue" )        echo "White";;
            "Magenta" )     echo "White";;
            "Cyan" )        echo "Black";;
            "White" )       echo "Black";;
            *)              echo "White";;
        esac
    else
        case "$color" in
            "Default" )     echo "Black";;
            "Black" )       echo "White";;
            "DarkRed" )     echo "White";;
            "DarkGreen" )   echo "White";;
            "DarkYellow" )  echo "White";;
            "DarkBlue" )    echo "White";;
            "DarkMagenta" ) echo "White";;
            "DarkCyan" )    echo "White";;
            "Gray" )        echo "Black";;
            "DarkGray" )    echo "White";;
            "Red" )         echo "White";;
            "Green" )       echo "Black";;
            "Yellow" )      echo "Black";;
            "Blue" )        echo "White";;
            "Magenta" )     echo "White";;
            "Cyan" )        echo "Black";;
            "White" )       echo "Black";;
            *)              echo "White";;
        esac
    fi
    
    echo "${colorString}"
}

Затем, в подпрограмме Color, мы можем сделать следующее:

function Color () {

    local foreground=$1
    local background=$2

    if [ "$foreground" == "" ]; then foreground="Default"; fi
    if [ "$background" == "" ]; then background="$color_background"; fi

    if [ "$foreground" == "Contrast" ]; then
        foreground=$(ContrastForeground ${background})
    fi
    
    ...

… и чтобы сделать наш текст с изменённым цветом фона немного более разборчивым, мы используем следующие строки:

WriteLine
WriteLine "Default contrasting color on predefined background"
WriteLine

WriteLine "Primary colored background" "Contrast" $color_primary
WriteLine "Mute colored background"    "Contrast" $color_mute
WriteLine "Info colored background"    "Contrast" $color_info
WriteLine "Success colored background" "Contrast" $color_success
WriteLine "Warning colored background" "Contrast" $color_warn
WriteLine "Error colored background"   "Contrast" $color_error

Полученный результат в терминале Linux


… и в терминале macOS




НЛО прилетело и оставило здесь промокод для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
Теги:
Хабы:
Всего голосов 13: ↑10 и ↓3+7
Комментарии7

Публикации

Информация

Сайт
firstvds.ru
Дата регистрации
Дата основания
Численность
51–100 человек
Местоположение
Россия
Представитель
FirstJohn