zsh right-justify in ps1

Solution 1:

You will find a detailed answer and an example here. The idea is to write the line before PS1 using the precmd callback, use $COLUMNS, and a bit of math to calculate the position of the text on the right side of the screen. Knowledge of escape sequences will also help you with cursor positioning and colouring.

Another solution can be to use a theme from Oh My ZSH.

Solution 2:

I've been looking for this too. For me, the fact that precmd() drawn lines don't redraw on resize or when ^L is used to clear the screen was something that kept itching at me. What I'm doing now is using ANSI escape sequences to move the cursor around a bit. Though I suspect there is a more elegant way to issue them, this is working for me:

_newline=$'\n'
_lineup=$'\e[1A'
_linedown=$'\e[1B'

PROMPT=...whatever...${_newline}...whatever...
RPROMPT=%{${_lineup}%}...whatever...%{${_linedown}%}

Keep in mind that the zsh manual states that %{...%} is for literal escape sequences that don't move the cursor. Even so, I'm using them because they allow to ignore the length of it's content (couldn't figure out how to issue the escape that moves the cursor using them though)

Solution 3:

Here is how I've configured this thing just now. This approach doesn't require any escape-sequence manipulations, but will make you have two different variables for primary prompt: PS1 with coloring and NPS1 without.

# Here NPS1 stands for "naked PS1" and isn't a built-in shell variable. I've
# defined it myself for PS1-PS2 alignment to operate properly.
PS1='%S%F{red}[%l]%f%s %F{green}%n@%m%f %B%#%b '
NPS1='[%l] %n@%m # '
RPS1='%B%F{green}(%~)%f%b'

# Hook function which gets executed right before shell prints prompt.
function precmd() {
    local expandedPrompt="$(print -P "$NPS1")"
    local promptLength="${#expandedPrompt}"
    PS2="> "
    PS2="$(printf "%${promptLength}s" "$PS2")"
}

Note the usage of print -P for prompt expansion, ${#variable} for getting the length of string stored in variable, and printf "%Nd" for left-hand padding with N spaces. Both print and printf are built-in commands, so there should be no performance hit.