tput setaf table de couleurs? Comment déterminer les codes de couleur?

79

Je suis en train de coloriser mon terminal PS1.

Je règle des variables de couleur en utilisant tput; par exemple, voici le violet:

PURPLE=$(tput setaf 125)

Question:

Comment trouver les codes de couleurs (par exemple 125) d'autres couleurs?

Existe-t-il un guide de couleurs / aide-mémoire quelque part?

Je ne sais pas ce que 125c'est… Y a-t-il un moyen de prendre une couleur hexadécimale et de la convertir en un nombre setafutilisable?

Mhulse
la source

Réponses:

153

Le nombre de couleurs disponibles pour tput est donné par tput colors.

Pour voir les 8 couleurs de base (telles qu’utilisées setfdans les terminaux urxvt et setafxterm):

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

Et généralement nommé comme ceci:

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

Pour voir les 256 couleurs étendues (utilisées par setafdans urxvt):

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

Si vous voulez des nombres et une sortie ordonnée:

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

Tableau de 256 couleurs en séquence, étiqueté avec leur index


Les 16 millions de couleurs nécessitent un peu de code (certaines consoles ne peuvent pas le montrer).
La base est:

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

fbest front/backou 3/4.

Un simple test de la capacité de votre console à présenter autant de couleurs est le suivant:

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

ligne rouge, allant du plus sombre au plus clair (de gauche à droite) Il présentera une ligne rouge avec un très petit changement de ton de gauche à droite. Si cette petite modification est visible, votre console est capable de 16 millions de couleurs.

Chacune r, get bcorrespond à une valeur comprise entre 0 et 255 pour les couleurs RVB (rouge, vert et bleu).

Si votre type de console supporte cela, ce code créera une table de couleurs:

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

graphique des échantillons de couleurs de premier plan avec leur index sous forme d'étiquettes

tableau des échantillons de couleurs de fond avec leur index sous forme d'étiquettes

Pour convertir une valeur de couleur hexadécimale en un indice de couleur (le plus proche) compris entre 0 et 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 ))"
}

Utilisez-le comme:

$ fromhex 00fc7b
048
$ fromhex #00fc7b
048

Pour trouver le numéro de couleur utilisé dans le format de couleurs 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

Utilisez-le comme ("basique" est les 16 premières couleurs, "couleur" est le groupe principal, "gris" est les dernières couleurs 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
la source
Votre fonction fromhex est géniale! Merci beaucoup!
Mhulse
Lovin' fromhex. Merci encore! Aussi, j'ai ajouté un chèque pour le# . Retour d'information?
Mhulse
1
Oui, la suppression d'un '#' est une protection raisonnable. Je trouve beaucoup plus simple à utiliser hex=${1#"#"}. Il n’enlèvera rien si $1n’a pas d’a #, et le supprime s’il existe. Voir mon code mis à jour.
Agréable! Beaucoup plus compact. Mise à jour de mon code maintenant. Je vous remercie!!!!
Mhulse
Notez qu'au moins dans ma version de xterm, the \e[0;%s8;2;%s;%s;%smne me donne pas 16 millions de couleurs, mais uniquement la couleur de la palette de 240 couleurs la plus proche de la RVB demandée.
Stéphane Chazelas
14

La réponse courte est que vous pouvez trouver sur le Web des tables de couleurs et les faire correspondre au numéro de couleur.

La réponse longue est que le mappage correct dépend du terminal -

Le 125est un paramètre pour une séquence d'échappement appelée setafdans la description du terminal. tputn'attache aucune signification particulière au nombre. Cela dépend en fait de l'émulateur de terminal particulier.

Il y a quelque temps, l'ANSI avait défini des codes pour 8 couleurs et il existait deux systèmes de numérotation. Les deux sont vus dans certaines descriptions de terminal comme les paires setf/setbou setaf/setab. Puisque ce dernier a la connotation de "couleurs ANSI", vous verrez qu'il est utilisé plus souvent. L'ancien (setf / setb) changeait l'ordre du rouge / bleu comme indiqué dans la FAQ ncurses Pourquoi les couleurs rouge / bleu sont-elles échangées? , mais dans les deux cas, le schéma a été établi pour ne numéroter que les couleurs. Il n'y a pas de relation prédéfinie entre ces numéros et le contenu RVB.

Pour les émulateurs de terminal spécifiques, il existe des palettes de couleurs prédéfinies qui peuvent être énumérées assez facilement - et peuvent être programmées à l'aide de ces séquences d'échappement. Il n'y a pas de normes pertinentes, et vous verrez des différences entre les émulateurs de terminaux, comme indiqué dans la FAQ de xterm. Je n'aime pas cette nuance de bleu .

Cependant, la convention est souvent confondue avec les normes. Lors du développement de xterm au cours des 20 dernières années, il a incorporé les couleurs ANSI (8), adapté la aixtermfonctionnalité (16) couleurs, ajouté des extensions pour les couleurs 88 et 256 couleurs. Une grande partie de celle-ci a été adoptée par d'autres développeurs pour différents émulateurs de terminaux. Ceci est résumé dans la FAQ de xterm Pourquoi ne pas associer "xterm" à "xterm-256color"? .

Le code source xterm comprend des scripts permettant de démontrer les couleurs, par exemple, en utilisant les mêmes séquences d'échappement que celles tpututilisées.

Vous pouvez également trouver cette question / réponse utile: Valeurs RVB des couleurs de l’indice de couleurs étendu Ansi (17-255)

Thomas Dickey
la source
Merci beaucoup pour votre aide Thomas, je l'apprécie vraiment! Je suis sous Mac / OS X sous iTerm. Votre explication m'aide vraiment à mieux comprendre ma configuration (j'ai copié / collé à partir des couleurs rapides de diverses personnes sur le Web). J'apprécie vraiment que vous preniez le temps de m'écrire une réponse détaillée et informative. :)
Mhulse
9

L' tpututilitaire utilise une table de conversion de 256 couleurs pour imprimer des séquences d'échappement ANSI 8 bits (en commençant par Escet [) qui utilise les fonctionnalités du terminal . Ces séquences de contrôle peuvent donc être interprétées en tant que couleurs. Ce sont des ensembles prédéfinis de 256 couleurs couramment utilisées sur les cartes graphiques.

Pour imprimer toutes les 256 couleurs du terminal, essayez la ligne suivante:

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

Astuce: Ajouter | columnà la liste des colonnes.

Cette table de recherche de 256 couleurs peut également être trouvée sur la page Wikipedia comme suit:

Graphique;  Code d'échappement ANSI;  Table de consultation 8 couleurs à 256 couleurs sur Wikipedia;  Mode 256 couleurs - au premier plan: ESC [38; 5; #m fond: ESC [48; 5; #m

Kenorb
la source
3

Avec zsh et dans une xtermborne -comme ( xtermet des vteterminaux à base comme gnome-terminal, xfce4-terminal... au moins), vous pouvez le faire:

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

L'équivalent bash:

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

(vous voulez que la séquence d'échappement interroge la couleur à envoyer après que la discipline de terminal echoest désactivée (avec -s) sinon la réponse serait affichée par la discipline de ligne la moitié du temps, d'où son envoi dans le cadre de l' readinvite ( var?prompten zsh comme en ksh, -p prompten bash)).

pour obtenir la définition de la couleur 125 (ici une spécification RVB, chaque nombre représentant l’intensité des composantes Rouge, Vert et Bleu sous forme de nombre hexadécimal compris entre 0 et FFFF).

Vous pouvez faire la même chose pour les 16 premières couleurs avec la xtermcontrolcommande:

$ xtermcontrol --get-color1
rgb:cdcd/0000/0000
Stéphane Chazelas
la source
Génial, merci beaucoup pour l'aide! +1
mhulse
@ Gilles, vous souhaitez que la requête soit envoyée via l'invite après la désactivation de l'écho de la discipline de terminal. Voir éditer.
Stéphane Chazelas
@ StéphaneChazelas En utilisant un autre programme de terminal (gnome-terminal) (qui est un terminal xterm), votre code a fonctionné correctement (en bash et en zsh). Curieusement: tput colorsne signale que 8si le terminal est capable de présenter 256 couleurs. En outre, xterm-color (Konsole) tput colorsne signale 8que si ce terminal est tout à fait capable de présenter 16 millions de couleurs (et toutes les 256 couleurs bien sûr). Et non, pas de tmux ou d’écran qui puisse "colorer" :-) (changer) les résultats (j’étais au courant de ce détail). En bref: votre code peut échouer sur certains terminaux / consoles.
Ah, tohex a ajouté à ma réponse, Un peu plus long que ce à quoi je m'attendais, mais les 256 couleurs ont des tours assez bizarres.
0

Couleurs ANSI sur terme de console

Selon le protocole utilisé par votre console, la séquence peut être: \e[38;5;XXXmou \e[3XXXmXXXcorrespond au numéro ansi.

Pour vous assurer d'utiliser la bonne séquence ANSI, vous devez utiliser tput.

En ce qui concerne le code d'échappement ANSI de Wikipedia , j'ai écrit ceci:

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

Pourrait rendre quelque chose comme:

entrez la description de l'image ici

... Ensuite, parce que je déteste courir plus de 200 fourches dans un petit script, j'ai écrit ceci:

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

Avec seulement 1 fourchette! Même résultat, mais beaucoup plus rapide!

F. Hauri
la source