From eb9f5ae295b433cac2178524c0e15ea2c1b116ac Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Thu, 12 Feb 2026 14:44:29 +0000 Subject: [PATCH] fix(table): Use ansi.Truncate instead of runewidth.Truncate runewidth.Truncate does not consider terminal escape characters - this means that if a table cell contains funky characters, then it will be incorrectly truncated. Signed-off-by: Justin Chadwell --- table/table.go | 6 +++--- table/table_test.go | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/table/table.go b/table/table.go index 4dd120360..c68386fc9 100644 --- a/table/table.go +++ b/table/table.go @@ -6,7 +6,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" - "github.com/mattn/go-runewidth" + "github.com/charmbracelet/x/ansi" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" @@ -419,7 +419,7 @@ func (m Model) headersView() string { continue } style := lipgloss.NewStyle().Width(col.Width).MaxWidth(col.Width).Inline(true) - renderedCell := style.Render(runewidth.Truncate(col.Title, col.Width, "…")) + renderedCell := style.Render(ansi.Truncate(col.Title, col.Width, "…")) s = append(s, m.styles.Header.Render(renderedCell)) } return lipgloss.JoinHorizontal(lipgloss.Top, s...) @@ -432,7 +432,7 @@ func (m *Model) renderRow(r int) string { continue } style := lipgloss.NewStyle().Width(m.cols[i].Width).MaxWidth(m.cols[i].Width).Inline(true) - renderedCell := m.styles.Cell.Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…"))) + renderedCell := m.styles.Cell.Render(style.Render(ansi.Truncate(value, m.cols[i].Width, "…"))) s = append(s, renderedCell) } diff --git a/table/table_test.go b/table/table_test.go index 6129245ca..28991aaf3 100644 --- a/table/table_test.go +++ b/table/table_test.go @@ -258,6 +258,21 @@ func TestModel_RenderRow(t *testing.T) { } } +func TestModel_RenderRow_AnsiWidth(t *testing.T) { + value := "\x1b[31mABCDEFGH\x1b[0m" + table := &Model{ + rows: []Row{{value}}, + cols: []Column{{Title: "col1", Width: 8}}, + styles: Styles{Cell: lipgloss.NewStyle()}, + } + + got := ansi.Strip(table.renderRow(0)) + want := "ABCDEFGH" + if got != want { + t.Fatalf("\n\nWant: \n%s\n\nGot: \n%s\n", want, got) + } +} + func TestTableAlignment(t *testing.T) { t.Run("No border", func(t *testing.T) { biscuits := New(