Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

table: note about auto-merge and HTML/Markdown modes #311

Merged
merged 1 commit into from
Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion table/README.md
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
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
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
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