waveterm/pkg/util/colprint/colprint.go
2024-11-19 17:20:47 -08:00

89 lines
1.8 KiB
Go

// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package colprint
import (
"fmt"
"io"
)
// formatFn is a function that converts a value of type T to its string representation
type formatFn[T any] func(T) (string, error)
// PrintColumns prints values in columns, adapting to long values by letting them span multiple columns
func PrintColumns[T any](values <-chan T, numCols int, sampleSize int, format formatFn[T], w io.Writer) error {
// Get first batch and determine column width
maxLen := 0
var samples []T
for v := range values {
samples = append(samples, v)
str, err := format(v)
if err != nil {
return err
}
if len(str) > maxLen {
maxLen = len(str)
}
if len(samples) >= sampleSize {
break
}
}
colWidth := maxLen + 2 // Add minimum padding
if colWidth < 1 {
colWidth = 1
}
// Print in columns using our determined width
col := 0
for _, v := range samples {
str, err := format(v)
if err != nil {
return err
}
if err := printColHelper(str, colWidth, &col, numCols, w); err != nil {
return err
}
}
// Continue with any remaining values
for v := range values {
str, err := format(v)
if err != nil {
return err
}
if err := printColHelper(str, colWidth, &col, numCols, w); err != nil {
return err
}
}
if col > 0 {
if _, err := fmt.Fprint(w, "\n"); err != nil {
return err
}
}
return nil
}
func printColHelper(str string, colWidth int, col *int, numCols int, w io.Writer) error {
nameColSpan := (len(str) + 1) / colWidth
if (len(str)+1)%colWidth != 0 {
nameColSpan++
}
if *col+nameColSpan > numCols {
if _, err := fmt.Fprint(w, "\n"); err != nil {
return err
}
*col = 0
}
if _, err := fmt.Fprintf(w, "%-*s", nameColSpan*colWidth, str); err != nil {
return err
}
*col += nameColSpan
return nil
}