aboutsummaryrefslogtreecommitdiff
path: root/internal/game/table.go
blob: e3dad97b6bec800b5b212fc7161e5261750b4620 (plain)
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
}