@@ -6,14 +6,11 @@ package tablecli
66
77import (
88 "bytes"
9- "fmt"
10- "io"
119 "os"
1210 "reflect"
1311 "regexp"
1412 "sort"
1513 "strings"
16- "text/tabwriter"
1714 "unicode"
1815 "unicode/utf8"
1916
@@ -221,60 +218,88 @@ func (t *Table) resizeLargestColumn(ttyWidth int) []int {
221218 return t .columnsSize ()
222219}
223220
224- const (
225- tabwriterMinWidth = 6
226- tabwriterWidth = 4
227- tabwriterPadding = 3
228- tabwriterPadChar = ' '
229- )
230-
231- // getNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text.
232- func getNewTabWriter (output io.Writer ) * tabwriter.Writer {
233- return tabwriter .NewWriter (output , tabwriterMinWidth , tabwriterWidth , tabwriterPadding , tabwriterPadChar , 0 )
234- }
235-
236221var tableWriterReplacer = strings .NewReplacer (
237222 "\f " , " " ,
238223 "\n " , " " ,
239224 "\r " , " " ,
240225)
241226
242- func (t * Table ) renderUsingTabWriter () string {
243- buf := bytes .NewBuffer (nil )
244- w := getNewTabWriter (buf )
227+ func (t * Table ) renderUsingTabWriterLike () string {
245228 padding := strings .Repeat (" " , t .TableWriterPadding )
246229
247- if len (t .Headers ) > 0 {
248- capitalizedHeaders := []string {}
249- for _ , header := range t .Headers {
250- capitalizedHeaders = append (capitalizedHeaders , strings .ToUpper (header ))
230+ // Process rows and calculate column widths
231+ processedRows := make ([][]string , len (t .rows ))
232+ for i , row := range t .rows {
233+ processedRows [i ] = make ([]string , len (row ))
234+ for j , col := range row {
235+ if idx := strings .IndexAny (col , "\f \n \r " ); idx >= 0 {
236+ if TableConfig .TabWriterTruncate || t .TableWriterTruncate {
237+ col = col [:idx ] + " ..."
238+ } else {
239+ col = tableWriterReplacer .Replace (col )
240+ }
241+ }
242+ processedRows [i ][j ] = col
251243 }
252- fmt .Fprintln (w , padding + strings .Join (capitalizedHeaders , "\t " ))
253244 }
254245
255- for _ , row := range t .rows {
256- newRow := make ([]string , len (row ))
257- for i , column := range row {
258- breakchar := strings .IndexAny (column , "\f \n \r " )
259- if breakchar >= 0 {
260- if TableConfig .TabWriterTruncate || t .TableWriterTruncate {
261- column = column [:breakchar ] + " ..."
262- } else {
263- column = tableWriterReplacer .Replace (column )
246+ // Calculate column widths
247+ var numCols int
248+ if len (t .Headers ) > 0 {
249+ numCols = len (t .Headers )
250+ } else if len (processedRows ) > 0 {
251+ numCols = len (processedRows [0 ])
252+ }
253+ widths := make ([]int , numCols )
254+ for i , h := range t .Headers {
255+ if w := runeLen (h ); w > widths [i ] {
256+ widths [i ] = w
257+ }
258+ }
259+ for _ , row := range processedRows {
260+ for i , col := range row {
261+ if i < numCols {
262+ if w := runeLen (col ); w > widths [i ] {
263+ widths [i ] = w
264264 }
265265 }
266+ }
267+ }
266268
267- newRow [i ] = column
269+ // Build output
270+ var buf strings.Builder
271+ if len (t .Headers ) > 0 {
272+ buf .WriteString (padding )
273+ for i , h := range t .Headers {
274+ if i > 0 {
275+ buf .WriteString (" " )
276+ }
277+ buf .WriteString (strings .ToUpper (h ))
278+ if i < numCols - 1 {
279+ buf .WriteString (strings .Repeat (" " , widths [i ]- runeLen (h )))
280+ }
281+ }
282+ buf .WriteString ("\n " )
283+ }
284+ for _ , row := range processedRows {
285+ buf .WriteString (padding )
286+ for i , col := range row {
287+ if i > 0 {
288+ buf .WriteString (" " )
289+ }
290+ buf .WriteString (col )
291+ if i < numCols - 1 {
292+ buf .WriteString (strings .Repeat (" " , widths [i ]- runeLen (col )))
293+ }
268294 }
269- fmt . Fprintln ( w , padding + strings . Join ( newRow , " \t " ) )
295+ buf . WriteString ( " \n " )
270296 }
271- w .Flush ()
272297 return buf .String ()
273298}
274299
275300func (t * Table ) String () string {
276301 if TableConfig .UseTabWriter {
277- return t .renderUsingTabWriter ()
302+ return t .renderUsingTabWriterLike ()
278303 }
279304 if t .Headers == nil && len (t .rows ) < 1 {
280305 return ""
0 commit comments