I have the following in my .zshrc:
setopt PROMPT_SUBST
precmd(){
echo""
LEFT="$fg[cyan]$USERNAME@$HOST $fg[green]$PWD"
RIGHT="$fg[yellow]$(date +%I:%M\ %P)"
RIGHTWIDTH=$(($COLUMNS-${#LEFT}))
echo $LEFT${(l:$RIGHTWIDTH:)RIGHT}
}
PROMPT="$ "
This gives me the following screenshot
The time part on the right is always not going all the way to the edge of the terminal, even when resized. I think this is due to the $(date +%I:%M\ %P)
Anyone know how to fix this?
EDIT: Zoomed in screenshot
While your idea is commendable, the problem you suffer from is that your LEFT
and RIGHT
contains ANSI escape sequences (for colors), which should be zero-width characters, but are nevertheless counted toward the length of a string if you naively use $#name
, or ${(l:expr:)name}
.
Also, as a matter of style, you're better off using Zsh's builtin prompt expansion, which wraps a lot of common things people may want to see in their prompts in short percent escape sequences. In particular, there are builtin sequences for colors, so you don't need to rely on nonstandard $fg[blah]
.
Below is an approximate of your prompt written in my preferred coding style... Not exactly, I made everything super verbose so as to be understandable (hopefully). The lengths of left and right preprompts are calculated after stripping the escape sequences for colors and performing prompt expansion, which gives the correct display length (I can't possibly whip that up in minutes; I ripped the expression off pure
).
precmd(){
local preprompt_left="%F{cyan}%n@%m %F{green}%~"
local preprompt_right="%F{yellow}%D{%I:%M %p}%f"
local preprompt_left_length=${#${(S%%)preprompt_left//(\%([KF1]|)\{*\}|\%[Bbkf])}}
local preprompt_right_length=${#${(S%%)preprompt_right//(\%([KF1]|)\{*\}|\%[Bbkf])}}
local num_filler_spaces=$((COLUMNS - preprompt_left_length - preprompt_right_length))
print -Pr $'\n'"$preprompt_left${(l:$num_filler_spaces:)}$preprompt_right"
}
PROMPT="$ "
Edit: In some terminal emulators, printing exactly $COLUMN
characters might wrap the line. In that case, replace the appropriate line with
local num_filler_spaces=$((COLUMNS - preprompt_left_length - preprompt_right_length - 1))
End of edit.
This is very customizable, because you can put almost anything in preprompt_left
and preprompt_right
and still get the correct lengths — just remember to use prompt escape sequence for zero width sequences, e.g., %F{}%f
for colors, %B%b
for bold, etc. Again, read the docs on prompt expansion: http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html.
Note: You might notice that %D{%I:%M %p}
expands to things like 11:35 PM
. That's because I would like to use %P
to get pm
, but not every implementation of strftime
supports %P
. Worst case scenario: if you really want lowercase but %P
is not supported, use your original command subsitution $(date +'%I:%M %P')
.
Also, I'm using %~
instead of %/
, so you'll get ~/Desktop
instead of /c/Users/johndoe/Desktop
. Some like it, some don't. However, as I said, this is easily customizable.