Skip to content

Adopt string-width for terminal width calculationsΒ #137

@bananabot9000

Description

@bananabot9000

Problem

The CLI calculates how many terminal columns a string occupies using manual methods -- raw .length, hand-rolled ANSI regex stripping, and hardcoded emoji width assumptions. This produces incorrect results for:

  • Emoji (πŸ‘¨β€πŸ‘©β€πŸ‘§ is 2 columns but multiple codepoints)
  • CJK characters (2 columns each, treated as 1)
  • Zero-width joiners, variation selectors, combining marks
  • Non-standard ANSI sequences the current regex doesn't match

The result: cursor positioning, line wrapping, and sticky zone sizing are wrong whenever these characters appear in output or input. This is the root cause behind width-related rendering bugs (#133) and compounds the history/viewport issues (#134, #135).

Expected behaviour

A string like "hello 🍌 δΈ–η•Œ" should measure as 14 columns (5 + 1 + 2 + 1 + 2 + 2 + 1), not whatever .length returns (varies by JS engine, but wrong).

Proposed solution

Adopt string-width (v8.2.0). It handles all of the above correctly.

Dependency tree (3 transitive, all zero-dep leaves):

string-width@8.2.0
β”œβ”€β”€ get-east-asian-width@1.5.0
└── strip-ansi@7.2.0
    └── ansi-regex@6.2.2

All MIT, all ESM, all pure JS, all sindresorhus. No native code.

Scope

Replace all manual width measurement with stringWidth() calls:

  • renderer.ts -- cursor row wrap calculation
  • terminal.ts -- editor line measurement, cursorLinesFromBottom, history line ANSI stripping
  • StatusLineBuilder.ts -- screenLines() and potentially text()/emoji() methods
  • buildPreviewLines() -- preview line wrapping

This is a refactor with no behaviour change (other than more accurate measurements). Should land before #134 and #135 so those fixes can rely on correct width calculations.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions