Usar echo -e no PS1 causa problemas de quebra de linha no shell

Usar echo -e no PS1 causa problemas de quebra de linha no shell

As questões:

Abra o prompt da linha de comando:

insira a descrição da imagem aqui

Digite a letra várias vezes:

insira a descrição da imagem aqui

Em vez de quebrar em uma nova linha, o texto inserido é quebrado na mesma linha:

insira a descrição da imagem aqui

Agora, comece a pressionar b. Na segunda vez que uma quebra de linha for necessária, ela será quebrada em uma nova linha:

insira a descrição da imagem aqui


O que causa esse comportamento?

Usar um PS1 como este causa o comportamento:

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

Observe que o motivo pelo qual desejo usar echo em vez da cor diretamente é porque desejo adicionar a cor condicionalmente com base no status de saída do comando anterior.

Usar a cor diretamente não causa esse comportamento.


Minhas perguntas são:

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

Atualizar

Para ser claro, eu realmente quero fazer isso usando echo porque quero mudar a corcondicionalmente.

Isso é o que tenho atualmente:

function setPs1Colors_start () {

    local previousExit=$?

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

    echo -en $ps1Color

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

}

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

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

Responder1

\033[1;35mtem 7 caracteres. bashnão consigo adivinhar que esses 7 caracteres têm na verdade uma largura nula. Caso contrário, pensará que têm 7 colunas de largura.

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

Então você tem que dizer quais dos caracteres no prompt não movem o cursor. Com bash, isso é feito usando \[...\]which informa ao shell que o que está dentro tem largura zero.

Observe também que a expansão do prompt bashé reconhecida \ecomo um caractere ESC, portanto você não precisa usar echo -e. Você pode simplesmente fazer:

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

Se você tiver que usar echo, ou melhor printf, você faria:

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

Ou:

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

Em zsh, o equivalente a bash's \[...\]é %{...%}como em tcsh, mas zshtem diretivas para alterar os atributos dos caracteres, então você prefere fazer:

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

Para primeiro plano em negrito-magenta. Ele também possui algumas formas de testes condicionais, incluindo on $?, portanto, seu rederro if, verde caso contrário pode ser escrito:

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

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

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

Em ksh88ou pdksh, você faria:

PS1=$(printf '\5\r\5\33[1;35m\5blah $ ')

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

ksh93usa apenas uma sequência de posicionamento do cursor: BS(que move o cursor uma coluna para a esquerda). Para mover para a direita, basta redesenhar 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 se enrole sozinho na margem (portanto, não funcionará corretamente com esteterminatorpor exemplo). Um efeito colateral se você receber um prompt com sequências de controle é que suas paradas de tabulação não ficarão alinhadas corretamente.

informação relacionada