|
| 1 | +package table |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "io" |
| 6 | + "strings" |
| 7 | +) |
| 8 | + |
| 9 | +// Column represents a column in the table |
| 10 | +type Column struct { |
| 11 | + Header string |
| 12 | + Width int |
| 13 | +} |
| 14 | + |
| 15 | +// Printer handles dynamic table printing with automatic width calculation |
| 16 | +type Printer struct { |
| 17 | + columns []Column |
| 18 | + rows [][]string |
| 19 | + writer io.Writer |
| 20 | +} |
| 21 | + |
| 22 | +// New creates a new table printer |
| 23 | +func New(writer io.Writer, headers ...string) *Printer { |
| 24 | + columns := make([]Column, len(headers)) |
| 25 | + for i, header := range headers { |
| 26 | + columns[i] = Column{ |
| 27 | + Header: header, |
| 28 | + Width: len(header), |
| 29 | + } |
| 30 | + } |
| 31 | + return &Printer{ |
| 32 | + columns: columns, |
| 33 | + rows: make([][]string, 0), |
| 34 | + writer: writer, |
| 35 | + } |
| 36 | +} |
| 37 | + |
| 38 | +// AddRow adds a row of data to the table |
| 39 | +func (p *Printer) AddRow(values ...string) error { |
| 40 | + if len(values) != len(p.columns) { |
| 41 | + return fmt.Errorf("expected %d columns, got %d", len(p.columns), len(values)) |
| 42 | + } |
| 43 | + |
| 44 | + // Update column widths based on this row's values |
| 45 | + for i, value := range values { |
| 46 | + if len(value) > p.columns[i].Width { |
| 47 | + p.columns[i].Width = len(value) |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + p.rows = append(p.rows, values) |
| 52 | + return nil |
| 53 | +} |
| 54 | + |
| 55 | +// Print outputs the table with calculated column widths |
| 56 | +func (p *Printer) Print() { |
| 57 | + // Add padding to widths |
| 58 | + for i := range p.columns { |
| 59 | + p.columns[i].Width += 2 |
| 60 | + } |
| 61 | + |
| 62 | + // Build format string |
| 63 | + formatParts := make([]string, len(p.columns)) |
| 64 | + for i, col := range p.columns { |
| 65 | + formatParts[i] = fmt.Sprintf("%%-%ds", col.Width) |
| 66 | + } |
| 67 | + format := strings.Join(formatParts, " ") + "\n" |
| 68 | + |
| 69 | + // Print header |
| 70 | + headers := make([]interface{}, len(p.columns)) |
| 71 | + separators := make([]interface{}, len(p.columns)) |
| 72 | + for i, col := range p.columns { |
| 73 | + headers[i] = col.Header |
| 74 | + separators[i] = strings.Repeat("-", col.Width) |
| 75 | + } |
| 76 | + fmt.Fprintf(p.writer, format, headers...) |
| 77 | + fmt.Fprintf(p.writer, format, separators...) |
| 78 | + |
| 79 | + // Print rows |
| 80 | + for _, row := range p.rows { |
| 81 | + rowInterface := make([]interface{}, len(row)) |
| 82 | + for i, v := range row { |
| 83 | + rowInterface[i] = v |
| 84 | + } |
| 85 | + fmt.Fprintf(p.writer, format, rowInterface...) |
| 86 | + } |
| 87 | +} |
0 commit comments