feat(list): limits column widths to fit on-screen
This commit is contained in:
parent
5ba0ff1e31
commit
d96b0f7a2c
1 changed files with 115 additions and 5 deletions
120
cmd/list.go
120
cmd/list.go
|
|
@ -24,10 +24,15 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/dgraph-io/badger/v4"
|
"github.com/dgraph-io/badger/v4"
|
||||||
"github.com/jedib0t/go-pretty/v6/table"
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
|
"github.com/jedib0t/go-pretty/v6/text"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
// listCmd represents the set command
|
// listCmd represents the set command
|
||||||
|
|
@ -102,9 +107,13 @@ func list(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("no columns selected; enable key, value, or ttl output")
|
return fmt.Errorf("no columns selected; enable key, value, or ttl output")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output := cmd.OutOrStdout()
|
||||||
tw := table.NewWriter()
|
tw := table.NewWriter()
|
||||||
tw.SetOutputMirror(cmd.OutOrStdout())
|
tw.SetOutputMirror(output)
|
||||||
configureListTable(tw)
|
configureListTable(tw)
|
||||||
|
if shouldLimitColumns(format) {
|
||||||
|
applyColumnConstraints(tw, columnKinds, output)
|
||||||
|
}
|
||||||
|
|
||||||
if !noHeader {
|
if !noHeader {
|
||||||
header := buildHeaderCells(columnKinds)
|
header := buildHeaderCells(columnKinds)
|
||||||
|
|
@ -237,8 +246,109 @@ func stringSliceToRow(values []string) table.Row {
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureListTable(tw table.Writer) {
|
func configureListTable(tw table.Writer) {
|
||||||
tw.SetStyle(table.StyleColoredBright)
|
tw.SetStyle(table.StyleColoredBlackOnGreenWhite)
|
||||||
tw.SetColumnConfigs([]table.ColumnConfig{
|
}
|
||||||
{Number: 2, WidthMax: 20},
|
|
||||||
})
|
func shouldLimitColumns(format string) bool {
|
||||||
|
switch format {
|
||||||
|
case "auto", "table", "tabular":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyColumnConstraints(tw table.Writer, columns []columnKind, out io.Writer) {
|
||||||
|
totalWidth := detectTerminalWidth(out)
|
||||||
|
if totalWidth <= 0 {
|
||||||
|
totalWidth = 100
|
||||||
|
}
|
||||||
|
widths := distributeWidths(totalWidth, columns)
|
||||||
|
configs := make([]table.ColumnConfig, 0, len(columns))
|
||||||
|
for idx, width := range widths {
|
||||||
|
configs = append(configs, table.ColumnConfig{
|
||||||
|
Number: idx + 1,
|
||||||
|
WidthMax: width,
|
||||||
|
WidthMaxEnforcer: text.WrapText,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
tw.SetColumnConfigs(configs)
|
||||||
|
tw.SetAllowedRowLength(totalWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fdWriter interface {
|
||||||
|
Fd() uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
func detectTerminalWidth(out io.Writer) int {
|
||||||
|
if f, ok := out.(fdWriter); ok {
|
||||||
|
if w, _, err := term.GetSize(int(f.Fd())); err == nil && w > 0 {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w, _, err := term.GetSize(int(os.Stdout.Fd())); err == nil && w > 0 {
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
if cols := os.Getenv("COLUMNS"); cols != "" {
|
||||||
|
if parsed, err := strconv.Atoi(cols); err == nil && parsed > 0 {
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func distributeWidths(total int, columns []columnKind) []int {
|
||||||
|
if total <= 0 {
|
||||||
|
total = 100
|
||||||
|
}
|
||||||
|
hasTTL := false
|
||||||
|
for _, c := range columns {
|
||||||
|
if c == columnTTL {
|
||||||
|
hasTTL = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base := make([]float64, len(columns))
|
||||||
|
sum := 0.0
|
||||||
|
for i, c := range columns {
|
||||||
|
pct := basePercentageForColumn(c, hasTTL)
|
||||||
|
base[i] = pct
|
||||||
|
sum += pct
|
||||||
|
}
|
||||||
|
if sum == 0 {
|
||||||
|
sum = 1
|
||||||
|
}
|
||||||
|
widths := make([]int, len(columns))
|
||||||
|
remaining := total
|
||||||
|
const minColWidth = 10
|
||||||
|
for i := range columns {
|
||||||
|
width := int((base[i] / sum) * float64(total))
|
||||||
|
if width < minColWidth {
|
||||||
|
width = minColWidth
|
||||||
|
}
|
||||||
|
widths[i] = width
|
||||||
|
remaining -= width
|
||||||
|
}
|
||||||
|
for i := 0; remaining > 0 && len(columns) > 0; i++ {
|
||||||
|
idx := i % len(columns)
|
||||||
|
widths[idx]++
|
||||||
|
remaining--
|
||||||
|
}
|
||||||
|
return widths
|
||||||
|
}
|
||||||
|
|
||||||
|
func basePercentageForColumn(c columnKind, hasTTL bool) float64 {
|
||||||
|
switch c {
|
||||||
|
case columnKey:
|
||||||
|
return 0.25
|
||||||
|
case columnValue:
|
||||||
|
if hasTTL {
|
||||||
|
return 0.5
|
||||||
|
}
|
||||||
|
return 0.75
|
||||||
|
case columnTTL:
|
||||||
|
return 0.25
|
||||||
|
default:
|
||||||
|
return 0.25
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue