zsh:命令启动时使用当前时间更新提示

zsh:命令启动时使用当前时间更新提示,zsh,prompt,zsh-zle,Zsh,Prompt,Zsh Zle,我有一个zsh提示符,我比较喜欢:它在precmd中计算当前时间,并在提示符的右侧显示: [Floatie:~] ^_^ cbowns% [9:28:31 on 2012-10-29] 但是,这并不是我想要的:正如您在下面看到的,这次实际上是上一个命令退出的时间,而不是命令启动的时间: [Floatie:~] ^_^ cbowns% date [9:28:26 on 2012-10-29] Mon

我有一个
zsh
提示符,我比较喜欢:它在
precmd
中计算当前时间,并在提示符的右侧显示:

[Floatie:~] ^_^ 
cbowns%                      [9:28:31 on 2012-10-29]
但是,这并不是我想要的:正如您在下面看到的,这次实际上是上一个命令退出的时间,而不是命令启动的时间:

[Floatie:~] ^_^ 
cbowns% date                           [9:28:26 on 2012-10-29]
Mon Oct 29 09:28:31 PDT 2012
[Floatie:~] ^_^ 
cbowns% date                           [9:28:31 on 2012-10-29]
Mon Oct 29 09:28:37 PDT 2012
[Floatie:~] ^_^ 
cbowns%                                [9:28:37 on 2012-10-29]
zsh
中是否有钩子在shell启动新命令之前运行命令,这样我就可以更新提示符时间戳?(我看到了,但我不需要它不断更新,只要在我按enter键时更新即可。)


^ ^
基于上一个命令的返回代码。当存在非零退出状态时,它以红色显示

zsh
将在执行行之前运行
preexec
函数。将该输出设置为当前时间是很简单的,一个简单的版本就是:

preexec() { date }
修改现有的提示将更具挑战性。

您可以使用它来覆盖前一行,如下所示:

preexec () {
  DATE=`date +"%H:%M:%S on %Y-%m-%d"`
  C=$(($COLUMNS-24))
  echo -e "\033[1A\033[${C}C ${DATE} "
}

事实上,这是可能的,无需求助于奇怪的黑客。我的.zshrc里有这个

RPROMPT='[%D{%L:%M:%S %p}]'

TMOUT=1

TRAPALRM() {
    zle reset-prompt
}
TRAPALRM函数每TMOUT秒调用一次(在本例中为1),在这里它执行提示刷新,直到命令开始执行为止(并且它不会干扰您在按enter键之前在提示上键入的任何内容)。我知道你不需要它不断刷新,但它仍然可以完成工作,而不需要一条线路


资料来源:(这是从2007年开始的!)

我很难做到这一点:

它在命令执行的右侧显示日期。 它不会覆盖显示的命令。 警告:它可能会覆盖当前的RPROMPT

strlen () {
    FOO=$1
    local zero='%([BSUbfksu]|([FB]|){*})'
    LEN=${#${(S%%)FOO//$~zero/}}
    echo $LEN
}

# show right prompt with date ONLY when command is executed
preexec () {
    DATE=$( date +"[%H:%M:%S]" )
    local len_right=$( strlen "$DATE" )
    len_right=$(( $len_right+1 ))
    local right_start=$(($COLUMNS - $len_right))

    local len_cmd=$( strlen "$@" )
    local len_prompt=$(strlen "$PROMPT" )
    local len_left=$(($len_cmd+$len_prompt))

    RDATE="\033[${right_start}C ${DATE}"

    if [ $len_left -lt $right_start ]; then
        # command does not overwrite right prompt
        # ok to move up one line
        echo -e "\033[1A${RDATE}"
    else
        echo -e "${RDATE}"
    fi

}
资料来源:


在接受行之前,您可以重新映射
Return
键以重置提示:

reset-prompt-and-accept-line() {
    zle reset-prompt
    zle accept-line
}

zle -N reset-prompt-and-accept-line

bindkey '^m' reset-prompt-and-accept-line

以@vitaŭt-bajaryn的酷炫ZSH风格为基础:

我认为重写accept line函数可能是最惯用的zsh解决方案:

function _reset-prompt-and-accept-line {
  zle reset-prompt
  zle .accept-line     # Note the . meaning the built-in accept-line.
}
zle -N accept-line _reset-prompt-and-accept-line


是的,这看起来很难,但是
preexec()
是一个好的开始。谢谢
zle重置提示
为您重新绘制zsh提示。这与回显脏话结合使用效果非常好。我将其设置如下:
preexec(){/usr/bin/ruby/usr/local/curses/curse}
非常有效;)分享快乐/悲伤提示的代码?@slashdottir-Sure。我把它改成了一些Unicode,但这个概念仍然适用<代码>本地笑脸=“%(?,%B%F{243}”☆%f%b,%b%f{1}☃%f%b)”,然后用
${smiley}
将其插入PS1变量。这是一个非常棒的解决方案,但当我尝试在混合中添加颜色时,它会很难抑制。看起来添加颜色设置器的位置在
echo
行中,但是如果颜色设置在转义字符之后,我会事先获得额外的
%{%}
字符。不知何故,无论我在哪里尝试重置颜色方案,我都会在尾端获得这些字符。我建议进行一些增强:1)在时间字符串前面添加日期字符串<代码>%Y-%m-%d%H:%m:%S,以及2)在
RDATE
前面使用换行符。。。i、 e.
RDATE=“\n\033[${right\u start}C${DATE}”
这真是太棒了。感谢您提供了这么一个有用的代码片段!我建议您也从那里进行一次黑客攻击来增强这一点:另外,请注意,这可能会使复制粘贴更烦人。这很好也很简单,但将TMOUT设置为1会对SSH会话造成严重破坏。如果我在登录后1秒钟内没有运行命令,我会被踢出。this无法显示长行的时间,因为当行太长时,zsh会隐藏rprompt。在执行命令之前有一个更新时间非常好。但是有了这个解决方案,向上箭头历史不再适用于我。有人知道解决方法吗?啊,一个有趣的解决方案。谢谢!当我这样做时,这不起作用
C-r somestring RET
,即直接从反向搜索运行一行,而不移动光标或修改它。我喜欢这种解决方案,但它在为我按enter键时增加了太多的延迟。你知道重置提示本质上有点慢,还是只是我的提示重置慢?我没有太多,主要是因为RPROMPT(
%{$fg[白色]]}[%*]%{$reset\u color%}
)中的时间和提示符(
%{$fg[cyan]]]}%c%{$fg\u bold[蓝色]]]}$(git\u提示符信息)%{$fg\u bold[蓝色]%{$reset\u color%}:
)如果您希望此功能与增量搜索(c-r)一起工作,请添加以下内容:
函数{reset-prompt-and-accept-iseach{zle reset prompt zle.zle isearch exit}zle-N zle isearch exit_reset-prompt-and-accept-isearch