ZSH PS1 adding spacing when tabbing

2

1

I'm having an issue with zsh/oh-my-zsh with my custom PS1 prompt (that I brought across from bash).

When I use the built-in zsh/oh-my-zsh prompt and tab for auto-completion, this works as expected.

When I use my own PS1 prompt, the whole input area moves across about 8 spaces and stays there until I send a break/new line.

Examples:

I typed in vim a and tabbed

Built in theme, robbyrussell with default prompt:

Built in theme, *robbyrussell* with default prompt:

Same theme, custom PS1 prompt:

Same theme, custom PS1 prompt:

PS1 string and variable definitions in .zshrc:

# Monokai colours
D=$'\e[37;40m'
PINK=$'\e[35;40m'
GREEN=$'\e[32;40m'
ORANGE=$'\e[33;40m'    

export PS1='${PINK}andrew${D}@${ORANGE}macbook${D}:%~$ '

As a test, I tried my prompt without the colour variables and it does work

Andrew White

Posted 2015-03-25T02:25:11.137

Reputation: 527

As you can see at http://superuser.com/questions/695338/ and http://superuser.com/questions/723552/ , it is possible to make this mistake with the Bourne Again shell, too. ☺

– JdeBP – 2015-03-25T20:07:20.677

Answers

3

It seems that the ANSI codes are messing with your terminal, possibly due to some interactions with the other contents of PS1 or because you do not reset to default.

Luckily, in zsh there is no need to use ANSI escape codes. You can use %F{color} and %K{color} to set foreground and background colors respectively and %f and %k to reset default values (See the Zsh Manual for more information)

Either of these should do the trick:

PS1='%5Fandrew%f@%3Fmacbook%f:%~$ '
PS1='%F{5}andrew%f@%F{3}macbook%f:%~$ '
PS1='%F{magenta}andrew%f@%F{yellow}macbook%f:%~$ '

I used %f instead of %7F or %F{white}, assuming you really wanted to just disable coloring in that place (hence naming the variable D instead of WHITE). If you want to use %F{white} instead, you should put a %f at the end of PS1.

If you use a 88-color or 256-color terminal, you can even use these the indices of these colors. For example %F{221} would get you a dark yellow.


Also note, that it is usually unnecessary to export PS1 in zsh - or bash for that matter.

Adaephon

Posted 2015-03-25T02:25:11.137

Reputation: 3 864

Thank you very much @Adaephon! This definitively solves the issue, and @mpy's answer below tells me why. Also thanks for the tip about 256 - I am running xterm-256, so that's fantastic! – Andrew White – 2015-04-07T09:41:58.630

1

The clean solution was given by @Adaephon's answer, which I definitively recommend. However, I want to give you the cause of your troubles, too:

The problems are resulting because zsh counts the escape codes to the length of the prompt. This is wrong, because these codes are processed by the terminal emulator and are not displayed and results in the offset when the prompt is partially redrawn.

But for that case a special syntax can be used in the prompt strings. Quoted from man zshmisc:

%{...%} Include a string as a literal escape sequence. The string within the braces should not change the cursor position. Brace pairs can nest.

So, in your example you would end up with

PS1='%{${PINK}%}andrew%{${D}%}@%{${ORANGE}%}macbook%{${D}%}:%~$ '

which looks ugly and is hard to read, but works as expected.

Finally also a remark: If you use PS1='...' (single quotes) you need the option PROMPTSUBST activated, so that your color escape codes get replaces every time the prompt is displayed. If you use PS1="..." (double quotes), the escape codes get replaced once when defining PS1. The latter is not dynamic, but is enough in your specific case.

mpy

Posted 2015-03-25T02:25:11.137

Reputation: 20 866

Thanks @mpy - that makes sense. So each escalate character is counted as an additional character when rebuilding the shell post-tab? Simple - thanks again! – Andrew White – 2015-04-07T09:40:55.037