github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+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 columns := len(table[0]) 27 28 if columns < 2 || !ui.IsTTY { 29 ui.DisplayNonWrappingTable(prefix, table, padding) 30 return 31 } 32 33 ui.displayWrappingTableWithWidth(prefix, table, padding) 34 } 35 36 // DisplayNonWrappingTable outputs a matrix of strings as a table to UI.Out. 37 // Prefix will be prepended to each row and padding adds the specified number 38 // of spaces between columns. 39 func (ui *UI) DisplayNonWrappingTable(prefix string, table [][]string, padding int) { 40 ui.terminalLock.Lock() 41 defer ui.terminalLock.Unlock() 42 43 if len(table) == 0 { 44 return 45 } 46 47 var columnPadding []int 48 49 rows := len(table) 50 columns := len(table[0]) 51 for col := 0; col < columns; col++ { 52 var max int 53 for row := 0; row < rows; row++ { 54 if strLen := wordSize(table[row][col]); max < strLen { 55 max = strLen 56 } 57 } 58 columnPadding = append(columnPadding, max+padding) 59 } 60 61 for row := 0; row < rows; row++ { 62 fmt.Fprintf(ui.Out, prefix) 63 for col := 0; col < columns; col++ { 64 data := table[row][col] 65 var addedPadding int 66 if col+1 != columns { 67 addedPadding = columnPadding[col] - wordSize(data) 68 } 69 fmt.Fprintf(ui.Out, "%s%s", data, strings.Repeat(" ", addedPadding)) 70 } 71 fmt.Fprintf(ui.Out, "\n") 72 } 73 } 74 75 // DisplayTableWithHeader outputs a simple non-wrapping table with bolded 76 // headers. 77 func (ui *UI) DisplayTableWithHeader(prefix string, table [][]string, padding int) { 78 if len(table) == 0 { 79 return 80 } 81 for i, str := range table[0] { 82 table[0][i] = ui.modifyColor(str, color.New(color.Bold)) 83 } 84 85 ui.DisplayNonWrappingTable(prefix, table, padding) 86 } 87 88 func wordSize(str string) int { 89 cleanStr := vtclean.Clean(str, false) 90 return runewidth.StringWidth(cleanStr) 91 }