Usando echo -e no PS1 causa problemas de quebra de linha no shell [duplicado]

0

Os problemas :

Abra o prompt da linha de comando:

Digitealetraváriasvezes:

Emvezdeenvolverumanovalinha,otextoéinseridonamesmalinha:

Agora,comeceapressionarb.Nasegundavezemqueumaquebradelinhaénecessária,elaseráagrupadaemumanovalinha:

Oquecausaessecomportamento?

UsarumPS1assimcausaocomportamento:

ps1Color="3[1;35m"
export PS1='$(echo -en $ps1Color) Baz $'

Note que a razão pela qual eu quero usar o echo em vez da cor diretamente é porque eu quero adicionar a cor condicionalmente com base no status de saída do comando anterior .

Usar a cor diretamente não faz com que esse comportamento ocorra.

Minhas perguntas são:

  • Como posso imprimir códigos de cores para uso em um PS1 usando echo ?
  • Se eu quiser fazer da minha PS1 uma cor diferente condicionalmente, qual é a melhor maneira de fazer isso?
  • Por que estou vendo esse comportamento?

Atualizar

Para deixar claro, eu realmente quero fazer isso usando echo porque eu quero mudar a cor condicionalmente .

Isso é o que eu tenho atualmente:

function setPs1Colors_start () {

    local previousExit=$?

    local ps1Color="3[1;35m"
    local ps1FailBackground="\e[41m"

    echo -en $ps1Color

    if [[ previousExit -ne 0 ]]
    then
        echo -en $ps1FailBackground
    fi

}

function setPs1Colors_end () {
    local ps1DefaultColor="3[0m"
    echo -en $ps1DefaultColor
}

export PS1='$(setPs1Colors_start)[$(date +%b\-%d\ %k:%M)][$(versionControlInfo)\W]\$$(setPs1Colors_end) '
    
por sixtyfootersdude 26.05.2017 / 22:22

1 resposta

6

3[1;35m tem 7 caracteres. bash não pode adivinhar que esses 7 caracteres têm realmente uma largura nula. Se não, achará que eles têm 7 colunas de largura.

Ele (ou melhor, readline o editor de linhas subjacente que ele usa) quer saber qual é a posição atual na tela porque está usando sequências de posicionamento do cursor (para cima, baixo, esquerda, direita) para mover o cursor quando você re usando chaves de edição.

Então você precisa dizer qual dos caracteres no prompt não move o cursor. Com bash , isso é feito usando \[...\] , que informa ao shell que o conteúdo tem largura zero.

Observe também que a expansão rápida em bash reconhece \e como um caractere ESC, portanto, você não precisa usar echo -e . Você pode apenas fazer:

PS1='\[\e[1;35m\] blah $ '

Se você tiver que usar echo ou melhor printf , faça:

PS1='\[$(if ...; then printf "$color1"; fi)\] blah $ '

Ou:

PS1='$(if ...; then printf "\[$color1\]"; fi) blah $ '

Em zsh , o equivalente a bash ' \[...\] é %{...%} como tcsh , mas zsh tem diretivas para alterar atributos de caractere, então você preferiria fazer:

PS1='%B%F{magenta}blah $ '

Para o primeiro plano em negrito e magenta. Ele também tem algumas formas de testes condicionais, incluindo $? , portanto, seu erro red , caso contrário, verde poderia ser escrito:

PS1='%F{%(?:green:red%)}blah%f $ '

tcsh tem %B , mas não %F{color} . Então, você usaria:

set prompt = '%{\e[1;35m%}blah $ '

Em ksh88 ou pdksh , você faria:

PS1=$(printf '\r[1;35mblah $ ')

Isso define um caractere (aqui 0x5) como o caractere escape . Então, colocando o texto entre um par deles, você está dizendo ao shell que não é visível. Você pode usar qualquer caractere diferente de 0x5, mas não deve ocorrer em seu prompt e, exceto em mksh, ele deve ser ignorado pelo terminal porque o shell realmente o grava (junto com o caractere CR).

ksh93 usa apenas uma seqüência de posicionamento do cursor: BS (que move o cursor uma coluna para a esquerda). Para ir para a direita, ele apenas redesenha os mesmos caracteres. Portanto, não é necessário saber a posição do cursor, apenas a largura de cada caractere digitado. Isso funciona desde que o terminal esteja sozinho na margem (por isso não funcionará corretamente com este terminator por exemplo). Um efeito colateral se você tiver um prompt com seqüências de controle é que suas paradas de tabulação não serão alinhadas corretamente.

    
por 26.05.2017 / 22:34

Tags