jp_term measures display width two ways
- Status: Todo
- Kind: Chore
- Authors: jp
- Date: 2026-09-08
- Label: package=jp_term
- Label: type=task
jp_term now holds two independent implementations of "how wide is this text on screen", which arrived from different directions and have never been compared.
jp_term::width::display_widthstrips ANSI withstrip-ansi-escapes, then measures withunicode-width. Its neighbours (truncate_to_width,wrap_ranges,prefix_end_for_width) walk grapheme clusters and probe for ligatures that collapse.jp_term::ansi::visual_widthtokenizes withansi::segments, joins the visible runs, and measures the result.advance_columnbuilds on it and adds tab stops and carriage returns.
They disagree in at least one way that matters: visual_width counts a tab as one column and advance_column exists because of it, while the width module has no notion of a tab at all. Whether they disagree on OSC 8 hyperlinks, partial escapes, or ligature collapse is unknown — nothing tests them against each other.
Why it is worth doing
The duplication was invisible while the two lived in different crates. Now a reader of jp_term has to pick one, and the names give no help: display_width and visual_width are the same phrase.
Shape of a fix
Start with a test that runs both over the same inputs — plain ASCII, CJK, VS16 emoji, ZWJ sequences, tabs, OSC 8 links, escapes split mid-sequence — and records where they differ. That answers whether this is one function with two names or two functions with one job each.
If they agree except on tabs, collapse to one and keep advance_column as the cursor-position variant. If they genuinely differ, the names have to say how.