Fix: Enable Bracketed Paste Mode in useTerminalInput#45
Closed
hqwlkj wants to merge 6 commits into
Closed
Conversation
- 添加粘贴标记以区分粘贴输入和普通输入 - 启用终端的括号粘贴模式,使用特殊起止标记包裹粘贴内容 - 累积起止标记之间的文本,作为一个整体传递给输入处理函数 - 规范化粘贴内容中的各种换行符为统一的 \n - 确保粘贴内容作为单次原子输入,避免碎片化事件 - 在输入状态管理中增加对粘贴事件的识别和处理
- 添加粘贴标记以区分粘贴输入和普通输入 - 启用终端的括号粘贴模式,使用特殊起止标记包裹粘贴内容 - 累积起止标记之间的文本,作为一个整体传递给输入处理函数 - 规范化粘贴内容中的各种换行符为统一的 \n - 确保粘贴内容作为单次原子输入,避免碎片化事件 - 在输入状态管理中增加对粘贴事件的识别和处理
- 新增通用 DropdownMenu 组件,实现带标题、帮助文本、滚动支持和状态指示的下拉列表 - 将 PromptInput 中技能选择列表替换为 DropdownMenu,简化代码结构 - 将模型和思考模式选择菜单同样替换为 DropdownMenu 组件实现 - 调整文本颜色,将光标前缀颜色改为 #229ac3,加强视觉一致性 - 优化 Footer 文本显示逻辑,仅在菜单或下拉框激活时显示 - 规范异常处理逻辑,改进 ignore 文件读取和路径过滤流程 - 修复 session.ts 中目录读取声明,避免未定义赋值风险
jeoor
added a commit
to jeoor/deepcode-cli
that referenced
this pull request
May 20, 2026
…psing - Detect bracketed paste (ESC[200~ / ESC[201~) and dispatch as atomic paste event - Large pastes (>10 lines or >1000 chars) are stored and replaced with a compact marker [paste #N] - Ctrl+O toggles expand/collapse, backspace/delete atomically remove the entire marker - Markers are highlighted with chalk.yellow and expanded back on submit - Follows existing terminal hook patterns (useBracketedPaste alongside useTerminalExtendedKeys) - Array-based chunk buffering to avoid O(n²) string concatenation on multi-chunk pastes - Lazy text cleaning deferred to expand/submit time Known limitation: expand/collapse briefly clears Ink <Static> content above the prompt (React render pipeline constraint). Reference: PR lessweb#45 (closed), inspired by pi project's paste marker approach.
jeoor
added a commit
to jeoor/deepcode-cli
that referenced
this pull request
May 20, 2026
…psing - Detect bracketed paste (ESC[200~ / ESC[201~) and dispatch as atomic paste event - Large pastes (>10 lines or >1000 chars) are stored and replaced with a compact marker [paste #N] - Ctrl+O toggles expand/collapse, backspace/delete atomically remove the entire marker - Markers are highlighted with chalk.yellow and expanded back on submit - Follows existing terminal hook patterns (useBracketedPaste alongside useTerminalExtendedKeys) - Array-based chunk buffering to avoid O(n²) string concatenation on multi-chunk pastes - Lazy text cleaning deferred to expand/submit time Known limitation: expand/collapse briefly clears Ink <Static> content above the prompt (React render pipeline constraint). Reference: PR lessweb#45 (closed), inspired by pi project's paste marker approach.
jeoor
added a commit
to jeoor/deepcode-cli
that referenced
this pull request
May 20, 2026
…psing - Detect bracketed paste (ESC[200~ / ESC[201~) and dispatch as atomic paste event - Large pastes (>10 lines or >1000 chars) stored and replaced with compact marker - Ctrl+O toggles expand/collapse with setTimeout(0) to mitigate render flicker - Backspace/delete atomically removes entire marker (only for real paste IDs) - Markers highlighted with chalk.yellow only when ID exists in pastesRef - Follows existing terminal hook patterns (useBracketedPaste alongside useTerminalExtendedKeys) - Array-based chunk buffering to avoid O(n²) string concat on multi-chunk pastes - Lazy text cleaning deferred to expand/submit time - Regex requires line/char suffix to avoid false positives on literal [paste #N] Known limitation: expand/collapse briefly clears Ink <Static> content (React render pipeline) Reference: PR lessweb#45 (closed), inspired by pi project's segmentWithMarkers approach
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
修复
useTerminalInput中 Bracketed Paste Mode(括号粘贴模式)的粘贴处理代码因未启用而成为死代码的问题,使粘贴多行代码时能够作为原子输入正确处理。Problem
在之前的 commit
4c015a3中,useTerminalInput添加了完整的 Bracketed Paste Mode 处理逻辑:\u001B[200~/\u001B[201~\r\n/\r→\n)paste标志位区分粘贴与按键输入但在实际运行中,Bracketed Paste Mode 从未被启用:
setBracketedPasteMode方法仅暴露在内部 API(useStdinContext)中,公开的useStdin()hook 不包含此方法useTerminalInput从未调用该方法或直接写入 ANSI 转义序列来启用该模式\u001B[200~/\u001B[201~标记因此粘贴多行文本时,终端逐行发送数据,粘贴内容中的
\r字符会被parseTerminalInput误判为 Enter 键,导致粘贴内容被拆解为零散的按键事件,无法正确保留原始格式。Solution
在
useTerminalInput中与setRawMode(true)同级启用 bracketed paste mode,通过直接写入 ANSI 转义序列到 stdout:这与 Ink 内部
App组件的handleSetBracketedPasteMode实现方式完全一致,都是向终端发送\u001B[?2004h(启用)/\u001B[?2004l(关闭)来控制 bracketed paste mode。Changes
src/ui/prompt/useTerminalInput.tsuseEffect中新增process.stdout.write("\u001B[?2004h")和对应的清理逻辑Diff
useEffect(() => { if (!isActive) { return; } setRawMode(true); + // Enable bracketed paste mode so the terminal wraps pasted text in + // \u001B[200~ / \u001B[201~ markers, allowing us to deliver the full + // paste as a single atomic input instead of fragmented key events. + process.stdout.write("\u001B[?2004h"); return () => { setRawMode(false); + process.stdout.write("\u001B[?2004l"); }; }, [isActive, setRawMode]);Effect
Before(Bracketed Paste 未启用)
粘贴
hello\nworld时,终端发送hello\rworld,其中\r被parseTerminalInput识别为key.return = true,粘贴内容被拆分为多个独立事件。After(Bracketed Paste 已启用)
粘贴
hello\nworld时,终端发送包裹后的完整内容:useTerminalInput累加起止标记之间的全部文本,归一化行尾符后作为一次原子操作交付给PromptInput.tsx,key.return = false,所有其他按键标志也为false,仅paste = true。效果对比
\r被误判为 Enterkey.tab = false)PromptInput.tsx归一化Verification
Notes
setBracketedPasteMode仅通过内部useStdinContext暴露,不在公开 APIuseStdin中。由于本项目使用自定义的useTerminalInput(直接监听stdin.on("data")而非 Ink 的useInput/usePaste),直接写入 ANSI 转义序列是最简洁且与 Ink 内部行为一致的方案。paste标志位在InputKey中已就绪,可供后续需要区分粘贴与普通输入的场景使用。