-
Notifications
You must be signed in to change notification settings - Fork 2
/
gout.go
185 lines (158 loc) · 4.23 KB
/
gout.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
/*
Package gout provides a custom G OUTput formatter
*/
package gout
import (
"bytes"
"fmt"
"io"
"os"
"github.com/drewstinnett/gout/v2/formats"
_ "github.com/drewstinnett/gout/v2/formats/builtin" // Include all the builtin formats by default
"github.com/drewstinnett/gout/v2/formats/yaml"
)
// Gout is a structure you can use that contains a formatter, and a target
// io.Writer
type Gout struct {
formatter formats.Formatter
writer io.Writer
}
// Use this for doing things without explicitly creating a new gout, similar to
// viper.Viper
//
// The pattern for usage is something like:
// gout.Print("Hello")
//
// works similarly to:
// custom := New()
// custom.Print("Hello")
var gi *Gout
func init() {
gi = New()
}
// Get gets the default Gout instance
func Get() *Gout {
return gi
}
// SetWriter set the io.Writer that will be used for printing. By default, this
// will be os.Stdout
func SetWriter(i io.Writer) { gi.SetWriter(i) }
// SetWriter sets the writer on a custom Gout instance
func (g *Gout) SetWriter(i io.Writer) {
g.writer = i
}
// SetFormatter sets the built in Gout instance
func SetFormatter(f formats.Formatter) { gi.SetFormatter(f) }
// SetFormatter sets the formatter on a custom Gout instance
func (g *Gout) SetFormatter(f formats.Formatter) {
g.formatter = f
}
// SetFormatterString sets the formatter from the string that the plugin was registered with
func SetFormatterString(s string) error {
return gi.SetFormatterString(s)
}
// SetFormatterString sets the formatter from the string that the plugin was registered with
func (g *Gout) SetFormatterString(s string) error {
if f, ok := formats.Formats[s]; ok {
g.formatter = f()
return nil
}
return fmt.Errorf("unknown formatter name: %v", s)
}
// Print print an item using the built in Gout instance
func Print(v any) (err error) { return gi.Print(v) }
// Print print an item from a custom Gout instance
func (g *Gout) Print(v any) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic while attempting to format: %v", r)
}
}()
var b []byte
b, err = g.itemizedFormatter(v)
if err != nil {
return err
}
fmt.Fprint(g.writer, string(b))
return err
}
// PrintMulti useful when wanting to print multiple items to a single
// serialized item
func PrintMulti(v ...any) (err error) { return gi.PrintMulti(v) }
// PrintMulti prints multiple items on a custom gout instance
func (g *Gout) PrintMulti(v ...any) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic while attempting to format: %v", r)
}
}()
var b []byte
// b, err = c.condensedFormatter(v)
b, err = g.itemizedFormatter(v)
if err != nil {
return err
}
fmt.Fprint(g.writer, string(b))
return err
}
// MustPrint print an item and panic if there is any sort of error
func MustPrint(v any) { gi.MustPrint(v) }
// MustPrint outputs data on a custom Gout instance
func (g *Gout) MustPrint(v any) {
err := g.Print(v)
if err != nil {
panic(err)
}
}
// MustPrintMulti print an multiple items and panic if there is any sort of
// error
func MustPrintMulti(v ...any) { gi.MustPrintMulti(v) }
// MustPrintMulti prints multiple items with a custom Gout instance
func (g *Gout) MustPrintMulti(v ...any) {
err := g.PrintMulti(v)
if err != nil {
panic(err)
}
}
// Option is an option that can be passed in to help configure a Gout instance
type Option func(*Gout)
// WithWriter can be passed to New(), specifying which writer should be used for
// output
func WithWriter(w io.Writer) Option {
return func(g *Gout) {
g.writer = w
}
}
// WithFormatter can be passed to New(), specifying which Formatter should be
// used for output
func WithFormatter(f formats.Formatter) Option {
return func(g *Gout) {
g.formatter = f
}
}
// New creates a pointer to a new Gout, with some sensible defaults
func New(opts ...Option) *Gout {
g := &Gout{
formatter: yaml.Formatter{},
writer: os.Stdout,
}
for _, opt := range opts {
opt(g)
}
return g
}
func (g *Gout) itemizedFormatter(v ...any) ([]byte, error) {
var buf bytes.Buffer
for _, item := range v {
bi, err := g.formatter.Format(item)
if err != nil {
return nil, err
}
buf.Write(bi)
}
b := buf.Bytes()
if !bytes.HasSuffix(b, []byte("\n")) {
b = append(b, "\n"...)
}
return b, nil
}