Fix emoji/CJK alignment in search results#328
Merged
Conversation
formatCell() and wrapText() measured string width by counting runes, not display cells. An emoji or CJK character occupies 2 terminal cells but only 1 rune, so the width math diverged from what lipgloss/table (which uses ansi.StringWidth) computed in selectColumns(). This caused column misalignment in search results containing emoji or CJK text. Replace utf8.RuneCountInString with ansi.StringWidth in both functions, and use ansi.Truncate for display-width-aware truncation in formatCell. Rename runeWidth → cellWidth to reflect the new semantics.
- Update TestWrapText "unicode characters" expected value: 世界 is 4 display cells (not 2 runes), changing the wrap point - Add emoji truncation case to TestFormatCellDoesNotTruncateURLs: a string under 40 runes but over 40 display cells must be truncated - Add TestStyledRenderTableEmojiAlignment: renders a full table through the styled pipeline with mixed ASCII, emoji, and CJK content, then asserts all lines have equal display width (proves selectColumns and formatCell agree end-to-end)
There was a problem hiding this comment.
Pull request overview
Improves terminal output rendering by switching wrapping and truncation logic from rune-counting to terminal display-cell width, preventing misalignment when strings contain emoji/CJK characters.
Changes:
- Update
wrapTextto measure word widths using terminal cell width (ansi.StringWidth) rather than rune counts. - Update
formatCelltruncation to use display width (ansi.StringWidth+ansi.Truncate) while continuing to exempt real HTTP(S) URLs. - Adjust and extend tests to validate Unicode wrapping, display-width truncation, and styled-table alignment with wide characters.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| internal/output/render.go | Switch wrapping and truncation to display-cell width to better match terminal rendering for emoji/CJK. |
| internal/output/output_test.go | Update expected wrap behavior and add coverage for display-width truncation and styled table alignment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jeremy
added a commit
to brianevanmiller/basecamp-cli
that referenced
this pull request
Mar 18, 2026
…evanmiller/feature-gap-analysis * origin/main: Show full content in detail views instead of truncating at 40 chars (basecamp#338) Switch CODEOWNERS from sip to cli team (basecamp#346) Fix dock ordering and add --all flag to `projects show` (basecamp#333) Add file upload command to SKILL.md (basecamp#343) Replace "pending" with "incomplete" in todos output; omit from default view (basecamp#327) Add `--in` as global alias for `--project` (basecamp#334) Fix 3 post-QA issues on api command (basecamp#330) deps: bump the go-dependencies group with 2 updates (basecamp#331) Improve tool instance disambiguation format (basecamp#329) Fix emoji/CJK alignment in search results (basecamp#328)
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.
Summary
formatCell()andwrapText()measured string width by rune count instead of display cells. Emoji and CJK characters occupy 2 terminal cells but only 1 rune, so the width math diverged fromselectColumns()(which useslipgloss.Width→ansi.StringWidth), causing column misalignment inbasecamp searchoutput.utf8.RuneCountInStringwithansi.StringWidthandansi.Truncatein both functions. RenameruneWidth→cellWidth.Fixes the alignment issue Michael reported on Mar 12.
Test plan
bin/cigreenTestWrapText/unicode_characters— wrap point shifts with display-width mathTestFormatCellDoesNotTruncateURLs/emoji_string_truncated_by_display_width— string under 40 runes but over 40 cells is truncatedTestStyledRenderTableEmojiAlignment— full styled table pipeline with emoji/CJK proves column alignment end-to-endSummary by cubic
Fixes emoji and CJK column misalignment in search result tables by using display-cell width for wrapping and truncation.
basecamp searchcolumns now align withlipglosssizing.ansi.StringWidthinwrapText()andformatCell(); useansi.Truncatefor 40-cell truncation (URLs are never truncated).runeWidth→cellWidthand added tests, including a full styled table regression that verifies equal line widths with mixed ASCII/emoji/CJK.Written for commit d07b79c. Summary will update on new commits.