Widget display width - #212
Merged
Merged
Conversation
MenuBar and ListView still measured text by UTF-16 String.length instead of display cells, so CJK/emoji content misaligned columns and could split a wide glyph or surrogate pair at a truncation boundary. - MenuBar: dropdownInnerWidth, dropdown row padding, titleStartCol and hitTestTitles now use WCWidth.stringWidth / cell-aware fitToCells. - ListView: row truncate+pad now uses fitToCells instead of take/padTo. Reuses the cell-aware clipToCells/fitToCells helpers from #205 (kept per-widget-private, matching the existing pattern). ASCII behaviour unchanged. Adds CJK/emoji regression specs.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DECISIONS — widget-display-width (#206)
Follow-up to #205. Converted the last two widgets that still sized text by UTF-16
String.lengthto measure by display cells (WCWidth).Changes
MenuBar.scala
dropdownInnerWidth:_.length→WCWidth.stringWidth(widest item by cells).item.padTo(innerWidth, ' ')→fitToCells(item, innerWidth)(cell-aware clip + pad; ASCII unchanged).
titleStartCol/hitTestTitles:title.length + 4→WCWidth.stringWidth(title) + 4.The
+4(2-cell opener + 2-cell closer, same for[ X ]andX) is unchanged;only the title measurement moved to cells, so a wide-char title no longer
mis-positions later dropdowns or mislands title hit-testing.
ListView.scala
view:content.take(width-2).padTo(width-2, ' ')→fitToCells(content, width-2).Old
.takecould slice a surrogate pair / wide glyph at the boundary and couldoverflow the row (UTF-16 count < display cells for wide content).
Key decision: helpers duplicated, not centralised
The #205
clipToCells/fitToCellsare private toTable, and #205 itselfalready duplicated the same logic privately into
TextFieldandMultiLineInput(
clipToWidth/padToWidth). I followed that established per-widget-private patternrather than extracting a shared util — keeps this change minimal and consistent with
the codebase as it stands. The copies in MenuBar/ListView are byte-identical to
Table's. If a future task wants one home for these,
WCWidth(termflow-terminal) isthe natural place; that refactor is out of scope here.
Tests
MenuBarSpec: wide-title (文件) hit-testing positions the next menu by cells;dropdown rows with a wide item (
打开) pad to display width; open dropdown alignsunder the correct menu. (Old
.lengthmath would have placed Edit at col 6 not 10.)ListViewSpec: CJK row aligns to the grid; wide content truncates on a glyphboundary (odd content width can't fit a half glyph); emoji (surrogate pairs)
truncate without leaving a lone surrogate half.
RenderCell.renderedGlyph(skipping the width-0 filler the renderer inserts after a wide glyph), since the raw
.chgrid interleaves a space after each 2-cell glyph.termflowWidgets/testgreen (309 tests).Risk
Low. Behaviour identical for pure-ASCII (
stringWidth == length,fitToCells==take+padTo).WCWidthwidth tables (ambiguous-width = 1, curated emoji ranges)are inherited from #205 and unchanged.