|
| 1 | +package main |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "strings" |
| 6 | + "unicode/utf8" |
| 7 | +) |
| 8 | + |
| 9 | +// Table is a table in the console. |
| 10 | +type Table interface { |
| 11 | + Add(row ...string) |
| 12 | + Print() |
| 13 | +} |
| 14 | + |
| 15 | +// PrintableTable is a printable table in the console. |
| 16 | +type PrintableTable struct { |
| 17 | + headers []string |
| 18 | + headerPrinted bool |
| 19 | + maxSizes []int |
| 20 | + rows [][]string |
| 21 | +} |
| 22 | + |
| 23 | +// NewTable creates a new table. |
| 24 | +func NewTable(headers []string) Table { |
| 25 | + return &PrintableTable{ |
| 26 | + headers: headers, |
| 27 | + maxSizes: make([]int, len(headers)), |
| 28 | + } |
| 29 | +} |
| 30 | + |
| 31 | +// Add adds a new row to a table. |
| 32 | +func (t *PrintableTable) Add(row ...string) { |
| 33 | + t.rows = append(t.rows, row) |
| 34 | +} |
| 35 | + |
| 36 | +// Print prints a table to stdout. |
| 37 | +func (t *PrintableTable) Print() { |
| 38 | + for _, row := range append(t.rows, t.headers) { |
| 39 | + t.calculateMaxSize(row) |
| 40 | + } |
| 41 | + |
| 42 | + if t.headerPrinted == false { |
| 43 | + t.printHeader() |
| 44 | + t.headerPrinted = true |
| 45 | + } |
| 46 | + |
| 47 | + for _, line := range t.rows { |
| 48 | + t.printRow(line) |
| 49 | + } |
| 50 | + |
| 51 | + t.rows = [][]string{} |
| 52 | +} |
| 53 | + |
| 54 | +func (t *PrintableTable) calculateMaxSize(row []string) { |
| 55 | + for index, value := range row { |
| 56 | + cellLength := utf8.RuneCountInString(value) |
| 57 | + if t.maxSizes[index] < cellLength { |
| 58 | + t.maxSizes[index] = cellLength |
| 59 | + } |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +func (t *PrintableTable) printHeader() { |
| 64 | + output := "" |
| 65 | + for col, value := range t.headers { |
| 66 | + output = output + t.cellValue(col, value) |
| 67 | + } |
| 68 | + fmt.Println(bold(output)) |
| 69 | +} |
| 70 | + |
| 71 | +func (t *PrintableTable) printRow(row []string) { |
| 72 | + output := "" |
| 73 | + for columnIndex, value := range row { |
| 74 | + output = output + t.cellValue(columnIndex, value) |
| 75 | + } |
| 76 | + fmt.Println(output) |
| 77 | +} |
| 78 | + |
| 79 | +func (t *PrintableTable) cellValue(col int, value string) string { |
| 80 | + padding := "" |
| 81 | + if col < len(t.headers)-1 { |
| 82 | + padding = strings.Repeat(" ", t.maxSizes[col]-utf8.RuneCountInString(value)) |
| 83 | + } |
| 84 | + return fmt.Sprintf("%s%s ", value, padding) |
| 85 | +} |
0 commit comments