I currently have the following line in my .zshrc:

export PROMPT=$(printf "\e[38;5;6m")%m$(printf "\e[m")%d-%h:" "

Which is supposed to show the hostname in blue and history and current working directory in normal terminal color. I'm not exactly sure how to describe it, but unexpected weirdness happens when you specify the first (several) letter(s) and several filenames match it. It's hard to describe, just try it.


Before completion:
before completion

After hitting Tab to display possible completions: after completion


Zsh needs to know how wide the prompt is in order to get the cursor position right. If it assumes an incorrect value for the width of the prompt, it will write text at the wrong place when redrawing the command line. That's what's happening after zsh moves to the next line to display possible completions: it redraws the command to be completed at the position where it thinks it should appear.

Your prompt contains escape sequences that have a width of zero: their effect is to change the appearance of the following text. Zsh doesn't know that: it assumes that every character has a width of 1 unless told otherwise. To tell zsh that a part of the prompt has a width of zero, surround it by %{…%}.

PROMPT=%{$(printf "\e[38;5;6m")%}%m%{$(printf "\e[m")%}%d-%h:" "

You can simplify this: there's no need to invoke printf, you can use the $'…' syntax to include backslash escapes.

PROMPT=$'%{\e[38;5;6m%}%m%{\e[m%}%d-%h: '

Don't export PROMPT: it's an internal shell variable, not an environment variable that other applications are meant to see.

Zsh has prompt escape sequences to change the text appearance in simple ways. I'm not sure what you intend with 38;5;6. Bold blue would be 34;1, or with zsh prompt escapes,

PROMPT='%F{blue}%B%m%b%f%d-%h: '

You've completely banjanxed zsh's idea of what's been printed and what it has to erase/rewrite as it displays menu completion and lets you edit the command line. This is because you've overcomplexified that prompt.

  • Don't use printf to just put a string literal inside a word.
  • Don't use hardwired CSI control sequences to change colour.

As I said at https://superuser.com/a/695350/38062 ,the Z Shell knows that things like %F{green} aren't printing sequences, without having to be told; and it also works out the correct escape sequences from terminfo, without having them hardwired.

PROMPT="%B%F{blue}%m%f%b%d-%h: "

Further reading

  • This works on two of my computers, but on the third, my prompt is just: **{blue}new**/tmp. Maybe it has something to do with the version? On that computer zsh is only version 4.3.4. – Accidental brine Apr 19 '15 at 18:28
  • Thanks, that worked: updating zsh on the third box fixed the problem. – Accidental brine Apr 19 '15 at 21:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.