fix(input): preserve tab characters in pasted content#3045
Conversation
Tab-separated data pasted from spreadsheets (e.g. Excel) was silently lost through three interception layers: stripUnsafeCharacters filtered tab as a C0 control char, TextInput consumed tab for autocomplete, and InputPrompt consumed tab for suggestion acceptance. - Add tab (0x09) to the preserve list in stripUnsafeCharacters - Skip tab→autocomplete interception when key.paste is true - Skip tab→suggestion-accept in InputPrompt when key.paste is true
📋 Review SummaryThis PR addresses a data loss issue where tab characters from pasted content (e.g., from Excel/Google Sheets) were being silently dropped. The fix spans three layers of the input handling system to preserve tabs during paste operations while maintaining existing autocomplete functionality. Overall, this is a well-targeted fix with minimal changes and clear reasoning. 🔍 General Feedback
🎯 Specific Feedback🟢 Medium
// During paste, let tab through as literal content (e.g. Excel tab-separated data)
if (
key.name === 'tab' &&
!key.paste &&
buffer.text.length === 0 &&
...
🔵 Low
✅ Highlights
|
E2E Test Report: Tab-Paste HandlingTest Date: 2026-04-09 Results Comparison
Overall Verdict: ✅ FIX VERIFIED (5/5 tests pass) Test Environment
|
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
The "shows unanswered questions as (not answered) in Submit tab" test fails intermittently on Windows CI due to arrow key navigation timing issues in the ink test renderer.
# Conflicts: # packages/cli/src/ui/components/InputPrompt.tsx
TLDR
Pasting tab-separated data (e.g. from Excel/Google Sheets) into the input prompt silently drops all tab characters, merging columns together. For example,
13354→2945→58becomes133542945 58. This fix preserves tab characters through all three interception layers.Screenshots / Video Demo
N/A — verified via E2E interactive tests (tmux). See test plan below.
Dive Deeper
Three layers conspired to drop tab characters:
stripUnsafeCharactersintextUtils.ts— strips all C0 control chars (0x00–0x1F) except CR/LF. Tab (0x09) was caught by this filter even through bracketed paste.TextInput.handleKey— interceptskey.name === 'tab'for autocomplete before the character reaches the text buffer.InputPrompt— intercepts tab for followup suggestion acceptance and completion acceptance.Fixes:
stripUnsafeCharactersalongside CR/LF!key.pasteguard to all three tab interception points so tabs arriving as part of a paste event are treated as literal contentReviewer Test Plan
npm run build && npm run bundlenode dist/cli.js --approval-mode yoloprintf '13354\t2945\t58'):Testing Matrix
Linked issues / bugs
Related to tab-paste data loss reported internally.