-
-
Notifications
You must be signed in to change notification settings - Fork 99
/
pp.go
317 lines (261 loc) · 8.75 KB
/
pp.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
// pp.go: API definitions. The core implementation is delegated to printer.go.
package pp
import (
"errors"
"fmt"
"io"
"os"
"runtime"
"sync"
"github.com/mattn/go-colorable"
)
// Global variable API
// see also: color.go
var (
// Default pretty printer. It's public so that you can modify config globally.
Default = newPrettyPrinter(3) // pp.* => PrettyPrinter.* => formatAll
// If the length of array or slice is larger than this,
// the buffer will be shorten as {...}.
BufferFoldThreshold = 1024
// PrintMapTypes when set to true will have map types will always appended to maps.
PrintMapTypes = true
// WithLineInfo add file name and line information to output
// call this function with care, because getting stack has performance penalty
WithLineInfo bool
)
// Internals
var (
defaultOut = colorable.NewColorableStdout()
defaultWithLineInfo = false
)
type PrettyPrinter struct {
// WithLineInfo adds file name and line information to output.
// Call this function with care, because getting stack has performance penalty.
WithLineInfo bool
// To support WithLineInfo, we need to know which frame we should look at.
// Thus callerLevel sets the number of frames it needs to skip.
callerLevel int
out io.Writer
currentScheme ColorScheme
outLock sync.Mutex
maxDepth int
coloringEnabled bool
decimalUint bool
thousandsSeparator bool
// This skips unexported fields of structs.
exportedOnly bool
// This skips empty fields of structs.
omitEmpty bool
}
// New creates a new PrettyPrinter that can be used to pretty print values
func New() *PrettyPrinter {
return newPrettyPrinter(2) // PrettyPrinter.* => formatAll
}
func newPrettyPrinter(callerLevel int) *PrettyPrinter {
return &PrettyPrinter{
WithLineInfo: defaultWithLineInfo,
callerLevel: callerLevel,
out: defaultOut,
currentScheme: defaultScheme,
maxDepth: -1,
coloringEnabled: true,
decimalUint: true,
exportedOnly: false,
omitEmpty: false,
}
}
// Print prints given arguments.
func (pp *PrettyPrinter) Print(a ...interface{}) (n int, err error) {
return fmt.Fprint(pp.out, pp.formatAll(a)...)
}
// Printf prints a given format.
func (pp *PrettyPrinter) Printf(format string, a ...interface{}) (n int, err error) {
return fmt.Fprintf(pp.out, format, pp.formatAll(a)...)
}
// Println prints given arguments with newline.
func (pp *PrettyPrinter) Println(a ...interface{}) (n int, err error) {
return fmt.Fprintln(pp.out, pp.formatAll(a)...)
}
// Sprint formats given arguments and returns the result as string.
func (pp *PrettyPrinter) Sprint(a ...interface{}) string {
return fmt.Sprint(pp.formatAll(a)...)
}
// Sprintf formats with pretty print and returns the result as string.
func (pp *PrettyPrinter) Sprintf(format string, a ...interface{}) string {
return fmt.Sprintf(format, pp.formatAll(a)...)
}
// Sprintln formats given arguments with newline and returns the result as string.
func (pp *PrettyPrinter) Sprintln(a ...interface{}) string {
return fmt.Sprintln(pp.formatAll(a)...)
}
// Fprint prints given arguments to a given writer.
func (pp *PrettyPrinter) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprint(w, pp.formatAll(a)...)
}
// Fprintf prints format to a given writer.
func (pp *PrettyPrinter) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
return fmt.Fprintf(w, format, pp.formatAll(a)...)
}
// Fprintln prints given arguments to a given writer with newline.
func (pp *PrettyPrinter) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprintln(w, pp.formatAll(a)...)
}
// Errorf formats given arguments and returns it as error type.
func (pp *PrettyPrinter) Errorf(format string, a ...interface{}) error {
return errors.New(pp.Sprintf(format, a...))
}
// Fatal prints given arguments and finishes execution with exit status 1.
func (pp *PrettyPrinter) Fatal(a ...interface{}) {
fmt.Fprint(pp.out, pp.formatAll(a)...)
os.Exit(1)
}
// Fatalf prints a given format and finishes execution with exit status 1.
func (pp *PrettyPrinter) Fatalf(format string, a ...interface{}) {
fmt.Fprintf(pp.out, format, pp.formatAll(a)...)
os.Exit(1)
}
// Fatalln prints given arguments with newline and finishes execution with exit status 1.
func (pp *PrettyPrinter) Fatalln(a ...interface{}) {
fmt.Fprintln(pp.out, pp.formatAll(a)...)
os.Exit(1)
}
func (pp *PrettyPrinter) SetColoringEnabled(enabled bool) {
pp.coloringEnabled = enabled
}
func (pp *PrettyPrinter) SetDecimalUint(enabled bool) {
pp.decimalUint = enabled
}
func (pp *PrettyPrinter) SetExportedOnly(enabled bool) {
pp.exportedOnly = enabled
}
// SetOmitEmpty makes empty fields in struct not be printed.
func (pp *PrettyPrinter) SetOmitEmpty(enabled bool) {
pp.omitEmpty = enabled
}
func (pp *PrettyPrinter) SetThousandsSeparator(enabled bool) {
pp.thousandsSeparator = enabled
}
// SetOutput sets pp's output
func (pp *PrettyPrinter) SetOutput(o io.Writer) {
pp.outLock.Lock()
defer pp.outLock.Unlock()
pp.out = o
}
// GetOutput returns pp's output.
func (pp *PrettyPrinter) GetOutput() io.Writer {
return pp.out
}
// ResetOutput sets pp's output back to the default output
func (pp *PrettyPrinter) ResetOutput() {
pp.outLock.Lock()
defer pp.outLock.Unlock()
pp.out = defaultOut
}
// SetColorScheme takes a colorscheme used by all future Print calls.
func (pp *PrettyPrinter) SetColorScheme(scheme ColorScheme) {
scheme.fixColors()
pp.currentScheme = scheme
}
// ResetColorScheme resets colorscheme to default.
func (pp *PrettyPrinter) ResetColorScheme() {
pp.currentScheme = defaultScheme
}
func (pp *PrettyPrinter) formatAll(objects []interface{}) []interface{} {
results := []interface{}{}
// fix for backwards capability
withLineInfo := pp.WithLineInfo
if pp == Default {
withLineInfo = WithLineInfo
}
if withLineInfo {
_, fn, line, _ := runtime.Caller(pp.callerLevel)
results = append(results, fmt.Sprintf("%s:%d\n", fn, line))
}
for _, object := range objects {
results = append(results, pp.format(object))
}
return results
}
// Print prints given arguments.
func Print(a ...interface{}) (n int, err error) {
return Default.Print(a...)
}
// Printf prints a given format.
func Printf(format string, a ...interface{}) (n int, err error) {
return Default.Printf(format, a...)
}
// Println prints given arguments with newline.
func Println(a ...interface{}) (n int, err error) {
return Default.Println(a...)
}
// Sprint formats given arguments and returns the result as string.
func Sprint(a ...interface{}) string {
return Default.Sprint(a...)
}
// Sprintf formats with pretty print and returns the result as string.
func Sprintf(format string, a ...interface{}) string {
return Default.Sprintf(format, a...)
}
// Sprintln formats given arguments with newline and returns the result as string.
func Sprintln(a ...interface{}) string {
return Default.Sprintln(a...)
}
// Fprint prints given arguments to a given writer.
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
return Default.Fprint(w, a...)
}
// Fprintf prints format to a given writer.
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
return Default.Fprintf(w, format, a...)
}
// Fprintln prints given arguments to a given writer with newline.
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
return Default.Fprintln(w, a...)
}
// Errorf formats given arguments and returns it as error type.
func Errorf(format string, a ...interface{}) error {
return Default.Errorf(format, a...)
}
// Fatal prints given arguments and finishes execution with exit status 1.
func Fatal(a ...interface{}) {
Default.Fatal(a...)
}
// Fatalf prints a given format and finishes execution with exit status 1.
func Fatalf(format string, a ...interface{}) {
Default.Fatalf(format, a...)
}
// Fatalln prints given arguments with newline and finishes execution with exit status 1.
func Fatalln(a ...interface{}) {
Default.Fatalln(a...)
}
// Change Print* functions' output to a given writer.
// For example, you can limit output by ENV.
//
// func init() {
// if os.Getenv("DEBUG") == "" {
// pp.SetDefaultOutput(ioutil.Discard)
// }
// }
func SetDefaultOutput(o io.Writer) {
Default.SetOutput(o)
}
// GetOutput returns pp's default output.
func GetDefaultOutput() io.Writer {
return Default.GetOutput()
}
// Change Print* functions' output to default one.
func ResetDefaultOutput() {
Default.ResetOutput()
}
// SetColorScheme takes a colorscheme used by all future Print calls.
func SetColorScheme(scheme ColorScheme) {
Default.SetColorScheme(scheme)
}
// ResetColorScheme resets colorscheme to default.
func ResetColorScheme() {
Default.ResetColorScheme()
}
// SetMaxDepth sets the printer's Depth, -1 prints all
func SetDefaultMaxDepth(v int) {
Default.maxDepth = v
}