Non-printing escape sequence: when?

The "non-printing escape sequence" is needed when using non-printing characters in $PS1 because bash needs to know the position of the cursor so that the screen can be updated correctly when you edit the command line. Bash does that by counting the number of characters in the $PS1 prompt and then that's the column number the cursor is in.

However, if you place non-printing sequences in $PS1, then that count is wrong and the line can be messed up if you edit the command line. Hence the introduction of the \[ and \] markers to indicate that the enclosed bytes should not be counted.


I found a sufficient solution by using octal escape sequences throughout, and by using the readline forms of the delimiter characters. PS1, echo -e and printf all do the right thing with exactly the same strings this way. I tested this in Bash 4 on OSX and Bash 3 on Linux.

I got the idea for \001 and \002 from an answer here: https://superuser.com/questions/301353/escape-non-printing-characters-in-a-function-for-a-bash-prompt?rq=1

Example:

$ TextGreen='\001\033[0;32m\002'
$ TextReset='\001\033[0m\002'
$ SomeString="${TextGreen}prompt_stuph${TextReset} \$ "
$ #
$ # now all of the following work as expected
$ #
$ PS1="$SomeString"
$ printf "$SomeString"
$ echo -e "$SomeString"

Something like ␛[01;38;05;129m, where the first character is the ASCII escape character (U+0027), is a terminal escape sequence. It instructs the terminal to start displaying bold, blinking text in color 129. \e is bash syntax for the escape character (inside $'…', in PS1, in echo -e and in printf).

\[ and \] are not terminal escape sequences, they're bash prompt escape sequences. They're interpreted by bash, not sent to the terminal. Their purpose is to tell bash that what's in between are non-printing characters, so that the width of the prompt is really the number of characters not inside \[…\]. Bash needs to know the width of the prompt to calculate the cursor position in the line editor.

Your function should not output \[…\] if it's meant to be used outside prompt strings. Include \[ and \] directly in the prompt string.