[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: customizing PS1 environment var with colour escape codes breaks readline



On Fri, May 20, 2005 at 10:38:09PM -0500, Kent West wrote:
> Jacobo221 wrote:
> 
> >I like customizing my PC. In my console I use the following PS1 var:
> >
> >PS1='\n\033[34;1m[\w]\033[0;34m\$ '
> >PS1=$PS1'\033[s\033[1;1f\033[37;47;1m\033[K Terminal: \033[2m\l\033[1m\033[;19fJobs: \033[2m\j\033[1m\033[;29fUser: \033[2m\u\033[1m\033[;45fHost: \033[2m\h\033[1m\033[;61f\d  \033[2m(\A)
> >\033[u'
> >PS1=$PS1'\033[0m'
> >
> >It works fine, but the thing is that suing colour escape codes seems to break readline! I mean, if I use that PS1 variable, readline behaves strange.
> >  
>
> I use bash, and also have a colour-coded prompt. I see similar problems
> to what you're describing. I've just learned to live with it. I only
> mention this so you'll know you're not alone. Sorry I don't have a
> solution for you.

There are several ingredients to getting this to work.  First one is to
bracket all escape/control sequences with \[ ... \].  This is required,
because those sequences are considered 'non-printing'...  Thus, it's a
feature, not a bug -- it's in fact documented in the bash man page
(section PROMPTING).   Don't worry, I also suffered from a misbehaving
colorized prompt for years, until I realised that subtlety... ;)

This first step should suffice for all 'normal' one-line prompts. What
you're trying to do (save/restore cursor position with \e[s ... \e[u ),
is advanced stuff, however.  Really, nothing for the faint of heart :)

You are lucky, though, that I've already spent several hours of my life
figuring out a similar issue.  Well, mostly.  The closest you can get
here, I think, is the following:

PS1='\n\[\e[1A\e[s\e[1;1f\e[37;47;1m\e[K\] '
PS1=$PS1'Terminal: \[\e[2m\]\l\[\e[1m\e[;19f\]'
PS1=$PS1'Jobs: \[\e[2m\]\j\[\e[1m\e[;29f\]'
PS1=$PS1'User: \[\e[2m\]\u\[\e[1m\e[;45f\]'
PS1=$PS1'Host: \[\e[2m\]\h\[\e[1m\e[;61f\]'
PS1=$PS1'\d  \[\e[2m\](\A) \[\e[u\]'
PS1=$PS1'\n\[\e[34;1m\][\w]\[\e[0;34m\]\$ '

(not exactly pretty, thus split across several lines for readability;
also, using the shorter \e instead of \033)

I'm not going to explain every last detail, but the key thing to note
is that the position of the \n is determining bash's idea of where the
prompt is.  This doesn't seem to be documented anywhere, so it took me
quite a few attempts...  Good ol' trial-and-error, I tell ya whut.

IOW, there's no way around putting the \n after the point where the
cursor position is restored (after printing the 'status line').
Unfortunately, this has the undesired side effect of making the status
line scroll out of the terminal window, when the prompt is at the very
bottom -- as you probably realized yourself.

So, we have to compensate for this effect, by scrolling the terminal
up one line, ahead of printing the status line.  As there doesn't seem
to be an escape sequence for simple scrolling (at least I haven't found
one), we'll have to emulate it somehow:

  \n\e[1A\e[s ...status line... \e[u\n ...rest of prompt...
or
  \n <cursor up> <save cursor pos> ... <restore cursor pos> \n ...

The first \n makes the window scroll, and the <cursor up> repositions
the cursor to where it was before the \n.  This makes sure we always
have an empty line at the bottom, to finally place our prompt in...

This is still not perfect, however, because the status line will
still temporarily scroll out of the window, whenever a long multi-line
command is retrieved from the history.  But I don't think there's a
workaround for this problem, as the prompt is always printed _before_
any commandline content is written.  So, the commandline length is
simply not yet known and may not be accounted for within the prompt
code.  Well... it seems to be a decent approximation, as you can now
use all of the readline stuff like Ctrl-A, Ctrl-E, left/right cursor,
etc., without messing up the commandline.
It should work at least with rxvt (my favorite terminal emulator, btw)
and xterm -- haven't tested it with other terminals, though... YMMV.

Happy hacking!

Almut



Reply to: