cloudposse/geodesic

Historical command line editing is broken

Closed this issue · 12 comments

Nuru commented

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.

  1. Enter a long command at the command line:
    echo top level this is a long command
    
  2. Press the up-arrow ↑ to recall the command to the command line.
  3. 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

Nuru commented

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.

Nuru commented

Replacing /etc/profile.d/prompt.sh with version from 0.9.18 does not solve the problem, nor does unsetting PROMPT_HOOKS.

Nuru commented

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 what I see in iTerm2:

image

Maybe related to my terminal (why it works).

Can you try just radically simplifying the prompt characters in /etc/profile.d and removing all the tput statements.

If that works, we can introduce another prompt format.

Nuru commented

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.

Nuru commented

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".

image

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.

Nuru commented

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.

Nuru commented

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

Nuru commented
            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.