myclaude -r: 固定块 ANSI 重绘修复对齐与滚动冲突 + cli 测试 mock 修复
- picker 弃用 Live 整屏接管,改固定 12 行块增量重绘(\x1b[{n}A 回到块顶逐行覆盖),scrollback 不受影响
- 每行单行渲染,title 列定宽 43 + CJK 感知截断,布局按 80 列设计
- tests: 新增 TestPickerBlock;test_cli which mock 改 side_effect 只命中后端二进制,避免 _npm_global_bin 多跑 subprocess.run;裸 --resume 测试更新为新 picker 语义
This commit is contained in:
@@ -189,6 +189,63 @@ def _make_rows(claude_env, n: int):
|
||||
return L._claude_session_rows(claude_env.cwd)
|
||||
|
||||
|
||||
def _ansi_strip(text: str) -> str:
|
||||
return re.sub(r"\x1b\[[0-9;]*m", "", text)
|
||||
|
||||
|
||||
class TestPickerBlock:
|
||||
"""Fixed 80-col block rendering (header + rows + status), CJK-aware."""
|
||||
|
||||
def _rows(self, claude_env, n: int):
|
||||
return _make_rows(claude_env, n)
|
||||
|
||||
def test_rows_are_single_line_within_80(self, claude_env) -> None:
|
||||
rows = self._rows(claude_env, 3)
|
||||
state = L._PickerState(rows=rows)
|
||||
lines = L._picker_block(state, claude_env.cwd, None)
|
||||
# header + 3 rows + status
|
||||
assert len(lines) == 5
|
||||
for line in lines[1:4]:
|
||||
assert len(_ansi_strip(line)) <= 80
|
||||
assert "Sessions in" in lines[0]
|
||||
|
||||
def test_selected_row_reversed(self, claude_env) -> None:
|
||||
rows = self._rows(claude_env, 3)
|
||||
state = L._PickerState(rows=rows, cursor=1)
|
||||
lines = L._picker_block(state, claude_env.cwd, None)
|
||||
assert "\x1b[7m" in lines[2]
|
||||
assert "\x1b[7m" not in lines[1]
|
||||
|
||||
def test_title_truncated_with_ellipsis(self, claude_env) -> None:
|
||||
# _make_rows writes title-less jsonl; inject a long CJK title directly.
|
||||
row = L.ClaudeSessionRow(
|
||||
cli_session_id="long",
|
||||
title="很长的中文标题" * 10,
|
||||
origin="cli",
|
||||
status=None,
|
||||
updated_at=1000.0,
|
||||
jsonl_path=Path("x.jsonl"),
|
||||
xiaohe_session_id=None,
|
||||
)
|
||||
state = L._PickerState(rows=[row])
|
||||
lines = L._picker_block(state, claude_env.cwd, None)
|
||||
plain = _ansi_strip(lines[1])
|
||||
assert "…" in plain
|
||||
assert len(plain) <= 80
|
||||
|
||||
def test_message_line_replaces_hint(self, claude_env) -> None:
|
||||
rows = self._rows(claude_env, 3)
|
||||
state = L._PickerState(rows=rows)
|
||||
lines = L._picker_block(state, claude_env.cwd, "client-only: no jsonl")
|
||||
assert "client-only" in lines[-1]
|
||||
assert "↑↓" not in lines[-1]
|
||||
|
||||
def test_cjk_display_width(self) -> None:
|
||||
assert L._disp_width("ab") == 2
|
||||
assert L._disp_width("中文") == 4
|
||||
assert L._disp_width("a中") == 3
|
||||
|
||||
|
||||
class TestPickerAdvance:
|
||||
"""Windowed picker state machine (no tty needed)."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user