Skip to content

get_character_cell_size returns 1 for EAW='A' chars; CJK terminals render them as 2 #4197

Description

@eating-saint

Bug

rich/cells.py:get_character_cell_size() returns width=1 for Unicode East Asian Width = A (Ambiguous) characters that fall through the binary search. On CJK terminals, these characters actually render as 2 cells wide.

Affected characters

  • U+2026 (HORIZONTAL ELLIPSIS)
  • U+201C (LEFT DOUBLE QUOTATION MARK)
  • U+201D (RIGHT DOUBLE QUOTATION MARK)
  • Many others in the General Punctuation block (U+2000-U+206F)

How to reproduce

from rich.cells import get_character_cell_size
import unicodedata

for ch in [chr(0x2026), chr(0x201C), chr(0x201D)]:
    print(f"U+{ord(ch):04X} EAW={unicodedata.east_asian_width(ch)} cells={get_character_cell_size(ch)}")
# All print cells=1, but on CJK terminals they occupy 2 columns

Impact

Any Rich widget or downstream consumer (Textual TextArea) doing cell-width layout gets wrong widths. In TextArea WrappedDocument, this causes widget height inflation — each keystroke of an affected character adds spurious line-break calculations and blue separator lines.

Fix

In the two return 1 fallthrough paths in get_character_cell_size(), add an East Asian Ambiguous check:

import unicodedata

if unicodedata.east_asian_width(character) == "A":
    return 2
return 1

The function is @lru_cache(maxsize=4096), so the unicodedata call (~170 ns) is amortized.

Note

wcwidth treats EAW=A as width=1 per the Unicode standard default, but real CJK terminals render them as width=2. A terminal-aware or opt-in approach may be needed for full correctness, but the immediate fix solves the layout corruption for CJK users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions