Skip to content

Commit

Permalink
table: note about auto-merge and HTML/Markdown modes (#311)
Browse files Browse the repository at this point in the history
  • Loading branch information
jedib0t authored Mar 24, 2024
1 parent b9fd422 commit 04a692c
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 95 deletions.
3 changes: 2 additions & 1 deletion table/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Pretty-print tables into ASCII/Unicode strings.
- Add Header(s) and Footer(s) (`AppendHeader`/`AppendFooter`)
- Add a Separator manually after any Row (`AppendSeparator`)
- Auto Index Rows (1, 2, 3 ...) and Columns (A, B, C, ...) (`SetAutoIndex`)
- Auto Merge
- Auto Merge (_not supported in CSV/HTML/Markdown/TSV modes_)
- Cells in a Row (`RowConfig.AutoMerge`)
- Columns (`ColumnConfig.AutoMerge`)
- Limit the length of
Expand Down Expand Up @@ -37,6 +37,7 @@ Pretty-print tables into ASCII/Unicode strings.
- CSV
- HTML Table (with custom CSS Class)
- Markdown Table
- TSV

```
+---------------------------------------------------------------------+
Expand Down
130 changes: 128 additions & 2 deletions table/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,10 @@ func TestTable_Render_Sorted(t *testing.T) {
tw.AppendRow(Row{11, "Sansa", "Stark", 6000})
tw.AppendFooter(testFooter)
tw.SetStyle(StyleLight)
tw.SortBy([]SortBy{{Name: "Last Name", Mode: Asc}, {Name: "First Name", Mode: Asc}})
tw.SortBy([]SortBy{
{Name: "Last Name", Mode: Asc},
{Name: "First Name", Mode: Asc},
})

compareOutput(t, tw.Render(), `┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
│ # │ FIRST NAME │ LAST NAME │ SALARY │ │
Expand All @@ -962,7 +965,12 @@ func TestTable_Render_Sorted(t *testing.T) {
├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
│ │ │ TOTAL │ 10000 │ │
└─────┴────────────┴───────────┴────────┴─────────────────────────────┘`)
tw.SortBy([]SortBy{{Number: 5, Mode: Dsc}, {Name: "Last Name", Mode: Asc}, {Name: "First Name", Mode: Asc}})

tw.SortBy([]SortBy{
{Number: 5, Mode: Dsc},
{Name: "Last Name", Mode: Asc},
{Name: "First Name", Mode: Asc},
})
compareOutput(t, tw.Render(), `┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
│ # │ FIRST NAME │ LAST NAME │ SALARY │ │
├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
Expand All @@ -975,6 +983,124 @@ func TestTable_Render_Sorted(t *testing.T) {
└─────┴────────────┴───────────┴────────┴─────────────────────────────┘`)
}

func TestTable_Render_SortedAlphaNumeric(t *testing.T) {
tw := NewWriter()
tw.AppendHeader(Row{"#", "Name", "Prefix", "Number", "Class"})
tw.SetColumnConfigs([]ColumnConfig{
{Number: 1, Align: text.AlignRight, AlignHeader: text.AlignCenter},
{Number: 2, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
{Number: 3, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
{Number: 4, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
{Number: 5, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
})
tw.AppendRows([]Row{
{0, "defiant", "NCC", 1764, "Constitution"},
{1, "Defiant", "nx", 74205, "Defiant"},
{2, "entente", "ncc", 2120, "Dreadnought"},
{3, "Enterprise", "NCC", 1701, "Constitution"},
{4, "Farragut", "NCC", 1647, "(Farragut-Type)"},
{5, "farragut", "NCC", 60597, "Nebula"},
{6, "Bonaventure", "", "10283NCC", "(Bonaventure-Typ)"},
{7, "IKS Ch'Tang", "", "-----------", "Bird-of-Prey"},
{8, "IKS Drovana", "", "-----------", "Vor'cha-Klasse"},
{9, "IKS Buruk", "", "-----------", "Bird-of-Prey"},
})
tw.SetStyle(StyleLight)

tw.SortBy([]SortBy{
{Name: "Name", Mode: Asc, IgnoreCase: false},
})
compareOutput(t, tw.Render(), `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`)

tw.SortBy([]SortBy{
{Name: "Name", Mode: Asc, IgnoreCase: true},
})
compareOutput(t, tw.Render(), `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`)

tw.SortBy([]SortBy{
{Name: "Prefix", Mode: Asc, IgnoreCase: true},
{Name: "Number", Mode: AscNumericAlpha},
})
compareOutput(t, tw.Render(), `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`)

tw.SortBy([]SortBy{
{Name: "Number", Mode: AscNumericAlpha},
{Name: "Name", Mode: Asc},
})
compareOutput(t, tw.Render(), `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`)

tw.SortBy([]SortBy{
{Name: "Number", Mode: DscAlphaNumeric, IgnoreCase: true},
{Name: "Name", Mode: Asc},
})
compareOutput(t, tw.Render(), `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`)
}

func TestTable_Render_Separator(t *testing.T) {
tw := NewWriter()
tw.AppendHeader(testHeader)
Expand Down
12 changes: 6 additions & 6 deletions table/sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ func (rs rowsSorter) Swap(i, j int) {
}

func (rs rowsSorter) Less(i, j int) bool {
shouldContinue, returnValue := false, false
realI, realJ := rs.sortedIndices[i], rs.sortedIndices[j]
lastSort := len(rs.sortBy) - 1
for sortIdx, sortBy := range rs.sortBy {
for _, sortBy := range rs.sortBy {
// extract the values/cells from the rows for comparison
rowI, rowJ, colIdx := rs.rows[realI], rs.rows[realJ], sortBy.Number-1
iVal, jVal := "", ""
Expand All @@ -123,12 +123,12 @@ func (rs rowsSorter) Less(i, j int) bool {
}

// compare and choose whether to continue
shouldContinue, returnValue := less(iVal, jVal, sortBy)
if !shouldContinue || lastSort == sortIdx {
return returnValue
shouldContinue, returnValue = less(iVal, jVal, sortBy)
if !shouldContinue {
break
}
}
return false
return returnValue
}

func less(iVal string, jVal string, sb SortBy) (bool, bool) {
Expand Down
86 changes: 0 additions & 86 deletions table/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,92 +290,6 @@ func TestTable_SetAutoIndex(t *testing.T) {
│ │ │ │ │ │ This is known. │
└───┴─────┴────────────┴───────────┴────────┴─────────────────────────────┘`
assert.Equal(t, expectedOut, table.Render())
tw := NewWriter()
tw.AppendHeader(Row{"#", "Name", "Prefix", "Number", "Class"})
tw.SetColumnConfigs([]ColumnConfig{
{Number: 1, Align: text.AlignRight, AlignHeader: text.AlignCenter},
{Number: 2, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
{Number: 3, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
{Number: 4, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
{Number: 5, Align: text.AlignAuto, AlignHeader: text.AlignCenter},
})
tw.AppendRows([]Row{
{0, "defiant", "NCC", 1764, "Constitution"},
{1, "Defiant", "nx", 74205, "Defiant"},
{2, "entente", "ncc", 2120, "Dreadnought"},
{3, "Enterprise", "NCC", 1701, "Constitution"},
{4, "Farragut", "NCC", 1647, "(Farragut-Type)"},
{5, "farragut", "NCC", 60597, "Nebula"},
{6, "Bonaventure", "", "10283NCC", "(Bonaventure-Typ)"},
{7, "IKS Ch'Tang", "", "-----------", "Bird-of-Prey"},
{8, "IKS Drovana", "", "-----------", "Vor'cha-Klasse"},
{9, "IKS Buruk", "", "-----------", "Bird-of-Prey"},
})
tw.SetStyle(StyleLight)
tw.SortBy([]SortBy{{Name: "Name", Mode: Asc, IgnoreCase: false}})
assert.Equal(t, `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`, tw.Render())

tw.SortBy([]SortBy{{Name: "Name", Mode: Asc, IgnoreCase: true}})
assert.Equal(t, `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`, tw.Render())

tw.SortBy([]SortBy{{Name: "Prefix", Mode: Asc, IgnoreCase: true}, {Name: "Number", Mode: AscNumericAlpha}})
assert.Equal(t, `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`, tw.Render())

tw.SortBy([]SortBy{{Name: "Number", Mode: AscNumericAlpha}, {Name: "Name", Mode: Asc}})
assert.Equal(t, `┌───┬─────────────┬────────┬─────────────┬───────────────────┐
│ # │ NAME │ PREFIX │ NUMBER │ CLASS │
├───┼─────────────┼────────┼─────────────┼───────────────────┤
│ 4 │ Farragut │ NCC │ 1647 │ (Farragut-Type) │
│ 3 │ Enterprise │ NCC │ 1701 │ Constitution │
│ 0 │ defiant │ NCC │ 1764 │ Constitution │
│ 2 │ entente │ ncc │ 2120 │ Dreadnought │
│ 5 │ farragut │ NCC │ 60597 │ Nebula │
│ 1 │ Defiant │ nx │ 74205 │ Defiant │
│ 9 │ IKS Buruk │ │ ----------- │ Bird-of-Prey │
│ 7 │ IKS Ch'Tang │ │ ----------- │ Bird-of-Prey │
│ 8 │ IKS Drovana │ │ ----------- │ Vor'cha-Klasse │
│ 6 │ Bonaventure │ │ 10283NCC │ (Bonaventure-Typ) │
└───┴─────────────┴────────┴─────────────┴───────────────────┘`, tw.Render())

}

func TestTable_SetCaption(t *testing.T) {
Expand Down

0 comments on commit 04a692c

Please sign in to comment.