/
printtable.go
107 lines (94 loc) · 2 KB
/
printtable.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package util
import "strings"
// PrintTable is a table for printing with fixed column width and padding
type PrintTable struct {
Columns []PrintColumn
NumRows int
}
// PrintColumn is a column in PrintTable
type PrintColumn struct {
Items []string
Width int
}
//------------//
// PrintTable //
//------------//
// AddRow adds a row of headers/values to the table
func (t *PrintTable) AddRow(items ...string) *PrintTable {
if t.Columns == nil {
t.Columns = make([]PrintColumn, len(items))
for i := range t.Columns {
c := &t.Columns[i]
c.Items = []string{}
c.Width = 0
}
} else if len(items) != len(t.Columns) {
panic("PrintTable columns mismatch")
}
for i := range t.Columns {
c := &t.Columns[i]
s := items[i]
c.Items = append(c.Items, s)
c.Width = max(len(s), c.Width)
}
t.NumRows++
return t
}
// RecalcWidth can be called to recalculate the columns width after manual updates are made
func (t *PrintTable) RecalcWidth() *PrintTable {
for i := range t.Columns {
t.Columns[i].RecalcWidth()
}
return t
}
func (t *PrintTable) String() string {
res := ""
for r := 0; r < t.NumRows; r++ {
for i := range t.Columns {
c := &t.Columns[i]
res += c.Pad(c.Items[r])
}
res += "\n"
}
return res
}
//-------------//
// PrintColumn //
//-------------//
// Pad adds padding the provided string to make it print nicely as a table cell
func (c *PrintColumn) Pad(s string) string {
width := min(len(s), c.Width)
pad := strings.Repeat(" ", c.Width-width+3)
return s[0:width] + pad
}
// RecalcWidth can be called to recalculate the column width after manual updates are made
func (c *PrintColumn) RecalcWidth() {
c.Width = maxLen(c.Items...)
}
func min(items ...int) int {
r := items[0]
for _, x := range items {
if r > x {
r = x
}
}
return r
}
func max(items ...int) int {
r := items[0]
for _, x := range items {
if r < x {
r = x
}
}
return r
}
func maxLen(items ...string) int {
r := len(items[0])
for _, x := range items {
if r < len(x) {
r = len(x)
}
}
return r
}