Align rprompt with top of prompt

promptzsh

I've recently been getting really excited about zsh, and making myself an extravagant prompt, but I'm stuck trying to align my RPROMPT. I have an output like this:

    | [14:59:44] git:(master)                           |
    | /home/zoey/.oh-my-zsh                             |
    | yes, zoey? :                           2016-05-26 |

where | represent the terminal edges. What I want is for the date to be vertically aligned with the time; as where it is, it is prone to be overwritten by a long command, whereas the git info is unlikely to get very long.

Is there any way to the vertical displacement of RPROMPT? Preferably something that is beginner-level zsh, as I'm used to bash, but I can copy-paste stuff if needed.

Here's the relevant bit of my .zshrc:

# show all but the last dir in the current path
function trim_pwd
{
    echo $(pwd | sed -e "s:/$::;s:[^/]*$::")
} 
setopt PROMPT_SUBST
# red for error, green for ok
ERRCOL='%(?:%F{green}:%F{red})'
PROMPT='${ERRCOL}[%f%B%F%D{%H:%M:%S}%f%b${ERRCOL}]%f %B$(git_prompt_info)%b
%F{green}%n%f@%F{yellow}%m%f:%F{blue}$(trim_pwd)%B%1/%b%f
%F{magenta}yes, %Bzoey%b?%f : '
RPROMPT='%F%D{%Y-%m-%d}%f'
# update clock per second
TRAPALRM() {
    zle reset-prompt
}
TMOUT=1

If I remove all of the formatting stuff, and just show the plain prompt:

setopt PROMPT_SUBST
PROMPT='[%D{%H:%M:%S}] $(git_prompt_info)
%n@%m:%/
yes, zoey? : '
RPROMPT='%D{%Y-%m-%d}'

Edit:
I am now able to handle variable-length plain text and fixed-width colored text with:

ERRCOL="%(?:%F{green}:%F{red})"
() {
    left="${ERRCOL}[%F%B%D{%H:%M:%S}%b${ERRCOL}]%f "
    right="%F%D{%Y-%m-%d}%f"
    local bare_left='[00:00:00] '
    local bare_right='0000-00-00'
    local middle_width=$((${COLUMNS}-1-${#bare_left}-${#bare_right}))
    git_prompt_info=$(git_prompt_info)
    middle=${(r:$middle_width:: :)git_prompt_info}
    PROMPT='${left}${middle}${right}'
    PROMPT+=$'\n : '
}

But the variable-length colored text in git_prompt_info is still counted. I have tried using the invisible substitution from this answer, but it doesn't seem to work, or I'm using it wrong:

right="%F%D{%Y-%m-%d}%f"
local invisible='%([BSUbfksu]|([FBK]|){*})'
local bare_right=${(S)right//$~invisible}
echo ${(%)bare_right}
echo ${(%)right}

prints the same colored line twice, i.e the substitution does nothing.

Best Answer

The point of RPROMPT is to be on the same line as the command you type. I'm not even sure if you can have a multiline RPROMPT (except by including some cursor motion commands in it). If you want a multiline prompt with something on the right of the first lines, include that in the left prompt. The variable COLUMNS contains the terminal width. Here's one way to do it, which uses a function to rebuild the prompt each time to get more control (I don't see offhand how to pad to the terminal width with only % escapes; it can be done with embedded substitutions but it gets hard to read or extend):

setopt prompt_subst
precmd_prompt () {
  git_prompt_info=${(r:$((COLUMNS-22)):: :)$(git_prompt_info)}
  PROMPT="[%D{%H:%M:%S}] %>>$git_prompt_info %D{%Y-%m-%d}"
  PROMPT+=$'\n%n@%m:%/\nyes, zoey? : '
}
precmd_functions+=(precmd_prompt)

If you want even more control over how the prompt is composed, build it from more pieces. For example, I hard-coded the length of the time and date above. Here's a variant that calculates the widths and pads or truncates the middle part containing the git information accordingly. This time I do the truncation manually to illustrate how it can be done. ${(%):-STUFF} expands prompt sequences in STUFF.

precmd_prompt () {
  PS1_1_left=${(%):-'[%D{%H:%M:%S}] '}
  PS1_1_right=${(%):-' %D{%Y-%m-%d'}
  local middle_width=$((COLUMNS-#PS1_1_left-#PS1_1_right}))
  local git_prompt_info=$(git_prompt_info)
  if ((#git_prompt_info < middle_width)); then
    PS1_1_middle=${(r:$middle_width:: :)git_prompt_info}
  else
    PS1_1_middle=${git_prompt_info:0:$middle_width}
  fi
  PROMPT='${PS1_1_left}${PS1_1_middle}${PS1_1_right}'
  PROMPT+=$'\n%n@%m:%/\nyes, zoey? : '
}
Related Question