20

I know that I can exec a date command in my zsh prompt. However, it shows the old time; to see the current time, I have to hit <return> and get a new prompt with the current time.

Is there a way to configure the zsh prompt to constantly update itself every second?

paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
anon
  • 41,035
  • 53
  • 197
  • 293

3 Answers3

69

Note: I wrote this answer for a similar question, but seeing how this question has more views I think reposting my answer here would be useful.

This is in fact possible without resorting to strange hacks. I've got this in my .zshrc

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

TMOUT=1

TRAPALRM() {
    zle reset-prompt
}

The TRAPALRM function gets called every TMOUT seconds (in this case 1), and here it performs a prompt refresh, and does so until a command starts execution (and it doesn't interfere with anything you type on the prompt before hitting enter).

Source: http://www.zsh.org/mla/users/2007/msg00944.html (It's from 2007!)

Community
  • 1
  • 1
nitarshan
  • 1,465
  • 2
  • 12
  • 11
  • 1
    I can confirm that this actually works, despite how simple this appears. All you really need is the `TMOUT=; TRAPALRM () { zle reset-prompt }` part in your `$HOME/.zshrc` file and you're good to go. – Alexej Magura Dec 20 '13 at 04:11
  • 4
    This should be the accepted answer. I'd also recommend a longer timeout than 1 second. I used `TMOUT=30`. I noticed my shell hanging when it was every second. – brock Dec 13 '14 at 19:47
  • 2
    Also, note that this might make copy-pasting more annoying. – d33tah Jul 01 '15 at 21:30
  • 1
    Set the Trapalrm BEFORE tmout as on one of my Centos boxes executing a null TRAPALRM cause a logout – zzapper May 04 '16 at 10:00
  • 1
    Don't like that as I'm not able anymore to scroll back and read thinks carefully. When the prompt refreshs it wants to scroll to bottom – Falk Jan 04 '18 at 02:13
  • 1
    This should be the accepted answer. Also, while it seems on some systems this causes inconvenience with copying and/or with scrolling, I'm using this technique without experiencing these issues. – Tom Apr 25 '20 at 13:38
  • Time formatting syntax in zsh, to save readers a search: http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html#Date-and-time – catleeball May 30 '20 at 08:25
  • This solution has a issue that:you can not scroll back in your terminal@nitarshan –  Jul 12 '20 at 13:04
  • 1
    @user13268019 Maybe it depends on which terminal? – trusktr Sep 19 '20 at 02:22
8

Sounds like a pleasant request to me. If anything it makes more sense than showing the time when the prompt was displayed.

Fortunately Peter Stephenson posted a technique. Try something like this in .zshrc:

PROMPT="[%T] %n@%M %~ %# "

schedprompt() {
  emulate -L zsh
  zmodload -i zsh/sched

  # Remove existing event, so that multiple calls to
  # "schedprompt" work OK.  (You could put one in precmd to push
  # the timer 30 seconds into the future, for example.)
  integer i=${"${(@)zsh_scheduled_events#*:*:}"[(I)schedprompt]}
  (( i )) && sched -$i

  # Test that zle is running before calling the widget (recommended
  # to avoid error messages).
  # Otherwise it updates on entry to zle, so there's no loss.
  zle && zle reset-prompt

  # This ensures we're not too far off the start of the minute
  sched +30 schedprompt
}

schedprompt
Dave Cohen
  • 1,277
  • 2
  • 15
  • 21
  • Just noticed the post asked for update every second. I haven't tried it, but I'm guessing "sched +1 schedprompt" at the end of schedprompt() would do it. – Dave Cohen Dec 04 '12 at 12:49
  • Turns out the call to reset-prompt undoes any scrolling in the term window. Makes it tough to scroll backwards and stay there for any length of time. – Dave Cohen Dec 05 '12 at 13:07
  • It's awesome! Not only it shows the current time but also it timestamps executed commands. Regarding the scrolling problem - you just need to turn off `scroll on output` feature of your terminal of choice. – defhlt Dec 08 '12 at 19:22
  • 4
    @ArtemIce If you just need the command timestamp (like I did), you can use something like this: preexec () { echo -e "\033[1A`date +%H:%M:%S` " } – Dan Berindei Dec 28 '12 at 15:02
6

This would be .... unpleasant in a standard zsh prompt (or bash, or other shells).

I suggest you'd be better off using Gnu Screen.

Screen can have a status line which can show the time. Here's an example screenrc scroll down to "Red Hat Magazine A guide to GNU Screen" to see the sample (i'll reproduce that here) which will, when screen is run, show the current time in the lower right corner of the terminal:

~/.screenrc

hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'

# Default screens
screen -t shell1        0
screen -t shell2        1

http://www.gnu.org/software/screen/

SuperMagic
  • 1,398
  • 8
  • 9