qwen-code TUI 间距与密度优化 PR1:减少终端空白行的设计实现与行数测量
【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code
本指南讲解 qwen-code 终端 UI(TUI)第一轮"间距与密度(spacing and density)"优化(PR1)的设计决策、落地方式与验证方法。它解决的是真实使用中的痛点:简单问答、文件列表、工具输出、报错信息、diff 与长流式输出之间夹杂的多余空行,迫使你在终端里反复滚动空白而非浏览内容。读完本文,你将掌握该轮优化改了什么、为什么只改间距不动结构、四条"间距标准"如何在源码中落地,以及如何在 100/80 列固定宽度下用快照与 tmux 证据复核行数收益。
为什么需要一次"只改间距"的专项优化
在常见的会话里,当前 TUI 会在三类位置额外消耗行数:
- 助手输出之前的空白间隔;
- 状态/工具块之间的空白间隔;
- 展开后的工具组内部的空白间隔。
这些位置本身不是问题——问题在于累积效果。以简单问答、文件列表、工具输出、错误状态、diff 和长流式输出为代表的场景中,用户需要翻越"空白空间"而不是直接阅读内容,可扫描性(scannability)被明显削弱。
PR1 是 qwen-code 议题 #4588(issue 4588)的第一轮聚焦推进。它刻意只处理间距与密度,从而让评审可以在改动前后直接比较行数占用,而不用同时评审思考轨迹可见性、工具边框、SubAgent 布局、品牌展示或主题色变化等其他维度。换句话说:这是一次"变量隔离"的优化,把间距单独拎出来改、单独拿出来量。
实现思路:保持结构,只动空白
实现保持既有信息结构和渲染表面不变,改动集中在三个点:
1. 历史条目间距在 HistoryItemDisplay 统一收敛
历史条目的间距逻辑集中在HistoryItemDisplay组件上。源码中的getHistoryItemMarginTop函数(HistoryItemDisplay.tsx)按HistoryItem.type决定每个条目渲染时的marginTop:
gemini(助手回复)与gemini_thought(思考块)保留1行的上边距;gemini_content、gemini_thought_content(连续性内容)、info、success、warning、error、retry_countdown、memory_saved、tool_group、tool_use_summary、compression、summary、user、user_prompt_submit_blocked、stop_hook_loop、goal_status、vision_notice等回合内(in-turn)后续块全部返回0,即不再额外插入前置空行。
对应到用户可见行为:
- 用户提问(user)与独立命令视图仍然以回合分隔符开头。
UserMessage自身带marginTop={1}(见 ConversationMessages.tsx),保证"新的一轮"有清晰的视觉起点; - 助手连续性输出、工具组、状态消息、工具摘要以及与回合相关的后续输出不再附加额外的前置空行。
测试侧有对应的断言佐证:在 HistoryItemDisplay.test.tsx 中,助手回复gemini条目仍断言以换行开头(output.startsWith('\n')为 true);而在 HistoryItemDisplay.test.tsx 中,tool_use_summary(工具摘要)断言不以换行开头(output.startsWith('\n')为 false)。这正是"独立用户回合保留一个分隔符、回合内后续块不再叠加第二个分隔符"的代码级验证。
2. 展开工具组:保留边框,去掉工具条目之间的空行
展开的工具组保持现有的边框与状态/标题结构不变,但不再在相邻工具条目之间插入空白行。实现位置在ToolGroupMessage的展开渲染分支:外层容器使用gap={0},每个工具条目以<Box key={tool.callId} flexDirection="column" minHeight={1}>紧挨排列(见 ToolGroupMessage.tsx),工具条目之间的行距完全由工具内容自身的高度决定,而不是靠空白行撑开。同样的gap={0}也用于折叠工具的摘要展示CompactToolGroupDisplay(见 CompactToolGroupDisplay.tsx),保证折叠与展开两条路径的密度口径一致。
3. 工具结果紧贴工具标题/状态行
工具结果直接渲染在工具标题/状态行的正下方。在 ToolMessage.tsx 中,结果渲染分支与头部行之间不再有空行:ToolMessage的最外层容器是paddingY={0},结果块(Markdown 字符串、diff、ANSI 输出、todo/findings/plan、subagent 摘要、图片等)直接以paddingLeft={STATUS_INDICATOR_WIDTH}的缩进块跟在头部之后。
这一改动不改变:
- 输出内容本身(文本、diff、ANSI 内容逐字保留);
- 截断行为(
availableTerminalHeight、MaxSizedBox、shell 输出行数上限ui.shellOutputMaxLines等照常生效); - shell 焦点行为(
(ctrl+f to focus)提示与ShellInputPrompt不受影响); - 确认提示(
ToolConfirmationMessage仍在确认分支内正常渲染); - 紧凑模式(compact mode)行为。
也就是说,这次优化对"密度"的追求是有边界的:它只移除为间隔而存在的空白行,绝不挤压内容本身。
间距标准(Spacing Standard)
PR1 确立的四条间距规则可以浓缩为一张对照表:
| 场景 | 规则 |
|---|---|
| 独立的用户回合 | 保留一个视觉分隔符 |
| 助手输出与回合内后续块 | 不叠加第二个分隔符 |
| 工具标题与工具结果内容 | 紧邻(adjacent) |
| 展开的多工具组 | 相邻工具条目之间不插入空行 |
另有一条刻意保持不变的规则:复杂的 Markdown 块(表格、代码块、数学块)保留其既有的内部布局。Markdown 空行行为有意不改——渲染器本就把连续空行折叠为一个间隔,同时保留表格、代码块、数学块等复杂块。
预期效果与量化测量
在同一终端宽度、同一渲染内容的条件下,目标场景应当消耗更少的可见行数:
- 简单问答:至少减少 1 个可见行;
- 展开的工具输出:每个此前带有"标题/结果空行间隔"的渲染工具结果,至少减少 1 行;
- 多工具组:每对相邻工具条目之间减少 1 行;
- 项目检查、diff、文件列表、报错、长流式输出等场景:除非终端换行导致不可避免的变化,否则不得增加行数(回归红线)。
100 列基准测量的四组数据
自动化间距断言与终端证据统一采用100 列夹具:
| 场景 | 宽度 | 基准行数 | PR1 行数 | 增量 | 证据 |
|---|---|---|---|---|---|
| 简单助手回复 | 100 | 2 | 1 | -1 | 移除历史前置间隔 |
| 单行结果的工具标题 | 100 | 3 | 2 | -1 | 标题与结果紧邻 |
| 三个工具展开组(含渲染结果) | 100 | 16 | 11 | -5 | 每个工具结果移除 1 个标题/结果间隔;相邻工具之间移除 1 个条目间隔 |
| 完整代表性夹具 | 100 | 26 | 19 | -7 | 相同渲染内容由 tmux 捕获 |
其中"三工具展开组"的 -5 行分解为:3 个工具结果各移除 1 行标题/结果间隔(-3),3 个工具之间有 2 处相邻条目间隔(-2),合计 -5。
快照差异还覆盖了既有的80 列夹具,以确认当前组件测试框架中行数增量一致。相关快照文件见 HistoryItemDisplay.test.tsx.snap。
如何复核与复现
仓库中与本轮改动直接相关的验证入口:
- 组件测试:
packages/cli/src/ui/components/HistoryItemDisplay.test.tsx中的renders assistant replies with a leading spacer row与renders tool summaries without a leading spacer row两个用例分别锁定了"保留用户回合分隔符"与"工具摘要无前置空行"两条规则; - 快照基线:
packages/cli/src/ui/components/__snapshots__/HistoryItemDisplay.test.tsx.snap覆盖 80 列与 100 列的渲染结果,用于对比行数增量; - tmux 终端证据:完整代表性夹具(26 → 19 行)通过 tmux 捕获同一渲染内容的实际终端帧,避免组件测试与实际终端渲染之间的偏差。
明确不做的事(Out of Scope)
PR1 是"间距专项",以下改动被明确排除在范围之外,留待后续 PR 单独评审:
- 隐藏思考轨迹(thinking traces);
- 移除工具边框(tool borders);
- 重新设计 SubAgent 输出布局;
- 改变启动品牌展示或横幅(banner);
- 改变主题颜色;
- 新增每回合助手耗时显示;
- 改变表格内联代码高亮。
这份范围清单与"为什么只改间距"一节相互印证:任何可能干扰"行数对比"的变量都被推迟,从而保证 PR1 的测量结果只反映间距与密度的收益。
小结
PR1 是 qwen-code 在 TUI 密度上迈出的第一步:通过HistoryItemDisplay的getHistoryItemMarginTop收敛历史条目间距、在ToolGroupMessage展开路径以gap={0}消除工具条目间空行、在ToolMessage以paddingY={0}让工具结果紧贴标题行,三处改动共同落实四条间距标准。100 列基准下,简单问答 -1 行、工具标题 + 单行结果 -1 行、三工具展开组 -5 行、完整代表性夹具 -7 行,且项目检查、diff、文件列表、报错与长流式输出不增行。后续维度(思考可见性、工具边框、SubAgent 布局、品牌、主题色、回合耗时、表格内联代码高亮)将作为独立主题另行处理。
【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考