diff --git a/list/render.go b/list/render.go
index 935416d..b3a72fb 100644
--- a/list/render.go
+++ b/list/render.go
@@ -6,15 +6,15 @@ import (
)
// Render renders the List in a human-readable "pretty" format. Example:
-// * Game Of Thrones
-// * Winter
-// * Is
-// * Coming
-// * This
-// * Is
-// * Known
-// * The Dark Tower
-// * The Gunslinger
+// | * Game Of Thrones
+// | * Winter
+// | * Is
+// | * Coming
+// | * This
+// | * Is
+// | * Known
+// | * The Dark Tower
+// | * The Gunslinger
func (l *List) Render() string {
l.initForRender()
diff --git a/list/render_html.go b/list/render_html.go
index 7b51001..143c6ee 100644
--- a/list/render_html.go
+++ b/list/render_html.go
@@ -7,23 +7,24 @@ import (
)
// RenderHTML renders the List in the HTML format. Example:
-//
-// - Game Of Thrones
-//
-// - Winter
-// - Is
-// - Coming
-//
-// - This
-// - Is
-// - Known
-//
-//
-// - The Dark Tower
-//
-//
+//
+//
+// - Game Of Thrones
+//
+// - Winter
+// - Is
+// - Coming
+//
+// - This
+// - Is
+// - Known
+//
+//
+// - The Dark Tower
+//
+//
func (l *List) RenderHTML() string {
l.initForRender()
diff --git a/list/render_markdown.go b/list/render_markdown.go
index 3c8aab8..9d24f64 100644
--- a/list/render_markdown.go
+++ b/list/render_markdown.go
@@ -1,15 +1,15 @@
package list
// RenderMarkdown renders the List in the Markdown format. Example:
-// * Game Of Thrones
-// * Winter
-// * Is
-// * Coming
-// * This
-// * Is
-// * Known
-// * The Dark Tower
-// * The Gunslinger
+// | * Game Of Thrones
+// | * Winter
+// | * Is
+// | * Coming
+// | * This
+// | * Is
+// | * Known
+// | * The Dark Tower
+// | * The Gunslinger
func (l *List) RenderMarkdown() string {
// make a copy of the original style and ensure it is restored on exit
originalStyle := l.style
diff --git a/progress/tracker_sort.go b/progress/tracker_sort.go
index da6ac18..aa998b9 100644
--- a/progress/tracker_sort.go
+++ b/progress/tracker_sort.go
@@ -56,8 +56,8 @@ func (sb sortByMessage) Less(i, j int) bool { return sb[i].message() < sb[j].mes
type sortByPercent []*Tracker
-func (sb sortByPercent) Len() int { return len(sb) }
-func (sb sortByPercent) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
+func (sb sortByPercent) Len() int { return len(sb) }
+func (sb sortByPercent) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
func (sb sortByPercent) Less(i, j int) bool {
if sb[i].PercentDone() == sb[j].PercentDone() {
return sb[i].timeStart.Before(sb[j].timeStart)
@@ -67,8 +67,8 @@ func (sb sortByPercent) Less(i, j int) bool {
type sortByValue []*Tracker
-func (sb sortByValue) Len() int { return len(sb) }
-func (sb sortByValue) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
+func (sb sortByValue) Len() int { return len(sb) }
+func (sb sortByValue) Swap(i, j int) { sb[i], sb[j] = sb[j], sb[i] }
func (sb sortByValue) Less(i, j int) bool {
if sb[i].value == sb[j].value {
return sb[i].timeStart.Before(sb[j].timeStart)
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644
index 0000000..2233099
--- /dev/null
+++ b/sonar-project.properties
@@ -0,0 +1,9 @@
+# Define the root directory for sources and tests
+sonar.sources = ./
+sonar.tests = ./
+
+# Include test files in test scope
+sonar.test.inclusions = **/*_test.go
+
+# Exclude test files from source scope
+sonar.exclusions = **/*_test.go
diff --git a/table/render.go b/table/render.go
index ca4bc99..2e93da5 100644
--- a/table/render.go
+++ b/table/render.go
@@ -9,15 +9,16 @@ import (
)
// Render renders the Table in a human-readable "pretty" format. Example:
-// ┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
-// │ # │ FIRST NAME │ LAST NAME │ SALARY │ │
-// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
-// │ 1 │ Arya │ Stark │ 3000 │ │
-// │ 20 │ Jon │ Snow │ 2000 │ You know nothing, Jon Snow! │
-// │ 300 │ Tyrion │ Lannister │ 5000 │ │
-// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
-// │ │ │ TOTAL │ 10000 │ │
-// └─────┴────────────┴───────────┴────────┴─────────────────────────────┘
+//
+// ┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
+// │ # │ FIRST NAME │ LAST NAME │ SALARY │ │
+// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
+// │ 1 │ Arya │ Stark │ 3000 │ │
+// │ 20 │ Jon │ Snow │ 2000 │ You know nothing, Jon Snow! │
+// │ 300 │ Tyrion │ Lannister │ 5000 │ │
+// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
+// │ │ │ TOTAL │ 10000 │ │
+// └─────┴────────────┴───────────┴────────┴─────────────────────────────┘
func (t *Table) Render() string {
t.initForRender()
diff --git a/table/render_automerge_test.go b/table/render_automerge_test.go
new file mode 100644
index 0000000..3781937
--- /dev/null
+++ b/table/render_automerge_test.go
@@ -0,0 +1,765 @@
+package table
+
+import (
+ "testing"
+
+ "github.com/jedib0t/go-pretty/v6/text"
+)
+
+func TestTable_Render_AutoMerge(t *testing.T) {
+ rcAutoMerge := RowConfig{AutoMerge: true}
+
+ t.Run("columns only", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE\nEXE", "RCE\nRUN"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y"})
+ tw.AppendFooter(Row{"", "", "", 7, 5, 3})
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 1, AutoMerge: true},
+ {Number: 2, AutoMerge: true},
+ {Number: 3, AutoMerge: true},
+ {Number: 4, AutoMerge: true},
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────────┬───────────┬─────┬─────┐
+│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │ RCE │
+│ │ │ │ │ │ EXE │ RUN │
+├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │ Y │
+├───┤ │ │ ├───────────┼─────┼─────┤
+│ 2 │ │ │ │ C 2 │ Y │ N │
+├───┤ │ ├───────────┼───────────┼─────┼─────┤
+│ 3 │ │ │ NS 1B │ C 3 │ N │ N │
+├───┤ ├────────┼───────────┼───────────┼─────┼─────┤
+│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │ N │
+├───┤ │ │ ├───────────┼─────┼─────┤
+│ 5 │ │ │ │ C 5 │ Y │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │ Y │
+├───┤ │ │ ├───────────┼─────┼─────┤
+│ 7 │ │ │ │ C 7 │ Y │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
+│ │ │ │ │ 7 │ 5 │ 3 │
+└───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘`)
+ })
+
+ t.Run("columns only with hidden columns", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE\nEXE", "RCE\nRUN"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "Y", "Y"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "N"})
+ tw.AppendFooter(Row{"", "", "", 7, 5, 3})
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 1, AutoMerge: true},
+ {Number: 2, AutoMerge: true},
+ {Number: 3, AutoMerge: true},
+ {Number: 4, Hidden: true},
+ {Number: 5, Hidden: true, Align: text.AlignCenter},
+ {Number: 6, Hidden: true, Align: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌─────────┬────────┬───────────┐
+│ NODE IP │ PODS │ NAMESPACE │
+├─────────┼────────┼───────────┤
+│ a.a.a.a │ Pod 1A │ NS 1A │
+│ │ │ │
+│ │ │ │
+│ │ ├───────────┤
+│ │ │ NS 1B │
+│ ├────────┼───────────┤
+│ │ Pod 1B │ NS 2 │
+│ │ │ │
+│ │ │ │
+├─────────┼────────┼───────────┤
+│ b.b.b.b │ Pod 2 │ NS 3 │
+│ │ │ │
+│ │ │ │
+├─────────┼────────┼───────────┤
+│ │ │ │
+└─────────┴────────┴───────────┘`)
+ })
+
+ t.Run("rows only", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE"}, rcAutoMerge)
+ tw.AppendHeader(Row{"", "", "", "", "EXE", "RUN"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y"}, RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignRight})
+ tw.AppendFooter(Row{"", "", "", 7, 5, 3})
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────────┬───────────┬───────────┐
+│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │
+│ ├─────────┼────────┼───────────┼───────────┼─────┬─────┤
+│ │ │ │ │ │ EXE │ RUN │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1B │ C 3 │ N │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
+│ 4 │ a.a.a.a │ Pod 1B │ NS 2 │ C 4 │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
+│ 5 │ a.a.a.a │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼───────────┤
+│ 7 │ b.b.b.b │ Pod 2 │ NS 3 │ C 7 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
+│ │ │ │ │ 7 │ 5 │ 3 │
+└───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘`)
+ })
+
+ t.Run("rows and columns", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE"}, rcAutoMerge)
+ tw.AppendHeader(Row{"", "", "", "", "EXE", "RUN"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y"}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 3})
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 1, AutoMerge: true},
+ {Number: 2, AutoMerge: true},
+ {Number: 3, AutoMerge: true},
+ {Number: 4, AutoMerge: true},
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────────┬───────────┬───────────┐
+│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │
+│ ├─────────┼────────┼───────────┼───────────┼─────┬─────┤
+│ │ │ │ │ │ EXE │ RUN │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├───┤ │ │ ├───────────┼─────┬─────┤
+│ 2 │ │ │ │ C 2 │ Y │ N │
+├───┤ │ ├───────────┼───────────┼─────┴─────┤
+│ 3 │ │ │ NS 1B │ C 3 │ N │
+├───┤ ├────────┼───────────┼───────────┼───────────┤
+│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │
+├───┤ │ │ ├───────────┼─────┬─────┤
+│ 5 │ │ │ │ C 5 │ Y │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │
+├───┤ │ │ ├───────────┼───────────┤
+│ 7 │ │ │ │ C 7 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
+│ │ │ │ │ 7 │ 5 │ 3 │
+└───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘`)
+ })
+
+ t.Run("rows and columns no headers or footers", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y"}, RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignRight})
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
+ {Number: 6, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌─────────┬────────┬───────┬─────┬───────┐
+│ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├─────────┼────────┼───────┼─────┼───┬───┤
+│ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
+├─────────┼────────┼───────┼─────┼───┼───┤
+│ a.a.a.a │ Pod 1A │ NS 1B │ C 3 │ N │ N │
+├─────────┼────────┼───────┼─────┼───┴───┤
+│ a.a.a.a │ Pod 1B │ NS 2 │ C 4 │ N │
+├─────────┼────────┼───────┼─────┼───┬───┤
+│ a.a.a.a │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
+├─────────┼────────┼───────┼─────┼───┴───┤
+│ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │
+├─────────┼────────┼───────┼─────┼───────┤
+│ b.b.b.b │ Pod 2 │ NS 3 │ C 7 │ Y │
+└─────────┴────────┴───────┴─────┴───────┘`)
+ })
+
+ t.Run("rows and columns no headers or footers with auto-index", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N"})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y"}, RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignRight})
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
+ {Number: 6, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────┬─────┬───┬───┐
+│ │ A │ B │ C │ D │ E │ F │
+├───┼─────────┼────────┼───────┼─────┼───┴───┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├───┼─────────┼────────┼───────┼─────┼───┬───┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
+├───┼─────────┼────────┼───────┼─────┼───┼───┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1B │ C 3 │ N │ N │
+├───┼─────────┼────────┼───────┼─────┼───┴───┤
+│ 4 │ a.a.a.a │ Pod 1B │ NS 2 │ C 4 │ N │
+├───┼─────────┼────────┼───────┼─────┼───┬───┤
+│ 5 │ a.a.a.a │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
+├───┼─────────┼────────┼───────┼─────┼───┴───┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │
+├───┼─────────┼────────┼───────┼─────┼───────┤
+│ 7 │ b.b.b.b │ Pod 2 │ NS 3 │ C 7 │ Y │
+└───┴─────────┴────────┴───────┴─────┴───────┘`)
+ })
+
+ t.Run("rows and columns and headers and footers", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE", "ID"}, rcAutoMerge)
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "EXE", "RUN", ""})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y", 123}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "N", 234})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N", 345})
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N", 456}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "N", 567})
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y", 678}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y", 789}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 3}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 3}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 1, AutoMerge: true},
+ {Number: 2, AutoMerge: true},
+ {Number: 3, AutoMerge: true},
+ {Number: 4, AutoMerge: true},
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────────┬───────────┬───────────┬─────┐
+│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │ ID │
+│ │ │ │ │ ├─────┬─────┼─────┤
+│ │ │ │ │ │ EXE │ RUN │ │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┼─────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │ 123 │
+├───┤ │ │ ├───────────┼─────┬─────┼─────┤
+│ 2 │ │ │ │ C 2 │ Y │ N │ 234 │
+├───┤ │ ├───────────┼───────────┼─────┼─────┼─────┤
+│ 3 │ │ │ NS 1B │ C 3 │ N │ N │ 345 │
+├───┤ ├────────┼───────────┼───────────┼─────┴─────┼─────┤
+│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │ 456 │
+├───┤ │ │ ├───────────┼─────┬─────┼─────┤
+│ 5 │ │ │ │ C 5 │ Y │ N │ 567 │
+├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┼─────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │ 678 │
+├───┤ │ │ ├───────────┼───────────┼─────┤
+│ 7 │ │ │ │ C 7 │ Y │ 789 │
+├───┼─────────┴────────┴───────────┼───────────┼───────────┼─────┤
+│ │ │ 7 │ 5 │ │
+│ │ │ ├─────┬─────┼─────┤
+│ │ │ │ 5 │ 3 │ │
+│ │ │ ├─────┴─────┼─────┤
+│ │ │ │ 5 │ │
+│ │ │ ├─────┬─────┼─────┤
+│ │ │ │ 5 │ 3 │ │
+│ │ │ ├─────┴─────┼─────┤
+│ │ │ │ 5 │ │
+└───┴──────────────────────────────┴───────────┴───────────┴─────┘`)
+ })
+
+ t.Run("samurai sudoku", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendRow(Row{"1.1\n1.1", "1.2\n1.2", "1.3\n1.3", " ", "2.1\n2.1", "2.2\n2.2", "2.3\n2.3"})
+ tw.AppendRow(Row{"1.4\n1.4", "1.5\n1.5", "1.6\n1.6", " ", "2.4\n2.4", "2.5\n2.5", "2.6\n2.6"})
+ tw.AppendRow(Row{"1.7\n1.7", "1.8\n1.8", "1.9\n0.1", "0.2\n0.2", "2.7\n0.3", "2.8\n2.8", "2.9\n2.9"})
+ tw.AppendRow(Row{" ", " ", "0.4\n0.4", "0.5\n0.5", "0.6\n0.6", " ", " "}, rcAutoMerge)
+ tw.AppendRow(Row{"3.1\n3.1", "3.2\n3.2", "3.3\n0.7", "0.8\n0.8", "4.1\n0.9", "4.2\n4.2", "4.3\n4.3"})
+ tw.AppendRow(Row{"3.4\n3.4", "3.5\n3.5", "3.6\n3.6", " ", "4.4\n4.4", "4.5\n4.5", "4.6\n4.6"})
+ tw.AppendRow(Row{"3.7\n3.7", "3.8\n3.8", "3.9\n3.9", " ", "4.7\n4.7", "4.8\n4.8", "4.9\n4.9"})
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 4, AutoMerge: true},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Box.PaddingLeft = ""
+ tw.Style().Box.PaddingRight = ""
+ tw.Style().Options.DrawBorder = true
+ tw.Style().Options.SeparateRows = true
+ tw.Style().Options.SeparateColumns = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬───┬───┬───┬───┬───┬───┐
+│1.1│1.2│1.3│ │2.1│2.2│2.3│
+│1.1│1.2│1.3│ │2.1│2.2│2.3│
+├───┼───┼───┤ ├───┼───┼───┤
+│1.4│1.5│1.6│ │2.4│2.5│2.6│
+│1.4│1.5│1.6│ │2.4│2.5│2.6│
+├───┼───┼───┼───┼───┼───┼───┤
+│1.7│1.8│1.9│0.2│2.7│2.8│2.9│
+│1.7│1.8│0.1│0.2│0.3│2.8│2.9│
+├───┴───┼───┼───┼───┼───┴───┤
+│ │0.4│0.5│0.6│ │
+│ │0.4│0.5│0.6│ │
+├───┬───┼───┼───┼───┼───┬───┤
+│3.1│3.2│3.3│0.8│4.1│4.2│4.3│
+│3.1│3.2│0.7│0.8│0.9│4.2│4.3│
+├───┼───┼───┼───┼───┼───┼───┤
+│3.4│3.5│3.6│ │4.4│4.5│4.6│
+│3.4│3.5│3.6│ │4.4│4.5│4.6│
+├───┼───┼───┤ ├───┼───┼───┤
+│3.7│3.8│3.9│ │4.7│4.8│4.9│
+│3.7│3.8│3.9│ │4.7│4.8│4.9│
+└───┴───┴───┴───┴───┴───┴───┘`)
+ })
+
+ testLongCol1 := "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR"
+ testLongRowCCs := []ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ {Number: 8, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ }
+ generateTableForLongRows := func() Writer {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6", "Column 7", "Column 8"}, rcAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs(testLongRowCCs)
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+ return tw
+ }
+
+ t.Run("long column no merge", func(t *testing.T) {
+ tw := generateTableForLongRows()
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1 + "W", testLongCol1 + "H", testLongCol1 + "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRW │ 0F4EB42DRH │ 0F4EB42DRY │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────────────────────┴──────────────────────────┴──────────────────────────┴──────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┘`)
+ })
+
+ t.Run("long column partially merged #1", func(t *testing.T) {
+ tw := generateTableForLongRows()
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1, testLongCol1 + "R", testLongCol1 + "R"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬─────────────┬─────────────┬─────────────┬─────────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼─────────────┴─────────────┼─────────────┴─────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRR │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────┴───────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────┘`)
+ })
+
+ t.Run("long column partially merged #2", func(t *testing.T) {
+ tw := generateTableForLongRows()
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1, testLongCol1, testLongCol1 + "E"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────────────────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────┴──────────┴──────────┼──────────────────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRE │
+├───┼──────────┼──────────┼──────────┼──────────┼────────────────────────────────┴──────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────────┘`)
+ })
+
+ t.Run("long column fully merged", func(t *testing.T) {
+ tw := generateTableForLongRows()
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1, testLongCol1, testLongCol1}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────┴──────────┴──────────┴──────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────┘`)
+ })
+
+ t.Run("headers and footers", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE1", "RCE2"}, rcAutoMerge)
+ tw.AppendHeader(Row{"", "", "", "", "EXE EXE EXE", "EXE EXE EXE"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y"}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 6, 4, 4}, rcAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────────┬───────────┬──────┬──────┐
+│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE1 │ RCE2 │
+│ ├─────────┴────────┴───────────┴───────────┼──────┴──────┤
+│ │ │ EXE EXE │
+│ │ │ EXE │
+├───┼─────────┬────────┬───────────┬───────────┼─────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1B │ C 3 │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
+│ 4 │ a.a.a.a │ Pod 1B │ NS 2 │ C 4 │ N │
+├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
+│ 5 │ a.a.a.a │ Pod 1B │ NS 2 │ C 5 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
+│ 7 │ b.b.b.b │ Pod 2 │ NS 3 │ C 7 │ Y │
+├───┼─────────┴────────┴───────────┼───────────┼─────────────┤
+│ │ │ 7 │ 5 │
+│ ├──────────────────────────────┼───────────┼─────────────┤
+│ │ │ 6 │ 4 │
+└───┴──────────────────────────────┴───────────┴─────────────┘`)
+ })
+
+ t.Run("long header column", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE1", "RCE2", "RCE3"}, rcAutoMerge)
+ tw.AppendHeader(Row{"", "", "", "", "EXE EXE EXE", "EXE EXE EXE", "EXE EXE EXE"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 7, 5, 5, 5}, rcAutoMerge)
+ tw.AppendFooter(Row{"", "", "", 6, 4, 4, 3}, rcAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬─────────┬────────┬───────────┬───────────┬──────┬──────┬──────┐
+│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE1 │ RCE2 │ RCE3 │
+│ ├─────────┴────────┴───────────┴───────────┼──────┴──────┴──────┤
+│ │ │ EXE EXE │
+│ │ │ EXE │
+├───┼─────────┬────────┬───────────┬───────────┼────────────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1B │ C 3 │ N │
+├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
+│ 4 │ a.a.a.a │ Pod 1B │ NS 2 │ C 4 │ N │
+├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
+│ 5 │ a.a.a.a │ Pod 1B │ NS 2 │ C 5 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ Y │
+├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
+│ 7 │ b.b.b.b │ Pod 2 │ NS 3 │ C 7 │ Y │
+├───┼─────────┴────────┴───────────┼───────────┼────────────────────┤
+│ │ │ 7 │ 5 │
+│ ├──────────────────────────────┼───────────┼─────────────┬──────┤
+│ │ │ 6 │ 4 │ 3 │
+└───┴──────────────────────────────┴───────────┴─────────────┴──────┘`)
+ })
+
+ t.Run("empty cells", func(t *testing.T) {
+ tw := NewWriter()
+ rowConfigAutoMerge := RowConfig{AutoMerge: true}
+ tw.AppendRow(Row{"Product", "Standalone", "foo bar", "a.a.a.a", ""}, rowConfigAutoMerge)
+ tw.AppendRow(Row{"Test", "Standalone", "bar baz", "b.b.b.b", ""}, rowConfigAutoMerge)
+ tw.AppendRow(Row{"Product", "RedisCluster", "foo baz", "", "Cluster #1"}, rowConfigAutoMerge)
+ tw.AppendRow(Row{"Product", "RedisCluster", "bar baz", "", "Cluster #2"}, rowConfigAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 1, AutoMerge: true},
+ {Number: 2, AutoMerge: true},
+ {Number: 3, AutoMerge: true},
+ {Number: 4, AutoMerge: true},
+ {Number: 5, AutoMerge: true},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `┌───┬─────────┬──────────────┬─────────┬─────────┬────────────┐
+│ │ A │ B │ C │ D │ E │
+├───┼─────────┼──────────────┼─────────┼─────────┼────────────┤
+│ 1 │ Product │ Standalone │ foo bar │ a.a.a.a │ │
+├───┼─────────┤ ├─────────┼─────────┤ │
+│ 2 │ Test │ │ bar baz │ b.b.b.b │ │
+├───┼─────────┼──────────────┼─────────┼─────────┼────────────┤
+│ 3 │ Product │ RedisCluster │ foo baz │ │ Cluster #1 │
+├───┤ │ ├─────────┤ ├────────────┤
+│ 4 │ │ │ bar baz │ │ Cluster #2 │
+└───┴─────────┴──────────────┴─────────┴─────────┴────────────┘`)
+ })
+
+ t.Run("everything", func(t *testing.T) {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1B", "C 3", "N", "N", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 4", "N", "Y", "N"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1B", "NS 2", "C 5", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 6", "N", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"b.b.b.b", "Pod 2", "NS 3", "C 7", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendFooter(Row{"foo", "foo", "foo", "foo", "bar", "bar", "bar"}, rcAutoMerge)
+ tw.AppendFooter(Row{7, 7, 7, 7, 7, 7, 7}, rcAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs([]ColumnConfig{
+ {Number: 1, AutoMerge: true},
+ {Number: 2, AutoMerge: true},
+ {Number: 3, AutoMerge: true},
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
+ })
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+
+ compareOutput(t, tw.Render(), `
+┌───┬───────────────────────────────────────────────────┐
+│ │ COLUMNS │
+├───┼─────────┬─────────┬─────────┬─────────┬───────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ Y │
+├───┤ │ │ ├─────────┼───────┬───┤
+│ 2 │ │ │ │ C 2 │ Y │ N │
+├───┤ │ ├─────────┼─────────┼───────┴───┤
+│ 3 │ │ │ NS 1B │ C 3 │ N │
+├───┤ ├─────────┼─────────┼─────────┼───┬───┬───┤
+│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │ Y │ N │
+├───┤ │ │ ├─────────┼───┴───┴───┤
+│ 5 │ │ │ │ C 5 │ Y │
+├───┼─────────┼─────────┼─────────┼─────────┼───┬───────┤
+│ 6 │ b.b.b.b │ Pod 2 │ NS 3 │ C 6 │ N │ Y │
+├───┤ │ │ ├─────────┼───┴───────┤
+│ 7 │ │ │ │ C 7 │ Y │
+├───┼─────────┴─────────┴─────────┴─────────┼───────────┤
+│ │ FOO │ BAR │
+│ ├───────────────────────────────────────┴───────────┤
+│ │ 7 │
+└───┴───────────────────────────────────────────────────┘`)
+ })
+}
+
+func TestTable_Render_AutoMergeLongColumns(t *testing.T) {
+ rcAutoMerge := RowConfig{AutoMerge: true}
+
+ testLongCol1 := "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR"
+ testLongRowCCs := []ColumnConfig{
+ {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ {Number: 8, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
+ }
+ generateTableForLongRows := func(longRow Row) Writer {
+ tw := NewWriter()
+ tw.AppendHeader(Row{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6", "Column 7", "Column 8"}, rcAutoMerge)
+ tw.AppendRow(longRow, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.AppendRow(Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
+ tw.SetAutoIndex(true)
+ tw.SetColumnConfigs(testLongRowCCs)
+ tw.SetStyle(StyleLight)
+ tw.Style().Options.SeparateRows = true
+ return tw
+ }
+
+ t.Run("no merge", func(t *testing.T) {
+ tw := generateTableForLongRows(
+ Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1 + "W", testLongCol1 + "H", testLongCol1 + "Y"},
+ )
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRW │ 0F4EB42DRH │ 0F4EB42DRY │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────────────────────┴──────────────────────────┴──────────────────────────┴──────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┘`)
+ })
+
+ t.Run("merge 2 pairs", func(t *testing.T) {
+ tw := generateTableForLongRows(
+ Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1, testLongCol1 + "R", testLongCol1 + "R"},
+ )
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬─────────────┬─────────────┬─────────────┬─────────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼─────────────┴─────────────┼─────────────┴─────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRR │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────┴───────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────┘`)
+ })
+
+ t.Run("marge 3 columns", func(t *testing.T) {
+ tw := generateTableForLongRows(
+ Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1, testLongCol1, testLongCol1 + "E"},
+ )
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────────────────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────┴──────────┴──────────┼──────────────────────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRE │
+├───┼──────────┼──────────┼──────────┼──────────┼────────────────────────────────┴──────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────────┘`)
+ })
+
+ t.Run("merge 4 columns", func(t *testing.T) {
+ tw := generateTableForLongRows(
+ Row{"a.a.a.a", "Pod 1A", "NS 1A", "C 1", testLongCol1, testLongCol1, testLongCol1, testLongCol1},
+ )
+
+ compareOutput(t, tw.Render(), `
+┌───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
+│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
+├───┼──────────┼──────────┼──────────┼──────────┼──────────┴──────────┴──────────┴──────────┤
+│ 1 │ a.a.a.a │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │
+│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │
+│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │
+│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │
+│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │
+│ │ │ │ │ │ 0F4EB42DR │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────┤
+│ 2 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────┤
+│ 3 │ a.a.a.a │ Pod 1A │ NS 1A │ C 2 │ Y │
+└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────┘`)
+ })
+}
diff --git a/table/render_csv.go b/table/render_csv.go
index 07da673..831194e 100644
--- a/table/render_csv.go
+++ b/table/render_csv.go
@@ -7,11 +7,12 @@ import (
)
// RenderCSV renders the Table in CSV format. Example:
-// #,First Name,Last Name,Salary,
-// 1,Arya,Stark,3000,
-// 20,Jon,Snow,2000,"You know nothing\, Jon Snow!"
-// 300,Tyrion,Lannister,5000,
-// ,,Total,10000,
+//
+// #,First Name,Last Name,Salary,
+// 1,Arya,Stark,3000,
+// 20,Jon,Snow,2000,"You know nothing\, Jon Snow!"
+// 300,Tyrion,Lannister,5000,
+// ,,Total,10000,
func (t *Table) RenderCSV() string {
t.initForRender()
diff --git a/table/render_html.go b/table/render_html.go
index bf712ec..fcea86b 100644
--- a/table/render_html.go
+++ b/table/render_html.go
@@ -13,49 +13,50 @@ const (
)
// RenderHTML renders the Table in HTML format. Example:
-//
-//
-//
-// # |
-// First Name |
-// Last Name |
-// Salary |
-// |
-//
-//
-//
-//
-// 1 |
-// Arya |
-// Stark |
-// 3000 |
-// |
-//
-//
-// 20 |
-// Jon |
-// Snow |
-// 2000 |
-// You know nothing, Jon Snow! |
-//
-//
-// 300 |
-// Tyrion |
-// Lannister |
-// 5000 |
-// |
-//
-//
-//
-//
-// |
-// |
-// Total |
-// 10000 |
-// |
-//
-//
-//
+//
+//
+//
+//
+// # |
+// First Name |
+// Last Name |
+// Salary |
+// |
+//
+//
+//
+//
+// 1 |
+// Arya |
+// Stark |
+// 3000 |
+// |
+//
+//
+// 20 |
+// Jon |
+// Snow |
+// 2000 |
+// You know nothing, Jon Snow! |
+//
+//
+// 300 |
+// Tyrion |
+// Lannister |
+// 5000 |
+// |
+//
+//
+//
+//
+// |
+// |
+// Total |
+// 10000 |
+// |
+//
+//
+//
func (t *Table) RenderHTML() string {
t.initForRender()
diff --git a/table/render_markdown.go b/table/render_markdown.go
index 1a8c488..adf573f 100644
--- a/table/render_markdown.go
+++ b/table/render_markdown.go
@@ -6,12 +6,13 @@ import (
)
// RenderMarkdown renders the Table in Markdown format. Example:
-// | # | First Name | Last Name | Salary | |
-// | ---:| --- | --- | ---:| --- |
-// | 1 | Arya | Stark | 3000 | |
-// | 20 | Jon | Snow | 2000 | You know nothing, Jon Snow! |
-// | 300 | Tyrion | Lannister | 5000 | |
-// | | | Total | 10000 | |
+//
+// | # | First Name | Last Name | Salary | |
+// | ---:| --- | --- | ---:| --- |
+// | 1 | Arya | Stark | 3000 | |
+// | 20 | Jon | Snow | 2000 | You know nothing, Jon Snow! |
+// | 300 | Tyrion | Lannister | 5000 | |
+// | | | Total | 10000 | |
func (t *Table) RenderMarkdown() string {
t.initForRender()
diff --git a/table/render_test.go b/table/render_test.go
index abeaa79..abc1a72 100644
--- a/table/render_test.go
+++ b/table/render_test.go
@@ -140,692 +140,6 @@ func TestTable_Render_AutoIndex(t *testing.T) {
└────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘`)
}
-func TestTable_Render_AutoMerge(t *testing.T) {
- rcAutoMerge := RowConfig{AutoMerge: true}
-
- t.Run("columns only", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE\nEXE", "RCE\nRUN"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"})
- tw.AppendFooter(Row{"", "", "", 7, 5, 3})
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 1, AutoMerge: true},
- {Number: 2, AutoMerge: true},
- {Number: 3, AutoMerge: true},
- {Number: 4, AutoMerge: true},
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬─────┬─────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │ RCE │
-│ │ │ │ │ │ EXE │ RUN │
-├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │ Y │
-├───┤ │ │ ├───────────┼─────┼─────┤
-│ 2 │ │ │ │ C 2 │ Y │ N │
-├───┤ │ ├───────────┼───────────┼─────┼─────┤
-│ 3 │ │ │ NS 1B │ C 3 │ N │ N │
-├───┤ ├────────┼───────────┼───────────┼─────┼─────┤
-│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │ N │
-├───┤ │ │ ├───────────┼─────┼─────┤
-│ 5 │ │ │ │ C 5 │ Y │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │ Y │
-├───┤ │ │ ├───────────┼─────┼─────┤
-│ 7 │ │ │ │ C 7 │ Y │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
-│ │ │ │ │ 7 │ 5 │ 3 │
-└───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘`)
- })
-
- t.Run("columns only with hidden columns", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE\nEXE", "RCE\nRUN"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "Y", "Y"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "N"})
- tw.AppendFooter(Row{"", "", "", 7, 5, 3})
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 1, AutoMerge: true},
- {Number: 2, AutoMerge: true},
- {Number: 3, AutoMerge: true},
- {Number: 4, Hidden: true},
- {Number: 5, Hidden: true, Align: text.AlignCenter},
- {Number: 6, Hidden: true, Align: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌─────────┬────────┬───────────┐
-│ NODE IP │ PODS │ NAMESPACE │
-├─────────┼────────┼───────────┤
-│ 1.1.1.1 │ Pod 1A │ NS 1A │
-│ │ │ │
-│ │ │ │
-│ │ ├───────────┤
-│ │ │ NS 1B │
-│ ├────────┼───────────┤
-│ │ Pod 1B │ NS 2 │
-│ │ │ │
-│ │ │ │
-├─────────┼────────┼───────────┤
-│ 2.2.2.2 │ Pod 2 │ NS 3 │
-│ │ │ │
-│ │ │ │
-├─────────┼────────┼───────────┤
-│ │ │ │
-└─────────┴────────┴───────────┘`)
- })
-
- t.Run("rows only", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE"}, rcAutoMerge)
- tw.AppendHeader(Row{"", "", "", "", "EXE", "RUN"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"}, RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignRight})
- tw.AppendFooter(Row{"", "", "", 7, 5, 3})
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬───────────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │
-│ ├─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ │ │ │ │ │ EXE │ RUN │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1B │ C 3 │ N │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 4 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 4 │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ 5 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼───────────┤
-│ 7 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 7 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ │ │ │ │ 7 │ 5 │ 3 │
-└───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘`)
- })
-
- t.Run("rows and columns", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE"}, rcAutoMerge)
- tw.AppendHeader(Row{"", "", "", "", "EXE", "RUN"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 3})
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 1, AutoMerge: true},
- {Number: 2, AutoMerge: true},
- {Number: 3, AutoMerge: true},
- {Number: 4, AutoMerge: true},
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬───────────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │
-│ │ │ │ │ ├─────┬─────┤
-│ │ │ │ │ │ EXE │ RUN │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┤ │ │ ├───────────┼─────┬─────┤
-│ 2 │ │ │ │ C 2 │ Y │ N │
-├───┤ │ ├───────────┼───────────┼─────┴─────┤
-│ 3 │ │ │ NS 1B │ C 3 │ N │
-├───┤ ├────────┼───────────┼───────────┼───────────┤
-│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │
-├───┤ │ │ ├───────────┼─────┬─────┤
-│ 5 │ │ │ │ C 5 │ Y │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├───┤ │ │ ├───────────┼───────────┤
-│ 7 │ │ │ │ C 7 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ │ │ │ │ 7 │ 5 │ 3 │
-└───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘`)
- })
-
- t.Run("rows and columns no headers or footers", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"}, RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignRight})
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
- {Number: 6, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌─────────┬────────┬───────┬─────┬───────┐
-│ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├─────────┼────────┼───────┼─────┼───┬───┤
-│ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
-├─────────┼────────┼───────┼─────┼───┼───┤
-│ 1.1.1.1 │ Pod 1A │ NS 1B │ C 3 │ N │ N │
-├─────────┼────────┼───────┼─────┼───┴───┤
-│ 1.1.1.1 │ Pod 1B │ NS 2 │ C 4 │ N │
-├─────────┼────────┼───────┼─────┼───┬───┤
-│ 1.1.1.1 │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
-├─────────┼────────┼───────┼─────┼───┴───┤
-│ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├─────────┼────────┼───────┼─────┼───────┤
-│ 2.2.2.2 │ Pod 2 │ NS 3 │ C 7 │ Y │
-└─────────┴────────┴───────┴─────┴───────┘`)
- })
-
- t.Run("rows and columns no headers or footers with auto-index", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"}, RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignRight})
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
- {Number: 6, Align: text.AlignCenter, AlignHeader: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────┬─────┬───┬───┐
-│ │ A │ B │ C │ D │ E │ F │
-├───┼─────────┼────────┼───────┼─────┼───┴───┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┼─────────┼────────┼───────┼─────┼───┬───┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
-├───┼─────────┼────────┼───────┼─────┼───┼───┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1B │ C 3 │ N │ N │
-├───┼─────────┼────────┼───────┼─────┼───┴───┤
-│ 4 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 4 │ N │
-├───┼─────────┼────────┼───────┼─────┼───┬───┤
-│ 5 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
-├───┼─────────┼────────┼───────┼─────┼───┴───┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├───┼─────────┼────────┼───────┼─────┼───────┤
-│ 7 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 7 │ Y │
-└───┴─────────┴────────┴───────┴─────┴───────┘`)
- })
-
- t.Run("rows and columns and footers", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE", "ID"}, rcAutoMerge)
- tw.AppendHeader(Row{"", "", "", "", "EXE", "RUN", ""})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y", 123}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N", 234})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N", 345})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N", 456}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N", 567})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y", 678}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y", 789}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 3}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 3}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 1, AutoMerge: true},
- {Number: 2, AutoMerge: true},
- {Number: 3, AutoMerge: true},
- {Number: 4, AutoMerge: true},
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬───────────┬─────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │ ID │
-│ │ │ │ │ ├─────┬─────┼─────┤
-│ │ │ │ │ │ EXE │ RUN │ │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┼─────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │ 123 │
-├───┤ │ │ ├───────────┼─────┬─────┼─────┤
-│ 2 │ │ │ │ C 2 │ Y │ N │ 234 │
-├───┤ │ ├───────────┼───────────┼─────┼─────┼─────┤
-│ 3 │ │ │ NS 1B │ C 3 │ N │ N │ 345 │
-├───┤ ├────────┼───────────┼───────────┼─────┴─────┼─────┤
-│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │ 456 │
-├───┤ │ │ ├───────────┼─────┬─────┼─────┤
-│ 5 │ │ │ │ C 5 │ Y │ N │ 567 │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┼─────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │ 678 │
-├───┤ │ │ ├───────────┼───────────┼─────┤
-│ 7 │ │ │ │ C 7 │ Y │ 789 │
-├───┼─────────┴────────┴───────────┼───────────┼───────────┼─────┤
-│ │ │ 7 │ 5 │ │
-│ │ │ ├─────┬─────┼─────┤
-│ │ │ │ 5 │ 3 │ │
-│ │ │ ├─────┴─────┼─────┤
-│ │ │ │ 5 │ │
-│ │ │ ├─────┬─────┼─────┤
-│ │ │ │ 5 │ 3 │ │
-│ │ │ ├─────┴─────┼─────┤
-│ │ │ │ 5 │ │
-└───┴──────────────────────────────┴───────────┴───────────┴─────┘`)
- })
-
- t.Run("samurai sudoku", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendRow(Row{"1.1\n1.1", "1.2\n1.2", "1.3\n1.3", " ", "2.1\n2.1", "2.2\n2.2", "2.3\n2.3"})
- tw.AppendRow(Row{"1.4\n1.4", "1.5\n1.5", "1.6\n1.6", " ", "2.4\n2.4", "2.5\n2.5", "2.6\n2.6"})
- tw.AppendRow(Row{"1.7\n1.7", "1.8\n1.8", "1.9\n0.1", "0.2\n0.2", "2.7\n0.3", "2.8\n2.8", "2.9\n2.9"})
- tw.AppendRow(Row{" ", " ", "0.4\n0.4", "0.5\n0.5", "0.6\n0.6", " ", " "}, rcAutoMerge)
- tw.AppendRow(Row{"3.1\n3.1", "3.2\n3.2", "3.3\n0.7", "0.8\n0.8", "4.1\n0.9", "4.2\n4.2", "4.3\n4.3"})
- tw.AppendRow(Row{"3.4\n3.4", "3.5\n3.5", "3.6\n3.6", " ", "4.4\n4.4", "4.5\n4.5", "4.6\n4.6"})
- tw.AppendRow(Row{"3.7\n3.7", "3.8\n3.8", "3.9\n3.9", " ", "4.7\n4.7", "4.8\n4.8", "4.9\n4.9"})
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 4, AutoMerge: true},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Box.PaddingLeft = ""
- tw.Style().Box.PaddingRight = ""
- tw.Style().Options.DrawBorder = true
- tw.Style().Options.SeparateRows = true
- tw.Style().Options.SeparateColumns = true
-
- compareOutput(t, tw.Render(), `
-┌───┬───┬───┬───┬───┬───┬───┐
-│1.1│1.2│1.3│ │2.1│2.2│2.3│
-│1.1│1.2│1.3│ │2.1│2.2│2.3│
-├───┼───┼───┤ ├───┼───┼───┤
-│1.4│1.5│1.6│ │2.4│2.5│2.6│
-│1.4│1.5│1.6│ │2.4│2.5│2.6│
-├───┼───┼───┼───┼───┼───┼───┤
-│1.7│1.8│1.9│0.2│2.7│2.8│2.9│
-│1.7│1.8│0.1│0.2│0.3│2.8│2.9│
-├───┴───┼───┼───┼───┼───┴───┤
-│ │0.4│0.5│0.6│ │
-│ │0.4│0.5│0.6│ │
-├───┬───┼───┼───┼───┼───┬───┤
-│3.1│3.2│3.3│0.8│4.1│4.2│4.3│
-│3.1│3.2│0.7│0.8│0.9│4.2│4.3│
-├───┼───┼───┼───┼───┼───┼───┤
-│3.4│3.5│3.6│ │4.4│4.5│4.6│
-│3.4│3.5│3.6│ │4.4│4.5│4.6│
-├───┼───┼───┤ ├───┼───┼───┤
-│3.7│3.8│3.9│ │4.7│4.8│4.9│
-│3.7│3.8│3.9│ │4.7│4.8│4.9│
-└───┴───┴───┴───┴───┴───┴───┘`)
- })
-
- t.Run("long column no merge", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6", "Column 7", "Column 8"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DRW", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DRH", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DRY"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 8, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬──────────┬──────────┬──────────┬──────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┬──────────────────────────┐
-│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
-├───┼──────────┼──────────┼──────────┼──────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
-│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
-│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
-│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
-│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
-│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRW │ 0F4EB42DRH │ 0F4EB42DRY │
-├───┼──────────┼──────────┼──────────┼──────────┼──────────────────────────┴──────────────────────────┴──────────────────────────┴──────────────────────────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┘`)
- })
-
- t.Run("long column partially merged #1", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6", "Column 7", "Column 8"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DRR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DRR"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 8, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬──────────┬──────────┬──────────┬──────────┬─────────────┬─────────────┬─────────────┬─────────────┐
-│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
-├───┼──────────┼──────────┼──────────┼──────────┼─────────────┴─────────────┼─────────────┴─────────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
-│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
-│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
-│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
-│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
-│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRR │
-├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────┴───────────────────────────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────┘`)
- })
-
- t.Run("long column partially merged #2", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6", "Column 7", "Column 8"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DRE"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 8, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────────────────────┐
-│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
-├───┼──────────┼──────────┼──────────┼──────────┼──────────┴──────────┴──────────┼──────────────────────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │ 4F8F5CB531E3D49A61CF417C │
-│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │ D133792CCFA501FD8DA53EE3 │
-│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │ 68FED20E5FE0248C3A0B64F9 │
-│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │ 8A6533CEE1DA614C3A8DDEC7 │
-│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │ 91FF05FEE6D971D57C134832 │
-│ │ │ │ │ │ 0F4EB42DR │ 0F4EB42DRE │
-├───┼──────────┼──────────┼──────────┼──────────┼────────────────────────────────┴──────────────────────────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────────────────────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────────────────────┘`)
- })
-
- t.Run("long column fully merged", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6", "Column 7", "Column 8"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR", "4F8F5CB531E3D49A61CF417CD133792CCFA501FD8DA53EE368FED20E5FE0248C3A0B64F98A6533CEE1DA614C3A8DDEC791FF05FEE6D971D57C1348320F4EB42DR"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y", "Y"}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- {Number: 8, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 24, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
-│ │ COLUMN 1 │ COLUMN 2 │ COLUMN 3 │ COLUMN 4 │ COLUMN 5 │ COLUMN 6 │ COLUMN 7 │ COLUMN 8 │
-├───┼──────────┼──────────┼──────────┼──────────┼──────────┴──────────┴──────────┴──────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ 4F8F5CB531E3D49A61CF417C │
-│ │ │ │ │ │ D133792CCFA501FD8DA53EE3 │
-│ │ │ │ │ │ 68FED20E5FE0248C3A0B64F9 │
-│ │ │ │ │ │ 8A6533CEE1DA614C3A8DDEC7 │
-│ │ │ │ │ │ 91FF05FEE6D971D57C134832 │
-│ │ │ │ │ │ 0F4EB42DR │
-├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-├───┼──────────┼──────────┼──────────┼──────────┼───────────────────────────────────────────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-└───┴──────────┴──────────┴──────────┴──────────┴───────────────────────────────────────────┘`)
- })
-
- t.Run("headers too", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE", "RCE"}, rcAutoMerge)
- tw.AppendHeader(Row{"", "", "", "", "EXE EXE EXE", "EXE EXE EXE"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"})
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "N"})
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 3}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 6, 4, 4}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬───────────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE │
-│ ├─────────┴────────┴───────────┴───────────┼───────────┤
-│ │ │ EXE EXE │
-│ │ │ EXE │
-├───┼─────────┬────────┬───────────┬───────────┼───────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┼─────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1B │ C 3 │ N │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 4 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 4 │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┬─────┤
-│ 5 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 5 │ Y │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────┴─────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼───────────┤
-│ 7 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 7 │ Y │
-├───┼─────────┴────────┴───────────┼───────────┼─────┬─────┤
-│ │ │ 7 │ 5 │ 3 │
-│ ├──────────────────────────────┼───────────┼─────┴─────┤
-│ │ │ 6 │ 4 │
-└───┴──────────────────────────────┴───────────┴───────────┘`)
- })
-
- t.Run("headers and footers too", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE1", "RCE2"}, rcAutoMerge)
- tw.AppendHeader(Row{"", "", "", "", "EXE EXE EXE", "EXE EXE EXE"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y"}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 5}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 6, 4, 4}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬──────┬──────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE1 │ RCE2 │
-│ ├─────────┴────────┴───────────┴───────────┼──────┴──────┤
-│ │ │ EXE EXE │
-│ │ │ EXE │
-├───┼─────────┬────────┬───────────┬───────────┼─────────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1B │ C 3 │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
-│ 4 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 4 │ N │
-├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
-│ 5 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 5 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼─────────────┤
-│ 7 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 7 │ Y │
-├───┼─────────┴────────┴───────────┼───────────┼─────────────┤
-│ │ │ 7 │ 5 │
-│ ├──────────────────────────────┼───────────┼─────────────┤
-│ │ │ 6 │ 4 │
-└───┴──────────────────────────────┴───────────┴─────────────┘`)
- })
-
- t.Run("long header column", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"Node IP", "Pods", "Namespace", "Container", "RCE1", "RCE2", "RCE3"}, rcAutoMerge)
- tw.AppendHeader(Row{"", "", "", "", "EXE EXE EXE", "EXE EXE EXE", "EXE EXE EXE"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 7, 5, 5, 5}, rcAutoMerge)
- tw.AppendFooter(Row{"", "", "", 6, 4, 4, 3}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬─────────┬────────┬───────────┬───────────┬──────┬──────┬──────┐
-│ │ NODE IP │ PODS │ NAMESPACE │ CONTAINER │ RCE1 │ RCE2 │ RCE3 │
-│ ├─────────┴────────┴───────────┴───────────┼──────┴──────┴──────┤
-│ │ │ EXE EXE │
-│ │ │ EXE │
-├───┼─────────┬────────┬───────────┬───────────┼────────────────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
-│ 2 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 2 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
-│ 3 │ 1.1.1.1 │ Pod 1A │ NS 1B │ C 3 │ N │
-├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
-│ 4 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 4 │ N │
-├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
-│ 5 │ 1.1.1.1 │ Pod 1B │ NS 2 │ C 5 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ Y │
-├───┼─────────┼────────┼───────────┼───────────┼────────────────────┤
-│ 7 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 7 │ Y │
-├───┼─────────┴────────┴───────────┼───────────┼────────────────────┤
-│ │ │ 7 │ 5 │
-│ ├──────────────────────────────┼───────────┼─────────────┬──────┤
-│ │ │ 6 │ 4 │ 3 │
-└───┴──────────────────────────────┴───────────┴─────────────┴──────┘`)
- })
-
- t.Run("everything", func(t *testing.T) {
- tw := NewWriter()
- tw.AppendHeader(Row{"COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS", "COLUMNS"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 1", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1A", "C 2", "Y", "Y", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1A", "NS 1B", "C 3", "N", "N", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 4", "N", "Y", "N"}, rcAutoMerge)
- tw.AppendRow(Row{"1.1.1.1", "Pod 1B", "NS 2", "C 5", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 6", "N", "Y", "Y"}, rcAutoMerge)
- tw.AppendRow(Row{"2.2.2.2", "Pod 2", "NS 3", "C 7", "Y", "Y", "Y"}, rcAutoMerge)
- tw.AppendFooter(Row{"foo", "foo", "foo", "foo", "bar", "bar", "bar"}, rcAutoMerge)
- tw.AppendFooter(Row{7, 7, 7, 7, 7, 7, 7}, rcAutoMerge)
- tw.SetAutoIndex(true)
- tw.SetColumnConfigs([]ColumnConfig{
- {Number: 1, AutoMerge: true},
- {Number: 2, AutoMerge: true},
- {Number: 3, AutoMerge: true},
- {Number: 5, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- {Number: 6, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- {Number: 7, Align: text.AlignCenter, AlignFooter: text.AlignCenter, AlignHeader: text.AlignCenter, WidthMax: 7, WidthMaxEnforcer: text.WrapHard},
- })
- tw.SetStyle(StyleLight)
- tw.Style().Options.SeparateRows = true
-
- compareOutput(t, tw.Render(), `
-┌───┬───────────────────────────────────────────────────┐
-│ │ COLUMNS │
-├───┼─────────┬─────────┬─────────┬─────────┬───────────┤
-│ 1 │ 1.1.1.1 │ Pod 1A │ NS 1A │ C 1 │ Y │
-├───┤ │ │ ├─────────┼───────┬───┤
-│ 2 │ │ │ │ C 2 │ Y │ N │
-├───┤ │ ├─────────┼─────────┼───────┴───┤
-│ 3 │ │ │ NS 1B │ C 3 │ N │
-├───┤ ├─────────┼─────────┼─────────┼───┬───┬───┤
-│ 4 │ │ Pod 1B │ NS 2 │ C 4 │ N │ Y │ N │
-├───┤ │ │ ├─────────┼───┴───┴───┤
-│ 5 │ │ │ │ C 5 │ Y │
-├───┼─────────┼─────────┼─────────┼─────────┼───┬───────┤
-│ 6 │ 2.2.2.2 │ Pod 2 │ NS 3 │ C 6 │ N │ Y │
-├───┤ │ │ ├─────────┼───┴───────┤
-│ 7 │ │ │ │ C 7 │ Y │
-├───┼─────────┴─────────┴─────────┴─────────┼───────────┤
-│ │ FOO │ BAR │
-│ ├───────────────────────────────────────┴───────────┤
-│ │ 7 │
-└───┴───────────────────────────────────────────────────┘`)
- })
-}
-
func TestTable_Render_BorderAndSeparators(t *testing.T) {
table := Table{}
table.AppendHeader(testHeader)
diff --git a/table/table.go b/table/table.go
index 1801c1c..6b7c906 100644
--- a/table/table.go
+++ b/table/table.go
@@ -164,14 +164,15 @@ func (t *Table) AppendRows(rows []Row, config ...RowConfig) {
// append is a separator, it will not be rendered in addition to the usual table
// separator.
//
-//******************************************************************************
+// ******************************************************************************
// Please note the following caveats:
-// 1. SetPageSize(): this may end up creating consecutive separator rows near
-// the end of a page or at the beginning of a page
-// 2. SortBy(): since SortBy could inherently alter the ordering of rows, the
-// separators may not appear after the row it was originally intended to
-// follow
-//******************************************************************************
+// 1. SetPageSize(): this may end up creating consecutive separator rows near
+// the end of a page or at the beginning of a page
+// 2. SortBy(): since SortBy could inherently alter the ordering of rows, the
+// separators may not appear after the row it was originally intended to
+// follow
+//
+// ******************************************************************************
func (t *Table) AppendSeparator() {
if t.separators == nil {
t.separators = make(map[int]bool)
@@ -439,12 +440,9 @@ func (t *Table) getColumnSeparator(row rowStr, colIdx int, hint renderHint) stri
separator = t.style.Box.BottomSeparator
}
} else {
- separator = t.getColumnSeparatorNonBorder(
- t.shouldMergeCellsHorizontallyAbove(row, colIdx, hint),
- t.shouldMergeCellsHorizontallyBelow(row, colIdx, hint),
- colIdx,
- hint,
- )
+ sm1 := t.shouldMergeCellsHorizontallyAbove(row, colIdx, hint)
+ sm2 := t.shouldMergeCellsHorizontallyBelow(row, colIdx, hint)
+ separator = t.getColumnSeparatorNonBorder(sm1, sm2, colIdx, hint)
}
}
return separator
@@ -721,7 +719,10 @@ func (t *Table) shouldMergeCellsHorizontallyBelow(row rowStr, colIdx int, hint r
var rowConfig RowConfig
if hint.isSeparatorRow {
- if hint.isHeaderRow && hint.rowNumber == 0 {
+ if hint.isRegularRow() {
+ rowConfig = t.getRowConfig(renderHint{rowNumber: hint.rowNumber + 1})
+ row = t.getRow(hint.rowNumber, renderHint{})
+ } else if hint.isHeaderRow && hint.rowNumber == 0 {
rowConfig = t.getRowConfig(renderHint{isHeaderRow: true, rowNumber: 1})
row = t.getRow(0, hint)
} else if hint.isHeaderRow && hint.isLastRow {
@@ -733,9 +734,6 @@ func (t *Table) shouldMergeCellsHorizontallyBelow(row rowStr, colIdx int, hint r
} else if hint.isFooterRow && hint.rowNumber >= 0 {
rowConfig = t.getRowConfig(renderHint{isFooterRow: true, rowNumber: 1})
row = t.getRow(hint.rowNumber, renderHint{isFooterRow: true})
- } else if hint.isRegularRow() {
- rowConfig = t.getRowConfig(renderHint{rowNumber: hint.rowNumber + 1})
- row = t.getRow(hint.rowNumber, renderHint{})
}
}
@@ -751,13 +749,13 @@ func (t *Table) shouldMergeCellsVertically(colIdx int, hint renderHint) bool {
rowPrev := t.getRow(hint.rowNumber-1, hint)
rowNext := t.getRow(hint.rowNumber, hint)
if colIdx < len(rowPrev) && colIdx < len(rowNext) {
- return rowPrev[colIdx] == rowNext[colIdx] || rowNext[colIdx] == ""
+ return rowPrev[colIdx] == rowNext[colIdx]
}
} else {
rowPrev := t.getRow(hint.rowNumber-2, hint)
rowCurr := t.getRow(hint.rowNumber-1, hint)
if colIdx < len(rowPrev) && colIdx < len(rowCurr) {
- return rowPrev[colIdx] == rowCurr[colIdx] || rowCurr[colIdx] == ""
+ return rowPrev[colIdx] == rowCurr[colIdx]
}
}
}
diff --git a/text/align.go b/text/align.go
index 764a1f8..7a6d92c 100644
--- a/text/align.go
+++ b/text/align.go
@@ -20,11 +20,11 @@ const (
)
// Apply aligns the text as directed. For ex.:
-// * AlignDefault.Apply("Jon Snow", 12) returns "Jon Snow "
-// * AlignLeft.Apply("Jon Snow", 12) returns "Jon Snow "
-// * AlignCenter.Apply("Jon Snow", 12) returns " Jon Snow "
-// * AlignJustify.Apply("Jon Snow", 12) returns "Jon Snow"
-// * AlignRight.Apply("Jon Snow", 12) returns " Jon Snow"
+// - AlignDefault.Apply("Jon Snow", 12) returns "Jon Snow "
+// - AlignLeft.Apply("Jon Snow", 12) returns "Jon Snow "
+// - AlignCenter.Apply("Jon Snow", 12) returns " Jon Snow "
+// - AlignJustify.Apply("Jon Snow", 12) returns "Jon Snow"
+// - AlignRight.Apply("Jon Snow", 12) returns " Jon Snow"
func (a Align) Apply(text string, maxLength int) string {
text = a.trimString(text)
sLen := utf8.RuneCountInString(text)
diff --git a/text/ansi.go b/text/ansi.go
index aaf5b30..6a396b1 100644
--- a/text/ansi.go
+++ b/text/ansi.go
@@ -8,7 +8,8 @@ var ANSICodesSupported = areANSICodesSupported()
// Escape encodes the string with the ANSI Escape Sequence.
// For ex.:
-// Escape("Ghost", "") == "Ghost"
+//
+// Escape("Ghost", "") == "Ghost"
// Escape("Ghost", "\x1b[91m") == "\x1b[91mGhost\x1b[0m"
// Escape("\x1b[94mGhost\x1b[0mLady", "\x1b[91m") == "\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m"
// Escape("Nymeria\x1b[94mGhost\x1b[0mLady", "\x1b[91m") == "\x1b[91mNymeria\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m"
@@ -30,7 +31,8 @@ func Escape(str string, escapeSeq string) string {
// StripEscape strips all ANSI Escape Sequence from the string.
// For ex.:
-// StripEscape("Ghost") == "Ghost"
+//
+// StripEscape("Ghost") == "Ghost"
// StripEscape("\x1b[91mGhost\x1b[0m") == "Ghost"
// StripEscape("\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m") == "GhostLady"
// StripEscape("\x1b[91mNymeria\x1b[94mGhost\x1b[0m\x1b[91mLady\x1b[0m") == "NymeriaGhostLady"
diff --git a/text/string.go b/text/string.go
index 6a21dda..9f5c9e8 100644
--- a/text/string.go
+++ b/text/string.go
@@ -13,11 +13,12 @@ var (
)
// InsertEveryN inserts the rune every N characters in the string. For ex.:
-// InsertEveryN("Ghost", '-', 1) == "G-h-o-s-t"
-// InsertEveryN("Ghost", '-', 2) == "Gh-os-t"
-// InsertEveryN("Ghost", '-', 3) == "Gho-st"
-// InsertEveryN("Ghost", '-', 4) == "Ghos-t"
-// InsertEveryN("Ghost", '-', 5) == "Ghost"
+//
+// InsertEveryN("Ghost", '-', 1) == "G-h-o-s-t"
+// InsertEveryN("Ghost", '-', 2) == "Gh-os-t"
+// InsertEveryN("Ghost", '-', 3) == "Gho-st"
+// InsertEveryN("Ghost", '-', 4) == "Ghos-t"
+// InsertEveryN("Ghost", '-', 5) == "Ghost"
func InsertEveryN(str string, runeToInsert rune, n int) string {
if n <= 0 {
return str
@@ -47,7 +48,8 @@ func InsertEveryN(str string, runeToInsert rune, n int) string {
// LongestLineLen returns the length of the longest "line" within the
// argument string. For ex.:
-// LongestLineLen("Ghost!\nCome back here!\nRight now!") == 15
+//
+// LongestLineLen("Ghost!\nCome back here!\nRight now!") == 15
func LongestLineLen(str string) int {
maxLength, currLength, eSeq := 0, 0, escSeq{}
for _, c := range str {
@@ -91,11 +93,12 @@ func OverrideRuneWidthEastAsianWidth(val bool) {
// Pad pads the given string with as many characters as needed to make it as
// long as specified (maxLen). This function does not count escape sequences
// while calculating length of the string. Ex.:
-// Pad("Ghost", 0, ' ') == "Ghost"
-// Pad("Ghost", 3, ' ') == "Ghost"
-// Pad("Ghost", 5, ' ') == "Ghost"
-// Pad("Ghost", 7, ' ') == "Ghost "
-// Pad("Ghost", 10, '.') == "Ghost....."
+//
+// Pad("Ghost", 0, ' ') == "Ghost"
+// Pad("Ghost", 3, ' ') == "Ghost"
+// Pad("Ghost", 5, ' ') == "Ghost"
+// Pad("Ghost", 7, ' ') == "Ghost "
+// Pad("Ghost", 10, '.') == "Ghost....."
func Pad(str string, maxLen int, paddingChar rune) string {
strLen := RuneWidthWithoutEscSequences(str)
if strLen < maxLen {
@@ -106,11 +109,12 @@ func Pad(str string, maxLen int, paddingChar rune) string {
// RepeatAndTrim repeats the given string until it is as long as maxRunes.
// For ex.:
-// RepeatAndTrim("", 5) == ""
-// RepeatAndTrim("Ghost", 0) == ""
-// RepeatAndTrim("Ghost", 5) == "Ghost"
-// RepeatAndTrim("Ghost", 7) == "GhostGh"
-// RepeatAndTrim("Ghost", 10) == "GhostGhost"
+//
+// RepeatAndTrim("", 5) == ""
+// RepeatAndTrim("Ghost", 0) == ""
+// RepeatAndTrim("Ghost", 5) == "Ghost"
+// RepeatAndTrim("Ghost", 7) == "GhostGh"
+// RepeatAndTrim("Ghost", 10) == "GhostGhost"
func RepeatAndTrim(str string, maxRunes int) string {
if str == "" || maxRunes == 0 {
return ""
@@ -123,10 +127,12 @@ func RepeatAndTrim(str string, maxRunes int) string {
// RuneCount is similar to utf8.RuneCountInString, except for the fact that it
// ignores escape sequences while counting. For ex.:
-// RuneCount("") == 0
-// RuneCount("Ghost") == 5
-// RuneCount("\x1b[33mGhost\x1b[0m") == 5
-// RuneCount("\x1b[33mGhost\x1b[0") == 5
+//
+// RuneCount("") == 0
+// RuneCount("Ghost") == 5
+// RuneCount("\x1b[33mGhost\x1b[0m") == 5
+// RuneCount("\x1b[33mGhost\x1b[0") == 5
+//
// Deprecated: in favor of RuneWidthWithoutEscSequences
func RuneCount(str string) int {
return RuneWidthWithoutEscSequences(str)
@@ -135,21 +141,23 @@ func RuneCount(str string) int {
// RuneWidth returns the mostly accurate character-width of the rune. This is
// not 100% accurate as the character width is usually dependent on the
// typeface (font) used in the console/terminal. For ex.:
-// RuneWidth('A') == 1
-// RuneWidth('ツ') == 2
-// RuneWidth('⊙') == 1
-// RuneWidth('︿') == 2
-// RuneWidth(0x27) == 0
+//
+// RuneWidth('A') == 1
+// RuneWidth('ツ') == 2
+// RuneWidth('⊙') == 1
+// RuneWidth('︿') == 2
+// RuneWidth(0x27) == 0
func RuneWidth(r rune) int {
return rwCondition.RuneWidth(r)
}
// RuneWidthWithoutEscSequences is similar to RuneWidth, except for the fact
// that it ignores escape sequences while counting. For ex.:
-// RuneWidthWithoutEscSequences("") == 0
-// RuneWidthWithoutEscSequences("Ghost") == 5
-// RuneWidthWithoutEscSequences("\x1b[33mGhost\x1b[0m") == 5
-// RuneWidthWithoutEscSequences("\x1b[33mGhost\x1b[0") == 5
+//
+// RuneWidthWithoutEscSequences("") == 0
+// RuneWidthWithoutEscSequences("Ghost") == 5
+// RuneWidthWithoutEscSequences("\x1b[33mGhost\x1b[0m") == 5
+// RuneWidthWithoutEscSequences("\x1b[33mGhost\x1b[0") == 5
func RuneWidthWithoutEscSequences(str string) int {
count, eSeq := 0, escSeq{}
for _, c := range str {
@@ -166,12 +174,13 @@ func RuneWidthWithoutEscSequences(str string) int {
}
// Snip returns the given string with a fixed length. For ex.:
-// Snip("Ghost", 0, "~") == "Ghost"
-// Snip("Ghost", 1, "~") == "~"
-// Snip("Ghost", 3, "~") == "Gh~"
-// Snip("Ghost", 5, "~") == "Ghost"
-// Snip("Ghost", 7, "~") == "Ghost "
-// Snip("\x1b[33mGhost\x1b[0m", 7, "~") == "\x1b[33mGhost\x1b[0m "
+//
+// Snip("Ghost", 0, "~") == "Ghost"
+// Snip("Ghost", 1, "~") == "~"
+// Snip("Ghost", 3, "~") == "Gh~"
+// Snip("Ghost", 5, "~") == "Ghost"
+// Snip("Ghost", 7, "~") == "Ghost "
+// Snip("\x1b[33mGhost\x1b[0m", 7, "~") == "\x1b[33mGhost\x1b[0m "
func Snip(str string, length int, snipIndicator string) string {
if length > 0 {
lenStr := RuneWidthWithoutEscSequences(str)
@@ -185,10 +194,11 @@ func Snip(str string, length int, snipIndicator string) string {
// Trim trims a string to the given length while ignoring escape sequences. For
// ex.:
-// Trim("Ghost", 3) == "Gho"
-// Trim("Ghost", 6) == "Ghost"
-// Trim("\x1b[33mGhost\x1b[0m", 3) == "\x1b[33mGho\x1b[0m"
-// Trim("\x1b[33mGhost\x1b[0m", 6) == "\x1b[33mGhost\x1b[0m"
+//
+// Trim("Ghost", 3) == "Gho"
+// Trim("Ghost", 6) == "Ghost"
+// Trim("\x1b[33mGhost\x1b[0m", 3) == "\x1b[33mGho\x1b[0m"
+// Trim("\x1b[33mGhost\x1b[0m", 6) == "\x1b[33mGhost\x1b[0m"
func Trim(str string, maxLen int) string {
if maxLen <= 0 {
return ""
diff --git a/text/transformer.go b/text/transformer.go
index 4551436..193a721 100644
--- a/text/transformer.go
+++ b/text/transformer.go
@@ -37,9 +37,9 @@ var (
type Transformer func(val interface{}) string
// NewNumberTransformer returns a number Transformer that:
-// * transforms the number as directed by 'format' (ex.: %.2f)
-// * colors negative values Red
-// * colors positive values Green
+// - transforms the number as directed by 'format' (ex.: %.2f)
+// - colors negative values Red
+// - colors positive values Green
func NewNumberTransformer(format string) Transformer {
return func(val interface{}) string {
if valStr := transformInt(format, val); valStr != "" {
diff --git a/text/valign.go b/text/valign.go
index 76b1943..f1a75e9 100644
--- a/text/valign.go
+++ b/text/valign.go
@@ -14,12 +14,12 @@ const (
)
// Apply aligns the lines vertically. For ex.:
-// * VAlignTop.Apply({"Game", "Of", "Thrones"}, 5)
-// returns {"Game", "Of", "Thrones", "", ""}
-// * VAlignMiddle.Apply({"Game", "Of", "Thrones"}, 5)
-// returns {"", "Game", "Of", "Thrones", ""}
-// * VAlignBottom.Apply({"Game", "Of", "Thrones"}, 5)
-// returns {"", "", "Game", "Of", "Thrones"}
+// - VAlignTop.Apply({"Game", "Of", "Thrones"}, 5)
+// returns {"Game", "Of", "Thrones", "", ""}
+// - VAlignMiddle.Apply({"Game", "Of", "Thrones"}, 5)
+// returns {"", "Game", "Of", "Thrones", ""}
+// - VAlignBottom.Apply({"Game", "Of", "Thrones"}, 5)
+// returns {"", "", "Game", "Of", "Thrones"}
func (va VAlign) Apply(lines []string, maxLines int) []string {
if len(lines) == maxLines {
return lines
@@ -42,12 +42,12 @@ func (va VAlign) Apply(lines []string, maxLines int) []string {
}
// ApplyStr aligns the string (of 1 or more lines) vertically. For ex.:
-// * VAlignTop.ApplyStr("Game\nOf\nThrones", 5)
-// returns {"Game", "Of", "Thrones", "", ""}
-// * VAlignMiddle.ApplyStr("Game\nOf\nThrones", 5)
-// returns {"", "Game", "Of", "Thrones", ""}
-// * VAlignBottom.ApplyStr("Game\nOf\nThrones", 5)
-// returns {"", "", "Game", "Of", "Thrones"}
+// - VAlignTop.ApplyStr("Game\nOf\nThrones", 5)
+// returns {"Game", "Of", "Thrones", "", ""}
+// - VAlignMiddle.ApplyStr("Game\nOf\nThrones", 5)
+// returns {"", "Game", "Of", "Thrones", ""}
+// - VAlignBottom.ApplyStr("Game\nOf\nThrones", 5)
+// returns {"", "", "Game", "Of", "Thrones"}
func (va VAlign) ApplyStr(text string, maxLines int) []string {
return va.Apply(strings.Split(text, "\n"), maxLines)
}