diff --git a/table.go b/table.go index f08d86d..899cac1 100644 --- a/table.go +++ b/table.go @@ -6,7 +6,6 @@ import ( "git.milar.in/milarin/gmath" "git.milar.in/milarin/slices" - "github.com/fatih/color" ) type Table struct { @@ -64,28 +63,30 @@ func (t *Table) AddRow(row ...interface{}) { func (t *Table) String() string { b := new(strings.Builder) - b.WriteRune('┌') + b.WriteRune('┏') for i, colwidth := range t.colwidth { - b.WriteString(strings.Repeat("─", colwidth)) + b.WriteString(strings.Repeat("━", colwidth)) if i < len(t.colwidth)-1 { - b.WriteRune('┬') + b.WriteRune('┯') } } - b.WriteRune('┐') + b.WriteRune('┓') b.WriteRune('\n') - bold := color.New(color.Bold) - t.printRow(b, bold.Sprint, t.head, t.headheight) + t.printRow(b, t.head, t.headheight) - if len(t.data) > 0 { - t.addNextCellLine(b) - } else { - t.addLastCellLine(b) - return b.String() + b.WriteRune('┣') + for i, colwidth := range t.colwidth { + b.WriteString(strings.Repeat("━", colwidth)) + if i < len(t.colwidth)-1 { + b.WriteRune('┿') + } } + b.WriteRune('┫') + b.WriteRune('\n') 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 { t.addNextCellLine(b) } @@ -96,9 +97,9 @@ func (t *Table) String() 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++ { - b.WriteRune('│') + b.WriteRune('┃') for colIndex := 0; colIndex < t.maxcols; colIndex++ { 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.WriteRune('│') + b.WriteString(fmt.Sprint(padStringRight(line, ' ', t.colwidth[colIndex]))) + if colIndex < t.maxcols-1 { + b.WriteRune('│') + } } - b.WriteRune('\n') + b.WriteString("┃\n") } } func (t *Table) addNextCellLine(b *strings.Builder) { - b.WriteRune('├') + b.WriteRune('┠') for i, colwidth := range t.colwidth { b.WriteString(strings.Repeat("─", colwidth)) if i < len(t.colwidth)-1 { b.WriteRune('┼') } } - b.WriteRune('┤') + b.WriteRune('┨') b.WriteRune('\n') } func (t *Table) addLastCellLine(b *strings.Builder) { - b.WriteRune('└') + b.WriteRune('┗') for i, colwidth := range t.colwidth { - b.WriteString(strings.Repeat("─", colwidth)) + b.WriteString(strings.Repeat("━", colwidth)) if i < len(t.colwidth)-1 { - b.WriteRune('┴') + b.WriteRune('┷') } } - b.WriteRune('┘') - b.WriteRune('\n') + b.WriteString("┛\n") } diff --git a/table_header.go b/table_header.go new file mode 100644 index 0000000..a2ca853 --- /dev/null +++ b/table_header.go @@ -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() +} diff --git a/utils.go b/utils.go index 8b0e968..21d7ffa 100644 --- a/utils.go +++ b/utils.go @@ -1,6 +1,7 @@ package tprint import ( + "fmt" "strings" "unicode" ) @@ -23,16 +24,15 @@ func strLen(str string) int { l := 0 runes := []rune(str) - colored := false for i := 0; i < len(runes); i++ { + + // skip control sequences if unicode.IsControl(runes[i]) { - if colored { - i += 3 - } else { - i += 4 + for j := i; j < len(runes)-1 && runes[j] != 'm'; j++ { + i = j } - colored = !colored + i++ continue } @@ -46,3 +46,14 @@ func padStringRight(str string, pad rune, length int) string { padding := length - strLen(str) 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) +}