Usando variáveis ​​para armazenar códigos de cores de terminal para PS1?


33

No meu .bashrc, uso códigos de cores do terminal ANSI para colorir vários bits. Se parece com isso:

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

onde virtual_enve git_branchsão funções bash que produzem coisas no stdout.

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

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[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 funcionarão corretamente se eu usar aspas duplas em vez disso PS1, mas o prompt somente será alterado quando o fizer source ~/.bashrc.

Eu tentei outras coisas que vi pessoas fazerem - usando printf, usando aspas simples para as cores, colocando a variável in \[e \]ao PS1invés da variável de cor, mas nada parece funcionar.

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


Você pode nos dar o seu .bashrc?
18714 cu Cullm

@cuonglm Todos os seus .bashrc pertencem a nós? Eu vou me mostrar.
CivFan

Respostas:


20

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 você havia tentado originalmente, mas escape dos comandos para que 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 ecoarmos isso, vemos:

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

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


1
Isso não parece funcionar se $ (git_branch) também estiver tentando imprimir usando $ {YELLOW} etc. Somente nessa seção, você ainda terá todos os caracteres [].
WB Reed

7

O problema é que sua variável GREENconté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 que o terminal mude de cor.

Você pode colocar caracteres de controle em GREEN(e YELLOWe RESET) manualmente, mas uma opção muito melhor é usar tputem primeiro lugar para que você não precise codificar nada e suporte 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 PS1é que a interpretação de certas seqüências de barra invertida é um recurso do prompt do bash (consulte a seção PROMPTING no manual. Esta substituição ocorre antes da expansão do parâmetro, comando substituição, expansão aritmética e remoção de cotação, portanto, não é aplicada aos resultados de todas as outras operações.


5
Ao fazer isso dessa maneira, você precisa agrupar as variáveis ​​de cores \[\]dentro do $PS1. Por exemplo: PS1='\u@\h:\w\[${YELLOW}\]'. Se você não fizer isso e acabar com um comando longo que passa para a próxima linha, encontrará todos os tipos de problemas. O shell usa o \[\]para determinar quais caracteres não são imprimíveis, portanto, não os fatoram no cálculo do tamanho do prompt. Ele precisa disso para que possa desenhar corretamente a linha quando exceder a largura do terminal.
317 Patrick Patrick

Eu não sabia tput, obrigado. Vou usar a resposta de Patrick por enquanto, mas revisitarei isso quando tiver uma chance.
Ismail Badawi

2

Mude a maneira como você preenche $ VERDE, $ AMARELO e $ RESET:

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
Isso, na verdade, faz exatamente a mesma coisa que a resposta de Celada. Mas o Celada é mais portátil, caso o terminal use códigos de escape diferentes para a configuração de cores. Também terá o mesmo problema com o prompt de várias linhas.
317 Patrick Patrick

2
O \[…\]bit precisa permanecer no prompt, você não pode colocá-lo em uma variável. Você o removeu completamente, o que resultará em problemas de exibição (o cursor não estará na posição em que o bash espera).
Gilles 'SO- stop be evil'

Além das preocupações com @Patrick, o echo -e não é portátil.
Helpermethod

1
Com a não portabilidade, surgem mais recursos - tput setafnão permite escolher entre o conjunto de cores "claras", como o ciano claro. @ A resposta de Cyrus, no entanto, sim.
CivFan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.