forked from danielgtaylor/openapi-cli-generator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
formatter.go
156 lines (131 loc) · 3.63 KB
/
formatter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package cli
import (
"encoding/json"
"fmt"
"reflect"
"github.com/alecthomas/chroma"
"github.com/alecthomas/chroma/quick"
"github.com/alecthomas/chroma/styles"
jmespath "github.com/danielgtaylor/go-jmespath-plus"
"github.com/spf13/viper"
"gopkg.in/yaml.v2"
)
func init() {
// Simple 256-color theme for JSON/YAML output in a terminal.
styles.Register(chroma.MustNewStyle("cli-dark", chroma.StyleEntries{
// Used for JSON/YAML
chroma.Comment: "#9e9e9e",
chroma.Keyword: "#ff5f87",
chroma.Punctuation: "#9e9e9e",
chroma.NameTag: "#5fafd7",
chroma.Number: "#d78700",
chroma.String: "#afd787",
// Used for HTTP
chroma.Name: "#5fafd7",
chroma.NameFunction: "#ff5f87",
chroma.NameNamespace: "#b2b2b2",
// Used for Markdown
chroma.GenericHeading: "#5fafd7",
chroma.GenericSubheading: "#5fafd7",
chroma.GenericEmph: "italic #875fd7",
chroma.GenericStrong: "bold #ffd787",
chroma.GenericDeleted: "#3a3a3a",
chroma.NameAttribute: "underline",
}))
}
// ResponseFormatter will filter, prettify, and print out the results of a call.
type ResponseFormatter interface {
Format(interface{}) error
}
// DefaultFormatter can apply JMESPath queries and can output prettyfied JSON
// and YAML output. If Stdout is a TTY, then colorized output is provided. The
// default formatter uses the `query` and `output-format` configuration
// values to perform JMESPath queries and set JSON (default) or YAML output.
type DefaultFormatter struct {
tty bool
}
// NewDefaultFormatter creates a new formatted with autodetected TTY
// capabilities.
func NewDefaultFormatter(tty bool) *DefaultFormatter {
return &DefaultFormatter{
tty: tty,
}
}
// Format will filter, prettify, colorize and output the data.
func (f *DefaultFormatter) Format(data interface{}) error {
if data == nil {
return nil
}
if viper.GetString("query") != "" {
result, err := jmespath.Search(viper.GetString("query"), data)
if err != nil {
return err
}
data = result
}
// Encode to the requested output format using nice formatting.
var encoded []byte
var err error
var lexer string
handled := false
kind := reflect.TypeOf(data).Kind()
if viper.GetBool("raw") && kind == reflect.String {
handled = true
dStr := data.(string)
encoded = []byte(dStr)
lexer = ""
if len(dStr) != 0 && (dStr[0] == '{' || dStr[0] == '[') {
// Looks like JSON to me!
lexer = "json"
}
} else if viper.GetBool("raw") && kind == reflect.Slice {
scalars := true
for _, item := range data.([]interface{}) {
switch item.(type) {
case nil, bool, int, int64, float64, string:
// The above are scalars used by decoders
default:
scalars = false
}
}
if scalars {
handled = true
for _, item := range data.([]interface{}) {
if item == nil {
encoded = append(encoded, []byte("null\n")...)
} else {
encoded = append(encoded, []byte(fmt.Sprintf("%v\n", item))...)
}
}
}
}
if !handled {
if viper.GetString("output-format") == "yaml" {
encoded, err = yaml.Marshal(data)
if err != nil {
return err
}
lexer = "yaml"
} else {
encoded, err = json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
lexer = "json"
}
}
// Make sure we end with a newline, otherwise things won't look right
// in the terminal.
if len(encoded) > 0 && encoded[len(encoded)-1] != '\n' {
encoded = append(encoded, '\n')
}
// Only colorize if we are a TTY.
if f.tty {
if err = quick.Highlight(Stdout, string(encoded), lexer, "terminal256", "cli-dark"); err != nil {
return err
}
} else {
fmt.Fprintln(Stdout, string(encoded))
}
return nil
}