table header

This commit is contained in:
Timon Ringwald 2022-08-25 16:55:19 +02:00
parent a5076cac48
commit 708c1e5d7a
3 changed files with 79 additions and 31 deletions

View File

@ -6,7 +6,6 @@ import (
"git.milar.in/milarin/gmath" "git.milar.in/milarin/gmath"
"git.milar.in/milarin/slices" "git.milar.in/milarin/slices"
"github.com/fatih/color"
) )
type Table struct { type Table struct {
@ -64,28 +63,30 @@ func (t *Table) AddRow(row ...interface{}) {
func (t *Table) String() string { func (t *Table) String() string {
b := new(strings.Builder) b := new(strings.Builder)
b.WriteRune('') b.WriteRune('')
for i, colwidth := range t.colwidth { for i, colwidth := range t.colwidth {
b.WriteString(strings.Repeat("", colwidth)) b.WriteString(strings.Repeat("", colwidth))
if i < len(t.colwidth)-1 { if i < len(t.colwidth)-1 {
b.WriteRune('') b.WriteRune('')
} }
} }
b.WriteRune('') b.WriteRune('')
b.WriteRune('\n') b.WriteRune('\n')
bold := color.New(color.Bold) t.printRow(b, t.head, t.headheight)
t.printRow(b, bold.Sprint, t.head, t.headheight)
if len(t.data) > 0 { b.WriteRune('┣')
t.addNextCellLine(b) for i, colwidth := range t.colwidth {
} else { b.WriteString(strings.Repeat("━", colwidth))
t.addLastCellLine(b) if i < len(t.colwidth)-1 {
return b.String() b.WriteRune('┿')
} }
}
b.WriteRune('┫')
b.WriteRune('\n')
for i, row := range t.data { for i, row := range t.data {
t.printRow(b, fmt.Sprint, row, t.rowheight[i]) t.printRow(b, row, t.rowheight[i])
if t.rowSep && i < len(t.data)-1 { if t.rowSep && i < len(t.data)-1 {
t.addNextCellLine(b) t.addNextCellLine(b)
} }
@ -96,9 +97,9 @@ func (t *Table) String() string {
return b.String() return b.String()
} }
func (t *Table) printRow(b *strings.Builder, printFunc func(...interface{}) string, rowData [][]string, rowHeight int) { func (t *Table) printRow(b *strings.Builder, rowData [][]string, rowHeight int) {
for lineIndex := 0; lineIndex < rowHeight; lineIndex++ { for lineIndex := 0; lineIndex < rowHeight; lineIndex++ {
b.WriteRune('') b.WriteRune('')
for colIndex := 0; colIndex < t.maxcols; colIndex++ { for colIndex := 0; colIndex < t.maxcols; colIndex++ {
line := "" line := ""
@ -109,33 +110,34 @@ func (t *Table) printRow(b *strings.Builder, printFunc func(...interface{}) stri
} }
} }
b.WriteString(printFunc(padStringRight(line, ' ', t.colwidth[colIndex]))) b.WriteString(fmt.Sprint(padStringRight(line, ' ', t.colwidth[colIndex])))
if colIndex < t.maxcols-1 {
b.WriteRune('│') b.WriteRune('│')
} }
b.WriteRune('\n') }
b.WriteString("┃\n")
} }
} }
func (t *Table) addNextCellLine(b *strings.Builder) { func (t *Table) addNextCellLine(b *strings.Builder) {
b.WriteRune('') b.WriteRune('')
for i, colwidth := range t.colwidth { for i, colwidth := range t.colwidth {
b.WriteString(strings.Repeat("─", colwidth)) b.WriteString(strings.Repeat("─", colwidth))
if i < len(t.colwidth)-1 { if i < len(t.colwidth)-1 {
b.WriteRune('┼') b.WriteRune('┼')
} }
} }
b.WriteRune('') b.WriteRune('')
b.WriteRune('\n') b.WriteRune('\n')
} }
func (t *Table) addLastCellLine(b *strings.Builder) { func (t *Table) addLastCellLine(b *strings.Builder) {
b.WriteRune('') b.WriteRune('')
for i, colwidth := range t.colwidth { for i, colwidth := range t.colwidth {
b.WriteString(strings.Repeat("", colwidth)) b.WriteString(strings.Repeat("", colwidth))
if i < len(t.colwidth)-1 { if i < len(t.colwidth)-1 {
b.WriteRune('') b.WriteRune('')
} }
} }
b.WriteRune('┘') b.WriteString("┛\n")
b.WriteRune('\n')
} }

35
table_header.go Normal file
View File

@ -0,0 +1,35 @@
package tprint
import (
"strings"
"git.milar.in/milarin/slices"
)
// TODO FormatHeaderTable is a quick hack
// a better solution would be to support nested tables.
// in that case, a header table is just a table with a singe col, single header row and single data row
func FormatHeaderTable(header string, table *Table) string {
b := new(strings.Builder)
tab := table.String()
splits := strings.Split(tab, "\n")
tabwidth := strLen(splits[0])
b.WriteRune('┏')
b.WriteString(strings.Repeat("━", tabwidth-2))
b.WriteString("┓\n┃")
b.WriteString(padStringCenter(header, ' ', tabwidth-2))
b.WriteString("┃\n")
b.WriteRune('┣')
b.WriteString(splits[0][3 : len(splits[0])-3])
b.WriteString("┫\n")
slices.Each(splits[1:], func(s string) {
b.WriteString(s)
b.WriteRune('\n')
})
return b.String()
}

View File

@ -1,6 +1,7 @@
package tprint package tprint
import ( import (
"fmt"
"strings" "strings"
"unicode" "unicode"
) )
@ -23,16 +24,15 @@ func strLen(str string) int {
l := 0 l := 0
runes := []rune(str) runes := []rune(str)
colored := false
for i := 0; i < len(runes); i++ { for i := 0; i < len(runes); i++ {
// skip control sequences
if unicode.IsControl(runes[i]) { if unicode.IsControl(runes[i]) {
if colored { for j := i; j < len(runes)-1 && runes[j] != 'm'; j++ {
i += 3 i = j
} else {
i += 4
} }
colored = !colored i++
continue continue
} }
@ -46,3 +46,14 @@ func padStringRight(str string, pad rune, length int) string {
padding := length - strLen(str) padding := length - strLen(str)
return str + strings.Repeat(string(pad), padding) return str + strings.Repeat(string(pad), padding)
} }
func padStringLeft(str string, pad rune, length int) string {
padding := length - strLen(str)
return strings.Repeat(string(pad), padding) + str
}
func padStringCenter(str string, pad rune, length int) string {
l := strLen(str)
fmt.Println(l, length)
return padStringLeft(padStringRight(str, pad, (length-l)/2+l), pad, length)
}