diff --git a/go.mod b/go.mod index c0af26f6d..3880aa61e 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.4-0.20240702125206-a62d9d2a8413 github.com/h2non/filetype v1.1.3 - github.com/jedib0t/go-pretty/v6 v6.6.9 + github.com/jedib0t/go-pretty/v6 v6.7.1 github.com/manifoldco/promptui v0.9.0 github.com/mattn/go-sqlite3 v1.14.32 github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 diff --git a/go.sum b/go.sum index be14d8f2c..cd1be9ff0 100644 --- a/go.sum +++ b/go.sum @@ -121,8 +121,8 @@ github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/jedib0t/go-pretty/v6 v6.6.9 h1:PQecJLK3L8ODuVyMe2223b61oRJjrKnmXAncbWTv9MY= -github.com/jedib0t/go-pretty/v6 v6.6.9/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.7.1 h1:bHDSsj93NuJ563hHuM7ohk/wpX7BmRFNIsVv1ssI2/M= +github.com/jedib0t/go-pretty/v6 v6.7.1/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/README.md b/vendor/github.com/jedib0t/go-pretty/v6/table/README.md index 3375bd3c7..cf7595418 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/README.md +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/README.md @@ -3,42 +3,7 @@ Pretty-print tables into ASCII/Unicode strings. - - Add Rows one-by-one or as a group (`AppendRow`/`AppendRows`) - - Add Header(s) and Footer(s) (`AppendHeader`/`AppendFooter`) - - Add a Separator manually after any Row (`AppendSeparator`) - - Auto Index Rows (1, 2, 3 ...) and Columns (A, B, C, ...) (`SetAutoIndex`) - - Auto Merge (_not supported in CSV/Markdown/TSV modes_) - - Cells in a Row (`RowConfig.AutoMerge`) - - Columns (`ColumnConfig.AutoMerge`) (_not supported in HTML mode_) - - Limit the length of - - Rows (`SetAllowedRowLength`) - - Columns (`ColumnConfig.Width*`) - - Auto-size Rows (`Style().Size.WidthMin` and `Style().Size.WidthMax`) - - Page results by a specified number of Lines (`SetPageSize`) - - Alignment - Horizontal & Vertical - - Auto (horizontal) Align (numeric columns aligned Right) - - Custom (horizontal) Align per column (`ColumnConfig.Align*`) - - Custom (vertical) VAlign per column with multi-line cell support (`ColumnConfig.VAlign*`) - - Mirror output to an `io.Writer` (ex. `os.StdOut`) (`SetOutputMirror`) - - Sort by one or more Columns (`SortBy`) - - Suppress/hide columns with no content (`SuppressEmptyColumns`) - - Suppress trailing spaces in the last column (`SupressTrailingSpaces`) - - Customizable Cell rendering per Column (`ColumnConfig.Transformer*`) - - Hide any columns that you don't want displayed (`ColumnConfig.Hidden`) - - Reset Headers/Rows/Footers at will to reuse the same Table Writer (`Reset*`) - - Completely customizable styles (`SetStyle`/`Style`) - - Many ready-to-use styles: [style.go](style.go) - - Colorize Headers/Body/Footers using [../text/color.go](../text/color.go) - - Custom text-case for Headers/Body/Footers - - Enable separators between each row - - Render table without a Border - - and a lot more... - - Render as: - - (ASCII/Unicode) Table - - CSV - - HTML Table (with custom CSS Class) - - Markdown Table - - TSV +## Sample Table Rendering ``` +---------------------------------------------------------------------+ @@ -57,14 +22,110 @@ Pretty-print tables into ASCII/Unicode strings. A demonstration of all the capabilities can be found here: [../cmd/demo-table](../cmd/demo-table) -If you want very specific examples, read ahead. +If you want very specific examples, look at the [Examples](#examples) section. + +## Features + +### Core Table Building + + - Add Rows one-by-one or as a group (`AppendRow`/`AppendRows`) + - Add Header(s) and Footer(s) (`AppendHeader`/`AppendFooter`) + - Add a Separator manually after any Row (`AppendSeparator`) + - Add Title above the table (`SetTitle`) + - Add Caption below the table (`SetCaption`) + - Import 1D or 2D arrays/grids as rows (`ImportGrid`) + - Reset Headers/Rows/Footers at will to reuse the same Table Writer (`Reset*`) + +### Indexing & Navigation + + - Auto Index Rows (1, 2, 3 ...) and Columns (A, B, C, ...) (`SetAutoIndex`) + - Set which column is the index column (`SetIndexColumn`) + - Pager interface for navigating through paged output (`Pager()`) + - `GoTo(pageNum)` - Jump to specific page + - `Next()` - Move to next page + - `Prev()` - Move to previous page + - `Location()` - Get current page number + - `Render()` - Render current page + - `SetOutputMirror()` - Mirror output to io.Writer + +### Auto Merge + + - Auto Merge cells (_not supported in CSV/Markdown/TSV modes_) + - Cells in a Row (`RowConfig.AutoMerge`) + - Columns (`ColumnConfig.AutoMerge`) (_not supported in HTML mode_) + - Custom alignment for merged cells (`RowConfig.AutoMergeAlign`) + +### Size & Width Control + + - Limit the length of Rows (`SetAllowedRowLength` or `Style().Size.WidthMax`) + - Auto-size Rows (`Style().Size.WidthMin` and `Style().Size.WidthMax`) + - Column width control (`ColumnConfig.WidthMin` and `ColumnConfig.WidthMax`) + - Custom width enforcement functions (`ColumnConfig.WidthMaxEnforcer`) + - Default: `text.WrapText` + - Options: `text.WrapSoft`, `text.WrapHard`, `text.Trim`, or custom function + +### Alignment + + - **Horizontal Alignment** + - Auto (numeric columns aligned Right, text aligned Left) + - Custom per column (`ColumnConfig.Align`, `AlignHeader`, `AlignFooter`) + - Options: Left, Center, Right, Justify, Auto + - **Vertical Alignment** + - Custom per column with multi-line cell support (`ColumnConfig.VAlign`, `VAlignHeader`, `VAlignFooter`) + - Options: Top, Middle, Bottom -**Hint**: I've tried to ensure that almost all supported use-cases are covered -by unit-tests and that they print the table rendered. Run -`go test -v github.com/jedib0t/go-pretty/v6/table` to see the test outputs and -help you figure out how to do something. +### Sorting & Filtering -# Examples + - Sort by one or more Columns (`SortBy`) + - Ascending or Descending mode per column + - Multiple column sorting support + - Suppress/hide columns with no content (`SuppressEmptyColumns`) + - Hide specific columns (`ColumnConfig.Hidden`) + - Suppress trailing spaces in the last column (`SuppressTrailingSpaces`) + +### Customization & Styling + + - **Row Coloring** + - Custom row painter function (`SetRowPainter`) + - Row painter with attributes (`RowPainterWithAttributes`) + - Access to row number and sorted position + - **Cell Transformation** + - Customizable Cell rendering per Column (`ColumnConfig.Transformer`, `TransformerHeader`, `TransformerFooter`) + - Use built-in transformers from `text` package (Number, JSON, Time, URL, etc.) + - **Column Styling** + - Per-column colors (`ColumnConfig.Colors`, `ColorsHeader`, `ColorsFooter`) + - Per-column alignment (horizontal and vertical) + - Per-column width constraints + - **Completely customizable styles** (`SetStyle`/`Style`) + - Many ready-to-use styles: [style.go](style.go) + - `StyleDefault` - Classic ASCII borders + - `StyleLight` - Light box-drawing characters + - `StyleBold` - Bold box-drawing characters + - `StyleDouble` - Double box-drawing characters + - `StyleRounded` - Rounded box-drawing characters + - `StyleColoredBright` - Bright colors, no borders + - `StyleColoredDark` - Dark colors, no borders + - Many more colored variants (Blue, Cyan, Green, Magenta, Red, Yellow) + - Colorize Headers/Body/Footers using [../text/color.go](../text/color.go) + - Custom text-case for Headers/Body/Footers + - Enable/disable separators between rows + - Render table with or without borders + - Customize box-drawing characters + - Title and caption styling options + - HTML rendering options (CSS class, escaping, newlines) + - Bidirectional text support (`Style().Format.Direction`) + +### Output Formats + + - **Render as:** + - (ASCII/Unicode) Table - Human-readable pretty format + - CSV - Comma-separated values + - HTML Table - With custom CSS Class and options + - Markdown Table - Markdown-compatible format + - TSV - Tab-separated values + - Mirror output to an `io.Writer` (ex. `os.StdOut`) (`SetOutputMirror`) + +## Examples All the examples below are going to start with the following block, although nothing except a single Row is mandatory for the `Render()` function to render @@ -106,7 +167,7 @@ Running the above will result in: +-----+------------+-----------+--------+-----------------------------+ ``` -## Styles +### Styles You can customize almost every single thing about the table above. The previous example just defaulted to `StyleDefault` during `Render()`. You can use a @@ -143,7 +204,7 @@ to get: Colored Table -### Roll your own Style +#### Roll your own Style You can also roll your own style: ```golang @@ -198,7 +259,7 @@ Or you can use one of the ready-to-use Styles, and just make a few tweaks: t.Style().Options.DrawBorder = false ``` -## Auto-Merge +### Auto-Merge You can auto-merge cells horizontally and vertically, but you have request for it specifically for each row/column using `RowConfig` or `ColumnConfig`. @@ -255,10 +316,22 @@ to get: └───┴─────────┴────────┴───────────┴───────────┴─────┴─────┘ ``` -## Paging +### Paging + +You can limit the number of lines rendered in a single "Page". This logic +can handle rows with multiple lines too. The recommended way is to use the +`Pager()` interface: + +```golang + pager := t.Pager(PageSize(1)) + pager.Render() // Render first page + pager.Next() // Move to next page and render + pager.Prev() // Move to previous page and render + pager.GoTo(3) // Jump to page 3 + pager.Location() // Get current page number +``` -You can limit then number of lines rendered in a single "Page". This logic -can handle rows with multiple lines too. Here is a simple example: +Or use the deprecated `SetPageSize()` method for simple cases: ```golang t.SetPageSize(1) t.Render() @@ -290,7 +363,7 @@ to get: +-----+------------+-----------+--------+-----------------------------+ ``` -## Sorting +### Sorting Sorting can be done on one or more columns. The following code will make the rows be sorted first by "First Name" and then by "Last Name" (in case of similar @@ -302,7 +375,7 @@ rows be sorted first by "First Name" and then by "Last Name" (in case of similar }) ``` -## Wrapping (or) Row/Column Width restrictions +### Wrapping (or) Row/Column Width restrictions You can restrict the maximum (text) width for a Row: ```golang @@ -323,7 +396,7 @@ to get: +-----+------------+-----------+--------+------- ~ ``` -## Column Control - Alignment, Colors, Width and more +### Column Control - Alignment, Colors, Width and more You can control a lot of things about individual cells/columns which overrides global properties/styles using the `SetColumnConfig()` interface: @@ -360,11 +433,11 @@ global properties/styles using the `SetColumnConfig()` interface: }) ``` -## Render As ... +### Render As ... Tables can be rendered in other common formats such as: -### ... CSV +#### ... CSV ```golang t.RenderCSV() @@ -378,7 +451,7 @@ to get: ,,Total,10000, ``` -### ... HTML Table +#### ... HTML Table ```golang t.Style().HTML = table.HTMLOptions{ @@ -436,7 +509,7 @@ to get: ``` -### ... Markdown Table +#### ... Markdown Table ```golang t.RenderMarkdown() diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render.go index 4ef68f996..80d84dacb 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render.go @@ -239,7 +239,7 @@ func (t *Table) renderLineMergeOutputs(out *strings.Builder, outLine *strings.Bu } func (t *Table) renderMarginLeft(out *strings.Builder, hint renderHint) { - out.WriteString(t.style.Format.Direction.Modifier()) + out.WriteString(t.directionModifier) if t.style.Options.DrawBorder { border := t.getBorderLeft(hint) colors := t.getBorderColors(hint) diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/render_init.go b/vendor/github.com/jedib0t/go-pretty/v6/table/render_init.go index 333c39887..f4c58170e 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/render_init.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/render_init.go @@ -43,11 +43,15 @@ func (t *Table) analyzeAndStringifyColumn(colIdx int, col interface{}, hint rend } else if colStrVal, ok := col.(string); ok { colStr = colStrVal } else { - colStr = fmt.Sprint(col) + colStr = convertValueToString(col) } colStr = strings.ReplaceAll(colStr, "\t", " ") colStr = text.ProcessCRLF(colStr) - return fmt.Sprintf("%s%s", t.style.Format.Direction.Modifier(), colStr) + // Avoid fmt.Sprintf when direction modifier is empty (most common case) + if t.directionModifier == "" { + return colStr + } + return t.directionModifier + colStr } func (t *Table) extractMaxColumnLengths(rows []rowStr, hint renderHint) { @@ -156,6 +160,9 @@ func (t *Table) initForRender() { // reset rendering state t.reset() + // cache the direction modifier to avoid repeated calls + t.directionModifier = t.style.Format.Direction.Modifier() + // initialize the column configs and normalize them t.initForRenderColumnConfigs() diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/sort.go b/vendor/github.com/jedib0t/go-pretty/v6/table/sort.go index 7a47765ae..7356f51a1 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/sort.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/sort.go @@ -63,7 +63,7 @@ func (t *Table) getSortedRowIndices() []int { sortedIndices[idx] = idx } - if t.sortBy != nil && len(t.sortBy) > 0 { + if len(t.sortBy) > 0 { sort.Sort(rowsSorter{ rows: t.rows, sortBy: t.parseSortBy(t.sortBy), diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/table.go b/vendor/github.com/jedib0t/go-pretty/v6/table/table.go index 191dd7719..c4127d440 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/table.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/table.go @@ -28,6 +28,8 @@ type Table struct { // columnConfigMap stores the custom-configuration by column // number and is generated before rendering columnConfigMap map[int]ColumnConfig + // directionModifier caches the direction modifier string to avoid repeated calls + directionModifier string // firstRowOfPage tells if the renderer is on the first row of a page? firstRowOfPage bool // htmlCSSClass stores the HTML CSS Class to use on the node @@ -305,12 +307,12 @@ func (t *Table) SetRowPainter(painter interface{}) { t.rowPainterWithAttributes = nil // if called as SetRowPainter(RowPainter(func...)) - switch painter.(type) { + switch p := painter.(type) { case RowPainter: - t.rowPainter = painter.(RowPainter) + t.rowPainter = p return case RowPainterWithAttributes: - t.rowPainterWithAttributes = painter.(RowPainterWithAttributes) + t.rowPainterWithAttributes = p return } diff --git a/vendor/github.com/jedib0t/go-pretty/v6/table/util.go b/vendor/github.com/jedib0t/go-pretty/v6/table/util.go index 4636e8814..b4179a20e 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/table/util.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/table/util.go @@ -1,8 +1,10 @@ package table import ( + "fmt" "reflect" "sort" + "strconv" ) // AutoIndexColumnID returns a unique Column ID/Name for the given Column Number. @@ -26,6 +28,48 @@ func widthEnforcerNone(col string, _ int) string { return col } +// convertValueToString converts a value to string using fast type assertions +// for common numeric types before falling back to fmt.Sprint. +// +//gocyclo:ignore +func convertValueToString(v interface{}) string { + switch val := v.(type) { + case int: + return strconv.FormatInt(int64(val), 10) + case int8: + return strconv.FormatInt(int64(val), 10) + case int16: + return strconv.FormatInt(int64(val), 10) + case int32: + return strconv.FormatInt(int64(val), 10) + case int64: + return strconv.FormatInt(val, 10) + case uint: + return strconv.FormatUint(uint64(val), 10) + case uint8: + return strconv.FormatUint(uint64(val), 10) + case uint16: + return strconv.FormatUint(uint64(val), 10) + case uint32: + return strconv.FormatUint(uint64(val), 10) + case uint64: + return strconv.FormatUint(val, 10) + case float32: + return strconv.FormatFloat(float64(val), 'g', -1, 32) + case float64: + return strconv.FormatFloat(val, 'g', -1, 64) + case bool: + if val { + return "true" + } + return "false" + case string: + return val + default: + return fmt.Sprint(v) + } +} + // isNumber returns true if the argument is a numeric type; false otherwise. func isNumber(x interface{}) bool { if x == nil { diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/README.md b/vendor/github.com/jedib0t/go-pretty/v6/text/README.md index afd163aff..2b240dec8 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/README.md +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/README.md @@ -1,8 +1,132 @@ -# text +# Text +[![Go Reference](https://pkg.go.dev/badge/github.com/jedib0t/go-pretty/v6/text.svg)](https://pkg.go.dev/github.com/jedib0t/go-pretty/v6/text) -[![Go Reference](https://pkg.go.dev/badge/github.com/jedib0t/go-pretty/v6.svg)](https://pkg.go.dev/github.com/jedib0t/go-pretty/v6/text) - -Package with utility functions to manipulate strings/text. +Package with utility functions to manipulate strings/text with full support for +ANSI escape sequences (colors, formatting, etc.). Used heavily in the other packages in this repo ([list](../list), -[progress](../progress), and [table](../table)). \ No newline at end of file +[progress](../progress), and [table](../table)). + +## Features + +### Colors & Formatting + + - **ANSI Color Support** - Full support for terminal colors and formatting + - Foreground colors (Black, Red, Green, Yellow, Blue, Magenta, Cyan, White) + - Background colors (matching foreground set) + - Hi-intensity variants for both foreground and background + - Text attributes (Bold, Faint, Italic, Underline, Blink, Reverse, Concealed, CrossedOut) + - Automatic color detection based on environment variables (`NO_COLOR`, `FORCE_COLOR`, `TERM`) + - Global enable/disable functions for colors + - Cached escape sequences for performance + - **Text Formatting** - Transform text while preserving escape sequences + - `FormatDefault` - No transformation + - `FormatLower` - Convert to lowercase + - `FormatTitle` - Convert to title case + - `FormatUpper` - Convert to uppercase + - **HTML Support** - Generate HTML class attributes for colors + - **Color Combinations** - Combine multiple colors and attributes + +### Alignment + + - **Horizontal Alignment** + - `AlignDefault` / `AlignLeft` - Left-align text + - `AlignCenter` - Center-align text + - `AlignRight` - Right-align text + - `AlignJustify` - Justify text (distribute spaces between words) + - `AlignAuto` - Auto-detect: right-align numbers, left-align text + - HTML and Markdown property generation for alignment + - **Vertical Alignment** + - `VAlignTop` - Align to top + - `VAlignMiddle` - Align to middle + - `VAlignBottom` - Align to bottom + - Works with both string arrays and multi-line strings + - HTML property generation for vertical alignment + +### Text Wrapping + + - **WrapHard** - Hard wrap at specified length, breaks words if needed + - Handles ANSI escape sequences without breaking formatting + - Preserves paragraph breaks + - **WrapSoft** - Soft wrap at specified length, tries to keep words intact + - Handles ANSI escape sequences without breaking formatting + - Preserves paragraph breaks + - **WrapText** - Similar to WrapHard but also respects line breaks + - Handles ANSI escape sequences without breaking formatting + +### String Utilities + + - **Width Calculation** + - `StringWidth` - Calculate display width of string (including escape sequences) + - `StringWidthWithoutEscSequences` - Calculate display width ignoring escape sequences + - `RuneWidth` - Calculate display width of a single rune (handles East Asian characters) + - `LongestLineLen` - Find the longest line in a multi-line string + - **String Manipulation** + - `Trim` - Trim string to specified length while preserving escape sequences + - `Pad` - Pad string to specified length with a character + - `Snip` - Snip string to specified length with an indicator (e.g., "~") + - `RepeatAndTrim` - Repeat string until it reaches specified length + - `InsertEveryN` - Insert a character every N characters + - `ProcessCRLF` - Process carriage returns and line feeds correctly + - `Widen` - Convert half-width characters to full-width + - **Escape Sequence Handling** + - All functions properly handle ANSI escape sequences + - Escape sequences are preserved during transformations + - Width calculations ignore escape sequences + +### Cursor Control + + - Move cursor in all directions + - `CursorUp` - Move cursor up N lines + - `CursorDown` - Move cursor down N lines + - `CursorLeft` - Move cursor left N characters + - `CursorRight` - Move cursor right N characters + - `EraseLine` - Erase all characters to the right of cursor + - Generate ANSI escape sequences for terminal cursor manipulation + +### Hyperlinks + + - **Terminal Hyperlinks** - Create clickable hyperlinks in supported terminals + - Uses OSC 8 escape sequences + - Format: `Hyperlink(url, text)` + - Falls back to plain text in unsupported terminals + +### Transformers + + - **Number Transformer** - Format numbers with colors + - Positive numbers colored green + - Negative numbers colored red + - Custom format string support (e.g., `%.2f`) + - Supports all numeric types (int, uint, float) + - **JSON Transformer** - Pretty-print JSON strings or objects + - Customizable indentation (prefix and indent string) + - Validates JSON before formatting + - **Time Transformer** - Format time.Time objects + - Custom layout support (e.g., `time.RFC3339`) + - Timezone localization support + - Auto-detects common time formats from strings + - **Unix Time Transformer** - Format Unix timestamps + - Handles seconds, milliseconds, microseconds, and nanoseconds + - Auto-detects timestamp unit based on value + - Timezone localization support + - **URL Transformer** - Format URLs with styling + - Underlined and colored blue by default + - Custom color support + +### Text Direction + + - **Bidirectional Text Support** + - `LeftToRight` - Force left-to-right text direction + - `RightToLeft` - Force right-to-left text direction + - Uses Unicode directional markers + +### Filtering + + - **String Filtering** - Filter string slices with custom functions + - `Filter(slice, predicate)` - Returns filtered slice + +### East Asian Character Support + + - Proper width calculation for East Asian characters (full-width, half-width) + - Configurable East Asian width handling via `OverrideRuneWidthEastAsianWidth()` + - Handles mixed character sets correctly \ No newline at end of file diff --git a/vendor/github.com/jedib0t/go-pretty/v6/text/transformer.go b/vendor/github.com/jedib0t/go-pretty/v6/text/transformer.go index 193a721cc..ef1222725 100644 --- a/vendor/github.com/jedib0t/go-pretty/v6/text/transformer.go +++ b/vendor/github.com/jedib0t/go-pretty/v6/text/transformer.go @@ -11,9 +11,15 @@ import ( // Transformer related constants const ( - unixTimeMinMilliseconds = int64(10000000000) - unixTimeMinMicroseconds = unixTimeMinMilliseconds * 1000 - unixTimeMinNanoSeconds = unixTimeMinMicroseconds * 1000 + // Pre-computed time conversion constants to avoid repeated calculations + nanosPerSecond = int64(time.Second) + microsPerSecond = nanosPerSecond / 1000 + millisPerSecond = nanosPerSecond / 1000000 + + // Thresholds for detecting unix timestamp units (10 seconds worth in each unit) + unixTimeMinMilliseconds = 10 * nanosPerSecond + unixTimeMinMicroseconds = 10 * nanosPerSecond * 1000 + unixTimeMinNanoSeconds = 10 * nanosPerSecond * 1000000 ) // Transformer related variables @@ -40,25 +46,15 @@ type Transformer func(val interface{}) string // - transforms the number as directed by 'format' (ex.: %.2f) // - colors negative values Red // - colors positive values Green +// +//gocyclo:ignore func NewNumberTransformer(format string) Transformer { - return func(val interface{}) string { - if valStr := transformInt(format, val); valStr != "" { - return valStr - } - if valStr := transformUint(format, val); valStr != "" { - return valStr - } - if valStr := transformFloat(format, val); valStr != "" { - return valStr - } - return fmt.Sprint(val) - } -} + // Pre-compute negative format string to avoid repeated allocations + negFormat := "-" + format -func transformInt(format string, val interface{}) string { - transform := func(val int64) string { + transformInt64 := func(val int64) string { if val < 0 { - return colorsNumberNegative.Sprintf("-"+format, -val) + return colorsNumberNegative.Sprintf(negFormat, -val) } if val > 0 { return colorsNumberPositive.Sprintf(format, val) @@ -66,54 +62,16 @@ func transformInt(format string, val interface{}) string { return colorsNumberZero.Sprintf(format, val) } - if number, ok := val.(int); ok { - return transform(int64(number)) - } - if number, ok := val.(int8); ok { - return transform(int64(number)) - } - if number, ok := val.(int16); ok { - return transform(int64(number)) - } - if number, ok := val.(int32); ok { - return transform(int64(number)) - } - if number, ok := val.(int64); ok { - return transform(number) - } - return "" -} - -func transformUint(format string, val interface{}) string { - transform := func(val uint64) string { + transformUint64 := func(val uint64) string { if val > 0 { return colorsNumberPositive.Sprintf(format, val) } return colorsNumberZero.Sprintf(format, val) } - if number, ok := val.(uint); ok { - return transform(uint64(number)) - } - if number, ok := val.(uint8); ok { - return transform(uint64(number)) - } - if number, ok := val.(uint16); ok { - return transform(uint64(number)) - } - if number, ok := val.(uint32); ok { - return transform(uint64(number)) - } - if number, ok := val.(uint64); ok { - return transform(number) - } - return "" -} - -func transformFloat(format string, val interface{}) string { - transform := func(val float64) string { + transformFloat64 := func(val float64) string { if val < 0 { - return colorsNumberNegative.Sprintf("-"+format, -val) + return colorsNumberNegative.Sprintf(negFormat, -val) } if val > 0 { return colorsNumberPositive.Sprintf(format, val) @@ -121,13 +79,37 @@ func transformFloat(format string, val interface{}) string { return colorsNumberZero.Sprintf(format, val) } - if number, ok := val.(float32); ok { - return transform(float64(number)) - } - if number, ok := val.(float64); ok { - return transform(number) + // Use type switch for O(1) type checking instead of sequential type assertions + return func(val interface{}) string { + switch v := val.(type) { + case int: + return transformInt64(int64(v)) + case int8: + return transformInt64(int64(v)) + case int16: + return transformInt64(int64(v)) + case int32: + return transformInt64(int64(v)) + case int64: + return transformInt64(v) + case uint: + return transformUint64(uint64(v)) + case uint8: + return transformUint64(uint64(v)) + case uint16: + return transformUint64(uint64(v)) + case uint32: + return transformUint64(uint64(v)) + case uint64: + return transformUint64(v) + case float32: + return transformFloat64(float64(v)) + case float64: + return transformFloat64(v) + default: + return fmt.Sprint(val) + } } - return "" } // NewJSONTransformer returns a Transformer that can format a JSON string or an @@ -135,8 +117,13 @@ func transformFloat(format string, val interface{}) string { func NewJSONTransformer(prefix string, indent string) Transformer { return func(val interface{}) string { if valStr, ok := val.(string); ok { + valStr = strings.TrimSpace(valStr) + // Validate JSON before attempting to indent to avoid unnecessary processing + if !json.Valid([]byte(valStr)) { + return fmt.Sprintf("%#v", valStr) + } var b bytes.Buffer - if err := json.Indent(&b, []byte(strings.TrimSpace(valStr)), prefix, indent); err == nil { + if err := json.Indent(&b, []byte(valStr), prefix, indent); err == nil { return b.String() } } else if b, err := json.MarshalIndent(val, prefix, indent); err == nil { @@ -154,17 +141,17 @@ func NewJSONTransformer(prefix string, indent string) Transformer { // location (use time.Local to get localized timestamps). func NewTimeTransformer(layout string, location *time.Location) Transformer { return func(val interface{}) string { - rsp := fmt.Sprint(val) + // Check for time.Time first to avoid unnecessary fmt.Sprint conversion if valTime, ok := val.(time.Time); ok { - rsp = formatTime(valTime, layout, location) - } else { - // cycle through some supported layouts to see if the string form - // of the object matches any of these layouts - for _, possibleTimeLayout := range possibleTimeLayouts { - if valTime, err := time.Parse(possibleTimeLayout, rsp); err == nil { - rsp = formatTime(valTime, layout, location) - break - } + return formatTime(valTime, layout, location) + } + // Only convert to string if not already time.Time + rsp := fmt.Sprint(val) + // Cycle through some supported layouts to see if the string form + // of the object matches any of these layouts + for _, possibleTimeLayout := range possibleTimeLayouts { + if valTime, err := time.Parse(possibleTimeLayout, rsp); err == nil { + return formatTime(valTime, layout, location) } } return rsp @@ -217,12 +204,13 @@ func formatTime(t time.Time, layout string, location *time.Location) string { } func formatTimeUnix(unixTime int64, timeTransformer Transformer) string { + // Use pre-computed constants instead of repeated time.Second.Nanoseconds() calls if unixTime >= unixTimeMinNanoSeconds { - unixTime = unixTime / time.Second.Nanoseconds() + unixTime = unixTime / nanosPerSecond } else if unixTime >= unixTimeMinMicroseconds { - unixTime = unixTime / (time.Second.Nanoseconds() / 1000) + unixTime = unixTime / microsPerSecond } else if unixTime >= unixTimeMinMilliseconds { - unixTime = unixTime / (time.Second.Nanoseconds() / 1000000) + unixTime = unixTime / millisPerSecond } return timeTransformer(time.Unix(unixTime, 0)) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 9f6e3b1d5..53765dfc4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -208,7 +208,7 @@ github.com/h2non/filetype/types # github.com/inconshreveable/mousetrap v1.1.0 ## explicit; go 1.18 github.com/inconshreveable/mousetrap -# github.com/jedib0t/go-pretty/v6 v6.6.9 +# github.com/jedib0t/go-pretty/v6 v6.7.1 ## explicit; go 1.18 github.com/jedib0t/go-pretty/v6/table github.com/jedib0t/go-pretty/v6/text