Skip to content

Terminal: DEC private mode lists, DECTCEM and bracketed paste - #2901

Open
insjang wants to merge 1 commit into
eclipse-platform:masterfrom
insjang:dec-modes
Open

insjang wants to merge 1 commit into
eclipse-platform:masterfrom
insjang:dec-modes

Conversation

@insjang

@insjang insjang commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

DEC private mode sequences may carry several modes at once, and ncurses does exactly that when it turns the mouse on: CSI ? 1006 ; 1000 h. The emulator looked at the first parameter only and dropped the rest, so a program could end up with half of what it asked for. Every parameter is now set or reset.

DECTCEM (mode 25) lets a program hide the cursor while it draws, or for good; a full screen program that hides it, such as htop, showed a cursor wandering over its screen. The request is passed to the view, which keeps its own blinking and focus handling and simply does not draw the cursor while a program has hidden it.

Bracketed paste (mode 2004) marks pasted text with CSI 200~ and CSI 201~ so that a program can take it as text rather than as keys typed - a shell does not run every line of a pasted snippet, an editor does not auto-indent it. Programs that ask for it and do not get it misread multi-line pastes. An end marker inside the text is removed so the paste cannot close its own bracket early.

@insjang insjang changed the title Terminal: take every mode in a DEC private set/reset, hide the cursor… Terminal: DEC private mode lists, DECTCEM and bracketed paste Sep 3, 2026
@insjang
insjang force-pushed the dec-modes branch 2 times, most recently from 1767cc4 to f214496 Compare September 30, 2026 08:06
@insjang

insjang commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

This is part of what eclipse-cdt/cdt#737 asks for: the terminal reports TERM=xterm, so shells and prompts (zsh with starship, syntax highlighting, autosuggestions) send xterm sequences that it did not handle. #2900, #2903 and #2904 cover more of the same list.

@insjang

insjang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on master (with #2894 in), one commit, e8629e9; all terminal tests pass. The flag that hides the cursor is now volatile, since the emulator thread sets it and the paint reads it.

How to test, in a runtime Eclipse with this org.eclipse.terminal.control, Terminal view, local shell:

  1. Several modes in one sequence: run htop or mc and click on the screen.
    Expected: the program reacts to the mouse. ncurses turns it on with CSI ? 1006 ; 1000 h, of which only the first mode used to be taken.
  2. Hidden cursor: printf '\e[?25l'; sleep 3; printf '\e[?25h'
    Expected: no cursor for three seconds, then it is back and blinks as before. In htop no cursor wanders over the screen.
  3. Bracketed paste: in bash 5.1 or later (bracketed paste is on by default), copy two lines such as echo one / echo two and paste them at the prompt.
    Expected: both lines appear at the prompt and nothing runs until Enter. Before this change each line ran as it arrived.
  4. A paste cannot close its own bracket: paste text that contains ESC [ 201 ~ (e.g. copied from printf 'a\e[201~b' output in a file): it arrives as "ab", still as one paste.
  5. Reset on a new connection: run printf '\e[?25l\e[?2004h', disconnect the terminal and connect again.
    Expected: the cursor is shown and pastes are not bracketed until the new shell asks for it.

Unit tests: VT100EmulatorTest covers several modes in one sequence, DECTCEM, bracketed paste with an embedded end marker, and the reset.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    54 files  ± 0      54 suites  ±0   37m 11s ⏱️ -13s
 4 979 tests + 6   4 957 ✅ + 6   22 💤 ±0  0 ❌ ±0 
12 828 runs  +18  12 674 ✅ +18  154 💤 ±0  0 ❌ ±0 

Results for commit 85c191e. ± Comparison against base commit c49150d.

♻️ This comment has been updated with latest results.

@insjang
insjang force-pushed the dec-modes branch 2 times, most recently from e980396 to edb0dab Compare November 4, 2026 19:10
… on request, and support bracketed paste

DEC private mode sequences may carry several modes at once, and
ncurses does exactly that when it turns the mouse on: CSI ? 1006 ; 1000 h.
The emulator looked at the first parameter only and dropped the rest,
so a program could end up with half of what it asked for. Every
parameter is now set or reset.

DECTCEM (mode 25) lets a program hide the cursor while it draws, or for
good; a full screen program that hides it, such as htop, showed a
cursor wandering over its screen. The request is passed to the view,
which keeps its own blinking and focus handling and simply does not
draw the cursor while a program has hidden it.

Bracketed paste (mode 2004) marks pasted text with CSI 200~ and
CSI 201~ so that a program can take it as text rather than as keys
typed - a shell does not run every line of a pasted snippet, an editor
does not auto-indent it. Programs that ask for it and do not get it
misread multi-line pastes. The text cannot close its own bracket early:
every ESC and C1 CSI in it is dropped, as xterm does, so no end marker
is left in it or put together from the pieces around one taken out
(ESC[20ESC[201~1~).

A paste sends each line break as a CR, as the Enter key does and as
Windows Terminal and tmux paste. The CR LF of a Windows clipboard reached
the shell as two breaks: readline drew two rows for every pasted line, a
paste taller than the screen pushed the prompt off it, and the redraw on
the next key landed where the prompt no longer was.

Input goes to the process in writes of at most 1000 bytes with a pause
between them. A write no longer ends inside a UTF-8 character or an
escape sequence: ConPTY has passed the pieces of a sequence split across
reads on as plain text (microsoft/terminal#16352), and an end marker cut
as ESC[20 and 1~ left the shell taking everything typed after it as part
of the paste, Enter included.

A reset, which runs before every connection, shows the cursor again and
turns bracketed paste off, so a program that hid the cursor or asked for
bracketed paste and was cut off by a disconnect or a crash does not leave
them set for whatever runs on the next connection.
@insjang

insjang commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

DEC private mode sequences may carry several modes at once, and ncurses does exactly that when it turns the mouse on: CSI ? 1006 ; 1000 h. The emulator looked at the first parameter only and dropped the rest, so a program could end up with half of what it asked for. Every parameter is now set or reset.

DECTCEM (mode 25) lets a program hide the cursor while it draws, or for good; a full screen program that hides it, such as htop, showed a cursor wandering over its screen. The request is passed to the view, which keeps its own blinking and focus handling and simply does not draw the cursor while a program has hidden it.

Bracketed paste (mode 2004) marks pasted text with CSI 200~ and CSI 201~ so that a program can take it as text rather than as keys typed - a shell does not run every line of a pasted snippet, an editor does not auto-indent it. Programs that ask for it and do not get it misread multi-line pastes. The text cannot close its own bracket early: every ESC and C1 CSI in it is dropped, as xterm does, so no end marker is left in it or put together from the pieces around one taken out (ESC[20ESC[2011).

A paste sends each line break as a CR, as the Enter key does and as Windows Terminal (microsoft/terminal#3449) and tmux paste. The CR LF of a Windows clipboard reached the shell as two breaks: readline drew two rows for every pasted line, a paste taller than the screen pushed the prompt off it, and the redraw on the next key landed where the prompt no longer was.

Input goes to the process in writes of at most 1000 bytes with a pause between them. A write no longer ends inside a UTF-8 character or an escape sequence: ConPTY has passed the pieces of a sequence split across reads on as plain text (microsoft/terminal#16352), and an end marker cut as ESC[20 and 1~ left the shell taking everything typed after it as part of the paste, Enter included.

How to test, in a Terminal on Windows with WSL bash (bracketed paste is on in bash 5.1 and later):

  1. Copy a few paragraphs of text (more than the terminal's height when doubled) and paste them at the prompt.
  2. Press Backspace a few times, then Up twice: the prompt and the history entry show as usual, with no rows left over from the paste.
  3. Clear the line, press Enter, type: the keys work.
    Before this change the paste was drawn with a blank row after every line, and Up redrew over rows of the paste with the prompt out of sight.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant