2012-10-29 58 views
22

我有一個zsh提示我比較喜歡當前時間更新提示:它計算的當前時間precmd和顯示器上的提示右側:的zsh:用當命令開始

[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會啓動一個新命令,以便我可以更新提示時間戳? (我看見Constantly updated clock in zsh prompt?,但我並不需要它不斷更新,當我按下回車鍵剛剛更新。)

(該^_^基於先前的命令返回碼,它以紅色顯示;_;當有一個非零退出狀態)。

+0

分享的快樂/悲傷提示的代碼? – slashdottir

+1

@slashdottir當然。我已經將它改爲一些Unicode,但這個概念仍然適用。 'local smiley =「%(?,%B%F {243}☆%f%b,%B%F {1}☃%f%b)」',然後用'$ {smiley }'。 – cbowns

回答

14

我有一個鬥爭,使這個:

的命令已被執行時,它會顯示在右側的日期。 它不會覆蓋顯示的命令。 警告:它可能會覆蓋當前的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 "[email protected]") 
    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 

} 

來源:

+0

這太棒了! – cbowns

+0

這是一個非常棒的解決方案,但當我嘗試在混合中添加顏色時,它會很難嗆。看起來添加顏色設置器的地方在'echo'行,但如果顏色設置在轉義字符後面,我會事先獲得額外的'%{%}'字符。不知何故,無論我在哪裏嘗試重置顏色方案,我都會在尾端獲得這些角色。 – Kevin

+0

我推薦一些增強功能:1)在時間字符串前面添加日期字符串...'%Y-%m-%d%H:%M:%S',以及2)在前面使用換行符'RDATE'... ie'RDATE =「\ n \ 033 [$ {right_start} C $ {DATE}」' –

7

zsh將在執行行之前運行preexec函數。這將是簡單的有輸出電流時,一個簡單的版本將只是:

preexec() { date } 

修改現有的提示會更具挑戰性。

+0

是的,這看起來很難,但'preexec()'是一個好的開始。謝謝! – cbowns

+0

'zle reset-prompt'爲您重繪zsh提示符。 –

4

您可以使用ANSI escape sequences前一行寫了,就像這樣:

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

這其實是可以不訴諸黑客怪。我在我的.zshrc

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

TMOUT=1 

TRAPALRM() { 
    zle reset-prompt 
} 

得到這個的TRAPALRM函數被每TMOUT秒(在這種情況下,1)調用,並在這裏進行及時更新,並且這樣做,直到命令開始執行(這不會影響您在輸入之前在提示中鍵入的任何內容)。我知道你不需要不斷刷新它,但它仍然可以完成工作,而不需要爲它自己排隊!

來源:http://www.zsh.org/mla/users/2007/msg00944.html(這是從2007年!)

+0

我會建議使用從那裏的黑客來加強這一點:http://stackoverflow.com/a/30456173/1091116 – d33tah

+0

另外,請注意,這可能會使複製粘貼更惱人。 – d33tah

+0

這很好很簡單,但將TMOUT設置爲1會對SSH會話造成嚴重破壞。如果我在登錄後1秒內沒有運行命令,我會被踢出。 –

2

您可以重新映射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 
+0

啊,一個有趣的解決方案。謝謝! – cbowns

5

建設關@vitaŭt-bajaryn的冷靜ZSH風格answer

我想重寫接受在線功能可能是最地道的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 
+0

當我做這樣的''C-r somestring RET''時,這不起作用,即直接從反向搜索中直接運行一行,而不移動光標或修改它。 –