Skip to content

Use string.GetColumns() for display width#4799

Merged
tig merged 3 commits intogui-cs:v2_developfrom
akrantz:fix/rune-width-to-getcolumns
Mar 7, 2026
Merged

Use string.GetColumns() for display width#4799
tig merged 3 commits intogui-cs:v2_developfrom
akrantz:fix/rune-width-to-getcolumns

Conversation

@akrantz
Copy link
Copy Markdown
Contributor

@akrantz akrantz commented Mar 6, 2026

Replace EnumerateRunes().Sum(GetColumns) with string.GetColumns() for grapheme-aware width measurement. The rune-sum pattern produces incorrect (inflated) results for multi-rune grapheme clusters like ZWJ emoji sequences -- e.g. a family emoji measures 8 columns by rune sum but occupies only 2 terminal cells.

Also fix Branch.GetWidth() which used string.Length instead of GetColumns(), under-counting width for wide CJK characters.

Fixed instances:

  • AppendAutocomplete.cs: autocomplete fragment width
  • ColorBar.cs: color label offset (removed obsolete TODO comment)
  • FileDialog.cs: feedback text centering
  • TabView.cs: tab header width
  • TableView.cs (4 instances): column auto-sizing, truncation, padding
  • Branch.cs: line truncation check + GetWidth() calculation

Added tests:

  • StringTests: 7 parameterized cases documenting rune-sum vs GetColumns discrepancy for ZWJ emoji, CJK, combining marks, and ASCII
  • TableViewTests: grapheme cluster width comparison + rendering test
  • TabViewTests: rendering test verifying emoji tab header width
  • TreeViewTests: rendering test with CJK wide characters

Fixes

Proposed Changes/Todos

  • Replace EnumerateRunes().Sum(GetColumns) with string.GetColumns() in 6 widget files (10 instances)
  • Fix Branch.GetWidth() using string.Length instead of GetColumns()
  • Remove obsolete TODO comment in ColorBar.cs
  • Add unit tests documenting the rune-sum vs grapheme-width discrepancy
  • Add widget-level rendering tests for TableView, TabView, TreeView

Pull Request checklist:

  • I've named my PR in the form of "Fixes #issue. Terse description."
  • My code follows the style guidelines of Terminal.Gui - if you use Visual Studio, hit CTRL-K-D to automatically reformat your files before committing.
  • My code follows the Terminal.Gui library design guidelines
  • I ran dotnet test before commit
  • I have made corresponding changes to the API documentation (using /// style comments)
  • My changes generate no new warnings
  • I have checked my code and corrected any poor grammar or misspellings
  • I conducted basic QA to assure all features are working

Replace EnumerateRunes().Sum(GetColumns) with string.GetColumns() for
grapheme-aware width measurement. The rune-sum pattern produces incorrect
(inflated) results for multi-rune grapheme clusters like ZWJ emoji
sequences -- e.g. a family emoji measures 8 columns by rune sum but
occupies only 2 terminal cells.

Also fix Branch.GetWidth() which used string.Length instead of
GetColumns(), under-counting width for wide CJK characters.

Fixed instances:
- AppendAutocomplete.cs: autocomplete fragment width
- ColorBar.cs: color label offset (removed obsolete TODO comment)
- FileDialog.cs: feedback text centering
- TabView.cs: tab header width
- TableView.cs (4 instances): column auto-sizing, truncation, padding
- Branch.cs: line truncation check + GetWidth() calculation

Added tests:
- StringTests: 7 parameterized cases documenting rune-sum vs GetColumns
  discrepancy for ZWJ emoji, CJK, combining marks, and ASCII
- TableViewTests: grapheme cluster width comparison + rendering test
- TabViewTests: rendering test verifying emoji tab header width
- TreeViewTests: rendering test with CJK wide characters

Fixes gui-cs#4798

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@akrantz akrantz requested a review from tig as a code owner March 6, 2026 13:41
Copy link
Copy Markdown
Collaborator

@tig tig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comments. Thank you for taking this on!!!

Comment thread Tests/UnitTests/Views/TableViewTests.cs
Comment thread Tests/UnitTests/Views/TabViewTests.cs Outdated
Comment thread Tests/UnitTests/Views/TreeViewTests.cs Outdated
Move grapheme width tests from UnitTests to UnitTestsParallelizable
per review feedback. Adapt tests to use CreateTestDriver() pattern
instead of [SetupFakeApplication].

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
akrantz added a commit to akrantz/Terminal.Gui that referenced this pull request Mar 6, 2026
@akrantz akrantz requested a review from tig March 6, 2026 17:41
Copy link
Copy Markdown
Collaborator

@tig tig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done. Very much appreciated.

@tig tig merged commit f7160ff into gui-cs:v2_develop Mar 7, 2026
11 checks passed
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.

2 participants