Skip to content

unstable/cli: help tables misalign when the left column contains wide or combining grapheme #7557

Closed

Description

@filipfalcon

What version of Effect is running?

4.0.0-rc.112

What steps can reproduce the bug?

// repro.mjs
import { NodeRuntime, NodeServices } from '@effect/platform-node';
import { Effect } from 'effect';
import { Command, Flag } from 'effect/unstable/cli';

const demo = Command.make('demo', {
  file: Flag.string('ファイル').pipe(Flag.withDescription('The file to read.')),
  verbose: Flag.boolean('verbose').pipe(Flag.withDescription('Say more.')),
});

NodeRuntime.runMain(
  Command.run(demo, { version: '0.0.0' }).pipe(Effect.provide(NodeServices.layer)),
);
node repro.mjs --help

What is the expected behavior?

Both flag descriptions start in the same column, as they do for ASCII-only flag names.

What do you see instead?

FLAGS
  --ファイル string    The file to read.
  --verbose        Say more.

The first description sits 4 cells further right. visualLength in CliOutput.ts is stripAnsi(text).length, i.e. UTF-16 code units, but a terminal draws cells: each CJK character is 1 unit and 2 cells, so the column is under-padded by one cell per character. The same measurement over-pads for combining marks (e + U+0301 is 2 units, 1 cell) and miscounts zero-width characters, so any localized command name, metavar, or alias breaks the table.

Additional information

Fixing this means the formatter needs a real display-width function (wide via East Asian Wide/Fullwidth and Emoji_Presentation, zero for combining marks and zero-width controls, segmented by grapheme). No dependency is required — Intl.Segmenter plus Unicode property escapes cover it in every supported runtime. Once that function exists internally, please consider exporting it: a custom CliOutput.Formatter or prompt renderer has to measure text by exactly the same rules as the built-in help to align with it, and today the only options are reimplementing the logic or pulling string-width.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions