feat(list): swaps out manual format parsing for a formatEnum implementing pflag.Value
This commit is contained in:
parent
a86100e045
commit
b99655a293
1 changed files with 58 additions and 123 deletions
173
cmd/list.go
173
cmd/list.go
|
|
@ -49,7 +49,7 @@ type ListArgs struct {
|
||||||
ttl bool
|
ttl bool
|
||||||
binary bool
|
binary bool
|
||||||
secrets bool
|
secrets bool
|
||||||
format *listFormat
|
render func(table.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
type listFormat struct {
|
type listFormat struct {
|
||||||
|
|
@ -58,58 +58,6 @@ type listFormat struct {
|
||||||
render func(table.Writer)
|
render func(table.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
defaultTableStyle = table.StyleDefault
|
|
||||||
plainTableStyle = table.StyleDefault
|
|
||||||
|
|
||||||
tableStylePresets = map[string]*table.Style{
|
|
||||||
"table": &defaultTableStyle,
|
|
||||||
"tabular": &defaultTableStyle,
|
|
||||||
"table-dark": &table.StyleColoredDark,
|
|
||||||
"table-bright": &table.StyleColoredBright,
|
|
||||||
}
|
|
||||||
|
|
||||||
supportedListFormats = buildSupportedListFormats()
|
|
||||||
)
|
|
||||||
|
|
||||||
func buildSupportedListFormats() map[string]*listFormat {
|
|
||||||
markdownSpec := &listFormat{
|
|
||||||
style: &plainTableStyle,
|
|
||||||
render: func(tw table.Writer) {
|
|
||||||
tw.RenderMarkdown()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
formats := map[string]*listFormat{
|
|
||||||
"csv": {
|
|
||||||
style: &plainTableStyle,
|
|
||||||
render: func(tw table.Writer) {
|
|
||||||
tw.RenderCSV()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"html": {
|
|
||||||
style: &plainTableStyle,
|
|
||||||
render: func(tw table.Writer) {
|
|
||||||
tw.RenderHTML()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"markdown": markdownSpec,
|
|
||||||
"md": markdownSpec,
|
|
||||||
}
|
|
||||||
for name, style := range tableStylePresets {
|
|
||||||
formats[name] = &listFormat{
|
|
||||||
limitColumns: true,
|
|
||||||
style: style,
|
|
||||||
render: func(tw table.Writer) {
|
|
||||||
tw.Render()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if defaultSpec, ok := formats["table"]; ok {
|
|
||||||
formats["auto"] = defaultSpec
|
|
||||||
}
|
|
||||||
return formats
|
|
||||||
}
|
|
||||||
|
|
||||||
func list(cmd *cobra.Command, args []string) error {
|
func list(cmd *cobra.Command, args []string) error {
|
||||||
store := &Store{}
|
store := &Store{}
|
||||||
targetDB := "@default"
|
targetDB := "@default"
|
||||||
|
|
@ -142,24 +90,14 @@ func list(cmd *cobra.Command, args []string) error {
|
||||||
output := cmd.OutOrStdout()
|
output := cmd.OutOrStdout()
|
||||||
tw := table.NewWriter()
|
tw := table.NewWriter()
|
||||||
tw.SetOutputMirror(output)
|
tw.SetOutputMirror(output)
|
||||||
|
tw.SetStyle(table.StyleLight)
|
||||||
|
|
||||||
formatSpec := flags.format
|
|
||||||
if formatSpec != nil && formatSpec.style != nil {
|
|
||||||
tw.SetStyle(*formatSpec.style)
|
|
||||||
} else {
|
|
||||||
tw.SetStyle(defaultTableStyle)
|
|
||||||
}
|
|
||||||
limitColumns := formatSpec != nil && formatSpec.limitColumns
|
|
||||||
var maxContentWidths []int
|
var maxContentWidths []int
|
||||||
if limitColumns {
|
|
||||||
maxContentWidths = make([]int, len(columnKinds))
|
maxContentWidths = make([]int, len(columnKinds))
|
||||||
}
|
|
||||||
|
|
||||||
if flags.header {
|
if flags.header {
|
||||||
header := buildHeaderCells(columnKinds)
|
header := buildHeaderCells(columnKinds)
|
||||||
if limitColumns {
|
|
||||||
updateMaxContentWidths(maxContentWidths, header)
|
updateMaxContentWidths(maxContentWidths, header)
|
||||||
}
|
|
||||||
tw.AppendHeader(stringSliceToRow(header))
|
tw.AppendHeader(stringSliceToRow(header))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,9 +145,7 @@ func list(cmd *cobra.Command, args []string) error {
|
||||||
columns = append(columns, formatExpiry(item.ExpiresAt()))
|
columns = append(columns, formatExpiry(item.ExpiresAt()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if limitColumns {
|
|
||||||
updateMaxContentWidths(maxContentWidths, columns)
|
updateMaxContentWidths(maxContentWidths, columns)
|
||||||
}
|
|
||||||
tw.AppendRow(stringSliceToRow(columns))
|
tw.AppendRow(stringSliceToRow(columns))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -220,61 +156,67 @@ func list(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if limitColumns {
|
|
||||||
applyColumnConstraints(tw, columnKinds, output, maxContentWidths)
|
applyColumnConstraints(tw, columnKinds, output, maxContentWidths)
|
||||||
}
|
|
||||||
|
|
||||||
if formatSpec != nil && formatSpec.render != nil {
|
flags.render(tw)
|
||||||
formatSpec.render(tw)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatEnum implements pflag.Value
|
||||||
|
type formatEnum string
|
||||||
|
|
||||||
|
func (e *formatEnum) String() string {
|
||||||
|
return string(*e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *formatEnum) Set(v string) error {
|
||||||
|
switch v {
|
||||||
|
case "table", "csv", "html", "markdown":
|
||||||
|
*e = formatEnum(v)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return errors.New(`must be one of "table", "csv", "html", or "markdown"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *formatEnum) Type() string {
|
||||||
|
return "format"
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
binary bool = false
|
||||||
|
secret bool = false
|
||||||
|
noKeys bool = false
|
||||||
|
noValues bool = false
|
||||||
|
ttl bool = false
|
||||||
|
noHeader bool = false
|
||||||
|
format formatEnum = "table"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
listCmd.Flags().BoolP("binary", "b", false, "include binary data in text output")
|
listCmd.Flags().BoolVarP(&binary, "binary", "b", false, "include binary data in text output")
|
||||||
listCmd.Flags().BoolP("secret", "S", false, "display values marked as secret")
|
listCmd.Flags().BoolVarP(&secret, "secret", "S", false, "display values marked as secret")
|
||||||
listCmd.Flags().Bool("no-keys", false, "suppress the key column")
|
listCmd.Flags().BoolVar(&noKeys, "no-keys", false, "suppress the key column")
|
||||||
listCmd.Flags().Bool("no-values", false, "suppress the value column")
|
listCmd.Flags().BoolVar(&noValues, "no-values", false, "suppress the value column")
|
||||||
listCmd.Flags().BoolP("ttl", "t", false, "append a TTL column when entries expire")
|
listCmd.Flags().BoolVarP(&ttl, "ttl", "t", false, "append a TTL column when entries expire")
|
||||||
listCmd.Flags().Bool("no-header", false, "omit the header rows")
|
listCmd.Flags().BoolVar(&noHeader, "no-header", false, "omit the header rows")
|
||||||
listCmd.Flags().StringP("format", "f", "table", "supports: table[-dark/-bright], csv, html, markdown")
|
listCmd.Flags().VarP(&format, "format", "o", "render output format (table|csv|markdown|html)")
|
||||||
rootCmd.AddCommand(listCmd)
|
rootCmd.AddCommand(listCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseFlags(cmd *cobra.Command) (ListArgs, error) {
|
func parseFlags(cmd *cobra.Command) (ListArgs, error) {
|
||||||
secrets, err := cmd.Flags().GetBool("secret")
|
var renderFunc func(tw table.Writer)
|
||||||
if err != nil {
|
switch format.String() {
|
||||||
return ListArgs{}, err
|
case "csv":
|
||||||
}
|
renderFunc = func(tw table.Writer) { tw.RenderCSV() }
|
||||||
noKeys, err := cmd.Flags().GetBool("no-keys")
|
case "html":
|
||||||
if err != nil {
|
renderFunc = func(tw table.Writer) { tw.RenderHTML() }
|
||||||
return ListArgs{}, err
|
case "markdown":
|
||||||
}
|
renderFunc = func(tw table.Writer) { tw.RenderMarkdown() }
|
||||||
noValues, err := cmd.Flags().GetBool("no-values")
|
default:
|
||||||
if err != nil {
|
renderFunc = func(tw table.Writer) { tw.Render() }
|
||||||
return ListArgs{}, err
|
|
||||||
}
|
|
||||||
ttl, err := cmd.Flags().GetBool("ttl")
|
|
||||||
if err != nil {
|
|
||||||
return ListArgs{}, err
|
|
||||||
}
|
|
||||||
noHeader, err := cmd.Flags().GetBool("no-header")
|
|
||||||
if err != nil {
|
|
||||||
return ListArgs{}, err
|
|
||||||
}
|
|
||||||
binary, err := cmd.Flags().GetBool("binary")
|
|
||||||
if err != nil {
|
|
||||||
return ListArgs{}, err
|
|
||||||
}
|
|
||||||
formatName, err := cmd.Flags().GetString("format")
|
|
||||||
if err != nil {
|
|
||||||
return ListArgs{}, err
|
|
||||||
}
|
|
||||||
formatSpec, err := resolveListFormat(formatName)
|
|
||||||
if err != nil {
|
|
||||||
return ListArgs{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
if noKeys && noValues && !ttl {
|
if noKeys && noValues && !ttl {
|
||||||
return ListArgs{}, fmt.Errorf("no columns selected; disable --no-keys/--no-values or pass --ttl")
|
return ListArgs{}, fmt.Errorf("no columns selected; disable --no-keys/--no-values or pass --ttl")
|
||||||
}
|
}
|
||||||
|
|
@ -285,18 +227,11 @@ func parseFlags(cmd *cobra.Command) (ListArgs, error) {
|
||||||
value: !noValues,
|
value: !noValues,
|
||||||
ttl: ttl,
|
ttl: ttl,
|
||||||
binary: binary,
|
binary: binary,
|
||||||
format: formatSpec,
|
render: renderFunc,
|
||||||
secrets: secrets,
|
secrets: secret,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveListFormat(name string) (*listFormat, error) {
|
|
||||||
if spec, ok := supportedListFormats[name]; ok {
|
|
||||||
return spec, nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("unsupported format %q", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
type columnKind int
|
type columnKind int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue