I'm using the readline library in C to create a bash-like prompt within bash. When I tried to make the prompt colorful, with color sequences like these, the coloring works great, but the cursor spacing is messed up. The input is wrapped around too early and the wrap-around is to the same line so it starts overwriting the prompt. I thought I should escape the color-sequences with \[
and \]
like
readline("\[\e[1;31m$\e[0m\] ")
But that prints the square brackets, and if I escape the backslashes it prints those too. How do I escape the color codes so the cursor still works?
The way to tell readline that a character sequence in a prompt string doesn't actually move the cursor when output to the screen is to surround it with the markers RL_PROMPT_START_IGNORE
(currently, this is the character literal '\001' in readline's C header file) and RL_PROMPT_END_IGNORE
(currently '\002').
And as @Joachim and @Alter said, use '\033' instead of '\e' for portability.
I found this question when looking to refine the GNU readline prompt in a bash script. Like readline in C code, \[
and \]
aren't special but \001
and \002
will work when given literally via the special treatment bash affords quoted words of the form $'string'
. I've been here before (and left unsatisfied due to not knowing to combine it with $'…'
), so I figured I'd leave my explanation here now that I have a solution.
Using the data provided here, I was able to conclude this result:
C1=$'\001\033[1;34m\002' # blue - from \e[1;34m
C0=$'\001\033[0;0m\002' # reset - from \e[0;0m
while read -p "${C1}myshell>$C0 " -e command; do
echo "you said: $command"
done
This gives a blue prompt that says myshell>
and has a trailing space, without colors for the actual command. Neither hitting Up nor entering a command that wraps to the next line will be confused by the non-printing characters.
As explained in the accepted answer, \001
(Start of Heading) and \002
(Start of Text) are the RL_PROMPT_START_IGNORE
and RL_PROMPT_END_IGNORE
markers, which tell bash and readline not to count anything between them for the purpose of painting the terminal. (Also found here: \033
is more reliable than \e
and since I'm now using octal codes anyway, I might as well use one more.)
There seems to be quite the dearth of documentation on this; the best I could find was in perl's documentation for Term::ReadLine::Gnu, which says:
PROMPT
may include some escape sequences. UseRL_PROMPT_START_IGNORE
to begin a sequence of non-printing characters, andRL_PROMPT_END_IGNORE
to end the sequence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With