Skip to content

Commit

Permalink
table: fix auto-index for CSV/HTML/Markdown modes; fixes #108 (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedib0t authored May 10, 2020
1 parent 1ad34bf commit e6e6696
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 54 deletions.
2 changes: 1 addition & 1 deletion table/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func (t *Table) renderRowsHeader(out *strings.Builder) {
if len(t.rowsHeader) > 0 {
t.renderRows(out, t.rowsHeader, renderHint{isHeaderRow: true})
} else if t.autoIndex {
t.renderRow(out, t.getAutoIndexColumnIDs(), renderHint{isHeaderRow: true})
t.renderRow(out, t.getAutoIndexColumnIDs(), renderHint{isAutoIndexRow: true, isHeaderRow: true})
}
t.renderRowSeparator(out, renderHint{isHeaderRow: true, isSeparatorRow: true})
}
Expand Down
26 changes: 19 additions & 7 deletions table/render_csv.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package table

import (
"fmt"
"strings"
"unicode/utf8"
)
Expand All @@ -19,9 +20,12 @@ func (t *Table) RenderCSV() string {
if t.title != "" {
out.WriteString(t.title)
}
t.csvRenderRows(&out, t.rowsHeader)
t.csvRenderRows(&out, t.rows)
t.csvRenderRows(&out, t.rowsFooter)
if t.autoIndex && len(t.rowsHeader) == 0 {
t.csvRenderRow(&out, t.getAutoIndexColumnIDs(), renderHint{isAutoIndexRow: true, isHeaderRow: true})
}
t.csvRenderRows(&out, t.rowsHeader, renderHint{isHeaderRow: true})
t.csvRenderRows(&out, t.rows, renderHint{})
t.csvRenderRows(&out, t.rowsFooter, renderHint{isFooterRow: true})
if t.caption != "" {
out.WriteRune('\n')
out.WriteString(t.caption)
Expand All @@ -38,14 +42,21 @@ func (t *Table) csvFixDoubleQuotes(str string) string {
return strings.Replace(str, "\"", "\\\"", -1)
}

func (t *Table) csvRenderRow(out *strings.Builder, row rowStr) {
func (t *Table) csvRenderRow(out *strings.Builder, row rowStr, hint renderHint) {
// when working on line number 2 or more, insert a newline first
if out.Len() > 0 {
out.WriteRune('\n')
}

// generate the columns to render in CSV format and append to "out"
for colIdx, colStr := range row {
// auto-index column
if colIdx == 0 && t.autoIndex {
if hint.isRegularRow() {
out.WriteString(fmt.Sprint(hint.rowNumber))
}
out.WriteRune(',')
}
if colIdx > 0 {
out.WriteRune(',')
}
Expand All @@ -62,8 +73,9 @@ func (t *Table) csvRenderRow(out *strings.Builder, row rowStr) {
}
}

func (t *Table) csvRenderRows(out *strings.Builder, rows []rowStr) {
for _, row := range rows {
t.csvRenderRow(out, row)
func (t *Table) csvRenderRows(out *strings.Builder, rows []rowStr, hint renderHint) {
for rowIdx, row := range rows {
hint.rowNumber = rowIdx + 1
t.csvRenderRow(out, row, hint)
}
}
26 changes: 26 additions & 0 deletions table/render_csv_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package table

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -27,7 +28,32 @@ This is known."
0,Valar,Morghulis,0,Faceless Men
,,Total,10000,
A Song of Ice and Fire`
assert.Equal(t, expectedOut, tw.RenderCSV())
}

func TestTable_RenderCSV_AutoIndex(t *testing.T) {
tw := NewWriter()
for rowIdx := 0; rowIdx < 10; rowIdx++ {
row := make(Row, 10)
for colIdx := 0; colIdx < 10; colIdx++ {
row[colIdx] = fmt.Sprintf("%s%d", AutoIndexColumnID(colIdx), rowIdx+1)
}
tw.AppendRow(row)
}
tw.SetAutoIndex(true)
tw.SetStyle(StyleLight)

expectedOut := `,A,B,C,D,E,F,G,H,I,J
1,A1,B1,C1,D1,E1,F1,G1,H1,I1,J1
2,A2,B2,C2,D2,E2,F2,G2,H2,I2,J2
3,A3,B3,C3,D3,E3,F3,G3,H3,I3,J3
4,A4,B4,C4,D4,E4,F4,G4,H4,I4,J4
5,A5,B5,C5,D5,E5,F5,G5,H5,I5,J5
6,A6,B6,C6,D6,E6,F6,G6,H6,I6,J6
7,A7,B7,C7,D7,E7,F7,G7,H7,I7,J7
8,A8,B8,C8,D8,E8,F8,G8,H8,I8,J8
9,A9,B9,C9,D9,E9,F9,G9,H9,I9,J9
10,A10,B10,C10,D10,E10,F10,G10,H10,I10,J10`
assert.Equal(t, expectedOut, tw.RenderCSV())
}

Expand Down
61 changes: 59 additions & 2 deletions table/render_html.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package table

import (
"fmt"
"html"
"strings"
)
Expand Down Expand Up @@ -67,17 +68,37 @@ func (t *Table) RenderHTML() string {
out.WriteString(DefaultHTMLCSSClass)
}
out.WriteString("\">\n")
t.htmlRenderRows(&out, t.rowsHeader, renderHint{isHeaderRow: true})
t.htmlRenderTitle(&out)
t.htmlRenderRowsHeader(&out)
t.htmlRenderRows(&out, t.rows, renderHint{})
t.htmlRenderRows(&out, t.rowsFooter, renderHint{isFooterRow: true})
t.htmlRenderRowsFooter(&out)
t.htmlRenderCaption(&out)
out.WriteString("</table>")
}
return t.render(&out)
}

func (t *Table) htmlRenderCaption(out *strings.Builder) {
if t.caption != "" {
out.WriteString(" <caption class=\"caption\" style=\"caption-side: bottom;\">")
out.WriteString(t.caption)
out.WriteString("</caption>\n")
}
}

func (t *Table) htmlRenderRow(out *strings.Builder, row rowStr, hint renderHint) {
out.WriteString(" <tr>\n")
for colIdx := 0; colIdx < t.numColumns; colIdx++ {
// auto-index column
if colIdx == 0 && t.autoIndex {
if hint.isHeaderRow {
out.WriteString(" <th>&nbsp;</th>\n")
} else {
out.WriteString(fmt.Sprintf(" <td>%d</td>\n", hint.rowNumber))
}
}

// get the column contents
var colStr string
if colIdx < len(row) {
colStr = row[colIdx]
Expand Down Expand Up @@ -154,3 +175,39 @@ func (t *Table) htmlRenderRows(out *strings.Builder, rows []rowStr, hint renderH
}
}
}

func (t *Table) htmlRenderRowsFooter(out *strings.Builder) {
if len(t.rowsFooter) > 0 {
t.htmlRenderRows(out, t.rowsFooter, renderHint{isFooterRow: true})
}
}

func (t *Table) htmlRenderRowsHeader(out *strings.Builder) {
if len(t.rowsHeader) > 0 {
t.htmlRenderRows(out, t.rowsHeader, renderHint{isHeaderRow: true})
} else if t.autoIndex {
hint := renderHint{isAutoIndexRow: true, isHeaderRow: true}
t.htmlRenderRows(out, []rowStr{t.getAutoIndexColumnIDs()}, hint)
}
}

func (t *Table) htmlRenderTitle(out *strings.Builder) {
if t.title != "" {
align := t.style.Title.Align.HTMLProperty()
colors := t.style.Title.Colors.HTMLProperty()
title := t.style.Title.Format.Apply(t.title)

out.WriteString(" <caption class=\"title\"")
if align != "" {
out.WriteRune(' ')
out.WriteString(align)
}
if colors != "" {
out.WriteRune(' ')
out.WriteString(colors)
}
out.WriteRune('>')
out.WriteString(title)
out.WriteString("</caption>\n")
}
}
56 changes: 56 additions & 0 deletions table/render_html_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package table

import (
"fmt"
"testing"

"github.com/jedib0t/go-pretty/text"
Expand All @@ -17,8 +18,16 @@ func TestTable_RenderHTML(t *testing.T) {
{Name: "Salary", VAlign: text.VAlignBottom},
{Number: 5, VAlign: text.VAlignBottom},
})
tw.SetTitle(testTitle1)
tw.SetCaption(testCaption)
tw.Style().Title = TitleOptions{
Align: text.AlignLeft,
Colors: text.Colors{text.BgBlack, text.Bold, text.FgHiBlue},
Format: text.FormatTitle,
}

expectedOut := `<table class="go-pretty-table">
<caption class="title" align="left" class="bg-black bold fg-hi-blue">Game Of Thrones</caption>
<thead>
<tr>
<th align="right">#</th>
Expand Down Expand Up @@ -67,10 +76,55 @@ func TestTable_RenderHTML(t *testing.T) {
<td>&nbsp;</td>
</tr>
</tfoot>
<caption class="caption" style="caption-side: bottom;">A Song of Ice and Fire</caption>
</table>`

assert.Equal(t, expectedOut, tw.RenderHTML())
}
func TestTable_RenderHTML_AutoIndex(t *testing.T) {
tw := NewWriter()
for rowIdx := 0; rowIdx < 3; rowIdx++ {
row := make(Row, 3)
for colIdx := 0; colIdx < 3; colIdx++ {
row[colIdx] = fmt.Sprintf("%s%d", AutoIndexColumnID(colIdx), rowIdx+1)
}
tw.AppendRow(row)
}
tw.SetAutoIndex(true)
tw.SetStyle(StyleLight)

expectedOut := `<table class="go-pretty-table">
<thead>
<tr>
<th>&nbsp;</th>
<th align="center">A</th>
<th align="center">B</th>
<th align="center">C</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<td>2</td>
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
<tr>
<td>3</td>
<td>A3</td>
<td>B3</td>
<td>C3</td>
</tr>
</tbody>
</table>`
assert.Equal(t, expectedOut, tw.RenderHTML())
}

func TestTable_RenderHTML_Colored(t *testing.T) {
tw := NewWriter()
Expand Down Expand Up @@ -110,6 +164,7 @@ func TestTable_RenderHTML_Colored(t *testing.T) {
})

expectedOut := `<table class="go-pretty-table">
<caption class="title">Game of Thrones</caption>
<thead>
<tr>
<th align="right" class="bg-white fg-black">#</th>
Expand Down Expand Up @@ -158,6 +213,7 @@ func TestTable_RenderHTML_Colored(t *testing.T) {
<td>&nbsp;</td>
</tr>
</tfoot>
<caption class="caption" style="caption-side: bottom;">A Song of Ice and Fire</caption>
</table>`

assert.Equal(t, expectedOut, tw.RenderHTML())
Expand Down
Loading

0 comments on commit e6e6696

Please sign in to comment.