40

我有一个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]

在 shell 启动新命令之前是否有一个zsh运行命令的钩子,以便我可以更新提示时间戳?(我在 zsh 提示符中看到了不断更新的时钟?,但我不需要它不断更新,只是在我按回车时更新。)

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

4

6 回答 6

43

这实际上是可能的,无需借助奇怪的技巧。我的 .zshrc 中有这个

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

TMOUT=1

TRAPALRM() {
    zle reset-prompt
}

TRAPALRM 函数每 TMOUT 秒调用一次(在本例中为 1),在这里它执行提示刷新,并一直执行到命令开始执行(并且它不会干扰您在按 Enter 之前在提示上键入的任何内容)。我知道您不需要不断刷新它,但它仍然可以完成工作,而无需自己排队!

资料来源:http ://www.zsh.org/mla/users/2007/msg00944.html (从 2007 年开始!)

于 2013-07-29T02:27:17.927 回答
19

我很难做到这一点:

它在右侧显示命令执行的日期。它不会覆盖显示的命令。警告:它可能会覆盖当前的 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

}

资料来源:

于 2014-10-27T10:44:37.660 回答
14

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

preexec() { date }

修改现有提示将更具挑战性。

于 2012-10-29T17:11:47.877 回答
14

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
于 2015-10-25T09:46:46.513 回答
9

以@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
于 2016-01-28T01:09:16.187 回答
5

您可以使用ANSI 转义序列覆盖上一行,如下所示:

preexec () {
  DATE=`date +"%H:%M:%S on %Y-%m-%d"`
  C=$(($COLUMNS-24))
  echo -e "\033[1A\033[${C}C ${DATE} "
}
于 2012-12-29T18:17:56.063 回答