2

Я пытаюсь выполнить более сложную функцию, которая создает строку PROMPT в ZSH, и в нормальных условиях она работает. Однако, поскольку у меня есть следующий TRAPINT для печати «^ C» при отправке SIGINT в приглашении, он не работает (он не вызывает мою функцию).

.zshrc

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

Однако, если я нажимаю ^ C в приглашении, он просто зависает:

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

Как мне сказать изнутри TRAPINT, что я в приглашении, а не в работающей программе, чтобы я не мог вернуть ошибку?

2 ответа2

1

Кажется, что подстановка команды не оценивается после того, как оболочка была прервана таким образом.

Вы можете обойти это, используя крюк precmd :

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

precmd запускается перед каждым приглашением. Обратите внимание, что precmd не выполняется повторно в тех случаях, когда приглашение просто перерисовывается без запуска командной строки (как в этом случае). Он все еще работает, так как значение MYPROMPT остается даже без запуска precmd .


  • Вы также можете иметь несколько функций precmd . Вы можете управлять ими с помощью модуля add-zsh-hook :

    autoload -Uz add-zsh-hook
    myprompt_function () {
        MYPROMPT='>'
    }
    add-zsh-hook precmd myprompt_function
    setopt PROMPT_SUBST
    PROMPT='${MYPROMPT}'
    
  • Вы также можете использовать специальную переменную массива psvar , доступ к членам которой можно получить с помощью подсказки escape %v или %Nv где N - индекс массива, который будет отображаться:

    precmd () {
        psvar[3]='>'
    }
    PROMPT='%3v'
    
0

Я принимаю ответ Адафона, но публикую здесь, чтобы показать мое окончательное решение:

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
}

TRAPINT условно проверяет, находится ли пользователь в приглашении или в исполняющей команде с помощью флага, который соответствующим образом установлен через precmd/preexec.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .