Zsh提示只显示一次上一个错误代码

Mar*_*rný 11 zsh

当前一个命令失败时,我希望我的提示显示交叉(✘).我使用以下代码:

export PROMPT=$'%(?..?\n)\n› '
Run Code Online (Sandbox Code Playgroud)

这给了我以下输出:

› echo Hello
Hello

› asjdfiasdf
zsh: command not found: asjdfiasdf
?

› 
?
Run Code Online (Sandbox Code Playgroud)

我想修改提示,以便在重新绘制提示后不重复交叉Enter(上例中的第三种情况).

可能吗?

sne*_*eep 7

我想我明白了.如果您发现错误,请告诉我...

preexec() {
    preexec_called=1
}
precmd() {
    if [ "$?" != 0 ] && [ "$preexec_called" = 1 ]
    then echo ?; unset preexec_called; fi
}
PROMPT=$'\n› '
Run Code Online (Sandbox Code Playgroud)

结果:

› ofaoisfsaoifoisafas
zsh: command not found: ofaoisfsaoifoisafas
?  

› 

› echo $? # (not overwritten)
127
Run Code Online (Sandbox Code Playgroud)


Ada*_*atz 5

我在 zsh 中执行此操作,但使用的是颜色而不是 unicode 字符。原理是一样的。

\n\n

首先,我设置颜色,确保仅在支持时使用它们:

\n\n\n\n
case $TERM in\n\n( rxvt* | vt100* | xterm* | linux | dtterm* | screen )\n  function PSC() { echo -n "%{\\e[${*}m%}"; } # insert color-specifying chars\n  ERR="%(0?,`PSC \'0;32\'`,`PSC \'1;31\'`)"      # if last cmd!=err, hash=green, else red\n  ;;\n\n( * )\n  function PSC() { true; }   # no color support? no problem!\n  ERR=\n  ;;\n\nesac\n
Run Code Online (Sandbox Code Playgroud)\n\n

接下来,我设置了一个神奇的输入函数(感谢这篇关于空命令的文章(忽略这个问题,看看我如何在这里调整它):

\n\n
function magic-enter() {    # from https://superuser.com/a/625663\n  if [[ -n $BUFFER ]]\n    then unset Z_EMPTY_CMD  # Enter was pressed on an empty line\n    else Z_EMPTY_CMD=1      # The line was NOT empty when Enter was pressed\n  fi\n  zle accept-line           # still perform the standard binding for Enter\n}\nzle -N magic-enter          # define magic-enter as a widget\nbindkey "^M" magic-enter    # Backup: use ^J\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在是时候解释捕获命令并使用其返回代码来设置提示颜色:

\n\n
setopt prompt_subst # allow variable substitution\n\nfunction preexec() { # just after cmd has been read, right before execution\n  Z_LAST_CMD="$1"   # since $_ is unreliable in the prompt\n  #Z_LAST_CMD="${1[(wr)^(*=*|sudo|-*)]}"    # avoid sudo prefix & options\n  Z_LAST_CMD_START="$(print -Pn \'%D{%s.%.}\')"\n  Z_LAST_CMD_START="${Z_LAST_CMD_START%.}" # zsh <= 5.1.1 makes %. a literal dot\n  Z_LAST_CMD_START="${Z_LAST_CMD_START%[%]}" # zsh <= 4.3.11 makes %. literal\n}\n\nfunction precmd() { # just before the prompt is rendered\n  local Z_LAST_RETVAL=$?                  # $? only works on the first line here\n  Z_PROMPT_EPOCH="$(print -Pn \'%D{%s.%.}\')"  # nanoseconds, like date +%s.%N\n  Z_PROMPT_EPOCH="${Z_PROMPT_EPOCH%.}"    # zsh <= 5.1.1 makes %. a literal dot\n  Z_PROMPT_EPOCH="${Z_PROMPT_EPOCH%[%]}"  # zsh <= 4.3.11 makes %. a literal %.\n  if [ -n "$Z_LAST_CMD_START" ]; then\n    Z_LAST_CMD_ELAPSED="$(( $Z_PROMPT_EPOCH - $Z_LAST_CMD_START ))"\n    Z_LAST_CMD_ELAPSED="$(printf %.3f "$Z_LAST_CMD_ELAPSED")s"\n  else\n    Z_LAST_CMD_ELAPSED="unknown time"\n  fi\n\n  # full line for error if we JUST got one (not after hitting <enter>)\n  if [ -z "$Z_EMPTY_CMD" ] && [ $Z_LAST_RETVAL != 0 ]; then\n    N=$\'\\n\'  # set $N to a literal line break\n    LERR="$N$(PSC \'1;0\')[$(PSC \'1;31\')%D{%Y/%m/%d %T}$(PSC \'1;0\')]"\n    LERR="$LERR$(PSC \'0;0\') code $(PSC \'1;31\')$Z_LAST_RETVAL"\n    LERR="$LERR$(PSC \'0;0\') returned by last command"\n    LERR="$LERR (run in \\$Z_LAST_CMD_ELAPSED):$N"\n    LERR="$LERR$(PSC \'1;31\')\\$Z_LAST_CMD$(PSC \'0;0\')$N$N"\n    print -PR "$LERR"\n  fi\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后设置提示:

\n\n
PROMPT="$(PSC \'0;33\')[$(PSC \'0;32\')%n@%m$(PSC \'0;33\') %~$PR]$ERR%#$(PSC \'0;0\') "\n
Run Code Online (Sandbox Code Playgroud)\n\n

它看起来是这样的:

\n\n

截屏

\n\n

 

\n\n

对这个问题的更直接的回答,改编自上面的内容:

\n\n
function magic-enter() {    # from https://superuser.com/a/625663\n  if [[ -n $BUFFER ]]\n    then unset Z_EMPTY_CMD  # Enter was pressed on an empty line\n    else Z_EMPTY_CMD=1      # The line was NOT empty when Enter was pressed\n  fi\n  zle accept-line           # still perform the standard binding for Enter\n}\nzle -N magic-enter          # define magic-enter as a widget\nbindkey "^M" magic-enter    # Backup: use ^J\n\nfunction precmd() { # just before the prompt is rendered\n  local Z_LAST_RETVAL=$?                  # $? only works on the first line here\n\n  # full line for error if we JUST got one (not after hitting <enter>)\n  if [ -z "$Z_EMPTY_CMD" ] && [ $Z_LAST_RETVAL != 0 ]; then\n    echo \'\xe2\x9c\x98\'\n  fi\n}\n\nPROMPT=$\'\\n\xe2\x80\xba \'\n
Run Code Online (Sandbox Code Playgroud)\n\n

与屏幕截图:

\n\n

更简单的截图

\n