Reviewed code and tests related to paste handling.
UnderstandAnalyzed terminal bracketed paste mode behavior.
UnderstandSummarized root cause of multiline paste bug.
UnderstandConsidered edge cases and brittleness concerns.
UnderstandAnalyze GitHub issue(s): https://github.com/badlogic/pi-mono/issues/767 read full comments
For each issue:
Read the issue in full, including all comments and linked issues/PRs.
For bugs:
For feature requests:
Do NOT implement unless explicitly asked. Analyze and propose only.
Let me look at the input handling code in the TUI package to understand how bracketed paste mode works:
Now let me look at the editor component to see how it handles paste events and enter key:
Let me look at how the terminal handles bracketed paste mode:
Now let me look at the tests for paste handling:
Now I have a complete picture. Let me summarize the analysis:
When using pi on Git for Windows bash in Windows Terminal, pasting multiline text triggers prompt submission instead of inserting all lines.
Git for Windows bash (mintty) doesn't support or properly enable bracketed paste mode in some configurations.
How bracketed paste works:
\x1b[?2004h to stdout (in terminal.ts:start())\x1b[200~ (start) + pasted content + \x1b[201~ (end)StdinBuffer detects these markers and emits a paste eventEditor handles paste events specially, inserting all content without treating newlines as submitWhat fails without bracketed paste support:
StdinBuffer splits input into individual sequences\r (carriage return) is emitted as a single characterhandleInput() matches \r as "enter" (submit action):
// In keys.ts matchesKey()case "enter": if (modifier === 0) { return data === "\r" || ... }The user's test confirms this:
6f 6e 65 0d 74 77 6f ("one\rtwo" with no markers)1b 5b 32 30 30 7e 6f 6e 65 0d 74 77 6f 1b 5b 32 30 31 7e (same content wrapped in bracketed paste markers)Likely differences in:
Newer versions may properly support bracketed paste via ConPTY.
Detect "implicit paste" in StdinBuffer.process() when:
\r or \nChanges to packages/tui/src/stdin-buffer.ts:
public process(data: string | Buffer): void { // ... existing timeout clearing and string conversion ...
// After converting to string, before existing logic: // Detect implicit paste: multi-character input with newlines but no bracketed paste markers // This handles terminals that don't support bracketed paste mode (e.g., some Git Bash configurations) if (!this.pasteMode && str.length > 1 && (str.includes('\r') || str.includes('\n')) && !str.includes(BRACKETED_PASTE_START) && !str.includes(BRACKETED_PASTE_END)) { // Emit as paste event to avoid treating newlines as submit this.emit("paste", str); return; }
// ... rest of existing logic ...}Edge cases to consider:
\r from Enter key: length === 1, so won't trigger\r: rare, and typically don't arrive with other content in the same data event\r or \n in the payloadpackages/tui/src/stdin-buffer.ts (primary fix)packages/tui/test/stdin-buffer.test.ts (add test case)packages/tui/CHANGELOG.md (document fix)The proposed fix is the most robust and least intrusive.
isn't that brittle? think of edge cases
You're right, let me think through the edge cases:
False positives (would incorrectly treat as paste):
False negatives (would miss actual pastes):
The fundamental problem: We cannot reliably distinguish between:
"one\rtwo""one" then pressing EnterIf they arrive in the same data event, they're byte-identical.
Better assessment:
The owner cannot reproduce on the same claimed setup (Win 11, Git Bash, Windows Terminal). This suggests:
Recommended approach:
Request more information on the issue:
git --version)echo $TERM and echo $TERM_PROGRAM.bashrc or .minttyrc configurationDocument the workaround: Users can use Shift+Enter or Alt+Enter to insert newlines manually, which works regardless of bracketed paste support.
Document as known limitation: Some terminal configurations don't support bracketed paste. Recommend WSL or native Windows Terminal with PowerShell as alternatives.
Implementing a heuristic that could break normal Enter-to-submit behavior for everyone seems worse than the original issue affecting a subset of users with unusual terminal configurations.
// In keys.ts matchesKey()case "enter": if (modifier === 0) { return data === "\r" || ... }public process(data: string | Buffer): void { // ... existing timeout clearing and string conversion ...
// After converting to string, before existing logic: // Detect implicit paste: multi-character input with newlines but no bracketed paste markers // This handles terminals that don't support bracketed paste mode (e.g., some Git Bash configurations) if (!this.pasteMode && str.length > 1 && (str.includes('\r') || str.includes('\n')) && !str.includes(BRACKETED_PASTE_START) && !str.includes(BRACKETED_PASTE_END)) { // Emit as paste event to avoid treating newlines as submit this.emit("paste", str); return; }
// ... rest of existing logic ...}