Usando le variabili per memorizzare i codici colore dei terminali per PS1?


33

Nel mio .bashrc, utilizzo i codici colore del terminale ANSI per colorare vari bit. Sembra così:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

dove virtual_enve git_branchsono funzioni bash che producono roba su stdout.

Ora, per semplificare la lettura e la modifica, vorrei memorizzare i codici colori in variabili e fare riferimento ad essi, anziché incorporarli direttamente in PS1. Quindi ho un sacco di variabili come questa:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

Mi piacerebbe poter scrivere qualcosa del tipo:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

Ma questo non funziona: i codici colore vengono visualizzati nel prompt, come se fossero sfuggiti. I colori funzionano correttamente se uso invece virgolette doppie PS1, ma il prompt cambia solo quando lo faccio source ~/.bashrc.

Ho provato altre cose che ho visto fare dalla gente: usare printf, usare virgolette singole per i colori, inserire la \[e \]in PS1invece della variabile color, ma nulla sembra funzionare.

Come posso usare le variabili per i codici colore?


Puoi darci il tuo .bashrc?
cuonglm,

@cuonglm Tutti i tuoi .bashrc ci appartengono? Mi mostrerò.
CivFan,

Risposte:


20

La soluzione è fare in modo che la shell sostituisca le variabili di colore quando si definisce il prompt, ma non le funzioni. Per fare ciò, usa le doppie virgolette come avevi provato originariamente, ma scappa dai comandi in modo che non vengano valutati fino a quando non viene disegnato il prompt.

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

Notare \prima di $()ogni comando.

Se riecheggiamo questo, vediamo:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

Come puoi vedere, le variabili di colore sono state sostituite, ma non i comandi.


1
Questo non sembra funzionare se $ (git_branch) sta anche provando a stampare usando $ {GIALLO} ecc. In quella sola sezione, otterrai comunque tutti i caratteri [].
WB Reed,

7

Il problema è che la variabile GREENcontiene la stringa letterale composta da "parentesi rovesciata barra rovesciata zero tre tre" e così via. Non contiene ad esempio un carattere di escape ASCII come richiesto per far cambiare colore al terminale.

Potresti inserire i caratteri di controllo in GREEN(e YELLOWe RESET) manualmente, ma un'opzione molto migliore è quella di utilizzare tputin primo luogo in modo da non dover codificare nulla e supportare qualsiasi tipo di terminale.

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

Il motivo per cui il mondo quando metti "backslash zero tre three" ecc ... direttamente in PS1è che l'interpretazione di alcune sequenze di backslash è una caratteristica del prompt di bash (vedi la sezione PROMPTING nel manuale. Questa sostituzione avviene prima dell'espansione dei parametri, comando sostituzione, espansione aritmetica e rimozione delle quotazioni, tuttavia, quindi non si applica ai risultati di tutte quelle altre operazioni.


5
Quando lo fai in questo modo, devi avvolgere le variabili di colore \[\]all'interno di $PS1. Ad esempio: PS1='\u@\h:\w\[${YELLOW}\]'. Se non lo fai, e finisci con un lungo comando che passa alla riga successiva, incontrerai ogni sorta di problemi. La shell usa il \[\]per determinare quali caratteri non sono stampabili, quindi non li considera nel calcolo della lunghezza del prompt. Ne ha bisogno in modo che possa tracciare correttamente la linea quando supera la larghezza del terminale.
Patrick,

Non lo sapevo tput, grazie. Per ora userò la risposta di Patrick, ma lo rivedrò quando ne avrò la possibilità.
Ismail Badawi,

2

Cambia il modo in cui riempi $ VERDE, $ GIALLO e $ RIPRISTINA:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

1
Questo in effetti fa esattamente la stessa cosa della risposta di Celada. Ma Celada è più portatile nel caso in cui il terminale usi diversi codici di escape per l'impostazione del colore. Avrà anche lo stesso problema con il prompt multi-linea.
Patrick,

2
Il \[…\]bit deve rimanere nel prompt, non è possibile inserirlo in una variabile. L'hai rimosso del tutto, il che provocherà problemi di visualizzazione (il cursore non si trova nella posizione in cui Bash se lo aspetta).
Gilles 'SO- smetti di essere malvagio' il

A parte le preoccupazioni di @Patrick, echo -e non è portatile.
helpermethod

1
Con la non portabilità derivano più funzioni - tput setafnon ti consente di scegliere tra il set di colori "leggero", come il ciano chiaro. La risposta di Cyrus, tuttavia, lo fa.
CivFan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.