^ C fazendo com que PROMPT = '$ (my_prompt_function)' nunca seja chamado

2

Estou tentando executar uma função mais complexa que constrói a cadeia PROMPT no ZSH e, em circunstâncias normais, está funcionando. No entanto, como eu tenho o seguinte TRAPINT para imprimir "^ C" quando envio SIGINT no prompt, ele não funciona (ele não chama minha função).

.zshrc

TRAPINT() {
    print -n "^C"
    return $(( 128 + $1 ))
}
my_prompt_function() {
    echo '>'
}
setopt PROMPT_SUBST
PROMPT='$(my_prompt_function)'

No entanto, se eu pressionar ^ C no prompt, ele simplesmente trava:

>
>^C
# ...hangs here until I press <Enter>

Como posso saber, a partir do TRAPINT, que estou no prompt, vs. em um programa em execução, para que eu não possa retornar um erro?

    
por Jrop 06.12.2016 / 21:13

2 respostas

1

Parece que a substituição do comando não é avaliada depois que o shell foi interrompido dessa maneira.

Você poderia contorná-lo usando o precmd hook:

precmd () {
    MYPROMPT='>'
}
setopt PROMPT_SUBST
PROMPT='${MYPROMPT}'

precmd é executado antes de cada prompt. Observe que precmd não é executado novamente nos casos em que o prompt é apenas redesenhado sem executar uma linha de comando (como neste caso). Ele ainda funciona, pois o valor de MYPROMPT permanece mesmo sem executar precmd .

  • Você também pode ter várias funções precmd . Você pode gerenciá-los com o módulo add-zsh-hook :

    autoload -Uz add-zsh-hook
    myprompt_function () {
        MYPROMPT='>'
    }
    add-zsh-hook precmd myprompt_function
    setopt PROMPT_SUBST
    PROMPT='${MYPROMPT}'
    
  • Você também pode usar a variável de matriz especial psvar , cujos membros podem ser acessados com o prompt escape %v ou %Nv , em que N é o índice da matriz a ser exibido:

    precmd () {
        psvar[3]='>'
    }
    PROMPT='%3v'
    
por 13.12.2016 / 09:39
0

Estou aceitando a resposta de Adaephon, mas postando aqui para mostrar minha solução final:

TRAPINT() {
  if [ "$IS_PROMPTING" == true ]; then
    print -n "^C"
    return $(( 128 + $1 ))
  fi
}
precmd() {
  IS_PROMPTING=true
  PROMPT=$(command-that-generates-prompt-string)
}
preexec() {
  IS_PROMPTING=false
}

O TRAPINT verifica condicionalmente se o usuário está no prompt ou dentro de um comando de execução por meio de um sinalizador definido apropriadamente via precmd / preexec.

    
por 13.12.2016 / 16:08

Tags