Skip to content

Fix text-presentation checkmark width for Docker progress output#5

Open
jchristn wants to merge 1 commit into
tomlm:mainfrom
jchristn:fix/docker-progress-padding
Open

Fix text-presentation checkmark width for Docker progress output#5
jchristn wants to merge 1 commit into
tomlm:mainfrom
jchristn:fix/docker-progress-padding

Conversation

@jchristn
Copy link
Copy Markdown

Summary

This PR fixes Docker Compose progress-row alignment by correcting how XTerm.NET calculates the cell width of text-presentation emoji-capable characters.

The issue was identified while integrating XTerm.NET through Termrig's Avalonia terminal control:

Root Cause

InputHandler.GetStringCellWidth previously treated every code point classified by NeoSmart.Unicode.Emoji.IsEmoji(...) as width 2:

int runeWidth = Emoji.IsEmoji(rune.ToString()) ? 2 : UnicodeCalculator.GetWidth(rune);

That is too broad for characters that can be rendered in either text or emoji presentation. Docker Compose emits U+2714 HEAVY CHECK MARK (\u2714) as a plain text-presentation character, without U+FE0F. Windows cmd.exe renders that glyph as a single terminal cell. XTerm.NET counted it as two cells, which shifted the rest of the row by one column.

The visible symptom in Termrig was a missing alignment space before Docker's status text:

Expected/cmd.exe:
 ? Network docker_default              Created

Before this fix in XTerm.NET-backed rendering:
 ? Network docker_default             Created

What Changed

This PR changes the base width calculation to use Wcwidth.UnicodeCalculator.GetWidth(rune) and preserves the existing variation-selector adjustments:

  • \u2714 is width 1.
  • \u2714\uFE0F remains width 2 because U+FE0F explicitly requests emoji presentation.
  • Existing CJK/wide-character behavior continues to come from UnicodeCalculator.
  • Existing variation selector, ZWJ, skin tone, keycap, and regional indicator logic remains in place.

Regression Coverage

The PR adds tests for:

  • Plain checkmark text presentation: \u2714X advances two cells total and stores the checkmark as width 1.
  • Explicit emoji presentation: \u2714\uFE0FX advances three cells total and stores the checkmark as a width-2 glyph with a spacer.
  • Docker-style progress alignment using a checkmark prefix, cursor-forward movement, and Created status text.
  • CSI Ps X erase-character preserving cursor position.
  • CSI Ps C cursor-forward clamping at the right margin without wrapping.

The CSI Ps X and CSI Ps C behavior already appears correct in the current code; those tests document the VT semantics that mattered during the Docker progress investigation and protect against future regressions.

Reproduction

Run Docker Compose in a terminal embedding XTerm.NET:

cd C:\Code\Pneuma\docker
docker compose up -d
docker compose down

Docker emits progress rows containing text-presentation checkmarks and column-sensitive status output. When \u2714 is counted as two cells, the status column is shifted.

A minimal library-level reproduction is included in the tests:

var terminal = new Terminal(new TerminalOptions { Cols = 20, Rows = 3 });
terminal.Write("\u2714X");

Assert.Equal(2, terminal.Buffer.X);
Assert.Equal(1, terminal.Buffer.Lines[0]?[0].Width);
Assert.Equal(1, terminal.Buffer.Lines[0]?[1].Width);

Report

I also included FIXES.md in this branch with the investigation notes, reproduction examples, Termrig links, and validation details so the reasoning is preserved in the repository while reviewing this PR.

Validation

Run from the repository root:

dotnet test src/XTerm.NET.slnx

Result locally:

Passed: 589
Failed: 0
Skipped: 0

@jchristn
Copy link
Copy Markdown
Author

Note: I merged fix/terminal in Termrig, so that branch is no longer present (everything is in main on Termrig).

@jchristn
Copy link
Copy Markdown
Author

Also, thanks for producing this fantastic library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant