Bash – Home key acting strange in bash (tty and X) on long input strings

arch linuxbashcommand line

When I hit Home if my current input is short enough (say, <36 characters), it works fine. However, when I've typed a longer command and then want to go back to the beginning, it seems like it does its job, but the command isn't displayed right anymore. It looks as if I'm not in the beginning but about 10 characters off. Although if I type "blindly", it works fine, but it looks like a total mess, as if the whole input is shifted to the right, but not redrawn. So I type over it, but "in fact" not, because the place I'm "erasing" is "actually" 10 characters to the right. Accordingly, if I try to erase the command, the first 10 characters are still displayed, but if I hit Enter it just displays another prompt as if the previous input was empty.

I know it's not the best explanation ever, but the point is that bash recognizes it and tries to do the right thing, but often fails.

I reproduce this both in tty and in a terminal in an X session.
When I hit Ctrl+V and then Home I see different sequences (^[OH in X, ^[[1~ in tty), but both seem to be in my /etc/inputrc:

# do not bell on tab-completion
#set bell-style none

set meta-flag on
set input-meta on
set convert-meta off
set output-meta on

$if mode=emacs

# for linux console and RH/Debian xterm
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[7~": beginning-of-line
"\e[3~": delete-char
"\e[2~": quoted-insert
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word
"\e[1;5C": forward-word
"\e[1;5D": backward-word

# for rxvt
"\e[8~": end-of-line

# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
"\eOH": beginning-of-line
"\eOF": end-of-line

# for freebsd console
"\e[H": beginning-of-line
"\e[F": end-of-line
$endif

echo $TERM shows linux in tty and xterm in X session.

It's

GNU bash, version 4.2.24(2)-release (i686-pc-linux-gnu)

Anyone have clues about this?

Best Answer

You need to surround the non-printing parts of your prompt (including but not limited to escape sequences for changing colors) with \[ and \].

Your original prompt: \e[0;36m[\u@\h \W]\$ \e[m
Fixed prompt: \[\e[0;36m\][\u@\h \W]\$ \[\e[m\]

The \[ and \] tell bash that everything in between does not actually print to the screen, i.e. has zero length. The calculated prompt length is needed to know where to echo characters you type. Leaving out \[ \] causes bash to compute an incorrect prompt length, which often leads to strange terminal geometry-dependent behavior due to bash's idea of where the cursor is not matching up with reality.

Related Question