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
|
package game
import (
"fmt"
"strings"
)
type tableGlyphs struct {
topLeft, topSep, topRight rune
side, colSep rune
sepLeft, sepCross, sepRight rune
botLeft, botSep, botRight rune
fillH, fillHSep rune
}
func tableGlyphSet(unicode bool) tableGlyphs {
if unicode {
return tableGlyphs{
topLeft: '╔', topSep: '╤', topRight: '╗', side: '║', colSep: '│',
sepLeft: '╟', sepCross: '┼', sepRight: '╢',
botLeft: '╚', botSep: '╧', botRight: '╝', fillH: '═', fillHSep: '─',
}
}
return tableGlyphs{
topLeft: '+', topSep: '+', topRight: '+', side: '|', colSep: '|',
sepLeft: '+', sepCross: '+', sepRight: '+',
botLeft: '+', botSep: '+', botRight: '+', fillH: '-', fillHSep: '-',
}
}
type Table struct {
Columns []string
Rows [][]string
}
func (t *Table) Render(unicode bool) []string {
g := tableGlyphSet(unicode)
nCols := len(t.Columns)
if nCols == 0 {
return nil
}
colWidths := make([]int, nCols)
for i, h := range t.Columns {
colWidths[i] = len(h)
}
for _, row := range t.Rows {
for i, cell := range row {
if i >= nCols {
break
}
if len(cell) > colWidths[i] {
colWidths[i] = len(cell)
}
}
}
makeSep := func(left, cross, right rune, fill rune) string {
var b strings.Builder
b.WriteRune(left)
for i := 0; i < nCols; i++ {
if i > 0 {
b.WriteRune(cross)
}
b.WriteString(strings.Repeat(string(fill), colWidths[i]+2))
}
b.WriteRune(right)
return b.String()
}
makeRow := func(cells []string) string {
var b strings.Builder
b.WriteRune(g.side)
for i := 0; i < nCols; i++ {
if i > 0 {
b.WriteRune(g.colSep)
}
cell := ""
if i < len(cells) {
cell = cells[i]
}
b.WriteString(fmt.Sprintf(" %-*s ", colWidths[i], cell))
}
b.WriteRune(g.side)
return b.String()
}
var out []string
out = append(out, makeSep(g.topLeft, g.topSep, g.topRight, g.fillH))
out = append(out, makeRow(t.Columns))
out = append(out, makeSep(g.sepLeft, g.sepCross, g.sepRight, g.fillHSep))
for _, row := range t.Rows {
out = append(out, makeRow(row))
}
out = append(out, makeSep(g.botLeft, g.botSep, g.botRight, g.fillH))
return out
}
|