bash: O prompt fica visualmente quebrado [duplicado]

3

A idéia da minha configuração PS1 é mostrar algumas informações estendidas, como status do repositório do Mercurial ou do Git, tempo de execução do comando, etc. O prompt é dividido por duas linhas porque produz muitos caracteres para caber em uma única linha. Aqui está o meu PS1 no meu .bashrc (não tenho certeza se todo o código-fonte é necessário aqui, espero que ajude):

function prompt_status {
        local color_app="\e[1;38;5;214m"
        local color_branch="\e[1;38;5;32m"
        local color_revision="\e[0;38;5;64m"
        if git rev-parse --is-inside-work-tree &> /dev/null; then
                local branch="$(git rev-parse --abbrev-ref HEAD | tr -d '\n')"
                local revision="$(git rev-parse HEAD | tr -d '\n')"
                echo -ne $color_app"git "$color_branch"$branch "$color_revision"($revision)"
        elif hg status &> /dev/null; then
                local branch="$(hg branch | tr -d '\n')"
                local revision_number="$(hg identify -n | tr -d '\n')"
                local revision="$(hg parent --template '{node}' | tr -d '\n')"
                echo -ne $color_app"hg "$color_branch"$branch "$color_revision"($revision_number:$revision)"
        else
                return
        fi
        echo -e " \e[0m"
}

function prompt_return_value {
        RET=$?
        if [[ $RET -eq 0 ]]; then
                echo -ne "" #echo -ne "\e[32m$RET\e[0m"
        else
                echo -ne "\e[1;37;41m$RET\e[0m "
        fi
}

function timer_start {
        timer=${timer:-$SECONDS}
}

function timer_stop {
        seconds_elapsed=$(($SECONDS - $timer))
        unset timer
}

function prompt_seconds_elapsed {
        local c;
        local t=${seconds_elapsed}s
        if [ $seconds_elapsed -ge 60 ]; then
                c=196
                t=$(format_seconds $seconds_elapsed)
        elif [ $seconds_elapsed -ge 20 ]; then
                c=214
        elif [ $seconds_elapsed -ge 10 ]; then
                c=100
        elif [ $seconds_elapsed -ge 5 ]; then
                c=34
        elif [ $seconds_elapsed -ge 1 ]; then
                c=22
        else
                return
        fi
        echo -ne "\e[0;38;5;${c}m${t} \e[0m"
}

function format_seconds {
        ((h=${1}/3600))
        ((m=(${1}%3600)/60))
        ((s=${1}%60))
        printf "%02d:%02d:%02d\n" $h $m $s
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

export PS1="\n\e[1;38;5;106m\u@\h \e[0;38;5;136m\w\[\e[0m\]\n\$(prompt_return_value)\$(prompt_seconds_elapsed)\$(prompt_status)\$ "

O problema é que o prompt parece quebrado quando uma janela de terminal tem pouca largura. Isso é o que eu recebo por 80 colunas:

username@some-very-long-hostname ~/tmp/d
06a14b06cac) $ 9866c9d0d26d2b27063a89ee1c330

É como embrulhar na segunda linha causando confusão total (veja o sinal $ no meio). Ele funciona quase perfeitamente para um número de coluna de terminal maior, digamos 120:

username@some-very-long-hostname ~/tmp/d
hg default (0:69866c9d0d26d2b27063a89ee1c3306a14b06cac) $

Também notei que adicionar mais texto ao final da linha do terminal causa um problema muito semelhante aos efeitos descritos para as 80 colunas acima. A pergunta é: bash manipula novas linhas ou "muito longo" incorretamente para PS1 ?

Obrigado.

UPDATE

Esta questão não é uma cópia exata de Por que meu prompt do bash está recebendo bug quando eu navego no histórico? . Depois de alguma discussão com @AdamKatz, parece que a saída de comprimento zero escapa de \[ e '] funciona apenas quando são literalmente colocados na string PS1 , mas eles não parecem funcionar quando retornados de uma função que causa aparecem sem escape no terminal.

    
por Lyubomyr Shaydariv 18.03.2015 / 16:25

1 resposta

2

Para prompts de várias linhas (incluindo quando ele é agrupado, inclusive a partir de seus comandos), você precisa colocar os códigos de cores em colchetes com escape (como \[$color\] ).

Este exemplo é verde, tem user@hostname:workingdir $ e depois volta a ficar sem cor:

PS1='\[\e[1;32m\]\u@\h:\w \$\[\e[0;0m\]'
    
por 18.03.2015 / 16:32

Tags