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

2

Estou tentando executar uma função mais complexa que constrói a seqüência de caracteres PROMPT no ZSH e, em circunstâncias normais, está funcionando. No entanto, como tenho o seguinte TRAPINT para imprimir "^ C" quando envio o SIGINT no prompt, ele não funciona (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 ^Cno prompt, ele simplesmente trava:

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

Como posso dizer, de dentro do TRAPINT, que estou no prompt, vs. em um programa em execução, para que não possa retornar um erro?

Jrop
fonte

Respostas:

1

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

Você pode contornar isso usando o precmdgancho:

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

precmdé executado antes de cada prompt. Observe que precmdnão é reexecutado nos casos em que o prompt é apenas redesenhado sem executar uma linha de comando (como neste caso). Ainda funciona como o valor dos MYPROMPTrestos mesmo sem execução precmd.


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

    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 especial da matriz psvar, cujos membros podem ser acessados ​​com o escape imediato %vou %Nvonde Nestá o índice da matriz a ser exibido:

    precmd () {
        psvar[3]='>'
    }
    PROMPT='%3v'
Adaephon
fonte
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 para ver se o usuário está no prompt ou dentro de um comando de execução por meio de um sinalizador que está definido adequadamente via precmd / preexec.

Jrop
fonte