Skip to content

Fix emoji/CJK alignment in search results#328

Merged
jeremy merged 2 commits intomainfrom
fix/emoji-alignment-r3
Mar 16, 2026
Merged

Fix emoji/CJK alignment in search results#328
jeremy merged 2 commits intomainfrom
fix/emoji-alignment-r3

Conversation

@jeremy
Copy link
Copy Markdown
Member

@jeremy jeremy commented Mar 16, 2026

Summary

  • formatCell() and wrapText() 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 from selectColumns() (which uses lipgloss.Widthansi.StringWidth), causing column misalignment in basecamp search output.
  • Replace utf8.RuneCountInString with ansi.StringWidth and ansi.Truncate in both functions. Rename runeWidthcellWidth.
  • Add renderer-level regression test that renders a full table with mixed ASCII/emoji/CJK content and asserts all lines have equal display width.

Fixes the alignment issue Michael reported on Mar 12.

Test plan

  • bin/ci green
  • Unit: TestWrapText/unicode_characters — wrap point shifts with display-width math
  • Unit: TestFormatCellDoesNotTruncateURLs/emoji_string_truncated_by_display_width — string under 40 runes but over 40 cells is truncated
  • Integration: TestStyledRenderTableEmojiAlignment — full styled table pipeline with emoji/CJK proves column alignment end-to-end

Summary by cubic

Fixes emoji and CJK column misalignment in search result tables by using display-cell width for wrapping and truncation. basecamp search columns now align with lipgloss sizing.

  • Bug Fixes
    • Replaced rune counting with ansi.StringWidth in wrapText() and formatCell(); use ansi.Truncate for 40-cell truncation (URLs are never truncated).
    • Renamed runeWidthcellWidth and 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.

jeremy added 2 commits March 16, 2026 00:48
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)
@jeremy jeremy requested a review from a team as a code owner March 16, 2026 07:49
Copilot AI review requested due to automatic review settings March 16, 2026 07:49
@github-actions github-actions bot added tests Tests (unit and e2e) output Output formatting and presentation labels Mar 16, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 wrapText to measure word widths using terminal cell width (ansi.StringWidth) rather than rune counts.
  • Update formatCell truncation 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.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

@jeremy jeremy merged commit 8e71cfa into main Mar 16, 2026
30 checks passed
@jeremy jeremy deleted the fix/emoji-alignment-r3 branch March 16, 2026 07:57
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

output Output formatting and presentation tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants