Tabela kolorów tput setaf? Jak ustalić kody kolorów?

79

Jestem w trakcie kolorowania terminala PS1.

Ustawiam zmienne kolorów za pomocą tput; na przykład tutaj jest fioletowy:

PURPLE=$(tput setaf 125)

Pytanie:

Jak znaleźć kody kolorów (np. 125) Innych kolorów?

Czy gdzieś jest kolorowy przewodnik po tabelach / ściągawka?

Po prostu nie jestem pewien, co to 125jest… Czy jest jakiś sposób, aby wziąć kolor heksadecymalny i przekonwertować go na liczbę, której setafmożna użyć?

mhulse
źródło

Odpowiedzi:

152

Liczba kolorów dostępnych dla tput jest podana przez tput colors.

Aby zobaczyć podstawowe 8 kolorów (używane przez setfw terminalu urxvt i setafxterm):

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

I zwykle nazywany tak:

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

Aby zobaczyć rozszerzone 256 kolorów (używane przez setafw urxvt):

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

Jeśli chcesz liczb i uporządkowanego wyjścia:

#!/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 kolorów w sekwencji, oznaczonych ich indeksem


16 milionów kolorów wymaga sporo kodu (niektóre konsole tego nie pokazują).
Podstawy to:

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

fbjest front/backlub 3/4.

Prostym testem zdolności konsoli do zaprezentowania tak wielu kolorów jest:

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

czerwona linia, przechodząca z ciemniejszej w jaśniejszą (od lewej do prawej) Przedstawi czerwoną linię z bardzo małą zmianą tonu od lewej do prawej. Jeśli ta niewielka zmiana jest widoczna, oznacza to, że Twoja konsola może wyświetlać 16 milionów kolorów.

Każdy r, gi bjest wartością od 0 do 255 dla RGB (czerwony, zielony, niebieski).

Jeśli Twój typ konsoli to obsługuje, ten kod utworzy tabelę kolorów:

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

wykres przykładowych kolorów pierwszego planu z ich indeksem jako etykiety

wykres przykładowych kolorów tła z ich indeksem jako etykiety

Aby przekonwertować wartość koloru szesnastkowego na (najbliższy) indeks kolorów 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 ))"
}

Użyj go jako:

$ fromhex 00fc7b
048
$ fromhex #00fc7b
048

Aby znaleźć numer koloru używany w formacie kolorów 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

Użyj go jako („podstawowy” to pierwsze 16 kolorów, „kolor” to główna grupa, „szary” to ostatnie szare kolory):

$ tohex 125                  ### A number in range 0-255
dec= 125 color= #af005f
$ tohex 6
dec=   6 basic= #008080
$ tohex 235
dec= 235  gray= #262626
Jeff Schaller
źródło
Twoja funkcja fromhex jest świetna! Dzięki wielkie!
mhulse
Kochać fromhex. Dzięki jeszcze raz! Ponadto, dodaje czek na# . Informacje zwrotne?
mhulse
1
Tak, usunięcie wiodącego „#” jest rozsądną ochroną. Uważam, że jest o wiele prostszy w użyciu hex=${1#"#"}. Nic nie usunie, jeśli $1nie ma #, i usunie go, jeśli istnieje. Zobacz mój zaktualizowany kod.
Miły! Znacznie bardziej kompaktowy. Aktualizuję mój kod teraz. Dziękuję Ci!!!!
mhulse
Zauważ, że przynajmniej w mojej wersji xterm \e[0;%s8;2;%s;%s;%smnie daje mi 16 milionów kolorów, tylko kolor z palety 240 kolorów, który jest najbliższy żądanej rgb.
Stéphane Chazelas,
14

Krótka odpowiedź jest taka, że ​​można znaleźć w internetowych tabelach kolorów i dopasować je do numeru koloru.

Długa odpowiedź jest taka, że ​​prawidłowe mapowanie zależy od terminala -

125Jest parametrem do sekwencji sterującej dalej setafw opisie zaciskowej. tputnie przywiązuje żadnego szczególnego znaczenia do liczby. To zależy od konkretnego emulatora terminala.

Jakiś czas temu ANSI zdefiniowało kody dla 8 kolorów i były dwa schematy ich numerowania. Oba są widoczne w niektórych opisach terminali jako pary setf/setblub setaf/setab. Ponieważ ten drugi ma konotację z „kolorami ANSI”, zobaczysz, że jest używany częściej. Ten pierwszy (setf / setb) zmienił kolejność dla koloru czerwonego / niebieskiego, jak podano w FAQ ncurses Dlaczego wymieniono kolor czerwony / niebieski? , ale w obu przypadkach ustanowiono schemat tylko numerowania kolorów. Nie ma predefiniowanego związku między tymi liczbami a treścią RGB.

Dla określonych emulatorów terminali istnieją predefiniowane palety kolorów, które można łatwo wyliczyć - i można je zaprogramować za pomocą tych sekwencji ucieczki. Nie ma odpowiednich standardów i zobaczysz różnice między emulatorami terminali, jak zauważono w xterm FAQ Nie podoba mi się ten odcień niebieskiego .

Konwencja jest jednak często mylona ze standardami. Opracowując xterm w ciągu ostatnich 20 lat, wprowadzono kolory ANSI (8), dostosowano kolory aixtermfunkcji (16), dodano rozszerzenia dla kolorów 88 i 256. Wiele z nich zostało przyjętych przez innych programistów dla różnych emulatorów terminali. Podsumowano to w FAQ Xterm. Dlaczego nie uczynić „xterm” równoznacznym z „xterm-256color”? .

Kod źródłowy xterm zawiera skrypty pokazujące kolory, np. Wykorzystujące te same sekwencje specjalne, które tputmogłyby zostać użyte.

Pomocne może być również to pytanie / odpowiedź: wartości RGB kolorów w rozszerzonym indeksie kolorów Ansi (17–255)

Thomas Dickey
źródło
Dziękuję bardzo za pomoc Thomas, naprawdę to doceniam! Korzystam z systemu Mac / OS X z systemem iTerm. Twoje wyjaśnienie naprawdę pomaga mi zrozumieć więcej na temat mojej konfiguracji (wykonałem dużo kopiowania / wklejania z szybkich kolorów różnych osób w Internecie). Naprawdę doceniam twój czas poświęcony na napisanie mi szczegółowej i pouczającej odpowiedzi. :)
mhulse
9

tputNarzędzie jest przy użyciu tabeli przeglądowej 256 kolorów do drukowania 8-bitowe sekwencje ANSI ucieczki (poczynając Esci [), który wykorzystuje możliwości terminala , aby te sekwencje kontrolne mogą być interpretowane jako barwniki. Są to wstępnie zdefiniowany zestaw 256 kolorów używanych powszechnie w kartach graficznych.

Aby wydrukować wszystkie 256 kolorów w terminalu, wypróbuj następującą linijkę:

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

Wskazówka: Dołącz | columndo listy kolumnowej.

Ta 256-kolorowa tabela odnośników znajduje się również na stronie Wikipedii w następujący sposób:

Wykres;  Kod ucieczki ANSI;  8-bitowa 256-kolorowa tabela przeglądowa z Wikipedii;  Tryb 256 kolorów - pierwszy plan: ESC [38; 5; #m tło: ESC [48; 5; #m

kenorb
źródło
3

Z zsh oraz w xterm-Jak terminala ( xtermi vteopartych o terminale, jak gnome-terminal, xfce4-terminal... co najmniej), można zrobić:

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

Odpowiednik bash:

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

(chcesz, aby sekwencja zmiany znaczenia wysłała zapytanie o kolor, który ma zostać wysłany po wyłączeniu dyscypliny terminalowej echo(z -s), w przeciwnym razie odpowiedź byłaby wyświetlana przez dyscyplinę liniową przez połowę czasu, stąd wysłanie jej jako części readzachęty ( var?promptw zsh jak w ksh, -p promptw bash)).

aby uzyskać definicję koloru 125 (tutaj jako specyfikacja RGB, gdzie każda liczba jest intensywnością składników czerwonego, zielonego i niebieskiego jako liczba szesnastkowa między 0 a FFFF).

Możesz zrobić to samo dla pierwszych 16 kolorów za pomocą xtermcontrolpolecenia:

$ xtermcontrol --get-color1
rgb:cdcd/0000/0000
Stéphane Chazelas
źródło
Wspaniale, dziękuję bardzo za pomoc! +1
mhulse
@Gilles, chcesz, aby zapytanie było wysyłane za pomocą monitu po wyłączeniu echa dyscypliny terminala. Zobacz edycję.
Stéphane Chazelas,
@ StéphaneChazelas Używając innego programu terminalowego (gnome-terminal) (który jest terminalem xterm) Mam twój kod do poprawnego działania (zarówno w bash, jak i zsh). Dziwne: tput colorsraporty tylko, 8jeśli terminal jest w stanie przedstawić 256 kolorów. Ponadto xterm-color (Konsole) tput colorszgłasza tylko, 8nawet jeśli terminal jest w pełni zdolny do przedstawienia 16 milionów kolorów (i oczywiście wszystkich 256 kolorów). I nie, nie ma tmuxa ani ekranu, który może „pokolorować” :-) (to znaczy zmienić) wyniki (byłem świadomy tego szczegółu). W skrócie: Twój kod może zawieść w niektórych terminalach / konsolach.
Ach, tohex dodał do mojej odpowiedzi: Trochę dłużej niż się spodziewałem, ale 256 kolorów ma dość dziwne zwroty.
0

Kolory ANSI na termin konsoli

W zależności od protokołu, którego używa konsola, sekwencja może być: \e[38;5;XXXmlub \e[3XXXmgdzie XXXodpowiada numerowi ansi.

Aby upewnić się, że używasz właściwej sekwencji ANSI, musisz użyć tput.

W odniesieniu do kodu ucieczkowego ANSI Wikipedii napisałem to:

#!/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

Może renderować coś takiego:

wprowadź opis zdjęcia tutaj

... Następnie, ponieważ nienawidzę uruchamiania ponad 200 widelców w małym skrypcie, napisałem to:

#!/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

Z tylko 1 widelcem! Ten sam wynik, ale o wiele szybciej!

F. Hauri
źródło