mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-13 09:28:01 -05:00
108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
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"
|
|
"github.com/rs/zerolog/log"
|
|
"golang.org/x/term"
|
|
)
|
|
|
|
type TableOptions struct {
|
|
Title string
|
|
}
|
|
|
|
// func GetDefaultTableOptions() TableOptions{
|
|
// return TableOptions{
|
|
// Title: "",
|
|
// }
|
|
// }
|
|
|
|
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 [3]string, rows [][3]string) {
|
|
// if we're not in a terminal or cygwin terminal, don't truncate the secret value
|
|
shouldTruncate := isatty.IsTerminal(os.Stdout.Fd())
|
|
|
|
// This will return an error if we're not in a terminal or
|
|
// if the terminal is a cygwin terminal like Git Bash.
|
|
width, _, err := term.GetSize(int(os.Stdout.Fd()))
|
|
if err != nil {
|
|
if shouldTruncate {
|
|
log.Error().Msgf("error getting terminal size: %s", err)
|
|
} else {
|
|
log.Debug().Err(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)
|
|
|
|
// t.SetTitle(tableOptions.Title)
|
|
t.Style().Options.DrawBorder = true
|
|
t.Style().Options.SeparateHeader = true
|
|
t.Style().Options.SeparateColumns = true
|
|
|
|
tableHeaders := table.Row{}
|
|
for _, header := range headers {
|
|
tableHeaders = append(tableHeaders, header)
|
|
}
|
|
|
|
t.AppendHeader(tableHeaders)
|
|
for _, row := range rows {
|
|
tableRow := table.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)
|
|
}
|
|
|
|
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
|
|
}
|