Skip to content

修复提示输入的换行、光标定位与 busy 状态显示#171

Merged
qorzj merged 2 commits into
mainfrom
fix/prompt-cursor-wrapping
Jun 9, 2026
Merged

修复提示输入的换行、光标定位与 busy 状态显示#171
qorzj merged 2 commits into
mainfrom
fix/prompt-cursor-wrapping

Conversation

@qorzj

@qorzj qorzj commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

变更

  • 统一输入框和提交后 user prompt 回显的前缀宽度与 hard wrap 规则,避免提交后提前换行。
  • 用 Ink 的光标定位能力替换手动 stdout 光标移动,减少重绘时的光标残留。
  • 在输入框布局变化后,只有当前布局完成测量时才启用真实终端光标;测量完成前使用模拟光标,修复选择 skill 后光标位置错误。
  • 调整 busy 状态 UI:spinner 从输入框前缀移到 status 行前方,输入框前缀始终保持 >
  • busy 开始但尚未收到 statusLine 时立即显示 spinner,避免首次提交后输入框上方空白。
  • busy 状态下统一隐藏真实终端光标和模拟光标,避免 status spinner 与底部进度更新造成光标显示/隐藏冲突和闪烁;非 busy 状态继续使用 IME 友好的真实终端光标。
  • 增加回归测试覆盖提交回显换行、换行边界光标,以及布局测量不匹配时禁用真实终端光标。

实现细节

  • src/ui/hooks/cursor.ts 改为使用 Ink 7 的 useCursor()useBoxMetrics(),不再 patch stdout.write 或手动写入上下移动光标的 ANSI 序列。
  • 光标位置从原来的 { rowsUp, column } 调整为基于输入区域的 { row, column },再结合 Ink 测量到的输入框绝对位置计算最终 { x, y }
  • PromptInput 使用固定的 prompt 前缀宽度计算输入内容宽度,并通过 wrap="hard" 让实时输入、换行边界和提交后回显保持一致。
  • 真实终端光标只在输入聚焦、TTY、无下拉菜单/覆盖提示、非 hard-wrap 边界、非 busy,并且当前布局已完成测量时启用。
  • 当真实终端光标未确认可用时,保留 inverse-video 模拟光标作为回退;busy 状态例外,busy 时光标始终隐藏以避免闪烁。
  • AppPromptInput 传入 cursorLayoutKey,将 status、视图、消息数量、最后一条消息、权限/问题提示等会改变输入框纵向位置的状态纳入布局 key,防止复用旧光标坐标。
  • StatusLine 独立渲染 busy spinner;即使 status 文本为空,只要 busy 就会显示 spinner。
  • 选中 skill、附件数量和终端宽度继续参与生成 prompt 内部布局 key,防止选择 skill 后继续使用旧布局的光标坐标。

验证

  • npm run typecheck
  • npm run lint
  • npm run format:check -- src/ui/views/App.tsx src/ui/views/PromptInput.tsx src/ui/hooks/cursor.ts src/ui/hooks/index.ts
  • npm run test:single -- src/tests/prompt-input-keys.test.ts

@qorzj qorzj changed the title 修复提示输入的换行与光标定位问题 修复提示输入的换行、光标定位与 busy 状态显示 Jun 9, 2026
@qorzj qorzj merged commit 766b057 into main Jun 9, 2026
18 checks passed
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