1 package cmdx
2
3 import (
4 "encoding/json"
5 "fmt"
6 "io"
7 "strings"
8 "text/tabwriter"
9
10 "github.com/spf13/cobra"
11 "github.com/spf13/pflag"
12 )
13
14 type (
15 TableHeader interface {
16 Header() []string
17 }
18 TableRow interface {
19 TableHeader
20 Columns() []string
21 Interface() interface{}
22 }
23 Table interface {
24 TableHeader
25 Table() [][]string
26 Interface() interface{}
27 Len() int
28 }
29
30 format string
31 )
32
33 const (
34 FormatQuiet format = "quiet"
35 FormatTable format = "table"
36 FormatJSON format = "json"
37 FormatJSONPretty format = "json-pretty"
38 FormatDefault format = "default"
39
40 FlagFormat = "format"
41
42 None = "<none>"
43 )
44
45 func PrintErrors(cmd *cobra.Command, errs map[string]error) {
46 for src, err := range errs {
47 fmt.Fprintf(cmd.ErrOrStderr(), "%s: %s\n", src, err.Error())
48 }
49 }
50
51 func PrintRow(cmd *cobra.Command, row TableRow) {
52 f := getFormat(cmd)
53
54 switch f {
55 case FormatQuiet:
56 if idAble, ok := row.(interface{ ID() string }); ok {
57 fmt.Fprintln(cmd.OutOrStdout(), idAble.ID())
58 break
59 }
60 fmt.Fprintln(cmd.OutOrStdout(), row.Columns()[0])
61 case FormatJSON:
62 printJSON(cmd.OutOrStdout(), row.Interface(), false)
63 case FormatJSONPretty:
64 printJSON(cmd.OutOrStdout(), row.Interface(), true)
65 case FormatTable, FormatDefault:
66 w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 8, 1, '\t', 0)
67
68 fields := row.Columns()
69 for i, h := range row.Header() {
70 fmt.Fprintf(w, "%s\t%s\t\n", h, fields[i])
71 }
72
73 w.Flush()
74 }
75 }
76
77 func PrintTable(cmd *cobra.Command, table Table) {
78 f := getFormat(cmd)
79
80 switch f {
81 case FormatQuiet:
82 if table.Len() == 0 {
83 fmt.Fprintln(cmd.OutOrStdout())
84 }
85
86 if idAble, ok := table.(interface{ IDs() []string }); ok {
87 for _, row := range idAble.IDs() {
88 fmt.Fprintln(cmd.OutOrStdout(), row)
89 }
90 break
91 }
92
93 for _, row := range table.Table() {
94 fmt.Fprintln(cmd.OutOrStdout(), row[0])
95 }
96 case FormatJSON:
97 printJSON(cmd.OutOrStdout(), table.Interface(), false)
98 case FormatJSONPretty:
99 printJSON(cmd.OutOrStdout(), table.Interface(), true)
100 default:
101 w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 8, 1, '\t', 0)
102
103 for _, h := range table.Header() {
104 fmt.Fprintf(w, "%s\t", h)
105 }
106 fmt.Fprintln(w)
107
108 for _, row := range table.Table() {
109 fmt.Fprintln(w, strings.Join(row, "\t")+"\t")
110 }
111
112 w.Flush()
113 }
114 }
115
116 func PrintJSONAble(cmd *cobra.Command, d interface{ String() string }) {
117 switch getFormat(cmd) {
118 default:
119 _, _ = fmt.Fprint(cmd.OutOrStdout(), d.String())
120 case FormatJSON:
121 var v interface{} = d
122 if i, ok := d.(interface{ Interface() interface{} }); ok {
123 v = i
124 }
125 printJSON(cmd.OutOrStdout(), v, false)
126 case FormatJSONPretty:
127 var v interface{} = d
128 if i, ok := d.(interface{ Interface() interface{} }); ok {
129 v = i
130 }
131 printJSON(cmd.OutOrStdout(), v, true)
132 }
133 }
134
135 func getQuiet(cmd *cobra.Command) bool {
136 q, err := cmd.Flags().GetBool(FlagQuiet)
137
138 if err != nil {
139 return false
140 }
141 return q
142 }
143
144 func getFormat(cmd *cobra.Command) format {
145 q := getQuiet(cmd)
146
147 if q {
148 return FormatQuiet
149 }
150
151 f, err := cmd.Flags().GetString(FlagFormat)
152
153 Must(err, "flag access error: %s", err)
154
155 switch f {
156 case string(FormatTable):
157 return FormatTable
158 case string(FormatJSON):
159 return FormatJSON
160 case string(FormatJSONPretty):
161 return FormatJSONPretty
162 default:
163 return FormatDefault
164 }
165 }
166
167 func printJSON(w io.Writer, v interface{}, pretty bool) {
168 e := json.NewEncoder(w)
169 if pretty {
170 e.SetIndent("", " ")
171 }
172 err := e.Encode(v)
173
174 Must(err, "Error encoding JSON: %s", err)
175 }
176
177 func RegisterJSONFormatFlags(flags *pflag.FlagSet) {
178 flags.StringP(FlagFormat, FlagFormat[:1], string(FormatDefault), fmt.Sprintf("Set the output format. One of %s, %s, and %s.", FormatDefault, FormatJSON, FormatJSONPretty))
179 }
180
181 func RegisterFormatFlags(flags *pflag.FlagSet) {
182 RegisterNoiseFlags(flags)
183 flags.StringP(FlagFormat, FlagFormat[:1], string(FormatDefault), fmt.Sprintf("Set the output format. One of %s, %s, and %s.", FormatTable, FormatJSON, FormatJSONPretty))
184 }
185
View as plain text