. U2 总览:交互式主屏
U1 阶段我们搭好了脚手架:Rust 项目、嵌套的 Ink TUI、xtask 自动化。但那时的 tui/src/App.tsx 只是一个静态空壳,渲染产品版本、当前 workspace cwd 和一行 backend-only 预览提示,用来验证 Ink 渲染链路是否打通。
. 主题令牌与半行背景块
这一篇讲两个最底层、被几乎所有 UI 模块引用的文件:集中式的主题令牌 themeConfig.ts,以及半行背景块用到的两个 glyph 常量 backgroundBlock.ts。它们对应主题计划文档里的 U2(半行背景块原语)和 U3(接入背景块与主题)。
. 主屏状态:配置与派生原子
这一篇深入 tui/src/state/homeScreenAtoms.ts 的状态部分:配置类型、默认值工厂、根配置原子,以及由它派生出来的正文、提交、滚动原子。这个文件里还有一大块布局计算(resolveHomeScreenLayout、layoutAtom、bottomSpacerRowsAtom、composerTopAtom),那部分留到下一篇专门讲。
. 布局算法:底部吸附与行预算
这一篇讲 U2 里最“数学”的部分:怎么在任意终端尺寸下,把 cwd 行、输入框、状态栏稳定地吸附在终端底部,正文区占据剩下的空间,并且正文与 cwd 之间永远只留一个空行。涉及 layout.ts 的常量与 headerRowCount,以及 homeScreenAtoms.ts 里的 resolveHomeScreenLayout、layoutAtom、bottomSpacerRowsAtom、composerTopAtom、maxBodyScrollOffsetRowsAtom。
. 顶部 Header 与状态栏 StatusBar
这一篇讲主屏最上面和最下面两条 chrome:Header.tsx 和 StatusBar.tsx。两者都很短,但都体现了一个共同思路:按终端列宽分档降级,窄屏优先保住核心信息。
. 工作目录与 Git 状态
cwd 行显示用户正在操作的项目目录,外加一个可选的 Git 状态标签,比如 ~/Projects/KQode ⎇ main*]。这一篇拆三个文件:展示组件 [CwdLine.tsx、格式化 helper cwdLine.ts、Git 解析 gitStatus.ts。
. 正文转录:BodyPane 与 bodyRows
正文区是主屏的“对话记录”:它把一组 BodyEntry(信息、用户 prompt、pending、成功、错误)渲染成多行文本,支持换行、滚动和滚动条,用户 prompt 还会渲染成带半行边缘的消息块。这一篇拆两个文件:纯数据 helper bodyRows.ts 和渲染组件 BodyPane.tsx。
. 输入框状态:composerAtoms
输入框(composer)这条线一共四篇,从状态开始。tui/src/state/composerAtoms.ts 持有输入框的全部可变状态,并把所有“编辑动作”封装成写原子。它在第一个 commit 里曾是一个 composerReducer,重构 commit 5432e018 把它改写成了 Jotai atoms。
. 输入框输入处理:键盘与 Enter 语义
上一篇的状态原子是“能做什么”,这一篇讲“按键怎么映射到这些动作”。核心是 usePromptComposerInput.ts,外加一小撮常量 constants.ts。它对应主屏计划的 U3:可输入、可换行、Enter 提交。
0. 输入框可视文本:换行与滚动窗口
输入框只占终端底部很少几行,但 prompt 可能很长、可能有真实换行。promptTextView.ts 负责把完整文本按列宽换行、再裁出一个包含光标的可见窗口,并顺带算出输入框要占几行、怎么格式化校验错误。
1. 输入框光标与渲染
输入框这条线的最后一篇,把三块拼起来:光标坐标计算 cursorPosition.ts、帧渲染 ComposerFrame.tsx、以及编排一切的 index.tsx。
2. 鼠标解析与滚动接线
正文能用滚轮、PageUp/PageDown 翻看,靠的是 mouse.ts 解析 SGR 鼠标序列,再由 HomeScreenView.tsx 把这些事件接到滚动原子上。这一篇把这条链路讲完。
3. U2 总结
前面十二篇把 U2 阶段的每个模块都逐函数拆了一遍。这一篇做个收束:U2 整体交付了什么、对应哪些计划单元、做了哪些关键技术决策,以及刻意留到后面的部分。