Skip to content

cli: export the terminal display-width measure #8863

Closed

Description

@filipfalcon

What is the problem this feature would solve?

#7572 fixed help alignment by measuring text in terminal cells instead of UTF-16 code units, which closed #7557. The measure itself stayed internal (visualLength in CliOutput.ts), so the second half of that issue is still open.

Anything a CLI draws next to the built-in output has to measure text by the same rules to line up with it: a custom CliOutput.Formatter, a boxed banner, a table, a prompt built on Prompt.Custom. Today the only options are copying the grapheme and East Asian Width logic into the application, or adding string-width. Either way the application's measure can disagree with the one the built-in help uses, so the two drift as either side changes.

What is the feature you are proposing to solve the problem?

Export the existing measure, for example as CliOutput.displayWidth:

CliOutput.displayWidth("ファイル") // 8
CliOutput.displayWidth("é")   // 1
CliOutput.displayWidth("1️⃣") // 2

It should strip ANSI styling as it does today, so styled and unstyled text measure the same. No new logic is needed, only the export and a doc comment.

What alternatives have you considered?

  • Reimplementing it per application: what we do today. It duplicates Unicode knowledge that already lives in Effect, and the two implementations can disagree.
  • string-width: an extra dependency that measures by its own tables, so it can still disagree with the built-in help.
  • A home in effect/String instead of effect/cli: also fine, since the measure is useful outside the CLI module.

Activity

  1. lloydrichards commented on Oct 7, 2026

    @lloydrichards
    Contributor

    I've been wanting to wait til v4 is release to see if porting boxes would make sense, but certainly a String.width functionality might benefit you here before then.
    ~ comment

    Probably interesting for this issue, I've needed to solve this exact same issue for effect-boxes and have a dependency-less implementation of this -> https://github.com/lloydrichards/effect-boxes/blob/main/packages/effect-boxes/src/internal/width.ts

     // Basic usage
     getStringWidth("hello") // => 5
     getStringWidth("👩‍💻") // => 2 (multi-char emoji)
     getStringWidth("你好") // => 4 (2 wide chars)
    
     // With ANSI codes (stripped by default)
     getStringWidth("\x1b[31mred\x1b[0m") // => 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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