diff --git a/util/padding.go b/util/padding.go new file mode 100644 index 0000000000000000000000000000000000000000..3043a73da4a7f12147cedf9df19098d75b9f8398 --- /dev/null +++ b/util/padding.go @@ -0,0 +1,50 @@ +package util + +import ( + "math" + "strings" + "unicode/utf8" +) + +const ( + ALIGN_LEFT = 0 + ALIGN_CENTER = 1 + ALIGN_RIGHT = 2 +) + +func Pad(s, pad string, width int, align int) string { + switch align { + case ALIGN_CENTER: + return PadCenter(s, pad, width) + case ALIGN_RIGHT: + return PadLeft(s, pad, width) + default: + return PadRight(s, pad, width) + } +} + +func PadRight(s, pad string, width int) string { + gap := width - utf8.RuneCountInString(s) + if gap > 0 { + return s + strings.Repeat(string(pad), gap) + } + return s +} + +func PadLeft(s, pad string, width int) string { + gap := width - utf8.RuneCountInString(s) + if gap > 0 { + return strings.Repeat(string(pad), gap) + s + } + return s +} + +func PadCenter(s, pad string, width int) string { + gap := width - utf8.RuneCountInString(s) + if gap > 0 { + gapLeft := int(math.Ceil(float64(gap / 2))) + gapRight := gap - gapLeft + return strings.Repeat(string(pad), gapLeft) + s + strings.Repeat(string(pad), gapRight) + } + return s +} diff --git a/util/table.go b/util/table.go new file mode 100644 index 0000000000000000000000000000000000000000..18d3b162688d7be6d7af2b300b4ac0f41141d2a4 --- /dev/null +++ b/util/table.go @@ -0,0 +1,94 @@ +package util + +import ( + "fmt" + "io" + "unicode/utf8" +) + +// const ( +// ALIGN_LEFT = 0 +// ALIGN_CENTER = 1 +// ALIGN_RIGHT = 2 +// ) + +type Table struct { + Out io.Writer + Rows [][]string + ColumnWidths []int + ColumnAlign []int + Separator string +} + +func CreateTable(out io.Writer) Table { + return Table{ + Out: out, + Separator: " ", + } +} + +// Clear removes all rows while preserving the layout +func (t *Table) Clear() { + t.Rows = [][]string{} +} + +// AddRow adds a new row to the table +func (t *Table) AddRow(col ...string) { + t.Rows = append(t.Rows, col) +} + +func (t *Table) Render() { + // lets figure out the max widths of each column + for _, row := range t.Rows { + for ci, col := range row { + l := utf8.RuneCountInString(col) + t.ColumnWidths = ensureArrayCanContain(t.ColumnWidths, ci) + if l > t.ColumnWidths[ci] { + t.ColumnWidths[ci] = l + } + } + } + + out := t.Out + for _, row := range t.Rows { + lastColumn := len(row) - 1 + for ci, col := range row { + if ci > 0 { + fmt.Fprint(out, t.Separator) + } + l := t.ColumnWidths[ci] + align := t.GetColumnAlign(ci) + if ci >= lastColumn && align != ALIGN_CENTER && align != ALIGN_RIGHT { + fmt.Fprint(out, col) + } else { + fmt.Fprint(out, Pad(col, " ", l, align)) + } + } + fmt.Fprint(out, "\n") + } +} + +// SetColumnsAligns sets the alignment of the columns +func (t *Table) SetColumnsAligns(colAligns []int) { + t.ColumnAlign = colAligns +} + +// GetColumnAlign return the column alignment +func (t *Table) GetColumnAlign(i int) int { + t.ColumnAlign = ensureArrayCanContain(t.ColumnAlign, i) + return t.ColumnAlign[i] +} + +// SetColumnAlign sets the column alignment for the given column index +func (t *Table) SetColumnAlign(i int, align int) { + t.ColumnAlign = ensureArrayCanContain(t.ColumnAlign, i) + t.ColumnAlign[i] = align +} + +func ensureArrayCanContain(array []int, idx int) []int { + diff := idx + 1 - len(array) + for i := 0; i < diff; i++ { + array = append(array, 0) + } + return array +}