Como incluir comandos no PS1 do Bash sem quebrar o cálculo do comprimento da linha?

12

Tonin apontou um bug no meu prompt padrão . Exemplo mínimo:

  1. Defina PS1:

    PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " ")$ '
    

    Neste ponto, o prompt é assim:

    $ 
    
  2. Agora acione a saída do código de saída executando:

    false
    

    Agora, o prompt contém o código de saída em vermelho no início da linha:

    1 $ 
    
  3. Pressione Ctrl - r .
  4. Digite "false". Agora o prompt contém apenas a pesquisa:

    (reverse-i-search)'false': false
    
  5. Pressione Enter .

O histórico do terminal resultante agora contém o seguinte:

1 $ch)'false': false

Resultado esperado:

1 $ false

Ou seja, parece que a saída da pesquisa de histórico é misturada com o prompt e ocultando o comando real que foi executado.

Eu tentei trabalhar com isso por usando PROMPT_COMMAND :

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " "
}
set_bash_prompt() {
    PS1='$(set_exit_code)$ ' # Double quotes give the same result
}
PROMPT_COMMAND=set_bash_prompt

Isso parece não funcionar - a linha parece exatamente igual a antes de pesquisar e executar.

Como posso corrigir isso?

    
por l0b0 19.12.2013 / 18:22

3 respostas

8

Eu encontrei a resposta em askubuntu.com . @qeirha mencionou que você precisa dizer ao bash que a sequência de caracteres não deve ser contada no comprimento do prompt, e você faz isso colocando-o em \[ \] . Com base no exemplo fornecido, aqui está uma solução:

red=$(tput setaf 1)

reset=$(tput sgr0)

[ "$PS1" = "\s-\v\\$ " ] && PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$red\] $exit_code \[$reset\] " ")$ '
    
por 19.12.2013 / 19:25
1
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] " ")$ '

(Desculpe, nenhuma explicação aqui. Veja Como personalizar a PS1 corretamente? ou qualquer outra pergunta sobre problemas de cálculo do tamanho do prompt e \[ .. \] .)

    
por 13.04.2017 / 14:36
1

Expandindo a resposta do @manatwork, mas mantendo seu código dividindo o PS1 compute em diferentes funções, você pode escrever o seu prompt da seguinte maneira:

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf "\[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] "
}
set_bash_prompt() {
    PS1="$(set_exit_code)$ " # with double quotes!
}
PROMPT_COMMAND=set_bash_prompt

As aspas duplas são obrigatórias quando você configura PS1 e quando usa printf na função.

    
por 19.12.2013 / 22:05

Tags