Skip to content

Commit

Permalink
table: option to avoid coloring borders/separators (#253)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedib0t authored Jan 10, 2023
1 parent 7d190d0 commit 4ea0370
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 9 deletions.
18 changes: 11 additions & 7 deletions table/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,15 +365,19 @@ func (t *Table) renderRowsHeader(out *strings.Builder) {
func (t *Table) renderTitle(out *strings.Builder) {
if t.title != "" {
colors := t.style.Title.Colors
colorsBorder := colors
if t.style.Options.DoNotColorBordersAndSeparators {
colorsBorder = nil
}
rowLength := t.maxRowLength
if t.allowedRowLength != 0 && t.allowedRowLength < rowLength {
rowLength = t.allowedRowLength
}
if t.style.Options.DrawBorder {
lenBorder := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.TopLeft+t.style.Box.TopRight)
out.WriteString(colors.Sprint(t.style.Box.TopLeft))
out.WriteString(colors.Sprint(text.RepeatAndTrim(t.style.Box.MiddleHorizontal, lenBorder)))
out.WriteString(colors.Sprint(t.style.Box.TopRight))
out.WriteString(colorsBorder.Sprint(t.style.Box.TopLeft))
out.WriteString(colorsBorder.Sprint(text.RepeatAndTrim(t.style.Box.MiddleHorizontal, lenBorder)))
out.WriteString(colorsBorder.Sprint(t.style.Box.TopRight))
}

lenText := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft+t.style.Box.PaddingRight)
Expand All @@ -382,12 +386,12 @@ func (t *Table) renderTitle(out *strings.Builder) {
}
titleText := text.WrapText(t.title, lenText)
for _, titleLine := range strings.Split(titleText, "\n") {
t.renderTitleLine(out, lenText, titleLine, colors)
t.renderTitleLine(out, lenText, titleLine, colors, colorsBorder)
}
}
}

func (t *Table) renderTitleLine(out *strings.Builder, lenText int, titleLine string, colors text.Colors) {
func (t *Table) renderTitleLine(out *strings.Builder, lenText int, titleLine string, colors text.Colors, colorsBorder text.Colors) {
titleLine = strings.TrimSpace(titleLine)
titleLine = t.style.Title.Format.Apply(titleLine)
titleLine = t.style.Title.Align.Apply(titleLine, lenText)
Expand All @@ -397,10 +401,10 @@ func (t *Table) renderTitleLine(out *strings.Builder, lenText int, titleLine str
out.WriteRune('\n')
}
if t.style.Options.DrawBorder {
out.WriteString(colors.Sprint(t.style.Box.Left))
out.WriteString(colorsBorder.Sprint(t.style.Box.Left))
}
out.WriteString(colors.Sprint(titleLine))
if t.style.Options.DrawBorder {
out.WriteString(colors.Sprint(t.style.Box.Right))
out.WriteString(colorsBorder.Sprint(t.style.Box.Right))
}
}
4 changes: 4 additions & 0 deletions table/render_hint.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ type renderHint struct {
rowNumber int // the row number/index
}

func (h *renderHint) isBorderOrSeparator() bool {
return h.isBorderTop || h.isSeparatorRow || h.isBorderBottom
}

func (h *renderHint) isRegularRow() bool {
return !h.isHeaderRow && !h.isFooterRow
}
Expand Down
34 changes: 34 additions & 0 deletions table/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,40 @@ func TestTable_Render_Colored(t *testing.T) {
)
})

t.Run("with borders and separators not colored", func(t *testing.T) {
tw := NewWriter()
tw.AppendHeader(testHeader)
tw.AppendRows(testRows)
tw.AppendRow(testRowMultiLine)
tw.AppendFooter(testFooter)
tw.SetTitle(testTitle1)
tw.Style().Title.Colors = text.Colors{text.FgYellow}
tw.Style().Color = ColorOptions{
Header: text.Colors{text.FgRed},
Row: text.Colors{text.FgGreen},
RowAlternate: text.Colors{text.FgHiGreen},
Footer: text.Colors{text.FgBlue},
}
tw.Style().Options.DoNotColorBordersAndSeparators = true

compareOutputColored(t, tw.Render(), ""+
"+---------------------------------------------------------------------+\n"+
"|\x1b[33m Game of Thrones \x1b[0m|\n"+
"+-----+------------+-----------+--------+-----------------------------+\n"+
"|\x1b[31m # \x1b[0m|\x1b[31m FIRST NAME \x1b[0m|\x1b[31m LAST NAME \x1b[0m|\x1b[31m SALARY \x1b[0m|\x1b[31m \x1b[0m|\n"+
"+-----+------------+-----------+--------+-----------------------------+\n"+
"|\x1b[32m 1 \x1b[0m|\x1b[32m Arya \x1b[0m|\x1b[32m Stark \x1b[0m|\x1b[32m 3000 \x1b[0m|\x1b[32m \x1b[0m|\n"+
"|\x1b[92m 20 \x1b[0m|\x1b[92m Jon \x1b[0m|\x1b[92m Snow \x1b[0m|\x1b[92m 2000 \x1b[0m|\x1b[92m You know nothing, Jon Snow! \x1b[0m|\n"+
"|\x1b[32m 300 \x1b[0m|\x1b[32m Tyrion \x1b[0m|\x1b[32m Lannister \x1b[0m|\x1b[32m 5000 \x1b[0m|\x1b[32m \x1b[0m|\n"+
"|\x1b[92m 0 \x1b[0m|\x1b[92m Winter \x1b[0m|\x1b[92m Is \x1b[0m|\x1b[92m 0 \x1b[0m|\x1b[92m Coming. \x1b[0m|\n"+
"|\x1b[92m \x1b[0m|\x1b[92m \x1b[0m|\x1b[92m \x1b[0m|\x1b[92m \x1b[0m|\x1b[92m The North Remembers! \x1b[0m|\n"+
"|\x1b[92m \x1b[0m|\x1b[92m \x1b[0m|\x1b[92m \x1b[0m|\x1b[92m \x1b[0m|\x1b[92m This is known. \x1b[0m|\n"+
"+-----+------------+-----------+--------+-----------------------------+\n"+
"|\x1b[34m \x1b[0m|\x1b[34m \x1b[0m|\x1b[34m TOTAL \x1b[0m|\x1b[34m 10000 \x1b[0m|\x1b[34m \x1b[0m|\n"+
"+-----+------------+-----------+--------+-----------------------------+",
)
})

t.Run("column customizations", func(t *testing.T) {
tw := NewWriter()
tw.AppendHeader(testHeader)
Expand Down
4 changes: 4 additions & 0 deletions table/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,10 @@ var (
// Options defines the global options that determine how the Table is
// rendered.
type Options struct {
// DoNotColorBordersAndSeparators disables coloring all the borders and row
// or column separators.
DoNotColorBordersAndSeparators bool

// DrawBorder enables or disables drawing the border around the Table.
// Example of a table where it is disabled:
// # │ FIRST NAME │ LAST NAME │ SALARY │
Expand Down
11 changes: 9 additions & 2 deletions table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,9 @@ func (t *Table) getAutoIndexColumnIDs() rowStr {
}

func (t *Table) getBorderColors(hint renderHint) text.Colors {
if hint.isHeaderRow {
if t.style.Options.DoNotColorBordersAndSeparators {
return nil
} else if hint.isHeaderRow {
return t.style.Color.Header
} else if hint.isFooterRow {
return t.style.Color.Footer
Expand Down Expand Up @@ -381,6 +383,9 @@ func (t *Table) getBorderRight(hint renderHint) string {
}

func (t *Table) getColumnColors(colIdx int, hint renderHint) text.Colors {
if hint.isBorderOrSeparator() && t.style.Options.DoNotColorBordersAndSeparators {
return text.Colors{} // not nil to force caller to paint with no colors
}
if t.rowPainter != nil && hint.isRegularNonSeparatorRow() && !t.isIndexColumn(colIdx, hint) {
colors := t.rowsColors[hint.rowNumber-1]
if colors != nil {
Expand Down Expand Up @@ -578,7 +583,9 @@ func (t *Table) getRowConfig(hint renderHint) RowConfig {
}

func (t *Table) getSeparatorColors(hint renderHint) text.Colors {
if hint.isHeaderRow {
if t.style.Options.DoNotColorBordersAndSeparators {
return nil
} else if hint.isHeaderRow {
return t.style.Color.Header
} else if hint.isFooterRow {
return t.style.Color.Footer
Expand Down

0 comments on commit 4ea0370

Please sign in to comment.