Skip to content

Use bracketed paste for multiline executed terminal text#302526

Merged
meganrogge merged 5 commits intomicrosoft:mainfrom
jcansdale:jcansdale/terminal-multiline-bracketed-paste
Mar 19, 2026
Merged

Use bracketed paste for multiline executed terminal text#302526
meganrogge merged 5 commits intomicrosoft:mainfrom
jcansdale:jcansdale/terminal-multiline-bracketed-paste

Conversation

@jcansdale
Copy link
Copy Markdown
Contributor

@jcansdale jcansdale commented Mar 17, 2026

Summary

  • treat multiline executed terminal text as pasted input by automatically enabling bracketed paste when supported
  • keep the existing explicit bracketed-paste behavior unchanged for current callers
  • add regression coverage for multiline executed text

Why This Is Required

Multiline executed text is currently sent as raw keystrokes unless the caller explicitly requests bracketed paste. That transport is incorrect for multiline payloads: embedded newlines behave like Enter, shell line editing can interfere, and repeated runs can corrupt the command or leave the shell stuck in a continuation prompt.

Applying bracketed paste automatically for multiline executed text fixes that mismatch while keeping the existing explicit API behavior intact.

Current Symptoms

The current behavior shows up as one or more of the following when the same multiline payload is executed repeatedly in a live terminal session:

  • the shell gets stuck in quote> or another continuation prompt
  • repeated executions return the wrong byte count
  • stale fragments of earlier input are replayed into later commands
  • command execution times out after the terminal state has been corrupted

A representative repro is prompting the following twice.

execute this in the terminal verbatim

echo 'L01 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L02 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L03 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L04 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L05 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L06 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L07 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L08 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L09 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L11 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L12 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L13 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L14 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L15 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L16 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L17 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L18 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
L19 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' | wc -c

Expected:

1064
1064

Observed in failing cases:

  • the first run may succeed
  • later runs can break quoting, replay fragments, or hang instead of returning 1064
echo 'L01 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaa
quote> L02 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L03 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L04 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L05 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L06 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L07 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L08 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L09 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L10 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L11 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L12 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L13 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L14 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L15 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L16 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L17 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L18 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> L19 aaaaaL02 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
quote> 

Integration Test Coverage

This change is exercised in the dedicated integration test repo:

The workflow runs the repro suite against:

  • VS Code stable
  • VS Code insiders
  • this PR built from source

Workflow file:

The suite covers:

  • executeCommand and sendText
  • bash and zsh on Unix-like runners
  • pwsh and Git Bash on Windows
  • 19-line, 40-line, and 50-line payloads
  • single-run and repeated-run stress cases

Most Recent Workflow Results

Latest completed run:

Per-job results:

  • ubuntu-latest / VS Code stable: 16 passed, 0 failed, 0 skipped
  • ubuntu-latest / VS Code insiders: 16 passed, 0 failed, 0 skipped
  • ubuntu-latest / VS Code PR: 16 passed, 0 failed, 0 skipped
  • macos-latest / VS Code stable: 3 passed, 13 failed, 0 skipped
  • macos-latest / VS Code insiders: 4 passed, 12 failed, 0 skipped
  • macos-latest / VS Code PR: 16 passed, 0 failed, 0 skipped
  • windows-latest / VS Code stable: 15 passed, 1 failed, 0 skipped
  • windows-latest / VS Code insiders: 16 passed, 0 failed, 0 skipped
  • windows-latest / VS Code PR: 16 passed, 0 failed, 0 skipped

The important signal from this run is:

  • baseline macOS stable and insiders still reproduce the multiline execution failures
  • baseline Windows stable still reproduces one failure in Git Bash: executeCommand 5x with the 40-line payload
  • Windows insiders passes the full 16-test Windows matrix, including both pwsh and Git Bash
  • the PR build passes the full repro suite on macOS, Linux, and Windows

Platform Scope

This should not be limited to macOS.

macOS still provides the clearest baseline reproduction, but the new Windows matrix shows the issue is not macOS-specific. On Windows stable, pwsh is clean while Git Bash still reproduces a multiline execution failure. That is consistent with this being an input-path mismatch that depends on shell behavior and bracketed paste support, not a macOS-only bug.

The latest integration results support applying the fix broadly wherever bracketed paste mode is supported:

  • macOS baseline builds still fail heavily, while the PR build passes the same suite
  • Windows stable still reproduces a Git Bash failure, while Windows insiders and the PR build pass the full Windows matrix
  • Linux shows no regression signal in either the baseline or PR matrix

Given that the change corrects a general terminal input-path mismatch, and given that the cross-platform integration results are clean for the PR build, the setting should apply wherever bracketed paste mode is supported rather than being special-cased to macOS.

Fixes #296955
Fixes #300762

Copilot AI review requested due to automatic review settings March 17, 2026 18:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates TerminalInstance.sendText to automatically wrap multiline text in bracketed paste sequences when the terminal has bracketed paste mode enabled, and adds a unit test to cover the multiline executed-text behavior.

Changes:

  • Automatically enable bracketed paste wrapping when sendText receives multiline text and xterm reports bracketed paste mode is enabled.
  • Preserve existing behavior for callers explicitly requesting bracketed paste mode.
  • Add a unit test validating multiline executed text is sent wrapped in bracketed paste sequences.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/vs/workbench/contrib/terminal/browser/terminalInstance.ts Adjusts sendText to auto-apply bracketed paste for multiline text when supported/enabled.
src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts Adds a regression/unit test for multiline executed text using bracketed paste, and refactors instance creation into a helper.

@jcansdale jcansdale marked this pull request as draft March 17, 2026 19:06
@microsoft microsoft deleted a comment Mar 17, 2026
@jcansdale jcansdale marked this pull request as ready for review March 19, 2026 00:21
meganrogge
meganrogge previously approved these changes Mar 19, 2026
Copy link
Copy Markdown
Collaborator

@meganrogge meganrogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@vs-code-engineering vs-code-engineering bot added this to the 1.113.0 milestone Mar 19, 2026
@meganrogge meganrogge enabled auto-merge (squash) March 19, 2026 15:06
@meganrogge
Copy link
Copy Markdown
Collaborator

cc @Tyriar

@meganrogge meganrogge merged commit 58757c0 into microsoft:main Mar 19, 2026
18 checks passed
kh4f added a commit to kh4f/vscode that referenced this pull request Mar 21, 2026
…quences

PR microsoft#302526 introduced automatic bracketed paste for any text containing
`\r` or `\n`. This unintentionally changed the behavior of
`sendText(text, false)` for control sequences such as `\u000D`, which
could previously be sent as raw keystrokes via the
`workbench.action.terminal.sendSequence` command to simulate Enter.

This patch restores the original behavior by applying automatic
bracketed paste only when:

- explicitly requested via `bracketedPasteMode`, or
- the text is multiline *and* `shouldExecute` is true

This preserves the multiline execution fix while keeping
non-executed control sequences raw.

A regression test is included to verify that `sendText('\r', false)`
sends a plain `\r` to the pty instead of wrapping it in bracketed paste.

Fixes microsoft#303665
meganrogge added a commit that referenced this pull request Mar 23, 2026
meganrogge added a commit that referenced this pull request Mar 23, 2026
…2526)"  (#304164)

Revert "Use bracketed paste for multiline executed terminal text (#302526)" (#304134)

This reverts commit 58757c0.
kh4f added a commit to kh4f/vscode that referenced this pull request Mar 23, 2026
…quences

PR microsoft#302526 introduced automatic bracketed paste for any text containing
`\r` or `\n`. This unintentionally changed the behavior of
`sendText(text, false)` for control sequences such as `\u000D`, which
could previously be sent as raw keystrokes via the
`workbench.action.terminal.sendSequence` command to simulate Enter.

This patch restores the original behavior by applying automatic
bracketed paste only when:

- explicitly requested via `bracketedPasteMode`, or
- the text is multiline *and* `shouldExecute` is true

This preserves the multiline execution fix while keeping
non-executed control sequences raw.

A regression test is included to verify that `sendText('\r', false)`
sends a plain `\r` to the pty instead of wrapping it in bracketed paste.

Fixes microsoft#303665
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.

Investigate alternatives to fixed 5ms pacing in the macOS multiline PTY workaround Terminal tool corrupts multiline commands exceeding 1024 bytes

5 participants