Re-escape os parênteses no PS1

5

Como outros outros apontaram, os códigos de cor em PS1 devem ser colocados entre \[ e \] para evitar que ocupem espaço horizontal. Eu adicionei o código necessário para .bashrc :

highlight()
{
    if [ -x /usr/bin/tput ]
    then
        printf '\['
        tput bold
        printf '\]'
        printf '\['
        tput setaf $1
        printf '\]'
    fi
    shift
    printf -- "$@"
    if [ -x /usr/bin/tput ]
    then
        printf '\['
        tput sgr0
        printf '\]'
    fi
}

highlight_error()
{
    highlight 1 "$@"
}

A última função é usada em PS1 nas substituições dos comandos normal e escape para poder alterar a string com base no resultado do comando anterior:

# Exit code
PS1="\$(exit_code=\${?#0}
highlight_error \"\${exit_code}\${exit_code:+ }\")"

...

if [ "$USER" == 'root' ]
then
    PS1="${PS1}$(highlight_error '\u')"
else
    PS1="${PS1}\u"
fi

O problema é que os colchetes com escape são emitidos como literais, então meu prompt se parece com isso depois de executar um comando que não existe:

\[\]\[\]127 \[\]user@machine:/path
$

Não foi possível envolver o escape highlight_error em printf %b . Como posso corrigir a saída para que eu possa usar as funções para as substituições de comando normais e com escape ?

    
por l0b0 12.04.2011 / 10:30

2 respostas

4

Parece que qualquer seqüência de escape realmente em PS1 literalmente precisa ser agrupada em \[ e \] , mas se você chamar uma função ou comando que produza saída, ela não precisará ser quebrada.

Então, por que não apenas mover o

"\$(exit_code=\${?#0}
highlight_error \"\${exit_code}\${exit_code:+ }\")"

material dentro de uma função, por exemplo

print_error_if_error()
{
    exit_code=$?
    if [ $exit_code -ne 0 ]; then
        highlight_error "$exit_code "
    fi
}

e, em seguida, acho que você pode remover todas as coisas \[ e \] ...

highlight()
{
    if [ -x /usr/bin/tput ]
    then
        tput bold
        tput setaf $1
    fi
    shift
    printf -- "$@"
    if [ -x /usr/bin/tput ]
    then
        tput sgr0
    fi
}

highlight_error()
{
    highlight 1 "$@"
}

PS1='$(print_error_if_error)'

# ...

if [ "$USER" = 'root' ]
then
    PS1="${PS1}$(highlight_error '\u')"
else
    PS1="${PS1}\u"
fi
    
por 12.04.2011 / 12:14
0

Veja essa pergunta sobre SO para obter uma solução usando o $PROMPT_COMMAND variable. Escreva o nome de uma função nela que será chamada toda vez que um novo prompt for exibido. Se você definir PS1 nessa função, poderá resolver seu problema e ter comandos de cores nas funções:

# ... Using your highlight and highlight_error functions ...

prompt(){
    exit_code=${?}
    PS1="\u@\h \$ "
    if [[ $exit_code != 0 ]];then
        PS1="$(highlight_error "($exit_code)") $PS1"
    fi
}

PROMPT_COMMAND="prompt"
    
por 06.10.2016 / 16:31