Skip to content

Commit

Permalink
Merge pull request #3139 from ActiveState/DX-2578
Browse files Browse the repository at this point in the history
Fix table spacing and `omitEmpty` option
  • Loading branch information
MDrakos authored Mar 20, 2024
2 parents bdf5b45 + b07d536 commit d47d8ff
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 17 deletions.
71 changes: 57 additions & 14 deletions internal/output/plain.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@ func sprintTable(vertical bool, slice []interface{}) (string, error) {
return "", nil
}

if vertical {
return sprintVerticalTable(slice)
}

headers := []string{}
rows := [][]string{}
for _, v := range slice {
Expand Down Expand Up @@ -333,14 +337,58 @@ func sprintTable(vertical bool, slice []interface{}) (string, error) {
}
}

if vertical {
t := table.New([]string{"", ""})
t.AddRow(verticalRows(headers, rows)...)
t.HideHeaders = true
return t.Render(), nil
return table.New(headers).AddRow(rows...).Render(), nil
}

type verticalRow struct {
header string
content string
}

func sprintVerticalTable(slice []interface{}) (string, error) {
if len(slice) == 0 {
return "", nil
}

return table.New(headers).AddRow(rows...).Render(), nil
rows := [][]verticalRow{}
for _, v := range slice {
meta, err := parseStructMeta(v)
if err != nil {
return "", err
}

row := []verticalRow{}
for _, field := range meta {
if funk.Contains(field.opts, string(HidePlain)) {
continue
}

stringValue, err := sprint(field.value)
if err != nil {
return "", err
}

if funk.Contains(field.opts, string(OmitEmpty)) && (stringValue == "" || stringValue == nilText) {
continue
}

if funk.Contains(field.opts, string(EmptyNil)) && stringValue == nilText {
stringValue = ""
}

row = append(row, verticalRow{header: localizedField(field.l10n), content: stringValue})
}

if len(row) > 0 {
rows = append(rows, row)
}
}

t := table.New([]string{"", ""})
t.AddRow(verticalRows(rows)...)
t.HideHeaders = true
t.Vertical = true
return t.Render(), nil
}

func asSlice(val interface{}) ([]interface{}, error) {
Expand Down Expand Up @@ -402,17 +450,12 @@ func columns(offset int, value string) []string {
return cols
}

func verticalRows(hdrs []string, rows [][]string) [][]string {
func verticalRows(rows [][]verticalRow) [][]string {
var vrows [][]string

for i, hrow := range rows {
for j, hcol := range hrow {
var header string
if j < len(hdrs) {
header = hdrs[j]
}

vrow := []string{header, hcol}
for _, hcol := range hrow {
vrow := []string{hcol.header, hcol.content}
vrows = append(vrows, vrow)
}

Expand Down
25 changes: 23 additions & 2 deletions internal/table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Table struct {
rows []row

HideHeaders bool
Vertical bool
}

func New(headers []string) *Table {
Expand Down Expand Up @@ -103,6 +104,13 @@ func (t *Table) calculateWidth(maxTableWidth int) ([]int, int) {
colWidthsCombined += colWidths[n]
}

// Capture the width of the vertical header before we equalize the column widths.
// We must respect this width when rescaling the columns.
var verticalHeaderWidth int
if len(colWidths) > 0 && t.Vertical {
verticalHeaderWidth = colWidths[0]
}

if colWidthsCombined >= maxTableWidth {
// Equalize widths by 20% of average width.
// This is to prevent columns that are much larger than others
Expand All @@ -115,7 +123,7 @@ func (t *Table) calculateWidth(maxTableWidth int) ([]int, int) {
tableWidth = mathutils.MinInt(tableWidth, maxTableWidth)

// Now scale back the row sizes according to the max width
rescaleColumns(colWidths, tableWidth)
rescaleColumns(colWidths, tableWidth, t.Vertical, verticalHeaderWidth)
logging.Debug("Table column widths: %v, total: %d", colWidths, tableWidth)

return colWidths, tableWidth
Expand All @@ -138,18 +146,31 @@ func equalizeWidths(colWidths []int, percentage int) {
}
}

func rescaleColumns(colWidths []int, targetTotal int) {
func rescaleColumns(colWidths []int, targetTotal int, vertical bool, verticalHeaderWidth int) {
total := float64(mathutils.Total(colWidths...))
multiplier := float64(targetTotal) / total

originalWidths := make([]int, len(colWidths))
for n := range colWidths {
originalWidths[n] = colWidths[n]
colWidths[n] = int(float64(colWidths[n]) * multiplier)
}

// Account for floats that got rounded
if len(colWidths) > 0 {
colWidths[len(colWidths)-1] += targetTotal - mathutils.Total(colWidths...)
}

// If vertical, respect the header width
// verticalHeaderWidth is the width of the header column before we equalized the column widths.
// We compare the current width of the header column with the original width and adjust the other columns accordingly.
if vertical && len(colWidths) > 0 && colWidths[0] < verticalHeaderWidth {
diff := verticalHeaderWidth - colWidths[0]
colWidths[0] += diff
for i := 1; i < len(colWidths); i++ {
colWidths[i] -= diff / (len(colWidths) - 1)
}
}
}

func renderRow(providedColumns []string, colWidths []int) string {
Expand Down
9 changes: 8 additions & 1 deletion internal/table/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{"1", "2", "3"}},
},
false,
false,
},
100,
},
Expand All @@ -42,6 +43,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{"1", "2", "3"}},
},
false,
false,
},
100,
},
Expand All @@ -57,6 +59,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{"1", "0123456789012345678901234567890123456789"}},
},
false,
false,
},
100,
},
Expand All @@ -71,6 +74,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{"123", "1234", "12345"}},
},
false,
false,
},
100,
},
Expand All @@ -85,6 +89,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{"1", "2", "3"}},
},
false,
false,
},
100,
},
Expand All @@ -100,6 +105,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{strings.Repeat(" ", 100)}},
},
false,
false,
},
100,
},
Expand All @@ -115,6 +121,7 @@ func TestTable_colWidths(t1 *testing.T) {
{[]string{"1", strings.Repeat(" ", 200)}},
},
false,
false,
},
100,
},
Expand Down Expand Up @@ -333,7 +340,7 @@ func Test_rescaleColumns(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rescaleColumns(tt.args.colWidths, tt.args.targetTotal)
rescaleColumns(tt.args.colWidths, tt.args.targetTotal, false, tt.args.colWidths[0])
if !reflect.DeepEqual(tt.args.colWidths, tt.want) {
t.Errorf("rescaleColumns() got = %v, want %v", tt.args.colWidths, tt.want)
}
Expand Down

0 comments on commit d47d8ff

Please sign in to comment.