таблица цветов tput setaf? Как определить цветовые коды?

79

Я нахожусь в процессе окраски моего терминала PS1.

Я устанавливаю переменные цвета, используя tput; например, вот фиолетовый:

PURPLE=$(tput setaf 125)

Вопрос:

Как мне найти цветовые коды (например 125) других цветов?

Есть ли где-нибудь руководство по таблице цветов / шпаргалка?

Я просто не уверен, что 125... Есть ли способ взять шестнадцатеричный цвет и преобразовать его в число, которое setafможно использовать?

mhulse
источник

Ответы:

153

Количество цветов, доступных для tput, определяется как tput colors.

Чтобы увидеть 8 основных цветов (используемых setfтерминалом urxvt и терминалом setafxterm):

$ printf '\e[%sm▒' {30..37} 0; echo           ### foreground
$ printf '\e[%sm ' {40..47} 0; echo           ### background

И обычно называется так:

Color       #define       Value       RGB
black     COLOR_BLACK       0     0, 0, 0
red       COLOR_RED         1     max,0,0
green     COLOR_GREEN       2     0,max,0
yellow    COLOR_YELLOW      3     max,max,0
blue      COLOR_BLUE        4     0,0,max
magenta   COLOR_MAGENTA     5     max,0,max
cyan      COLOR_CYAN        6     0,max,max
white     COLOR_WHITE       7     max,max,max

Чтобы увидеть расширенные 256 цветов (как используется setafв urxvt):

$ printf '\e[48;5;%dm ' {0..255}; printf '\e[0m \n'

Если вам нужны цифры и упорядоченный вывод:

#!/bin/bash
color(){
    for c; do
        printf '\e[48;5;%dm%03d' $c $c
    done
    printf '\e[0m \n'
}

IFS=$' \t\n'
color {0..15}
for ((i=0;i<6;i++)); do
    color $(seq $((i*36+16)) $((i*36+51)))
done
color {232..255}

256 цветов в последовательности, помечены их индексом


16 миллионов цветов требуют совсем немного кода (некоторые консоли не могут показать это).
Основы это:

fb=3;r=255;g=1;b=1;printf '\e[0;%s8;2;%s;%s;%sm▒▒▒ ' "$fb" "$r" "$g" "$b"

fbэто front/backили 3/4.

Простой тест способности вашей консоли представить так много цветов:

for r in {200..255..5}; do fb=4;g=1;b=1;printf '\e[0;%s8;2;%s;%s;%sm   ' "$fb" "$r" "$g" "$b"; done; echo

красная линия, переходящая от темной к светлой (слева направо) Он будет отображать красную линию с очень небольшим изменением тона слева направо. Если это небольшое изменение видно, ваша консоль способна отображать 16 миллионов цветов.

Каждый r, gи bявляется значением от 0 до 255 для RGB (красный, зеленый, синий).

Если ваш тип консоли поддерживает это, этот код создаст таблицу цветов:

mode2header(){
    #### For 16 Million colors use \e[0;38;2;R;G;Bm each RGB is {0..255}
    printf '\e[mR\n' # reset the colors.
    printf '\n\e[m%59s\n' "Some samples of colors for r;g;b. Each one may be 000..255"
    printf '\e[m%59s\n'   "for the ansi option: \e[0;38;2;r;g;bm or \e[0;48;2;r;g;bm :"
}
mode2colors(){
    # foreground or background (only 3 or 4 are accepted)
    local fb="$1"
    [[ $fb != 3 ]] && fb=4
    local samples=(0 63 127 191 255)
    for         r in "${samples[@]}"; do
        for     g in "${samples[@]}"; do
            for b in "${samples[@]}"; do
                printf '\e[0;%s8;2;%s;%s;%sm%03d;%03d;%03d ' "$fb" "$r" "$g" "$b" "$r" "$g" "$b"
            done; printf '\e[m\n'
        done; printf '\e[m'
    done; printf '\e[mReset\n'
}
mode2header
mode2colors 3
mode2colors 4

диаграмма образцов цветов переднего плана с индексом в качестве меток

диаграмма образцов цветов фона с указателем в качестве меток

Чтобы преобразовать шестнадцатеричное значение цвета в (ближайший) 0-255 цветовой индекс:

fromhex(){
    hex=${1#"#"}
    r=$(printf '0x%0.2s' "$hex")
    g=$(printf '0x%0.2s' ${hex#??})
    b=$(printf '0x%0.2s' ${hex#????})
    printf '%03d' "$(( (r<75?0:(r-35)/40)*6*6 + 
                       (g<75?0:(g-35)/40)*6   +
                       (b<75?0:(b-35)/40)     + 16 ))"
}

Используйте это как:

$ fromhex 00fc7b
048
$ fromhex #00fc7b
048

Чтобы найти номер цвета, используемый в формате цветов HTML :

#!/bin/dash
tohex(){
    dec=$(($1%256))   ### input must be a number in range 0-255.
    if [ "$dec" -lt "16" ]; then
        bas=$(( dec%16 ))
        mul=128
        [ "$bas" -eq "7" ] && mul=192
        [ "$bas" -eq "8" ] && bas=7
        [ "$bas" -gt "8" ] && mul=255
        a="$((  (bas&1)    *mul ))"
        b="$(( ((bas&2)>>1)*mul ))" 
        c="$(( ((bas&4)>>2)*mul ))"
        printf 'dec= %3s basic= #%02x%02x%02x\n' "$dec" "$a" "$b" "$c"
    elif [ "$dec" -gt 15 ] && [ "$dec" -lt 232 ]; then
        b=$(( (dec-16)%6  )); b=$(( b==0?0: b*40 + 55 ))
        g=$(( (dec-16)/6%6)); g=$(( g==0?0: g*40 + 55 ))
        r=$(( (dec-16)/36 )); r=$(( r==0?0: r*40 + 55 ))
        printf 'dec= %3s color= #%02x%02x%02x\n' "$dec" "$r" "$g" "$b"
    else
        gray=$(( (dec-232)*10+8 ))
        printf 'dec= %3s  gray= #%02x%02x%02x\n' "$dec" "$gray" "$gray" "$gray"
    fi
}

for i in $(seq 0 255); do
    tohex ${i}
done

Используйте его как («основной» - первые 16 цветов, «цвет» - основная группа, «серый» - последние серые цвета):

$ tohex 125                  ### A number in range 0-255
dec= 125 color= #af005f
$ tohex 6
dec=   6 basic= #008080
$ tohex 235
dec= 235  gray= #262626
Джефф Шаллер
источник
Ваша функция fromhex великолепна! Спасибо!
Mhulse
Люблю fromhex. Еще раз спасибо! Также я добавил чек на# . Обратная связь?
Mhulse
1
Да, удаление ведущего «#» является разумной защитой. Я считаю, что намного проще в использовании hex=${1#"#"}. Он ничего $1не удалит, если у него нет #, и удалит его, если он существует. Смотрите мой обновленный код.
Приятно! Гораздо компактнее. Обновление моего кода сейчас. Спасибо!!!!
mhulse
Обратите внимание, что, по крайней мере, в моей версии xterm \e[0;%s8;2;%s;%s;%smмне не дают 16M цветов, только цвет в палитре 240, который ближе всего к запрашиваемому rgb.
Стефан Шазелас
14

Краткий ответ: вы можете найти в Интернете таблицы цветов и сопоставить их с номером цвета.

Длинный ответ заключается в том, что правильное отображение зависит от терминала -

125Является параметром для управляющей последовательности , указанной как setafв терминальном описании. tputне придает особого значения числу. Это на самом деле зависит от конкретного эмулятора терминала.

Некоторое время назад ANSI определила коды для 8 цветов, и было две схемы для их нумерации. Эти два видны в некоторых терминальных описаниях как пары setf/setbили setaf/setab. Поскольку последний имеет значение «цвета ANSI», вы увидите, что он используется чаще. Первый (setf / setb) изменил порядок для красного / синего, как отмечено в FAQ по ncurses. Почему красный / синий взаимозаменяемы? , но в любом случае схема была создана для нумерации цветов. Нет предопределенной связи между этими числами и контентом RGB.

Для конкретных эмуляторов терминала существуют предопределенные цветовые палитры, которые можно легко перечислить - и которые можно запрограммировать с помощью этих escape-последовательностей. Там нет ни одного соответствующих стандартов, и вы увидите разницу между эмуляторов терминала, как отмечено в XTERM FAQ Мне не нравится , что оттенок синего .

Однако соглашение часто путают со стандартами. В развитие xterm за последние 20 лет он включил цвета ANSI (8), адаптировал aixtermфункцию (16) цветов, добавил расширения для 88- и 256 цветов. Многое из этого было принято другими разработчиками для различных эмуляторов терминала. Это кратко изложено в FAQ по xterm. Почему бы не сделать «xterm» приравненным к «xterm-256color»? ,

Исходный код xterm включает в себя сценарии для демонстрации цветов, например, с использованием тех же escape-последовательностей, которые tputбудут использоваться.

Вам также может пригодиться этот вопрос / ответ: значения RGB цветов в расширенном индексе цветов Ansi (17-255)

Томас Дики
источник
Большое спасибо за вашу помощь, Томас, я действительно ценю это! Я на Mac / OS X под управлением iTerm. Ваше объяснение действительно помогает мне лучше понять мои настройки (я много копировал / вставлял из приглашений разных людей в Интернете). Я очень ценю, что вы нашли время написать мне подробный и информативный ответ. :)
mhulse
9

tputУтилита использует справочную таблицу 256 цветов для печати 8-битных ANSI управляющие последовательности (начиная с Escи [) , что делает использование возможностей терминала , так что эти управляющие последовательности могут быть интерпретированы как цвета. Это предопределенный набор из 256 цветов, обычно используемых в графических картах.

Чтобы напечатать все 256 цветов в терминале, попробуйте следующий однострочный:

for c in {0..255}; do tput setaf $c; tput setaf $c | cat -v; echo =$c; done

Подсказка: добавить | columnв список столбцов .

Эту 256-цветную таблицу поиска можно также найти на странице Википедии следующим образом:

Диаграмма;  Escape-код ANSI;  8-битная 256-цветная справочная таблица в Википедии;  256-цветный режим - передний план: ESC [38; 5; #m фон: ESC [48; 5; #m

kenorb
источник
3

С zsh и в xtermтерминале -подобного терминала ( xtermи vteтерминалах -подобного типа gnome-terminal, xfce4-terminalкак минимум ...) вы можете сделать:

$ read -s -t1 -d $'\a' $'c?\e]4;125;?\a' && echo "${c##*;}"
rgb:afaf/0000/5f5f

Эквивалент bash:

read -s -t1 -d $'\a' -p $'\e]4;125;?\a' c && echo "${c##*;}"

(вы хотите, чтобы escape-последовательность запрашивала цвет для отправки послеecho отключения терминальной дисциплины (с -s), в противном случае ответ будет отображаться строковой дисциплиной половину времени, следовательно, отправка его как части readзапроса ( var?promptв zsh) как в кш, -p promptв баш)).

чтобы получить определение цвета 125 (здесь в качестве спецификации RGB, каждое число представляет собой интенсивность красного, зеленого и синего компонентов в виде шестнадцатеричного числа от 0 до FFFF).

Вы можете сделать то же самое для первых 16 цветов с помощью xtermcontrolкоманды:

$ xtermcontrol --get-color1
rgb:cdcd/0000/0000
Стефан Шазелас
источник
Круто, большое спасибо за помощь! +1
mhulse
@ Жиль, вы хотите, чтобы запрос отправлялся через приглашение после того, как эхо дисциплины терминала отключено. Смотрите редактировать.
Стефан Шазелас
@ StéphaneChazelas Используя другую терминальную программу (gnome-терминал) (которая является терминалом xterm), я получил ваш код для правильной работы (как в bash, так и в zsh) Как ни странно: tput colorsотчеты только в 8том случае, если терминал способен отображать 256 цветов. Кроме того, xterm-color (Konsole) tput colorsсообщает только о 8том, что этот терминал полностью способен отображать 16 миллионов цветов (и, конечно, все 256 цветов). И нет, нет tmux или экрана, который может «покрасить» :-) (изменить то есть) результаты (я знал об этой детали). Вкратце: ваш код может не работать в некоторых терминалах / консолях.
Ах, к моему ответу добавился tohex, немного длиннее, чем я ожидал, но 256 цветов имеют довольно необычные повороты.
0

ANSI Colours на консольном сроке

В зависимости от того, какой протокол используется вашей консолью, последовательность может быть: \e[38;5;XXXmили \e[3XXXmгде XXXсоответствует номеру ANSI.

Чтобы убедиться, что вы используете правильную последовательность ANSI, вы должны использовать tput.

Что касается кода ESC Википедии , я написал это:

#!/bin/bash


for ((i=0; i<256; i++)) ;do
    echo -n '  '
    tput setab $i
    tput setaf $(( ( (i>231&&i<244 ) || ( (i<17)&& (i%8<2)) ||
        (i>16&&i<232)&& ((i-16)%6 <(i<100?3:2) ) && ((i-16)%36<15) )?7:16))
    printf " C %03d " $i
    tput op
    (( ((i<16||i>231) && ((i+1)%8==0)) || ((i>16&&i<232)&& ((i-15)%6==0)) )) &&
        printf "\n" ''
done

Может сделать что-то вроде:

введите описание изображения здесь

... Затем, поскольку я ненавижу запуск более 200 вилок в небольшом сценарии, я написал это:

#!/bin/bash

# Connector fifos directory
read TMPDIR < <(mktemp -d /dev/shm/bc_shell_XXXXXXX)

fd=3
# find next free fd
nextFd() { while [ -e /dev/fd/$fd ];do ((fd++)) ;done;printf -v $1 %d $fd;}

tputConnector() {
    mkfifo $TMPDIR/tput
    nextFd TPUTIN
    eval "exec $TPUTIN> >(LANG=C exec stdbuf -o0 tput -S - >$TMPDIR/tput 2>&1)"
    nextFd TPUTOUT
    eval "exec $TPUTOUT<$TMPDIR/tput"
}
myTput() { echo -e "$1\ncr" 1>&$TPUTIN && IFS= read -r -d $'\r' -u $TPUTOUT $2
}
tputConnector

myTput op op
myTput "setaf 7" grey
myTput "setaf 16" black
fore=("$black" "$grey")
for ((i=0; i<256; i++)) ;do
    myTput "setab $i" bgr
    printf "  %s%s  %3d  %s" "$bgr" "${fore[ i>231 && i<244||(i<17)&& (i%8<2)||
        (i>16&&i<232)&&((i-16)%6*11+(i-16)/6%6*14+(i-16)/36*10)<58
        ? 1 : 0 ]}" $i "$op"
    (( ((i<16||i>231) && ((i+1)%8==0)) || ((i>16&&i<232)&& ((i-15)%6==0)) )) &&
        printf "\n" ''
done

Только с 1 вилкой! Тот же результат, но намного быстрее!

Ф. Хаури
источник