Skip to content

🐛 VS16 (U+FE0F) emoji measured at the wrong width #81

Description

@natemoo-re
  • Package: clayterm
  • Version: v0.6.0 (reproduced on main @ d75fb4b)
  • Runtime: Deno 2.x
  • OS: platform-independent (WASM); reproduced on macOS

Describe the bug

We measure text width by summing per-codepoint widths with no grapheme-cluster awareness, so a base character followed by U+FE0F (variation selector-16) is mis-measured—the base keeps its text-presentation width and FE0F adds 0, instead of the pair clustering into one width-2 emoji glyph. 🌡️⚠️✅ measures 1+0+1+0+2 = 4 columns instead of 6, and a lone ⚠️ measures 1 instead of 2. Plain CJK (你好你 => 6) and already-emoji-presentation bases (🌊🌊 => 4) are correct, so the gap is specifically base + FE0F.

To Reproduce

A base codepoint immediately followed by U+FE0F should be a single width-2 cluster. The lone ⚠️ box reports bounds.width 1 (want 2), the 🌡️⚠️✅ fit box reports 4 (want 6), and a fit-bordered box prints ┌──┐ instead of ┌──────┐.

Expected behavior

FE0F promotes its base to width-2 emoji presentation instead of collapsing to 0. 🌡️⚠️✅ is 2+2+2 = 6, and a fit-bordered box around it is 8 cells wide (6 content + 2 border) with a top border of ┌──────┐.

Additional Information

Failing test case on nm/repro/vs16-emoji-width (test · diff).

The width table is fine; the gap is in the measurement loops. measure() (src/clayterm.c:677) does w += wcwidth(cp) with no lookahead (src/clayterm.c:693-695), and wcwidth() (src/wcwidth.c:1095) maps U+FE0F to 0 (src/wcwidth.c:547) by design; render_text() (src/clayterm.c:269) has the same per-codepoint loop (src/clayterm.c:288). The fix likely lives in those two loops as a one-codepoint lookahead—when the next codepoint is U+FE0F, treat base + FE0F as a single width-2 cluster and consume both, leaving the table and wcwidth() untouched.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions