Historical command line editing is broken
Closed this issue · 12 comments
what
Concerning version 0.12.6. Also reproduced in 0.11.0.
Editing historical command lines using emacs keys is broken in certain circumstances. My guess is that it has to do with a divergence between the actual length of the prompt when output versus the length of the prompt when queried by the command line editor.
Reproducing this bug is a little tricky. This seems to work for me, but you might have to try some variations.
- Enter a long command at the command line:
echo top level this is a long command
- Press the up-arrow ↑ to recall the command to the command line.
- Press ctrl-A to move the cursor to the beginning of the command line.
Expected: cursor hovers over "e" in echo.
Observed: cursor hovers over "c" in echo.
why
Not only does this cause difficulty in editing historical command lines, it results in a dangerous situation where the command visible on the command line is not exactly what will be submitted when you hit return.
What version are you using?
You can set PROMPT_STYLE=plain
which will probably eliminate your problems
Using 0.12.6
. Previously using 0.9.18
which did not have this problem.
PROMPT_STYLE=plain
does not solve the problem.
Commenting out PROMPT_HOOKS+=("geodesic_prompt")
from /etc/profile.d/prompt.sh
eliminates the issue (and the nice prompt) but of course does not survive a restart of the container.
Replacing /etc/profile.d/prompt.sh
with version from 0.9.18
does not solve the problem, nor does unsetting PROMPT_HOOKS
.
Also, something is buffering the first ctrl-P. If, on a blank line, I type ctrl-P, nothing happens. After typing another character, the first ctrl-P is recognized and acted on, and so is the second. It's as though ctrl-P were some sort of optional prefix character and it is being held in case the second character makes a 2-character special command, the way ~ does in some versions of ssh
.
I can get to the previous line easily via up-arrow, but if I try ctrl-P, I have to do it twice and then ctrl-N.
SOLUTION
I was exactly right about the way ctrl-P is being treated. The default command to detach the terminal from a running container is ctrl-P ctrl-Q, so the ctrl-P was being held to see if a ctrl-Q follows. Solution is to specify an alternate sequence using the --detach-keys
option such as --detach-keys=ctrl-@,ctrl-@
on the docker run
command line (or in your global docker config JSON file).
This is clearly because the various pieces of code that need to compute the size of the prompt are not coming up with compatible answers. The unicode glyphs take up more than a single character width and more than a single byte and there is some bug or inconsistency in bash
and/or readline
and/or something else. (In the case of PROMPT_STYLE=plain
the problem appears to be the formatting characters emitted by tput
are not being escaped as invisible.)
I have tried a lot of workarounds, mostly variations on adding extra spaces to the prompt then flagging the glyphs as invisible and having them overwrite the added spaces, but so far nothing works consistently for both scrolling and searching through history.
Short of dropping the glyphs altogether, you might be able to get away with limiting glyphs to the banner line and using only single-byte single-width characters on the final prompt line.
I'm using the OS X Terminal. I seem to see some improvement in Terminal if I turn on the "Unicode East Asian Ambiguous characters are wide" option in Terminal -> Preferences -> Advanced, but not complete solution. What do you see when you search for "echo" and then start to edit the line (key sequence ctrl-R e c h o ctrl-A
)? I see a colon left over from search and the cursor over the space between the colon and the "e" in "echo".
Okay, I think we'll introduce a new prompt style that uses these gyphs: 0x20E0
, 0x2234
∴ ⃠
Also, the tputs
that do ansi should be wrapped in \[
... \]
to instruct bash that it needs to adjust the width for zero width characters.
FWIW, I reproduced the issues in iTerm2 version 3.1.7. The problem goes away in iTerm2 if the option "Use Unicode Version 9 widths" it enabled. Documentation for this feature says "Unicode version 9 offers better formatting for Emoji."
Glyphs 0x20E0
and 0x2234
seem to have the same problem of being double-width and messing up Terminal. Using those in the prompt will not solve this issue.
I suggest you use these single-width glyphs instead.
✗
BALLOT X
Unicode: U+2717, UTF-8: E2 9C 97
✓
CHECK MARK
Unicode: U+2713, UTF-8: E2 9C 93
⨠
Z NOTATION SCHEMA PIPING
Unicode: U+2A20, UTF-8: E2 A8 A0
AWS_VAULT_ACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 2)$'\x02\u2713 \x01'$(tput sgr0)$'\x02'; # green bold '✓'
AWS_VAULT_INACTIVE_MARK=$'\x01'$(tput bold)$(tput setaf 1)$'\x02\u2717 \x01'$(tput sgr0)$'\x02'; # red bold '✗'
BLACK_RIGHTWARDS_ARROWHEAD=$'\u2a20 '; # '⨠'
BANNER_MARK='⧉ '
Above seems to work for me. Invisible characters wrapped in $'\x01'
…$'\x02'
instead of \[
…\]
to sidestep some bugs/odd behaviors if the variables are used outside of PSx
.