First characters of the command repeated in the display when completing
If the characters on your command line are sometimes displayed at an offset, this is often because zsh has computed the wrong width for the prompt. The symptoms are that the display looks fine as long as you're adding characters or moving character by character but becomes garbled (with some characters appearing further right than they should) when you use other commands that move the cursor (Home, completion, etc.) or when the command overlaps a second line.
Zsh needs to know the width of the prompt in order to know where the characters of the command are placed. It assumes that each character occupies one position unless told otherwise.
One possibility is that your prompt contains escape sequences which are not properly delimited. Escape sequences that change the color or other formatting aspects of the text, or that change the window title or other effects, have zero width. They need to be included within a percent-braces construct %{…%}
. More generally, an escape sequence like %42{…%}
tells zsh to assume that what is inside the braces is 42 characters wide.
So check your prompt settings (PS1
, PROMPT
, or the variables that they reference) and make sure that all escape sequences (such as \e[…m
to change text attributes — note that it may be present via some variable like $fg[red]
) are inside %{…%}
. Since you're using oh-my-zsh, check both your own settings and the definitions that you're using from oh-my-zsh.
The same issue arises in bash. There zero-width sequences in a prompt need to be enclosed in \[…\]
.
Another possibility is that your prompt contains non-ASCII characters and that zsh (or any other application) and your terminal have a different idea of how wide they are. This can happen if there is a mismatch between the encoding of your terminal and the encoding that is declared in the shell, and the two encodings result in different widths for certain byte sequences. Typically you might run into this issue when using a non-Unicode terminal but declaring a Unicode locale or vice versa.
Applications rely on environment variables to know the locale; the relevant setting is LC_CTYPE
, which is determined from the environment variables LANGUAGE
, LC_ALL
, LC_CTYPE
and LANG
(the first of these that is set applies). The command locale | grep LC_CTYPE
tells you your current setting. Usually the best way to avoid locale issues is to let the terminal emulator set LC_CTYPE
, since it knows what encoding it expects; but if that's not working for you, make sure to set LC_CTYPE
.
The same symptoms can occur when the previous command displayed some output that didn't end in a newline, so that the prompt is displayed in the middle of the line but the shell doesn't realize that. In this case that would only happen after running such a command, not persistently.
If a line isn't displayed properly, the command redisplay
or clear-screen
(bound to Ctrl+L by default) will fix it.
I had the same problem and found my solution here: https://github.com/robbyrussell/oh-my-zsh/issues/5157#issuecomment-226031519. Simply put the following into your ~/.zshrc
.
export LC_CTYPE=en_US.UTF-8
I had this issue in iTerm 2 on macOS. I ended up solving it by going to Preferences -> Profiles -> Text and ticking off "Use Unicode Version 9 Widths".