tput setaf tabla de colores? ¿Cómo determinar los códigos de color?

79

Estoy en el proceso de colorear mi terminal PS1.

Estoy configurando variables de color usando tput; por ejemplo, aquí está el morado:

PURPLE=$(tput setaf 125)

Pregunta:

¿Cómo encuentro los códigos de color (p 125. Ej. ) De otros colores?

¿Hay alguna guía de tabla de colores / hoja de trucos en alguna parte?

No estoy seguro de qué 125es ... ¿Hay alguna forma de tomar un color hexadecimal y convertirlo en un número que setafpueda usar?

mhulse
fuente

Respuestas:

153

El recuento de colores disponibles para tput viene dado por tput colors.

Para ver los 8 colores básicos (como los utilizados setfen el terminal urxvt y setafen el terminal xterm):

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

Y generalmente se llama así:

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

Para ver los 256 colores extendidos (como los utilizados setafen urxvt):

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

Si desea números y una salida ordenada:

#!/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 cartas de colores en secuencia, etiquetadas con su índice


Los 16 millones de colores necesitan bastante código (algunas consolas no pueden mostrar esto).
Lo básico es:

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

fbes front/backo 3/4.

Una prueba simple de la capacidad de su consola para presentar tantos colores es:

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

línea roja, desvaneciéndose de más oscuro a más claro (de izquierda a derecha) Presentará una línea roja con un cambio de tono muy pequeño de izquierda a derecha. Si ese pequeño cambio es visible, su consola es capaz de 16 millones de colores.

Cada uno r, gy bes un valor de 0 a 255 para RGB (rojo, verde, azul).

Si su tipo de consola admite esto, este código creará una tabla de colores:

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

tabla de colores de primer plano de muestra con su índice como etiquetas

tabla de colores de fondo de muestra con su índice como etiquetas

Para convertir un valor de color hexadecimal a un índice de color 0-255 (más cercano):

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 ))"
}

Úselo como:

$ fromhex 00fc7b
048
$ fromhex #00fc7b
048

Para encontrar el número de color como se usa en formato de colores 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

Úselo como ("básico" son los primeros 16 colores, "color" es el grupo principal, "gris" son los últimos colores grises):

$ 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
fuente
¡Tu función fromhex es genial! ¡Muchas gracias!
mhulse
Lovin ' fromhex. ¡Gracias de nuevo! Además, agregué un cheque para el# . ¿Realimentación?
mhulse
1
Sí, eliminar un '#' inicial es una protección razonable. Me parece mucho más simple de usar hex=${1#"#"}. No eliminará nada si $1no tiene un #, y lo eliminará si existe. Ver mi código actualizado.
¡Agradable! Mucho más compacto. Actualizando mi código ahora. ¡¡¡¡Gracias!!!!
mhulse
Tenga en cuenta que, al menos en mi versión de xterm \e[0;%s8;2;%s;%s;%sm, no me da 16 millones de colores, solo el color en la paleta de 240 colores más cercano al rgb solicitado.
Stéphane Chazelas
14

La respuesta corta es que puede encontrar en la web tablas de colores y combinarlas con el número de color.

La respuesta larga es que la asignación correcta depende del terminal:

El 125es un parámetro para una secuencia de escape denominada setafen la descripción del terminal. tputno atribuye ningún significado particular al número. Eso realmente depende del emulador de terminal particular.

Hace un tiempo, ANSI definió códigos para 8 colores, y había dos esquemas para numerarlos. Los dos se ven en algunas descripciones terminales como los pares setf/setbo setaf/setab. Como este último tiene la connotación de "colores ANSI", verá que se usa con más frecuencia. El primero (setf / setb) cambió el orden de rojo / azul como se indica en las preguntas frecuentes de ncurses ¿Por qué se intercambian rojo / azul? , pero en cualquier caso, el esquema se estableció solo para numerar los colores. No existe una relación predefinida entre esos números y el contenido RGB.

Para emuladores de terminal específicos, hay paletas de colores predefinidas que se pueden enumerar con bastante facilidad y se pueden programar utilizando estas secuencias de escape. No hay estándares relevantes, y verá diferencias entre los emuladores de terminal, como se señala en las preguntas frecuentes de xterm . No me gusta ese tono de azul .

Sin embargo, la convención a menudo se confunde con los estándares. En el desarrollo de xterm en los últimos 20 años, incorporó colores ANSI (8), adaptó la aixtermfunción (16) colores, agregó extensiones para 88 y 256 colores. Gran parte de eso ha sido adoptado por otros desarrolladores para diferentes emuladores de terminal. Esto se resume en las preguntas frecuentes de xterm ¿Por qué no hacer que "xterm" se equipare a "xterm-256color"? .

El código fuente de xterm incluye scripts para demostrar los colores, por ejemplo, usando las mismas secuencias de escape que tputusaría.

También puede encontrar útil esta pregunta / respuesta: valores RGB de los colores en el índice de colores extendidos de Ansi (17-255)

Thomas Dickey
fuente
Muchas gracias por tu ayuda Thomas, ¡realmente lo aprecio! Estoy en una Mac / OS X con iTerm. Su explicación realmente me ayuda a comprender más sobre mi configuración (he copiado / pegado muchas veces los colores de los avisos de otras personas en la web). Realmente aprecio que se haya tomado el tiempo de escribirme una respuesta detallada e informativa. :)
mhulse
9

La tpututilidad está utilizando una tabla de búsqueda de 256 colores para imprimir secuencias de escape ANSI de 8 bits (comenzando con Escy [) que hace uso de capacidades de terminal , por lo que estas secuencias de control pueden interpretarse como colores. Estos son un conjunto predefinido de 256 colores que se usan comúnmente en las tarjetas gráficas.

Para imprimir los 256 colores en el terminal, intente con la siguiente línea:

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

Sugerencia: agregue | columna la lista de columnas.

Esta tabla de búsqueda de 256 colores también se puede encontrar en la página de Wikipedia de la siguiente manera:

Gráfico;  Código de escape ANSI;  Tabla de búsqueda de 8 colores y 256 colores en Wikipedia;  Modo de 256 colores: primer plano: ESC [38; 5; #m fondo: ESC [48; 5; #m

kenorb
fuente
3

Con zsh y en un xtermterminal similar ( xtermy vteterminales basados ​​como gnome-terminal, xfce4-terminal... al menos), puede hacer:

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

El equivalente bash:

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

(desea que la secuencia de escape consulte el color que se enviará después de queecho se deshabilite la disciplina del terminal (con -s) de lo contrario, la disciplina de la línea mostrará la respuesta la mitad del tiempo, de ahí el envío como parte de la readsolicitud ( var?prompten zsh como en ksh, -p prompten bash)).

para obtener la definición del color 125 (aquí como una especificación RGB, cada número es la intensidad de los componentes rojo, verde y azul como un número hexadecimal entre 0 y FFFF).

Puede hacer lo mismo para los primeros 16 colores con el xtermcontrolcomando:

$ xtermcontrol --get-color1
rgb:cdcd/0000/0000
Stéphane Chazelas
fuente
Impresionante, muchas gracias por la ayuda! +1
mhulse
@Gilles, desea que la consulta se envíe a través de la solicitud después de deshabilitar el eco de disciplina de terminal. Ver editar.
Stéphane Chazelas
@ StéphaneChazelas Usando otro programa de terminal (gnome-terminal) (que es una terminal xterm) Obtuve su código para que funcione correctamente (tanto en bash como en zsh) Por extraño que parezca: tput colorsinforma solo 8si la terminal es capaz de presentar 256 colores. Además, el xterm-color (Konsole) tput colorssolo informa 8incluso si ese terminal es totalmente capaz de presentar 16 millones de colores (y los 256 colores, por supuesto). Y no, no hay tmux o pantalla que pueda "colorear" :-) (cambio) los resultados (estaba al tanto de ese detalle). En resumen: su código puede fallar en algunos terminales / consolas.
Ah, tohex agregó a mi respuesta, un poco más de lo que esperaba, pero los 256 colores tienen un poco de peculiaridad.
0

Colores ANSI en término de consola

Según el protocolo de término que utilice su consola, la secuencia podría ser: \e[38;5;XXXmo \e[3XXXmdonde XXXcorresponda al número ansi.

Para asegurarse de usar la secuencia ANSI correcta, debe usarla tput.

Con respecto al código de escape ANSI de Wikipedia , escribí esto:

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

Podría representar algo como:

ingrese la descripción de la imagen aquí

... Entonces, como odio ejecutar más de 200 tenedores en un pequeño script, escribí esto:

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

¡Con solo 1 tenedor! ¡El mismo resultado, pero mucho más rápido!

F. Hauri
fuente