Bash prompt que não vai atrapalhar comandos longos

6

Estou tentando configurar um prompt bash para - hostname(screen#):directory$ , que é colorido em verde se o último comando for concluído com êxito, vermelho, se não. Isto é o que eu tenho até agora, que realmente faz o trabalho, mas parece causar problemas de exibição, se o comando envolver uma linha:

 PS1="\[\'if [[ \$? = "0" ]]; then echo '\e[32m'; else echo '\e[31m' ; fi\' - \h(${WINDOW}):\W$\e[00m "

Pesquisando o problema, encontramos esta útil postagem de SO com um comentário que menciona caracteres não-imprimíveis em \[ e \] para evitar esse problema. Por isso, tentei o seguinte, mas isso não resolveu o problema e, além disso, quebra a mudança de cor:

PS1="\[\'if [[ \$? = "0" ]]; then echo '\e[32m'; else echo '\e[31m' ; fi\'\] - \h(${WINDOW}):\W$\[\e[00m\] "

Como posso manter a estrutura deste prompt, com cores, mas corrigi-lo para que comandos longos sejam exibidos corretamente?

    
por dotancohen 20.11.2012 / 19:33

4 respostas

9

Eu tenho um prompt de fantasia com cores, e agora bash não parece saber o quão grande é o meu terminal. As linhas envolvem incorretamente.

Eu tenho outra maneira correta de fazer isso, colocar esse código no seu ~/.bashrc ou criar um novo arquivo e source file :

PROMPT_COMMAND=$(
    cat<<-'EOF'

    retval=$?

    RED=$(tput setaf 1)
    GREEN=$(tput setaf 2)
    STOP=$(tput sgr0)

    # arithmetic using bash parameter expansion on a array
    if (($retval + ${PIPESTATUS[@]/%/+} + 0)); then
        PS1="\[$RED\]\u@\h:\w$ \[$STOP\]"
    else
        PS1="\[$GREEN\]\u@\h:\w$ \[$STOP\]"
    fi
EOF
)

Isso fará o truque =)

O Bash executará o código dentro de PROMPT_COMMAND para cada comando.

Se você tem problema de copiar / colar, você pode baixar o script

EXPLICAÇÕES

  • (())éaritméticaembash,consulte link
  • PROMPT_COMMAND : se definido, o valor é executado como um comando antes de emitir cada prompt principal. Veja man bash | less +/PROMPT_COMMAND
  • tput é melhor que códigos de escape ANSI de codificação rígida. Consulte o link
  • PIPESTATUS : uma variável de matriz contendo uma lista de valores de status de saída dos processos no pipeline de primeiro plano executado mais recentemente (que pode conter apenas um único comando). Veja man bash | less +/PIPESTATUS
  • cat<<-'EOF' é um aqui doc especial: o caractere - significa que posso indentar código, e as aspas simples em 'EOF' significam não interpolar variáveis
por 20.11.2012 / 21:20
3

Eu tenho um prompt de 2 linhas, então o material potencialmente longo não afetará a linha de comando:

glennj@homebase ~/tmp
2219 $ set | grep PS1=
PS1='\n\u@\h \w\n\! \$ '
    
por 21.11.2012 / 00:43
1

Não é \[ , apenas \[ . Você também tem um \[ extra no início.

    
por 20.11.2012 / 20:00
1

Esta não é uma resposta direta à pergunta original, é apenas um exemplo de uso.

Baseado e graças à resposta do @ stArdustͲ, encontrei uma solução adequada para um prompt de comando personalizado para mostrar o status da bateria * , no canto superior direito do terminal. As cores são definidas em um arquivo independente que é originado de dentro de .bashrc .

PROMPT_COMMAND=$(
    cat<<-'EOF'
    function battery_percentage {
        PERCENTAGE=$(upower -i $(echo $(upower -e |grep 'battery')) |grep 'percentage' |sed -e 's/^[ \t]*//;s/[[:space:]]\+/ /g;s/[ \t]*$//' |cut -d' ' -f2 |cut -d"%" -f1)
        BColor='IGray'
        if [ "${PERCENTAGE}" -lt 15 ]
            then PColor='BlinkIRed'
                 PBackground='On_White'
            else PColor='Gray'
        fi
        echo "
\[\e[s\]\[\e[1;$((COLUMNS-26))f\]
PROMPT_COMMAND=$(
    cat<<-'EOF'
    function battery_percentage {
        PERCENTAGE=$(upower -i $(echo $(upower -e |grep 'battery')) |grep 'percentage' |sed -e 's/^[ \t]*//;s/[[:space:]]\+/ /g;s/[ \t]*$//' |cut -d' ' -f2 |cut -d"%" -f1)
        BColor='IGray'
        if [ "${PERCENTAGE}" -lt 15 ]
            then PColor='BlinkIRed'
                 PBackground='On_White'
            else PColor='Gray'
        fi
        echo "
\[\e[s\]\[\e[1;$((COLUMNS-26))f\]%pre%1\e[0;38;5;8m%pre%2Battery%pre%1\e[0;38;5;7m%pre%2 82% %pre%1\e[0m%pre%2 %pre%1\e[0;38;5;8m%pre%23.6 hours%pre%1\e[0m%pre%2\[\e[u\]\[\e[0;38;5;232m\]\[\e[48;5;5m\] \u \[\e[0;38;5;5m\]\[\e[48;5;11m\] \[\e[0;38;5;232m\]\[\e[48;5;11m\]@\H \[\e[0;38;5;11m\]\[\e[48;5;0m\]\[\e[0m\] \[\e[0;38;5;6m\]\w\a \[\e[1;38;5;5m\]→\e[0m
1${!BColor}%pre%2Battery%pre%1${!PColor}%pre%2 ${PERCENTAGE}% %pre%1${Reset}%pre%2" } function battery_time { TIME=$(upower -i $(echo $(upower -e |grep 'battery')) |grep 'time' |sed -e 's/^[ \t]*//;s/[[:space:]]\+/ /g;s/[ \t]*$//' |cut -d' ' -f4,5) echo "%pre%1${IGray}%pre%2${TIME}%pre%1${Reset}%pre%2" } export PS1="\[\e[s\]\[\e[1;\$((COLUMNS-26))f\]$(battery_percentage) $(battery_time)\[\e[u\]${PS1}" EOF )
1\e[0;38;5;8m%pre%2Battery%pre%1\e[0;38;5;7m%pre%2 82% %pre%1\e[0m%pre%2 %pre%1\e[0;38;5;8m%pre%23.6 hours%pre%1\e[0m%pre%2\[\e[u\]\[\e[0;38;5;232m\]\[\e[48;5;5m\] \u \[\e[0;38;5;5m\]\[\e[48;5;11m\] \[\e[0;38;5;232m\]\[\e[48;5;11m\]@\H \[\e[0;38;5;11m\]\[\e[48;5;0m\]\[\e[0m\] \[\e[0;38;5;6m\]\w\a \[\e[1;38;5;5m\]→\e[0m
1${!BColor}%pre%2Battery%pre%1${!PColor}%pre%2 ${PERCENTAGE}% %pre%1${Reset}%pre%2" } function battery_time { TIME=$(upower -i $(echo $(upower -e |grep 'battery')) |grep 'time' |sed -e 's/^[ \t]*//;s/[[:space:]]\+/ /g;s/[ \t]*$//' |cut -d' ' -f4,5) echo "%pre%1${IGray}%pre%2${TIME}%pre%1${Reset}%pre%2" } export PS1="\[\e[s\]\[\e[1;\$((COLUMNS-26))f\]$(battery_percentage) $(battery_time)\[\e[u\]${PS1}" EOF )

Finalmente, o PS1 se parece com:

%pre%

Note, Eu tenho alguns problemas de posicionamento do cursor, porém, quando eu rolar para cima e para baixo através do histórico de comandos.

* de um laptop ThinkPad

    
por 06.04.2015 / 13:29

Tags