Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions packages/cli/src/ui/components/SuggestionsDisplay.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,41 @@ describe('SuggestionsDisplay', () => {
expect(lines[0]).toMatch(/^ {2}pr/);
expect(lines[1]).toMatch(/^> issue-to-pr/);
});

it('keeps slash command names intact when argument hints overflow', () => {
const { lastFrame } = render(
<SuggestionsDisplay
suggestions={[
{
label: 'review',
value: 'review',
argumentHint:
'[pr-number|file-path] [--effort low|medium|high] [--comment] [--fix]',
sourceBadge: '[Skill]',
description: 'Review changed code.',
},
{
label: 'doctor',
value: 'doctor',
argumentHint:
'[memory|cpu-profile|rollback] [--sample] [--snapshot] [--duration]',
description: 'Diagnose Qwen Code environment.',
},
]}
activeIndex={0}
isLoading={false}
width={120}
scrollOffset={0}
userInput="/rev"
mode="slash"
/>,
);

const lines = (lastFrame() ?? '').split('\n');

expect(lines).toContainEqual(expect.stringMatching(/^> review(?: |$)/));
expect(lines).toContainEqual(expect.stringMatching(/^ {2}doctor(?: |$)/));
Comment on lines +204 to +205

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The new test pins only the name-survival half of the fix: it never asserts that the argument hint wraps and stays visible, which is this PR's second stated behavior ("Argument hints continue to yield space by wrapping"). The sibling reverse-mode test asserts both sides of its tradeoff (reference intact AND description truncated); this one asserts only one side. — Failure scenario: a future change that renders the hint with wrap="truncate-end" (or skips it when the column overflows) keeps the command names intact, so this test stays green while the wrap-instead-of-vanish behavior silently regresses. Verified by probe: under a simulated truncate mutation this test file still passed 10/10 while the frame no longer contained the hint tail ([--fix]).

Suggested change
expect(lines).toContainEqual(expect.stringMatching(/^> review(?: |$)/));
expect(lines).toContainEqual(expect.stringMatching(/^ {2}doctor(?: |$)/));
expect(lines).toContainEqual(expect.stringMatching(/^> review(?: |$)/));
expect(lines).toContainEqual(expect.stringMatching(/^ {2}doctor(?: |$)/));
expect(lastFrame()).toContain('[--fix]');
中文说明

新测试只固定了修复中"命令名存活"这一半:它没有断言参数提示换行后仍然可见——而这是本 PR 明确承诺的第二个行为("参数提示仍可通过换行让出空间")。同文件中 reverse 模式的姊妹测试同时断言了权衡的两个方面(引用完整保留且描述被截断),而本测试只断言了一方面。— 故障场景:未来若有改动把提示渲染为 wrap="truncate-end"(或在列溢出时直接跳过提示),命令名依然完整,本测试仍然通过,但"换行而不是消失"的行为会悄无声息地回归。已用探针验证:在模拟的截断变异下,整个测试文件仍 10/10 通过,而渲染帧中已不再包含提示尾部([--fix])。建议补充对换行后提示内容的断言,例如 expect(lastFrame()).toContain('[--fix]');——已验证在当前 HEAD 通过、在上述截断变异下失败。

— qwen3.8-max via Qwen Code /review (v0.21.7)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. I agree this would strengthen a broader contract around hint visibility. This PR is intentionally scoped to the reported defect: the actionable command name must not lose characters. Argument hints are secondary and may legitimately be wrapped, truncated, or hidden by a future narrow-width policy, so asserting the full [--fix] tail would broaden the behavior guaranteed here. CI is green and the focused change has already received an approval, so I would prefer to keep this PR small and handle hint-visibility guarantees in a follow-up.

});
});

describe('SuggestionsDisplay tabs', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/ui/components/SuggestionsDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export function SuggestionsDisplay({
: { flexShrink: 1 as const })}
>
<Box>
{labelElement}
<Box flexShrink={0}>{labelElement}</Box>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] With the label now wrapped in <Box flexShrink={0}>, the sibling argumentHint/sourceBadge Text nodes (default flexShrink: 1) absorb all remaining flex shrink. In very narrow terminals they collapse to ~1 column and wrap one character per line, inflating suggestion rows. — Failure scenario: a terminal ≤ ~40 columns (tmux split panes, side-by-side IDE windows) with slash commands carrying long argumentHints — measured on the real component: at width 20 the two-suggestion frame grows from 37 lines pre-fix to 88 lines post-fix (hint as 1-2-char vertical strips plus ~29 trailing blank lines); at width 30, an openwork-desktop-sync + [direction] row grows from 3 to 13 lines. With MAX_SUGGESTIONS_TO_SHOW = 8 the completion menu can balloon vertically and push the conversation off-screen (Ink bottom-anchors overflowing frames). Navigation and mouse hit-testing still work, and pre-fix rendering at these widths was already garbled, so this exacerbates a pre-existing edge case rather than regressing a working path. Suggested fix: skip the hint/badge or apply wrap="truncate-end" when the remaining label-column width after the command name is below a small threshold (e.g. < 8 columns), so narrow terminals degrade to "name only" instead of a one-character vertical strip.

中文说明

标签被包进 <Box flexShrink={0}> 之后,同级的 argumentHint/sourceBadge 文本节点(默认 flexShrink: 1)会吸收全部剩余 flex 收缩。在极窄终端里它们塌缩到约 1 列宽、按每行一个字符换行,使建议行高度暴涨。— 故障场景:终端宽度 ≤ 约 40 列(tmux 分屏、IDE 并排窗口)且命令带有较长 argumentHint 时,在真实组件上实测:宽度 20 时,两条建议的渲染帧从修复前 37 行涨到修复后 88 行(提示变成 1-2 个字符的竖条,另有约 29 行尾部空行);宽度 30 时,openwork-desktop-sync + [direction] 的行从 3 行涨到 13 行。MAX_SUGGESTIONS_TO_SHOW = 8 时,补全菜单可能纵向膨胀、把对话内容挤出屏幕(Ink 对溢出帧做底部对齐)。键盘导航和鼠标命中测试仍然正常,且这些宽度下修复前的渲染本来就是错乱的,因此这是既有边界情况的加剧,而非对原本正常路径的回归。建议:当命令名之后标签列剩余宽度低于某个较小阈值(例如 < 8 列)时,跳过提示/徽标或改用 wrap="truncate-end",让窄终端退化为"只显示名称",而不是出现每行一个字符的竖条。

— qwen3.8-max via Qwen Code /review (v0.21.7)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed measurements. I agree that long-name and extremely narrow terminal combinations deserve a bounded fallback. A robust solution likely needs an explicit remaining-width policy that truncates or hides hints and badges, plus a width-matrix test suite, rather than another isolated flex adjustment. That is broader than the focused command-name truncation fixed here, and rendering at those widths was already degraded before this change. With CI green and the focused fix already approved, I would prefer to defer that broader narrow-width policy to a follow-up.

{suggestion.argumentHint && (
<Text color={theme.text.secondary}>
{' '}
Expand Down
Loading