github.com/cloudfoundry/cli@v7.1.0+incompatible/util/ui/table.go (about) 1 package ui 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/fatih/color" 8 "github.com/lunixbochs/vtclean" 9 runewidth "github.com/mattn/go-runewidth" 10 ) 11 12 // DefaultTableSpacePadding is the default space padding in tables. 13 const DefaultTableSpacePadding = 3 14 15 // DisplayKeyValueTable outputs a matrix of strings as a table to UI.Out. 16 // Prefix will be prepended to each row and padding adds the specified number 17 // of spaces between columns. The final columns may wrap to multiple lines but 18 // will still be confined to the last column. Wrapping will occur on word 19 // boundaries. 20 func (ui *UI) DisplayKeyValueTable(prefix string, table [][]string, padding int) { 21 rows := len(table) 22 if rows == 0 { 23 return 24 } 25 26 var displayTable [][]string 27 for _, row := range table { 28 if len(row) > 0 { 29 displayTable = append(displayTable, row) 30 } 31 } 32 columns := len(displayTable[0]) 33 34 if columns < 2 || !ui.IsTTY { 35 ui.DisplayNonWrappingTable(prefix, displayTable, padding) 36 return 37 } 38 39 ui.displayWrappingTableWithWidth(prefix, displayTable, padding) 40 } 41 42 // DisplayNonWrappingTable outputs a matrix of strings as a table to UI.Out. 43 // Prefix will be prepended to each row and padding adds the specified number 44 // of spaces between columns. 45 func (ui *UI) DisplayNonWrappingTable(prefix string, table [][]string, padding int) { 46 ui.terminalLock.Lock() 47 defer ui.terminalLock.Unlock() 48 49 if len(table) == 0 { 50 return 51 } 52 53 var columnPadding []int 54 55 rows := len(table) 56 columns := len(table[0]) 57 for col := 0; col < columns; col++ { 58 var max int 59 for row := 0; row < rows; row++ { 60 if strLen := wordSize(table[row][col]); max < strLen { 61 max = strLen 62 } 63 } 64 columnPadding = append(columnPadding, max+padding) 65 } 66 67 for row := 0; row < rows; row++ { 68 fmt.Fprint(ui.Out, prefix) 69 for col := 0; col < columns; col++ { 70 data := table[row][col] 71 var addedPadding int 72 if col+1 != columns { 73 addedPadding = columnPadding[col] - wordSize(data) 74 } 75 fmt.Fprintf(ui.Out, "%s%s", data, strings.Repeat(" ", addedPadding)) 76 } 77 fmt.Fprintf(ui.Out, "\n") 78 } 79 } 80 81 // DisplayTableWithHeader outputs a simple non-wrapping table with bolded 82 // headers. 83 func (ui *UI) DisplayTableWithHeader(prefix string, table [][]string, padding int) { 84 if len(table) == 0 { 85 return 86 } 87 for i, str := range table[0] { 88 table[0][i] = ui.modifyColor(str, color.New(color.Bold)) 89 } 90 91 ui.DisplayNonWrappingTable(prefix, table, padding) 92 } 93 94 func wordSize(str string) int { 95 cleanStr := vtclean.Clean(str, false) 96 return runewidth.StringWidth(cleanStr) 97 }