Utilizando variáveis para armazenar códigos de cores do terminal para PS1?

31

No meu .bashrc , eu uso códigos de cores do terminal ANSI para colorir vários bits. Parece assim:

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

em que virtual_env e git_branch são funções bash que produzem resultados na stdout.

Agora, para facilitar a leitura e a modificação, gostaria de armazenar os códigos de cores em variáveis e consultá-los, em vez de incorporá-los diretamente no PS1 . Então eu tenho um monte de variáveis assim:

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

Eu gostaria de poder escrever algo como:

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

Mas isso não funciona - os códigos de cores aparecem no prompt, como se tivessem escapado. As cores funcionam corretamente se eu usar aspas duplas em vez de PS1 , mas o prompt só muda quando eu faço source ~/.bashrc .

Já experimentei outras coisas que vi pessoas fazerem - usando printf , usando aspas simples para as cores, colocando as variáveis \[ e \] in PS1 em vez da variável color, mas nada parece funcionar.

Como posso usar variáveis para os códigos de cores?

    
por Ismail Badawi 03.07.2014 / 20:34

3 respostas

19

A solução é fazer com que o shell substitua as variáveis de cor ao definir o prompt, mas não as funções. Para fazer isso, use aspas duplas como tinha tentado originalmente, mas escape dos comandos para que eles não sejam avaliados até que o prompt seja desenhado.

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

Observe o \ antes do $() em cada comando.

Se fizermos eco disso, vemos:

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

Como você pode ver, as variáveis de cor foram substituídas, mas não os comandos.

    
por 03.07.2014 / 20:53
6

O problema é que sua variável GREEN contém a cadeia literal que consiste em "barra invertida barra invertida zero três três" e assim por diante. Ele não contém, por exemplo, um caractere de escape ASCII conforme necessário para fazer com que seu terminal mude de cor.

Você pode colocar caracteres de controle em GREEN (e YELLOW e RESET ) manualmente, mas uma opção muito melhor é usar tput para que você não precise codificar nada e você suportará qualquer tipo de terminal.

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

A razão pela qual o mundo quando você coloca "barra invertida zero três três", etc ... diretamente em PS1 é que a interpretação de certas sequências de barra invertida é um recurso do bash (veja a seção PROMPTING no manual.Esta substituição ocorre antes expansão do parâmetro, substituição de comando, expansão aritmética e remoção de cotação, embora, por isso não é aplicada aos resultados de todas as outras operações.

    
por 03.07.2014 / 20:53
2

Mude a maneira de preencher $ GREEN, $ YELLOW e $ RESET:

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

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '
    
por 03.07.2014 / 21:07