feat: truncate secret value if terminal is too small

This commit is contained in:
jon4hz
2023-03-10 21:19:56 +01:00
parent 14206de926
commit c900022697
5 changed files with 77 additions and 10 deletions

View File

@@ -2,8 +2,14 @@ package visualize
import (
"os"
"strings"
"github.com/jedib0t/go-pretty/table"
"github.com/mattn/go-isatty"
"github.com/muesli/ansi"
"github.com/muesli/reflow/truncate"
log "github.com/sirupsen/logrus"
"golang.org/x/term"
)
type TableOptions struct {
@@ -16,8 +22,33 @@ type TableOptions struct {
// }
// }
const (
// combined width of the table borders and padding
borderWidths = 10
// char to indicate that a string has been truncated
ellipsis = "…"
)
// Given headers and rows, this function will print out a table
func Table(headers []string, rows [][]string) {
func Table(headers [3]string, rows [][3]string) {
// if we're not in a terminal, don't truncate the secret value
shouldTruncate := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
width, _, err := term.GetSize(int(os.Stdout.Fd()))
if err != nil {
if shouldTruncate {
log.Errorf("error getting terminal size: %s", err)
} else {
log.Debug(err)
}
}
longestSecretName, longestSecretType := getLongestValues(append(rows, headers))
availableWidth := width - longestSecretName - longestSecretType - borderWidths
if availableWidth < 0 {
availableWidth = 0
}
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.SetStyle(table.StyleLight)
@@ -35,7 +66,11 @@ func Table(headers []string, rows [][]string) {
t.AppendHeader(tableHeaders)
for _, row := range rows {
tableRow := table.Row{}
for _, val := range row {
for i, val := range row {
// only truncate the first column (secret value)
if i == 1 && stringWidth(val) > availableWidth && shouldTruncate {
val = truncate.StringWithTail(val, uint(availableWidth), ellipsis)
}
tableRow = append(tableRow, val)
}
t.AppendRow(tableRow)
@@ -43,3 +78,28 @@ func Table(headers []string, rows [][]string) {
t.Render()
}
// getLongestValues returns the length of the longest secret name and type from all rows (including the header).
func getLongestValues(rows [][3]string) (longestSecretName, longestSecretType int) {
for _, row := range rows {
if len(row[0]) > longestSecretName {
longestSecretName = stringWidth(row[0])
}
if len(row[2]) > longestSecretType {
longestSecretType = stringWidth(row[2])
}
}
return
}
// stringWidth returns the width of a string.
// ANSI escape sequences are ignored and double-width characters are handled correctly.
func stringWidth(str string) (width int) {
for _, l := range strings.Split(str, "\n") {
w := ansi.PrintableRuneWidth(l)
if w > width {
width = w
}
}
return width
}