diff options
Diffstat (limited to 'internal/game/table.go')
| -rw-r--r-- | internal/game/table.go | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/internal/game/table.go b/internal/game/table.go new file mode 100644 index 0000000..e3dad97 --- /dev/null +++ b/internal/game/table.go @@ -0,0 +1,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 +} |
