Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

Commit

Permalink
make it generic
Browse files Browse the repository at this point in the history
Signed-off-by: Doug Davis <dug@us.ibm.com>
  • Loading branch information
Doug Davis committed Jul 24, 2018
1 parent b9a47ba commit 4a5c773
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 45 deletions.
21 changes: 1 addition & 20 deletions cmd/svcat/output/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,12 @@ func getClassStatusText(status v1beta1.ClusterServiceClassStatus) string {
func writeClassListTable(w io.Writer, classes []servicecatalog.Class) {
t := NewListTable(w)

// Pre-parse the data so we allow the last column to be really wide.
// We can't set the MinWidth after data has been loaded
maxNameWidth := len("Name")
maxNSWidth := len("Namespace")
maxDescWidth := len("Description")
for _, class := range classes {
if tmp := len(class.GetExternalName()); tmp > maxNameWidth {
maxNameWidth = tmp
}
if tmp := len(class.GetNamespace()); tmp > maxNSWidth {
maxNSWidth = tmp
}
if tmp := len(class.GetDescription()); tmp > maxDescWidth {
maxDescWidth = tmp
}
}
if tmp := (80 - (maxNameWidth + maxNSWidth + 11)); tmp > maxDescWidth {
t.SetColMinWidth(2, tmp)
}

t.SetHeader([]string{
"Name",
"Namespace",
"Description",
})
t.SetVariableColumn(3)

for _, class := range classes {
t.Append([]string{
Expand Down
24 changes: 1 addition & 23 deletions cmd/svcat/output/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,36 +57,14 @@ func writePlanListTable(w io.Writer, plans []v1beta1.ClusterServicePlan, classNa
"Class",
"Description",
})

// Pre-parse the data so we allow the last column to be really wide.
// We can't set the MinWidth after data has been loaded
maxNameWidth := len("Name")
maxClassWidth := len("Class")
maxDescWidth := len("Description")

for _, plan := range plans {
if tmp := len(plan.Spec.ExternalName); tmp > maxNameWidth {
maxNameWidth = tmp
}
tmp := len(classNames[plan.Spec.ClusterServiceClassRef.Name])
if tmp > maxClassWidth {
maxClassWidth = tmp
}
if tmp := len(plan.Spec.Description); tmp > maxDescWidth {
maxDescWidth = tmp
}
}
if tmp := (80 - (maxNameWidth + maxClassWidth + 11)); tmp > maxDescWidth {
t.SetColMinWidth(2, tmp)
}

for _, plan := range plans {
t.Append([]string{
plan.Spec.ExternalName,
classNames[plan.Spec.ClusterServiceClassRef.Name],
plan.Spec.Description,
})
}
t.SetVariableColumn(3)

t.Render()
}
Expand Down
104 changes: 102 additions & 2 deletions cmd/svcat/output/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,112 @@ import (
"github.com/olekukonko/tablewriter"
)

const DEFAULT_PAGE_WIDTH = 80

// ListTable is a proxy for tablewriter.Table so we can support variable a
// width column that tries to full up extract space.
// For each func on tablewriter.Table we'll need a proxy func.
// We save the headers and rows and only send them on when Render() is called
// because the tablewriter stuff won't process the call to SetColMinWidth
// if its called after some rows have been added. So we need to calc the
// value of our special column first, call SetColMinWidth and then add the
// headers/rows.

type ListTable struct {
table *tablewriter.Table

columnWidths []int // Max width of data in column we've seen
variableColumn int // 0 == not set
pageWidth int // Defaults to 80
headers []string
rows [][]string
}

// Just some proxy funcs
func (lt *ListTable) SetBorder(b bool) { lt.table.SetBorder(b) }
func (lt *ListTable) SetVariableColumn(c int) { lt.variableColumn = c }
func (lt *ListTable) SetColMinWidth(c, w int) { lt.table.SetColMinWidth(c, w) }
func (lt *ListTable) SetPageWidth(w int) { lt.pageWidth = w }

// Track the width of each header value as we save them
func (lt *ListTable) SetHeader(keys []string) {
if tmp := (len(keys) - len(lt.columnWidths)); tmp > 0 {
lt.columnWidths = append(lt.columnWidths, make([]int, tmp)...)
}

for i, header := range keys {
if tmp := len(header); tmp > lt.columnWidths[i] {
lt.columnWidths[i] = tmp
}
}

// Save the headers for when we call Render
lt.headers = keys
}

// For each column in the row see if its longer than any previous value, and
// save it if so.
func (lt *ListTable) Append(row []string) {
// Expand our slice if needed
if tmp := (len(row) - len(lt.columnWidths)); tmp > 0 {
lt.columnWidths = append(lt.columnWidths, make([]int, tmp)...)
}

// Look for a wider cell than what we've seen before
for i, cell := range row {
if tmp := len(cell); tmp > lt.columnWidths[i] {
lt.columnWidths[i] = tmp
}
}

// Just save the row for when we call Render
lt.rows = append(lt.rows, row)
}

// Calc the width of the variable column if asked to.
// Then pass our headers and rows to the real Render func
func (lt *ListTable) Render() {
if lt.variableColumn > 0 && lt.variableColumn <= len(lt.columnWidths)+1 {
// Add up the width of all columns except our special one
total := 2 // 2 == left border + space
for i, w := range lt.columnWidths {
if i+1 != lt.variableColumn {
total = total + 3 + w // 2 == space before/after text + col-sep
}
}

// Space left for our special column if we use the full page width
remaining := lt.pageWidth - total - 3 // 3 == space+border of this col

// If this column doesn't push us past the page width then just
// set it to the max cell width so Render() doesn't chop it on us.
// Otherwise, chop it so we don't go page the page width.
colWidth := lt.columnWidths[lt.variableColumn-1]
if remaining >= colWidth {
lt.SetColMinWidth(lt.variableColumn-1, colWidth)
} else {
lt.SetColMinWidth(lt.variableColumn-1, remaining)
}
}

// Pass along all of the data (header and rows) to the real tablewriter
lt.table.SetHeader(lt.headers)
for _, row := range lt.rows {
lt.table.Append(row)
}
lt.table.Render()
}

// NewListTable builds a table formatted to list a set of results.
func NewListTable(w io.Writer) *tablewriter.Table {
func NewListTable(w io.Writer) *ListTable {
t := tablewriter.NewWriter(w)
t.SetBorder(false)
t.SetColumnSeparator(" ")
return t

return &ListTable{
table: t,
pageWidth: DEFAULT_PAGE_WIDTH,
}
}

// NewDetailsTable builds a table formatted to list details for a single result.
Expand Down

0 comments on commit 4a5c773

Please sign in to comment.