From b49153bd3884c941d891f7fc7a9bb995b973fe69 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Sat, 8 Aug 2026 22:39:37 +0200 Subject: [PATCH] some refactoring, fix stringer func --- pkg/printer/cast.go | 67 +++++++++++++++----------------------------- pkg/printer/table.go | 46 +++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 49 deletions(-) diff --git a/pkg/printer/cast.go b/pkg/printer/cast.go index 3f7c077..9eea16e 100644 --- a/pkg/printer/cast.go +++ b/pkg/printer/cast.go @@ -1,3 +1,5 @@ +package printer + /* Copyright © 2026 Thomas von Dein @@ -14,7 +16,6 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ -package printer import ( "fmt" @@ -25,7 +26,9 @@ import ( "github.com/elastic/go-elasticsearch/v9/typedapi/types" ) -func any2string(in any) string { +// stringer returns the string representation of different types of +// values +func stringer(in any) string { //nolint:gocritic switch val := in.(type) { case string: @@ -54,52 +57,26 @@ func any2string(in any) string { return string(val) case nil: return "null" - case types.Percentage, types.DateTime: - return val.(string) + case *types.Float64: + // ignore err here, because types.Float64.MarshalJSON() never returns one + f, _ := val.MarshalJSON() + return string(f) + default: + // Caution: this may cause a panic if the [unknown] type does + // not implement fmt.Stringer. In this case add another case + // to the type switch for it above. + return in.(fmt.Stringer).String() } - - return "" } -func (data *Table) preprocessRows() { - if data.processed { - // only do it once - return +// visibleLen returns the length of a string but only visible chars, +// w/o ansi color escapes +func visibleLen(word string) int { + if !strings.Contains(word, "\x1b") { + // no ansi escape in there, use faster method + return len(word) } - // convert entries to strings - data.rows = make([][]string, len(data.Entries)) - for rowidx, entries := range data.Entries { - data.rows[rowidx] = make([]string, len(entries)) - - for colidx, entry := range data.Entries[rowidx] { - data.rows[rowidx][colidx] = any2string(entry) - } - } - - // determine header lenght's - for idx, head := range data.Headers { - data.lenHeaders[idx] = visibleLen(head) - } - - // determine max width per column - for _, entries := range data.rows { - currentWidth := 0 - - for idx, entry := range entries { - length := visibleLen(entry) - - if data.lenHeaders[idx] < length { - if length > currentWidth+data.maxwidth { - data.lenHeaders[idx] = data.maxwidth - currentWidth - } else { - data.lenHeaders[idx] = length - } - } - - currentWidth += data.lenHeaders[idx] - } - } - - data.processed = true + // contains escapes, need to clean up before counting + return len(ansiCtrlSeq.ReplaceAllLiteralString(word, "")) } diff --git a/pkg/printer/table.go b/pkg/printer/table.go index 3f331f6..7317b3a 100644 --- a/pkg/printer/table.go +++ b/pkg/printer/table.go @@ -291,7 +291,7 @@ func (table *Table) AddRowLate(fields ...any) { row := make([]string, len(fields)) for idx, field := range fields { - row[idx] = any2string(field) + row[idx] = stringer(field) } table.rows = append(table.rows, row) @@ -311,9 +311,47 @@ func (table *Table) toMap() []map[string]any { return raw } -// return the length of a string but only visible chars, w/o ansi color escapes -func visibleLen(word string) int { - return len(ansiCtrlSeq.ReplaceAllLiteralString(word, "")) +func (data *Table) preprocessRows() { + if data.processed { + // only do it once + return + } + + // convert entries to strings + data.rows = make([][]string, len(data.Entries)) + for rowidx, entries := range data.Entries { + data.rows[rowidx] = make([]string, len(entries)) + + for colidx, entry := range data.Entries[rowidx] { + data.rows[rowidx][colidx] = stringer(entry) + } + } + + // determine header lenght's + for idx, head := range data.Headers { + data.lenHeaders[idx] = visibleLen(head) + } + + // determine max width per column + for _, entries := range data.rows { + currentWidth := 0 + + for idx, entry := range entries { + length := visibleLen(entry) + + if data.lenHeaders[idx] < length { + if length > currentWidth+data.maxwidth { + data.lenHeaders[idx] = data.maxwidth - currentWidth + } else { + data.lenHeaders[idx] = length + } + } + + currentWidth += data.lenHeaders[idx] + } + } + + data.processed = true } func isInt(num string) bool {