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
4 changes: 3 additions & 1 deletion packages/claude-code-plugin/hooks/lib/tiny_actor_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from itertools import zip_longest

from buddy_renderer import display_width, pad_to_display_width


def layout_grid(
cards: list[list[str]],
Expand Down Expand Up @@ -55,7 +57,7 @@ def layout_grid(
padded_cards.append(padded)

for line_parts in zip_longest(*padded_cards, fillvalue=" " * card_width):
parts = [part.ljust(card_width) for part in line_parts]
parts = [pad_to_display_width(part, card_width) for part in line_parts]
# Pad row to full width when fewer cards than max_columns
while len(parts) < max_columns:
parts.append(" " * card_width)
Expand Down
60 changes: 60 additions & 0 deletions packages/claude-code-plugin/tests/test_tiny_actor_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
if _lib_dir not in sys.path:
sys.path.insert(0, _lib_dir)

from buddy_renderer import display_width
from tiny_actor_grid import layout_grid

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -79,6 +80,65 @@ def test_all_lines_consistent_width(self):
widths = {len(line) for line in lines}
assert len(widths) == 1, f"Expected uniform width, got {widths}"

def test_cjk_labels_consistent_display_width(self):
"""Cards with CJK text must produce uniform display width across rows."""
from buddy_renderer import pad_to_display_width

def _cjk_card() -> list[str]:
return [
pad_to_display_width("한국어", _CARD_WIDTH),
pad_to_display_width("테스트", _CARD_WIDTH),
pad_to_display_width("라벨", _CARD_WIDTH),
]

cards = [_cjk_card(), _make_card(label="A"), _cjk_card()]
lines = layout_grid(cards, available_width=80, card_width=_CARD_WIDTH, gap=2)
widths = {display_width(line) for line in lines}
assert len(widths) == 1, f"CJK grid display widths not uniform: {widths}"

def test_ansi_colored_text_consistent_display_width(self):
"""Cards with ANSI escape codes must produce uniform display width."""
from buddy_renderer import pad_to_display_width

RED = "\033[31m"
RESET = "\033[0m"

def _ansi_card() -> list[str]:
return [
pad_to_display_width(f"{RED}colored{RESET}", _CARD_WIDTH),
pad_to_display_width(f"{RED}face{RESET}", _CARD_WIDTH),
pad_to_display_width(f"{RED}text{RESET}", _CARD_WIDTH),
]

cards = [_ansi_card(), _make_card(label="B"), _ansi_card()]
lines = layout_grid(cards, available_width=80, card_width=_CARD_WIDTH, gap=2)
widths = {display_width(line) for line in lines}
assert len(widths) == 1, f"ANSI grid display widths not uniform: {widths}"

def test_mixed_cjk_ansi_ascii_consistent(self):
"""Mixed CJK, ANSI, and ASCII cards in one grid stay aligned."""
from buddy_renderer import pad_to_display_width

GREEN = "\033[32m"
RESET = "\033[0m"

cjk_card = [
pad_to_display_width("보안전문가", _CARD_WIDTH),
pad_to_display_width("분석중", _CARD_WIDTH),
pad_to_display_width("완료", _CARD_WIDTH),
]
ansi_card = [
pad_to_display_width(f"{GREEN}status{RESET}", _CARD_WIDTH),
pad_to_display_width(f"{GREEN}ok{RESET}", _CARD_WIDTH),
pad_to_display_width(f"{GREEN}done{RESET}", _CARD_WIDTH),
]
ascii_card = _make_card(label="Z")

cards = [cjk_card, ansi_card, ascii_card]
lines = layout_grid(cards, available_width=80, card_width=_CARD_WIDTH, gap=2)
widths = {display_width(line) for line in lines}
assert len(widths) == 1, f"Mixed grid display widths not uniform: {widths}"


# ---------------------------------------------------------------------------
# Edge cases
Expand Down
Loading