我正在尝试执行一个更复杂的函数,该函数在 ZSH 中构造 PROMPT 字符串,在正常情况下,它可以正常工作。但是,由于我在提示符下发送 SIGINT 时有以下 TRAPINT 来打印“^C”,因此它不起作用(它不调用我的函数)。
.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 内部判断我是在提示符下,还是在正在运行的程序中,以便不能返回错误?
答案1
看来当 shell 以这种方式中断后,命令替换就不会被评估。
您可以使用钩子来解决这个问题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
,其成员可以通过提示转义符来访问%v
,或者%Nv
其中N
要显示的数组索引:precmd () { psvar[3]='>' } PROMPT='%3v'
答案2
我接受 Adaephon 的回答,但在这里发帖展示我的最终解决方案:
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 适当设置的标志在执行命令内。