mirror of
https://github.com/charmbracelet/lipgloss.git
synced 2024-11-23 14:26:29 +03:00
fix: shared indices for first row of data and headers (StyleFunc bug) (#377)
* test(table): show differing styles between first row and headers * fix(table): remove overlapping indices for styling rows and headers * test(table): remove TestTableShrink; it's fixed on another branch * docs(table): add godoc for HeaderRow const * fix(test): use HeaderRow for table header styling
This commit is contained in:
parent
b08e7e4762
commit
f8dd5072db
@ -7,6 +7,10 @@ import (
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
)
|
||||
|
||||
// HeaderRow denotes the header's row index used when rendering headers. Use
|
||||
// this value when looking to customize header styles in StyleFunc.
|
||||
const HeaderRow int = -1
|
||||
|
||||
// StyleFunc is the style function that determines the style of a Cell.
|
||||
//
|
||||
// It takes the row and column of the cell as an input and determines the
|
||||
@ -235,15 +239,15 @@ func (t *Table) String() string {
|
||||
// the StyleFunc after the headers and rows. Update the widths for a final
|
||||
// time.
|
||||
for i, cell := range t.headers {
|
||||
t.widths[i] = max(t.widths[i], lipgloss.Width(t.style(0, i).Render(cell)))
|
||||
t.heights[0] = max(t.heights[0], lipgloss.Height(t.style(0, i).Render(cell)))
|
||||
t.widths[i] = max(t.widths[i], lipgloss.Width(t.style(HeaderRow, i).Render(cell)))
|
||||
t.heights[0] = max(t.heights[0], lipgloss.Height(t.style(HeaderRow, i).Render(cell)))
|
||||
}
|
||||
|
||||
for r := 0; r < t.data.Rows(); r++ {
|
||||
for i := 0; i < t.data.Columns(); i++ {
|
||||
cell := t.data.At(r, i)
|
||||
|
||||
rendered := t.style(r+1, i).Render(cell)
|
||||
rendered := t.style(r, i).Render(cell)
|
||||
t.heights[r+btoi(hasHeaders)] = max(t.heights[r+btoi(hasHeaders)], lipgloss.Height(rendered))
|
||||
t.widths[i] = max(t.widths[i], lipgloss.Width(rendered))
|
||||
}
|
||||
@ -452,7 +456,7 @@ func (t *Table) constructHeaders() string {
|
||||
s.WriteString(t.borderStyle.Render(t.border.Left))
|
||||
}
|
||||
for i, header := range t.headers {
|
||||
s.WriteString(t.style(0, i).
|
||||
s.WriteString(t.style(HeaderRow, i).
|
||||
MaxHeight(1).
|
||||
Width(t.widths[i]).
|
||||
MaxWidth(t.widths[i]).
|
||||
@ -537,7 +541,7 @@ func (t *Table) constructRow(index int, isOverflow bool) string {
|
||||
cell = t.data.At(index, c)
|
||||
}
|
||||
|
||||
cells = append(cells, t.style(index+1, c).
|
||||
cells = append(cells, t.style(index, c).
|
||||
Height(height).
|
||||
MaxHeight(height).
|
||||
Width(t.widths[c]).
|
||||
|
@ -7,11 +7,12 @@ import (
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
"github.com/charmbracelet/x/exp/golden"
|
||||
)
|
||||
|
||||
var TableStyle = func(row, col int) lipgloss.Style {
|
||||
switch {
|
||||
case row == 0:
|
||||
case row == HeaderRow:
|
||||
return lipgloss.NewStyle().Padding(0, 1).Align(lipgloss.Center)
|
||||
case row%2 == 0:
|
||||
return lipgloss.NewStyle().Padding(0, 1)
|
||||
@ -65,7 +66,7 @@ func TestTableExample(t *testing.T) {
|
||||
BorderStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("99"))).
|
||||
StyleFunc(func(row, col int) lipgloss.Style {
|
||||
switch {
|
||||
case row == 0:
|
||||
case row == HeaderRow:
|
||||
return HeaderStyle
|
||||
case row%2 == 0:
|
||||
return EvenRowStyle
|
||||
@ -91,8 +92,8 @@ func TestTableExample(t *testing.T) {
|
||||
└──────────┴───────────────────────────────┴─────────────────┘
|
||||
`)
|
||||
|
||||
if table.String() != expected {
|
||||
t.Fatalf("expected:\n\n%s\n\ngot:\n\n%s", expected, table.String())
|
||||
if got := ansi.Strip(table.String()); got != expected {
|
||||
t.Fatalf("expected:\n\n%s\n\ngot:\n\n%s", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,7 +527,7 @@ func TestTableRowSeparators(t *testing.T) {
|
||||
|
||||
func TestTableHeights(t *testing.T) {
|
||||
styleFunc := func(row, col int) lipgloss.Style {
|
||||
if row == 0 {
|
||||
if row == HeaderRow {
|
||||
return lipgloss.NewStyle().Padding(0, 1)
|
||||
}
|
||||
if col == 0 {
|
||||
@ -584,7 +585,7 @@ func TestTableHeights(t *testing.T) {
|
||||
|
||||
func TestTableMultiLineRowSeparator(t *testing.T) {
|
||||
styleFunc := func(row, col int) lipgloss.Style {
|
||||
if row == 0 {
|
||||
if row == HeaderRow {
|
||||
return lipgloss.NewStyle().Padding(0, 1)
|
||||
}
|
||||
if col == 0 {
|
||||
@ -1140,6 +1141,33 @@ func TestTableHeightWithOffset(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStyleFunc(t *testing.T) {
|
||||
TestStyle := func(row, col int) lipgloss.Style {
|
||||
switch {
|
||||
// this is the header
|
||||
case row == HeaderRow:
|
||||
return lipgloss.NewStyle().Align(lipgloss.Center)
|
||||
// this is the first row of data
|
||||
case row == 0:
|
||||
return lipgloss.NewStyle().Padding(0, 1).Align(lipgloss.Right)
|
||||
default:
|
||||
return lipgloss.NewStyle().Padding(0, 1)
|
||||
}
|
||||
}
|
||||
|
||||
table := New().
|
||||
Border(lipgloss.NormalBorder()).
|
||||
StyleFunc(TestStyle).
|
||||
Headers("LANGUAGE", "FORMAL", "INFORMAL").
|
||||
Row("Chinese", "Nǐn hǎo", "Nǐ hǎo").
|
||||
Row("French", "Bonjour", "Salut").
|
||||
Row("Japanese", "こんにちは", "やあ").
|
||||
Row("Russian", "Zdravstvuyte", "Privet").
|
||||
Row("Spanish", "Hola", "¿Qué tal?")
|
||||
|
||||
golden.RequireEqual(t, []byte(table.String()))
|
||||
}
|
||||
|
||||
func TestClearRows(t *testing.T) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
9
table/testdata/TestStyleFunc.golden
vendored
Normal file
9
table/testdata/TestStyleFunc.golden
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
┌──────────┬──────────────┬───────────┐
|
||||
│ LANGUAGE │ FORMAL │ INFORMAL │
|
||||
├──────────┼──────────────┼───────────┤
|
||||
│ Chinese │ Nǐn hǎo │ Nǐ hǎo │
|
||||
│ French │ Bonjour │ Salut │
|
||||
│ Japanese │ こんにちは │ やあ │
|
||||
│ Russian │ Zdravstvuyte │ Privet │
|
||||
│ Spanish │ Hola │ ¿Qué tal? │
|
||||
└──────────┴──────────────┴───────────┘
|
Loading…
Reference in New Issue
Block a user