Gilles identificou seu principal problema, mas eu queria tentar explicá-lo de maneira diferente.
O Bash interpreta que o prompt especial escapa apenas antes de expandir quaisquer variáveis no prompt. Isso significa que o uso \e
de uma variável expandida a partir do prompt não funciona, mesmo que funcione diretamente PS1
.
Por exemplo, isso funciona conforme o esperado e fornece texto em vermelho:
PS1='\e[1;31m this is in red '
Mas isso não acontece, apenas coloca um literal \e
no prompt:
RED='\e[1;31m'
PS1="$RED not in red "
Se você deseja armazenar as fugas de cor nas variáveis, é possível usar ANSI-C entre aspas ( $'...'
) para colocar um caractere de escape literal na variável.
Para fazer isso, você pode mudar a sua definição de GREEN
, RED
e NONE
, por isso, o seu valor é a seqüência de escape real.
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
Se você fizer isso, o primeiro PS1
com aspas simples deve funcionar:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
No entanto, você terá um segundo problema.
Tente executar isso, pressione e Up Arrow, em seguida Home, e seu cursor não retornará ao início da linha.
Para corrigir isso, altere PS1
para incluir \[
e \]
contornar as seqüências de escape de cores, por exemplo
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
Você não pode usá-lo get_exit_status
corretamente aqui, pois a saída contém caracteres de impressão (o código de saída) e caracteres não imprimíveis (os códigos de cores), e não há como marcá-lo corretamente no prompt. A colocação \[...\]
marcaria como não imprimível na íntegra, o que não está correto. Você precisará alterar a função para que ela imprima apenas o código de cor adequado e, em seguida, coloque-a \[...\]
no prompt.
\[
é\1
e\[
é\2
. Aqueles corresponde a algo de alguma linha de leituraRL_PROMPT_{START,END}_IGNORE
que solicita que ele ignore os bytes ao contar o comprimento do prompt na tela. Consulte lists.gnu.org/archive/html/bug-bash/2015-08/msg00027.html .\]
é\2
? E você quer dizer que é por isso que é necessário${exitStatus}
? Meu ponto era que${exitStatus}
não contém caracteres não imprimíveis, então o bash deve ser capaz de determinar corretamente quantos caracteres ele se move o prompt sem a\[
e\]
no\[${exitStatus}\]
.\e
e\033
(e\[
/\]
,\u
e\h
) no prompt, apenas o faz antes de expandir as variáveis. EntãoPS1='\e[1;31m red'
funciona,red='\e[1;31m'; PS1='$red red'
não.Quando você executa
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
, aPS1
variável é definida como${RED}\h $(get_path) ${exitStatus}${NONE}
, onde apenas\h
é uma sequência de escape rápida. Depois que as seqüências de prompt são expandidas (produzindo${RED}darkstar $(get_path) ${exitStatus}${NONE}
), o shell executa as expansões usuais, como expansões variáveis. Você recebe um prompt exibido que se parece\e[1;31mdarkstar PATH 0\e[m
. Nada ao longo do caminho expande as\e
seqüências para caracteres de escape reais.Quando você executa
PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
, aPS1
variável é definida como\e[1;31m\h PATH 0\e[m
. As variáveisRED
,exitStatus
eNONE
são expandidos no momento da atribuição. Em seguida, a linha contém três sequências de escape rápidas (\e
,\h
, e\e
de novo). Não há variáveis de shell para expandir neste estágio.Para ver as cores, você precisa que as variáveis de cores contenham caracteres de escape reais. Você pode fazer assim:
$'…'
expande sequências de barra invertida-octal e algumas seqüências de letra de barra invertida como\n
, mas não incluindo\e
. Fiz três outras alterações no seu prompt:\[…\]
em seqüências que não sejam de impressão, como comandos de mudança de cor. Caso contrário, sua tela acabará distorcida porque o bash não pode descobrir a largura do prompt.\w
é uma sequência de escape interna para imprimir o diretório atual.$?
no prompt, se não tiver umPROMPT_COMMAND
em primeiro lugar.fonte
PS1
é errado, mas o conselho para uso$'...'
deRED
eGREEN
deve fazê-lo funcionar usando dogbane dePS1
.Experimentar:
fonte
Aqui está a abordagem que eu segui, evita o uso de
PROMPT_COMMAND
.Então meu
$PS1
é o seguinte:fonte
$?
pode ter é um número inteiro, você realmente deve usá-loprintf '%b' "$GREEN"
. Além disso, evite usar nomes de funções prefixados com__
ou_
como eles são usados pela conclusão do bash.Aqui você vai - Isso funciona para mim (TM) no Ubuntu e em outros Linux (Linuxen?).
O motivo para colocar a detecção do código de saída
$PS1
é que um host possui um$PROMPT_COMMAND
conjunto somente leitura antes da leitura do .bashrc.fonte
Por
PROMPT_COMMAND
isso, é mais fácil definir uma função e usar isso:fonte