|
- // Copyright 2014 Oleku Konko All rights reserved.
- // Use of this source code is governed by a MIT
- // license that can be found in the LICENSE file.
-
- // This module is a Table Writer API for the Go Programming Language.
- // The protocols were written in pure Go and works on windows and unix systems
-
- // Create & Generate text based table
- package tablewriter
-
- import (
- "bytes"
- "fmt"
- "io"
- "regexp"
- "strings"
- )
-
- const (
- MAX_ROW_WIDTH = 30
- )
-
- const (
- CENTER = "+"
- ROW = "-"
- COLUMN = "|"
- SPACE = " "
- NEWLINE = "\n"
- )
-
- const (
- ALIGN_DEFAULT = iota
- ALIGN_CENTER
- ALIGN_RIGHT
- ALIGN_LEFT
- )
-
- var (
- decimal = regexp.MustCompile(`^-?(?:\d{1,3}(?:,\d{3})*|\d+)(?:\.\d+)?$`)
- percent = regexp.MustCompile(`^-?\d+\.?\d*$%$`)
- )
-
- type Border struct {
- Left bool
- Right bool
- Top bool
- Bottom bool
- }
-
- type Table struct {
- out io.Writer
- rows [][]string
- lines [][][]string
- cs map[int]int
- rs map[int]int
- headers [][]string
- footers [][]string
- caption bool
- captionText string
- autoFmt bool
- autoWrap bool
- reflowText bool
- mW int
- pCenter string
- pRow string
- pColumn string
- tColumn int
- tRow int
- hAlign int
- fAlign int
- align int
- newLine string
- rowLine bool
- autoMergeCells bool
- noWhiteSpace bool
- tablePadding string
- hdrLine bool
- borders Border
- colSize int
- headerParams []string
- columnsParams []string
- footerParams []string
- columnsAlign []int
- }
-
- // Start New Table
- // Take io.Writer Directly
- func NewWriter(writer io.Writer) *Table {
- t := &Table{
- out: writer,
- rows: [][]string{},
- lines: [][][]string{},
- cs: make(map[int]int),
- rs: make(map[int]int),
- headers: [][]string{},
- footers: [][]string{},
- caption: false,
- captionText: "Table caption.",
- autoFmt: true,
- autoWrap: true,
- reflowText: true,
- mW: MAX_ROW_WIDTH,
- pCenter: CENTER,
- pRow: ROW,
- pColumn: COLUMN,
- tColumn: -1,
- tRow: -1,
- hAlign: ALIGN_DEFAULT,
- fAlign: ALIGN_DEFAULT,
- align: ALIGN_DEFAULT,
- newLine: NEWLINE,
- rowLine: false,
- hdrLine: true,
- borders: Border{Left: true, Right: true, Bottom: true, Top: true},
- colSize: -1,
- headerParams: []string{},
- columnsParams: []string{},
- footerParams: []string{},
- columnsAlign: []int{}}
- return t
- }
-
- // Render table output
- func (t *Table) Render() {
- if t.borders.Top {
- t.printLine(true)
- }
- t.printHeading()
- if t.autoMergeCells {
- t.printRowsMergeCells()
- } else {
- t.printRows()
- }
- if !t.rowLine && t.borders.Bottom {
- t.printLine(true)
- }
- t.printFooter()
-
- if t.caption {
- t.printCaption()
- }
- }
-
- const (
- headerRowIdx = -1
- footerRowIdx = -2
- )
-
- // Set table header
- func (t *Table) SetHeader(keys []string) {
- t.colSize = len(keys)
- for i, v := range keys {
- lines := t.parseDimension(v, i, headerRowIdx)
- t.headers = append(t.headers, lines)
- }
- }
-
- // Set table Footer
- func (t *Table) SetFooter(keys []string) {
- //t.colSize = len(keys)
- for i, v := range keys {
- lines := t.parseDimension(v, i, footerRowIdx)
- t.footers = append(t.footers, lines)
- }
- }
-
- // Set table Caption
- func (t *Table) SetCaption(caption bool, captionText ...string) {
- t.caption = caption
- if len(captionText) == 1 {
- t.captionText = captionText[0]
- }
- }
-
- // Turn header autoformatting on/off. Default is on (true).
- func (t *Table) SetAutoFormatHeaders(auto bool) {
- t.autoFmt = auto
- }
-
- // Turn automatic multiline text adjustment on/off. Default is on (true).
- func (t *Table) SetAutoWrapText(auto bool) {
- t.autoWrap = auto
- }
-
- // Turn automatic reflowing of multiline text when rewrapping. Default is on (true).
- func (t *Table) SetReflowDuringAutoWrap(auto bool) {
- t.reflowText = auto
- }
-
- // Set the Default column width
- func (t *Table) SetColWidth(width int) {
- t.mW = width
- }
-
- // Set the minimal width for a column
- func (t *Table) SetColMinWidth(column int, width int) {
- t.cs[column] = width
- }
-
- // Set the Column Separator
- func (t *Table) SetColumnSeparator(sep string) {
- t.pColumn = sep
- }
-
- // Set the Row Separator
- func (t *Table) SetRowSeparator(sep string) {
- t.pRow = sep
- }
-
- // Set the center Separator
- func (t *Table) SetCenterSeparator(sep string) {
- t.pCenter = sep
- }
-
- // Set Header Alignment
- func (t *Table) SetHeaderAlignment(hAlign int) {
- t.hAlign = hAlign
- }
-
- // Set Footer Alignment
- func (t *Table) SetFooterAlignment(fAlign int) {
- t.fAlign = fAlign
- }
-
- // Set Table Alignment
- func (t *Table) SetAlignment(align int) {
- t.align = align
- }
-
- // Set No White Space
- func (t *Table) SetNoWhiteSpace(allow bool) {
- t.noWhiteSpace = allow
- }
-
- // Set Table Padding
- func (t *Table) SetTablePadding(padding string) {
- t.tablePadding = padding
- }
-
- func (t *Table) SetColumnAlignment(keys []int) {
- for _, v := range keys {
- switch v {
- case ALIGN_CENTER:
- break
- case ALIGN_LEFT:
- break
- case ALIGN_RIGHT:
- break
- default:
- v = ALIGN_DEFAULT
- }
- t.columnsAlign = append(t.columnsAlign, v)
- }
- }
-
- // Set New Line
- func (t *Table) SetNewLine(nl string) {
- t.newLine = nl
- }
-
- // Set Header Line
- // This would enable / disable a line after the header
- func (t *Table) SetHeaderLine(line bool) {
- t.hdrLine = line
- }
-
- // Set Row Line
- // This would enable / disable a line on each row of the table
- func (t *Table) SetRowLine(line bool) {
- t.rowLine = line
- }
-
- // Set Auto Merge Cells
- // This would enable / disable the merge of cells with identical values
- func (t *Table) SetAutoMergeCells(auto bool) {
- t.autoMergeCells = auto
- }
-
- // Set Table Border
- // This would enable / disable line around the table
- func (t *Table) SetBorder(border bool) {
- t.SetBorders(Border{border, border, border, border})
- }
-
- func (t *Table) SetBorders(border Border) {
- t.borders = border
- }
-
- // Append row to table
- func (t *Table) Append(row []string) {
- rowSize := len(t.headers)
- if rowSize > t.colSize {
- t.colSize = rowSize
- }
-
- n := len(t.lines)
- line := [][]string{}
- for i, v := range row {
-
- // Detect string width
- // Detect String height
- // Break strings into words
- out := t.parseDimension(v, i, n)
-
- // Append broken words
- line = append(line, out)
- }
- t.lines = append(t.lines, line)
- }
-
- // Append row to table with color attributes
- func (t *Table) Rich(row []string, colors []Colors) {
- rowSize := len(t.headers)
- if rowSize > t.colSize {
- t.colSize = rowSize
- }
-
- n := len(t.lines)
- line := [][]string{}
- for i, v := range row {
-
- // Detect string width
- // Detect String height
- // Break strings into words
- out := t.parseDimension(v, i, n)
-
- if len(colors) > i {
- color := colors[i]
- out[0] = format(out[0], color)
- }
-
- // Append broken words
- line = append(line, out)
- }
- t.lines = append(t.lines, line)
- }
-
- // Allow Support for Bulk Append
- // Eliminates repeated for loops
- func (t *Table) AppendBulk(rows [][]string) {
- for _, row := range rows {
- t.Append(row)
- }
- }
-
- // NumLines to get the number of lines
- func (t *Table) NumLines() int {
- return len(t.lines)
- }
-
- // Clear rows
- func (t *Table) ClearRows() {
- t.lines = [][][]string{}
- }
-
- // Clear footer
- func (t *Table) ClearFooter() {
- t.footers = [][]string{}
- }
-
- // Center based on position and border.
- func (t *Table) center(i int) string {
- if i == -1 && !t.borders.Left {
- return t.pRow
- }
-
- if i == len(t.cs)-1 && !t.borders.Right {
- return t.pRow
- }
-
- return t.pCenter
- }
-
- // Print line based on row width
- func (t *Table) printLine(nl bool) {
- fmt.Fprint(t.out, t.center(-1))
- for i := 0; i < len(t.cs); i++ {
- v := t.cs[i]
- fmt.Fprintf(t.out, "%s%s%s%s",
- t.pRow,
- strings.Repeat(string(t.pRow), v),
- t.pRow,
- t.center(i))
- }
- if nl {
- fmt.Fprint(t.out, t.newLine)
- }
- }
-
- // Print line based on row width with our without cell separator
- func (t *Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) {
- fmt.Fprint(t.out, t.pCenter)
- for i := 0; i < len(t.cs); i++ {
- v := t.cs[i]
- if i > len(displayCellSeparator) || displayCellSeparator[i] {
- // Display the cell separator
- fmt.Fprintf(t.out, "%s%s%s%s",
- t.pRow,
- strings.Repeat(string(t.pRow), v),
- t.pRow,
- t.pCenter)
- } else {
- // Don't display the cell separator for this cell
- fmt.Fprintf(t.out, "%s%s",
- strings.Repeat(" ", v+2),
- t.pCenter)
- }
- }
- if nl {
- fmt.Fprint(t.out, t.newLine)
- }
- }
-
- // Return the PadRight function if align is left, PadLeft if align is right,
- // and Pad by default
- func pad(align int) func(string, string, int) string {
- padFunc := Pad
- switch align {
- case ALIGN_LEFT:
- padFunc = PadRight
- case ALIGN_RIGHT:
- padFunc = PadLeft
- }
- return padFunc
- }
-
- // Print heading information
- func (t *Table) printHeading() {
- // Check if headers is available
- if len(t.headers) < 1 {
- return
- }
-
- // Identify last column
- end := len(t.cs) - 1
-
- // Get pad function
- padFunc := pad(t.hAlign)
-
- // Checking for ANSI escape sequences for header
- is_esc_seq := false
- if len(t.headerParams) > 0 {
- is_esc_seq = true
- }
-
- // Maximum height.
- max := t.rs[headerRowIdx]
-
- // Print Heading
- for x := 0; x < max; x++ {
- // Check if border is set
- // Replace with space if not set
- if !t.noWhiteSpace {
- fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE))
- }
-
- for y := 0; y <= end; y++ {
- v := t.cs[y]
- h := ""
-
- if y < len(t.headers) && x < len(t.headers[y]) {
- h = t.headers[y][x]
- }
- if t.autoFmt {
- h = Title(h)
- }
- pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn)
- if t.noWhiteSpace {
- pad = ConditionString((y == end && !t.borders.Left), SPACE, t.tablePadding)
- }
- if is_esc_seq {
- if !t.noWhiteSpace {
- fmt.Fprintf(t.out, " %s %s",
- format(padFunc(h, SPACE, v),
- t.headerParams[y]), pad)
- } else {
- fmt.Fprintf(t.out, "%s %s",
- format(padFunc(h, SPACE, v),
- t.headerParams[y]), pad)
- }
- } else {
- if !t.noWhiteSpace {
- fmt.Fprintf(t.out, " %s %s",
- padFunc(h, SPACE, v),
- pad)
- } else {
- // the spaces between breaks the kube formatting
- fmt.Fprintf(t.out, "%s%s",
- padFunc(h, SPACE, v),
- pad)
- }
- }
- }
- // Next line
- fmt.Fprint(t.out, t.newLine)
- }
- if t.hdrLine {
- t.printLine(true)
- }
- }
-
- // Print heading information
- func (t *Table) printFooter() {
- // Check if headers is available
- if len(t.footers) < 1 {
- return
- }
-
- // Only print line if border is not set
- if !t.borders.Bottom {
- t.printLine(true)
- }
-
- // Identify last column
- end := len(t.cs) - 1
-
- // Get pad function
- padFunc := pad(t.fAlign)
-
- // Checking for ANSI escape sequences for header
- is_esc_seq := false
- if len(t.footerParams) > 0 {
- is_esc_seq = true
- }
-
- // Maximum height.
- max := t.rs[footerRowIdx]
-
- // Print Footer
- erasePad := make([]bool, len(t.footers))
- for x := 0; x < max; x++ {
- // Check if border is set
- // Replace with space if not set
- fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE))
-
- for y := 0; y <= end; y++ {
- v := t.cs[y]
- f := ""
- if y < len(t.footers) && x < len(t.footers[y]) {
- f = t.footers[y][x]
- }
- if t.autoFmt {
- f = Title(f)
- }
- pad := ConditionString((y == end && !t.borders.Top), SPACE, t.pColumn)
-
- if erasePad[y] || (x == 0 && len(f) == 0) {
- pad = SPACE
- erasePad[y] = true
- }
-
- if is_esc_seq {
- fmt.Fprintf(t.out, " %s %s",
- format(padFunc(f, SPACE, v),
- t.footerParams[y]), pad)
- } else {
- fmt.Fprintf(t.out, " %s %s",
- padFunc(f, SPACE, v),
- pad)
- }
-
- //fmt.Fprintf(t.out, " %s %s",
- // padFunc(f, SPACE, v),
- // pad)
- }
- // Next line
- fmt.Fprint(t.out, t.newLine)
- //t.printLine(true)
- }
-
- hasPrinted := false
-
- for i := 0; i <= end; i++ {
- v := t.cs[i]
- pad := t.pRow
- center := t.pCenter
- length := len(t.footers[i][0])
-
- if length > 0 {
- hasPrinted = true
- }
-
- // Set center to be space if length is 0
- if length == 0 && !t.borders.Right {
- center = SPACE
- }
-
- // Print first junction
- if i == 0 {
- if length > 0 && !t.borders.Left {
- center = t.pRow
- }
- fmt.Fprint(t.out, center)
- }
-
- // Pad With space of length is 0
- if length == 0 {
- pad = SPACE
- }
- // Ignore left space as it has printed before
- if hasPrinted || t.borders.Left {
- pad = t.pRow
- center = t.pCenter
- }
-
- // Change Center end position
- if center != SPACE {
- if i == end && !t.borders.Right {
- center = t.pRow
- }
- }
-
- // Change Center start position
- if center == SPACE {
- if i < end && len(t.footers[i+1][0]) != 0 {
- if !t.borders.Left {
- center = t.pRow
- } else {
- center = t.pCenter
- }
- }
- }
-
- // Print the footer
- fmt.Fprintf(t.out, "%s%s%s%s",
- pad,
- strings.Repeat(string(pad), v),
- pad,
- center)
-
- }
-
- fmt.Fprint(t.out, t.newLine)
- }
-
- // Print caption text
- func (t Table) printCaption() {
- width := t.getTableWidth()
- paragraph, _ := WrapString(t.captionText, width)
- for linecount := 0; linecount < len(paragraph); linecount++ {
- fmt.Fprintln(t.out, paragraph[linecount])
- }
- }
-
- // Calculate the total number of characters in a row
- func (t Table) getTableWidth() int {
- var chars int
- for _, v := range t.cs {
- chars += v
- }
-
- // Add chars, spaces, seperators to calculate the total width of the table.
- // ncols := t.colSize
- // spaces := ncols * 2
- // seps := ncols + 1
-
- return (chars + (3 * t.colSize) + 2)
- }
-
- func (t Table) printRows() {
- for i, lines := range t.lines {
- t.printRow(lines, i)
- }
- }
-
- func (t *Table) fillAlignment(num int) {
- if len(t.columnsAlign) < num {
- t.columnsAlign = make([]int, num)
- for i := range t.columnsAlign {
- t.columnsAlign[i] = t.align
- }
- }
- }
-
- // Print Row Information
- // Adjust column alignment based on type
-
- func (t *Table) printRow(columns [][]string, rowIdx int) {
- // Get Maximum Height
- max := t.rs[rowIdx]
- total := len(columns)
-
- // TODO Fix uneven col size
- // if total < t.colSize {
- // for n := t.colSize - total; n < t.colSize ; n++ {
- // columns = append(columns, []string{SPACE})
- // t.cs[n] = t.mW
- // }
- //}
-
- // Pad Each Height
- pads := []int{}
-
- // Checking for ANSI escape sequences for columns
- is_esc_seq := false
- if len(t.columnsParams) > 0 {
- is_esc_seq = true
- }
- t.fillAlignment(total)
-
- for i, line := range columns {
- length := len(line)
- pad := max - length
- pads = append(pads, pad)
- for n := 0; n < pad; n++ {
- columns[i] = append(columns[i], " ")
- }
- }
- //fmt.Println(max, "\n")
- for x := 0; x < max; x++ {
- for y := 0; y < total; y++ {
-
- // Check if border is set
- if !t.noWhiteSpace {
- fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn))
- fmt.Fprintf(t.out, SPACE)
- }
-
- str := columns[y][x]
-
- // Embedding escape sequence with column value
- if is_esc_seq {
- str = format(str, t.columnsParams[y])
- }
-
- // This would print alignment
- // Default alignment would use multiple configuration
- switch t.columnsAlign[y] {
- case ALIGN_CENTER: //
- fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y]))
- case ALIGN_RIGHT:
- fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y]))
- case ALIGN_LEFT:
- fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y]))
- default:
- if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) {
- fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y]))
- } else {
- fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y]))
-
- // TODO Custom alignment per column
- //if max == 1 || pads[y] > 0 {
- // fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y]))
- //} else {
- // fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y]))
- //}
-
- }
- }
- if !t.noWhiteSpace {
- fmt.Fprintf(t.out, SPACE)
- } else {
- fmt.Fprintf(t.out, t.tablePadding)
- }
- }
- // Check if border is set
- // Replace with space if not set
- if !t.noWhiteSpace {
- fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE))
- }
- fmt.Fprint(t.out, t.newLine)
- }
-
- if t.rowLine {
- t.printLine(true)
- }
- }
-
- // Print the rows of the table and merge the cells that are identical
- func (t *Table) printRowsMergeCells() {
- var previousLine []string
- var displayCellBorder []bool
- var tmpWriter bytes.Buffer
- for i, lines := range t.lines {
- // We store the display of the current line in a tmp writer, as we need to know which border needs to be print above
- previousLine, displayCellBorder = t.printRowMergeCells(&tmpWriter, lines, i, previousLine)
- if i > 0 { //We don't need to print borders above first line
- if t.rowLine {
- t.printLineOptionalCellSeparators(true, displayCellBorder)
- }
- }
- tmpWriter.WriteTo(t.out)
- }
- //Print the end of the table
- if t.rowLine {
- t.printLine(true)
- }
- }
-
- // Print Row Information to a writer and merge identical cells.
- // Adjust column alignment based on type
-
- func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx int, previousLine []string) ([]string, []bool) {
- // Get Maximum Height
- max := t.rs[rowIdx]
- total := len(columns)
-
- // Pad Each Height
- pads := []int{}
-
- // Checking for ANSI escape sequences for columns
- is_esc_seq := false
- if len(t.columnsParams) > 0 {
- is_esc_seq = true
- }
- for i, line := range columns {
- length := len(line)
- pad := max - length
- pads = append(pads, pad)
- for n := 0; n < pad; n++ {
- columns[i] = append(columns[i], " ")
- }
- }
-
- var displayCellBorder []bool
- t.fillAlignment(total)
- for x := 0; x < max; x++ {
- for y := 0; y < total; y++ {
-
- // Check if border is set
- fmt.Fprint(writer, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn))
-
- fmt.Fprintf(writer, SPACE)
-
- str := columns[y][x]
-
- // Embedding escape sequence with column value
- if is_esc_seq {
- str = format(str, t.columnsParams[y])
- }
-
- if t.autoMergeCells {
- //Store the full line to merge mutli-lines cells
- fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ")
- if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" {
- // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty.
- displayCellBorder = append(displayCellBorder, false)
- str = ""
- } else {
- // First line or different content, keep the content and print the cell border
- displayCellBorder = append(displayCellBorder, true)
- }
- }
-
- // This would print alignment
- // Default alignment would use multiple configuration
- switch t.columnsAlign[y] {
- case ALIGN_CENTER: //
- fmt.Fprintf(writer, "%s", Pad(str, SPACE, t.cs[y]))
- case ALIGN_RIGHT:
- fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y]))
- case ALIGN_LEFT:
- fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y]))
- default:
- if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) {
- fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y]))
- } else {
- fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y]))
- }
- }
- fmt.Fprintf(writer, SPACE)
- }
- // Check if border is set
- // Replace with space if not set
- fmt.Fprint(writer, ConditionString(t.borders.Left, t.pColumn, SPACE))
- fmt.Fprint(writer, t.newLine)
- }
-
- //The new previous line is the current one
- previousLine = make([]string, total)
- for y := 0; y < total; y++ {
- previousLine[y] = strings.TrimRight(strings.Join(columns[y], " "), " ") //Store the full line for multi-lines cells
- }
- //Returns the newly added line and wether or not a border should be displayed above.
- return previousLine, displayCellBorder
- }
-
- func (t *Table) parseDimension(str string, colKey, rowKey int) []string {
- var (
- raw []string
- maxWidth int
- )
-
- raw = getLines(str)
- maxWidth = 0
- for _, line := range raw {
- if w := DisplayWidth(line); w > maxWidth {
- maxWidth = w
- }
- }
-
- // If wrapping, ensure that all paragraphs in the cell fit in the
- // specified width.
- if t.autoWrap {
- // If there's a maximum allowed width for wrapping, use that.
- if maxWidth > t.mW {
- maxWidth = t.mW
- }
-
- // In the process of doing so, we need to recompute maxWidth. This
- // is because perhaps a word in the cell is longer than the
- // allowed maximum width in t.mW.
- newMaxWidth := maxWidth
- newRaw := make([]string, 0, len(raw))
-
- if t.reflowText {
- // Make a single paragraph of everything.
- raw = []string{strings.Join(raw, " ")}
- }
- for i, para := range raw {
- paraLines, _ := WrapString(para, maxWidth)
- for _, line := range paraLines {
- if w := DisplayWidth(line); w > newMaxWidth {
- newMaxWidth = w
- }
- }
- if i > 0 {
- newRaw = append(newRaw, " ")
- }
- newRaw = append(newRaw, paraLines...)
- }
- raw = newRaw
- maxWidth = newMaxWidth
- }
-
- // Store the new known maximum width.
- v, ok := t.cs[colKey]
- if !ok || v < maxWidth || v == 0 {
- t.cs[colKey] = maxWidth
- }
-
- // Remember the number of lines for the row printer.
- h := len(raw)
- v, ok = t.rs[rowKey]
-
- if !ok || v < h || v == 0 {
- t.rs[rowKey] = h
- }
- //fmt.Printf("Raw %+v %d\n", raw, len(raw))
- return raw
- }
|