Skip to content

Latest commit

 

History

History
34 lines (20 loc) · 2.14 KB

File metadata and controls

34 lines (20 loc) · 2.14 KB

p06 · TUI 差分渲染

接受终端的约束而不是绕过它:"coding agent 本质是聊天界面,一切可线性化。"

问题

终端 UI 的两条路各有致命伤:全屏 TUI(opencode 一派)独占视口,丢掉终端原生的滚回缓冲和搜索;朴素追加打印又会闪烁,而且没法原地更新流式生成中的 markdown。

它是怎么做的

走 Claude Code 一派的"流式 TUI",但引入保留模式组件树(pi-tui 包):

  • 每个 Component 实现 render(width): string[],Container 垂直排列;组件缓存渲染输出——流式完成的消息不必每帧重新解析 markdown;
  • 差分算法:首帧全量输出;之后找第一个差异行,从那行重绘到底;
  • 终端宽度变化(软换行全变)→ 清屏全量重绘;
  • 关键坑:差异行已滚出可见视口上方时只能全量重绘——终端不允许写入滚回缓冲区,这是协议级约束,绕不过去;
  • 用同步输出转义序列 CSI ?2026h/l 把一帧的输出原子化提交,Ghostty/iTerm2 下完全无闪烁;
  • 代价算过账:内存里保存完整滚回缓冲(几百 KB 字符串),作者实测 V8 下可接受。

为什么好

这是"约束逼出简洁"的一个完整案例:不能随意定位光标、不能写滚回区——接受这两条终端铁律之后,剩下的唯一可行架构(线性组件树 + 从差异行重绘到底)反而比全屏 TUI 的自由布局简单得多。作者的架构论点值得记住:coding agent 本质是聊天界面,一切可线性化——需要二维布局的那一刻,往往是功能本身该被质疑的一刻(呼应 p02)。

与本系列的差异

notes 没有 TUI 章节(Reina 是桌面 GUI,渲染走 DOM)。仅参考——但"组件缓存 + 首个差异行重绘"的思路对任何流式渲染面(包括 GUI 里的消息列表虚拟化)都成立。

来源

主博文 pi-tui 章节 · packages/tui


← pi 档案目录 · agent_analysis