169 lines
4.2 KiB
Go
169 lines
4.2 KiB
Go
|
package pterm
|
||
|
|
||
|
import (
|
||
|
"encoding/csv"
|
||
|
"strings"
|
||
|
"unicode/utf8"
|
||
|
|
||
|
"github.com/pterm/pterm/internal"
|
||
|
)
|
||
|
|
||
|
// DefaultTable contains standards, which can be used to print a TablePrinter.
|
||
|
var DefaultTable = TablePrinter{
|
||
|
Style: &ThemeDefault.TableStyle,
|
||
|
HeaderStyle: &ThemeDefault.TableHeaderStyle,
|
||
|
Separator: " | ",
|
||
|
SeparatorStyle: &ThemeDefault.TableSeparatorStyle,
|
||
|
LeftAlignment: true,
|
||
|
RightAlignment: false,
|
||
|
}
|
||
|
|
||
|
// TableData is the type that contains the data of a TablePrinter.
|
||
|
type TableData [][]string
|
||
|
|
||
|
// TablePrinter is able to render tables.
|
||
|
type TablePrinter struct {
|
||
|
Style *Style
|
||
|
HasHeader bool
|
||
|
HeaderStyle *Style
|
||
|
Separator string
|
||
|
SeparatorStyle *Style
|
||
|
Data TableData
|
||
|
Boxed bool
|
||
|
LeftAlignment bool
|
||
|
RightAlignment bool
|
||
|
}
|
||
|
|
||
|
// WithStyle returns a new TablePrinter with a specific Style.
|
||
|
func (p TablePrinter) WithStyle(style *Style) *TablePrinter {
|
||
|
p.Style = style
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithHasHeader returns a new TablePrinter, where the first line is marked as a header.
|
||
|
func (p TablePrinter) WithHasHeader(b ...bool) *TablePrinter {
|
||
|
p.HasHeader = internal.WithBoolean(b)
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithHeaderStyle returns a new TablePrinter with a specific HeaderStyle.
|
||
|
func (p TablePrinter) WithHeaderStyle(style *Style) *TablePrinter {
|
||
|
p.HeaderStyle = style
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithSeparator returns a new TablePrinter with a specific separator.
|
||
|
func (p TablePrinter) WithSeparator(separator string) *TablePrinter {
|
||
|
p.Separator = separator
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithSeparatorStyle returns a new TablePrinter with a specific SeparatorStyle.
|
||
|
func (p TablePrinter) WithSeparatorStyle(style *Style) *TablePrinter {
|
||
|
p.SeparatorStyle = style
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithData returns a new TablePrinter with specific Data.
|
||
|
func (p TablePrinter) WithData(data [][]string) *TablePrinter {
|
||
|
p.Data = data
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithCSVReader return a new TablePrinter with specified Data extracted from CSV.
|
||
|
func (p TablePrinter) WithCSVReader(reader *csv.Reader) *TablePrinter {
|
||
|
if records, err := reader.ReadAll(); err == nil {
|
||
|
p.Data = records
|
||
|
}
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithBoxed returns a new TablePrinter with a box around the table.
|
||
|
func (p TablePrinter) WithBoxed(b ...bool) *TablePrinter {
|
||
|
p.Boxed = internal.WithBoolean(b)
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithLeftAlignment returns a new TablePrinter with left alignment.
|
||
|
func (p TablePrinter) WithLeftAlignment(b ...bool) *TablePrinter {
|
||
|
b2 := internal.WithBoolean(b)
|
||
|
p.LeftAlignment = b2
|
||
|
p.RightAlignment = false
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// WithRightAlignment returns a new TablePrinter with right alignment.
|
||
|
func (p TablePrinter) WithRightAlignment(b ...bool) *TablePrinter {
|
||
|
b2 := internal.WithBoolean(b)
|
||
|
p.LeftAlignment = false
|
||
|
p.RightAlignment = b2
|
||
|
return &p
|
||
|
}
|
||
|
|
||
|
// Srender renders the TablePrinter as a string.
|
||
|
func (p TablePrinter) Srender() (string, error) {
|
||
|
if p.Style == nil {
|
||
|
p.Style = NewStyle()
|
||
|
}
|
||
|
if p.SeparatorStyle == nil {
|
||
|
p.SeparatorStyle = NewStyle()
|
||
|
}
|
||
|
if p.HeaderStyle == nil {
|
||
|
p.HeaderStyle = NewStyle()
|
||
|
}
|
||
|
|
||
|
var ret string
|
||
|
maxColumnWidth := make(map[int]int)
|
||
|
|
||
|
for _, row := range p.Data {
|
||
|
for ci, column := range row {
|
||
|
columnLength := utf8.RuneCountInString(RemoveColorFromString(column))
|
||
|
if columnLength > maxColumnWidth[ci] {
|
||
|
maxColumnWidth[ci] = columnLength
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for ri, row := range p.Data {
|
||
|
for ci, column := range row {
|
||
|
columnString := p.createColumnString(column, maxColumnWidth[ci])
|
||
|
|
||
|
if ci != len(row) && ci != 0 {
|
||
|
ret += p.Style.Sprint(p.SeparatorStyle.Sprint(p.Separator))
|
||
|
}
|
||
|
|
||
|
if p.HasHeader && ri == 0 {
|
||
|
ret += p.Style.Sprint(p.HeaderStyle.Sprint(columnString))
|
||
|
} else {
|
||
|
ret += p.Style.Sprint(columnString)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ret += "\n"
|
||
|
}
|
||
|
|
||
|
ret = strings.TrimSuffix(ret, "\n")
|
||
|
|
||
|
if p.Boxed {
|
||
|
ret = DefaultBox.Sprint(ret)
|
||
|
}
|
||
|
|
||
|
return ret, nil
|
||
|
}
|
||
|
|
||
|
func (p TablePrinter) createColumnString(data string, maxColumnWidth int) string {
|
||
|
columnLength := utf8.RuneCountInString(RemoveColorFromString(data))
|
||
|
if p.RightAlignment {
|
||
|
return strings.Repeat(" ", maxColumnWidth-columnLength) + data
|
||
|
}
|
||
|
return data + strings.Repeat(" ", maxColumnWidth-columnLength)
|
||
|
}
|
||
|
|
||
|
// Render prints the TablePrinter to the terminal.
|
||
|
func (p TablePrinter) Render() error {
|
||
|
s, _ := p.Srender()
|
||
|
Println(s)
|
||
|
|
||
|
return nil
|
||
|
}
|