microsoft / microsoft/vscode

Terminal Cursor Appearing 8 Chars Before End of Prompt

Open
#336,187 0 comments 0 reactions 1 assignee Claimed by @Giuspepe View on GitHub
triage-needed
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

OS: Arch Linux x86_64
Kernel: Linux 7.2.4-arch1-2
Shell: bash 5.3.15
Readline: 8.3.003-1
VS Code Version: Latest commit compiled from source

When opening new terminals in VS Code, the cursor sometimes appears 8 characters to the left of where it needs to be, causing any text typed to be hidden under the prompt until the 8th character. It becomes annoying as I constantly have to press Enter to get a new prompt with correct cursor placement. This appears to be a `readline` bug that affects Linux/Bash users only.

Similar Open Issues: #317754 and #324914

I experience the bug randomly while using VS Code normally, but these steps reproduce the bug 100% reliably:

1. Ensure `"terminal.integrated.shellIntegration.enabled": true` in `settings.json` (`true` by default already).
2. Open VS Code (any window size, no project folder needs to be open).
3. Open a New Terminal. Open a second New Terminal for the sake of getting a divider between the visible selected terminal and the multiple terminal manager. You can stay in either terminal for the next steps.
4. Run `PS1="$(printf '%*s' $(( $(tput cols) - 3 )) '' | tr ' ' '-')"'$ '`. This almost completely fills the width with the prompt, leaving only one character worth of space left for the cursor.
5. Click and drag (and keep holding) the divider to the left to shrink the terminal width and cause the prompt to wrap to the next line.
6. Then drag the divider back to the right until the prompt is unwrapped and comfortably contained on one line and let go. The bug should now be caught:
`--------------█-----$ ` ← cursor 8 cells before `$ `
7. Typing causes the first 7 characters to hide behind the prompt, until the 8th
character is displayed. E.g. typing `123456789` renders:
`--------------------$89█` ← cursor now past the `9`
Note: the glyph depends on your `terminal.cursorStyle` (block █ shown).

What fixes the bug:

- Set `"terminal.integrated.shellIntegration.enabled"` to `false` in `settings.json`.
- Within `src/vs/workbench/contrib/terminal/common/scripts/shellIntegration-bash.sh`: change:

`__vsc_custom_PS1="\[$(__vsc_prompt_start)\]$__vsc_original_PS1\[$(__vsc_prompt_end)\]"`

to:

`__vsc_custom_PS1="\[$(__vsc_prompt_start)\]$__vsc_original_PS1$(__vsc_prompt_end)"`

Hypothesis for cause of bug:

- Characters inside of `\[` and `\]` are non-printing. `__vsc_prompt_start` and `__vsc_prompt_end` each emit 8 bytes (`ESC ] 6 3 3 ; A BEL` and `ESC ] 6 3 3 ; B BEL` respectively) to the terminal, but `readline` (the library that draws the prompt and manages user input) does not count either of the 8 bytes toward the prompt's on-screen width.
- The terminal is narrowed too much, causing the prompt to wrap (split across two lines). The 8 byte `__vsc_prompt_end` now lives on the second line. `_rl_last_c_pos += WRAP_OFFSET(line)` on `display.c:1489` causes `readline` to add `__vsc_prompt_end`'s 8 extra chars to its cursor model.
- The terminal grows back to a larger width such that the prompt is unwrapped (no longer occupies two lines - fits on one line). `readline` now runs `_rl_move_cursor_relative`, which on `display.c:3017` evaluates `else if (cpos > dpos)` — its model of the cursor is 8 chars farther right than the target — and on `display.c:3018` **emits the correction** `_rl_backspace (cpos - dpos)`, i.e. 8 backspaces left, despite the cursor already being in the right spot and not needing this correction. The bug is now reproduced -> the cursor is 8 chars to the left of where it should be.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.