Skip to content

Commit bbcec08

Browse files
author
Massimiliano Pippi
committed
move output format decision outside command
1 parent 0006a86 commit bbcec08

File tree

4 files changed

+77
-19
lines changed

4 files changed

+77
-19
lines changed

Diff for: cli/board/details.go

+14-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323

2424
"github.com/arduino/arduino-cli/cli/errorcodes"
2525
"github.com/arduino/arduino-cli/cli/feedback"
26-
"github.com/arduino/arduino-cli/cli/globals"
2726
"github.com/arduino/arduino-cli/cli/instance"
2827
"github.com/arduino/arduino-cli/commands/board"
2928
rpc "github.com/arduino/arduino-cli/rpc/commands"
@@ -52,14 +51,21 @@ func runDetailsCommand(cmd *cobra.Command, args []string) {
5251
os.Exit(errorcodes.ErrGeneric)
5352
}
5453

55-
if globals.OutputFormat == "json" {
56-
feedback.PrintJSON(res)
57-
} else {
58-
outputDetailsResp(res)
59-
}
54+
feedback.PrintResult(detailsResult{details: res})
55+
}
56+
57+
// ouput from this command requires special formatting, let's create a dedicated
58+
// feedback.Result implementation
59+
type detailsResult struct {
60+
details *rpc.BoardDetailsResp
61+
}
62+
63+
func (dr detailsResult) Data() interface{} {
64+
return dr.details
6065
}
6166

62-
func outputDetailsResp(details *rpc.BoardDetailsResp) {
67+
func (dr detailsResult) String() string {
68+
details := dr.details
6369
// Table is 4 columns wide:
6470
// | | | | |
6571
// Board name: Arduino Nano
@@ -104,5 +110,5 @@ func outputDetailsResp(details *rpc.BoardDetailsResp) {
104110
}
105111
}
106112

107-
feedback.Print(t.Render())
113+
return t.Render()
108114
}

Diff for: cli/cli.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,13 @@ func toLogLevel(s string) (t logrus.Level, found bool) {
101101
return
102102
}
103103

104-
func isValidFormat(arg string) bool {
105-
return map[string]bool{
106-
"json": true,
107-
"text": true,
104+
func parseFormatString(arg string) (feedback.OutputFormat, bool) {
105+
f, found := map[string]feedback.OutputFormat{
106+
"json": feedback.JSON,
107+
"text": feedback.Text,
108108
}[arg]
109+
110+
return f, found
109111
}
110112

111113
func preRun(cmd *cobra.Command, args []string) {
@@ -141,9 +143,12 @@ func preRun(cmd *cobra.Command, args []string) {
141143
}
142144

143145
// check the right format was passed
144-
if !isValidFormat(globals.OutputFormat) {
146+
if f, found := parseFormatString(globals.OutputFormat); !found {
145147
feedback.Error("Invalid output format: " + globals.OutputFormat)
146148
os.Exit(errorcodes.ErrBadCall)
149+
} else {
150+
// use the format to configure the Feedback
151+
feedback.SetFormat(f)
147152
}
148153

149154
globals.InitConfigs()

Diff for: cli/feedback/exported.go

+10
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ func SetDefaultFeedback(f *Feedback) {
2929
fb = f
3030
}
3131

32+
// SetFormat can be used to change the output format at runtime
33+
func SetFormat(f OutputFormat) {
34+
fb.SetFormat(f)
35+
}
36+
3237
// OutputWriter returns the underlying io.Writer to be used when the Print*
3338
// api is not enough
3439
func OutputWriter() io.Writer {
@@ -68,3 +73,8 @@ func Error(v ...interface{}) {
6873
func PrintJSON(v interface{}) {
6974
fb.PrintJSON(v)
7075
}
76+
77+
// PrintResult is a convenient wrapper...
78+
func PrintResult(res Result) {
79+
fb.PrintResult(res)
80+
}

Diff for: cli/feedback/feedback.go

+43-6
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,48 @@ import (
2424
"github.com/sirupsen/logrus"
2525
)
2626

27+
// OutputFormat is used to determine the output format
28+
type OutputFormat int
29+
30+
const (
31+
// Text means plain text format, suitable for ansi terminals
32+
Text OutputFormat = iota
33+
// JSON means JSON format
34+
JSON
35+
)
36+
37+
// Result is anything more complex than a sentence that needs to be printed
38+
// for the user.
39+
type Result interface {
40+
fmt.Stringer
41+
Data() interface{}
42+
}
43+
2744
// Feedback wraps an io.Writer and provides an uniform API the CLI can use to
2845
// provide feedback to the users.
2946
type Feedback struct {
30-
out io.Writer
31-
err io.Writer
47+
out io.Writer
48+
err io.Writer
49+
format OutputFormat
3250
}
3351

3452
// New creates a Feedback instance
35-
func New(out, err io.Writer) *Feedback {
53+
func New(out, err io.Writer, format OutputFormat) *Feedback {
3654
return &Feedback{
37-
out: out,
38-
err: err,
55+
out: out,
56+
err: err,
57+
format: format,
3958
}
4059
}
4160

4261
// DefaultFeedback provides a basic feedback object to be used as default.
4362
func DefaultFeedback() *Feedback {
44-
return New(os.Stdout, os.Stderr)
63+
return New(os.Stdout, os.Stderr, Text)
64+
}
65+
66+
// SetFormat can be used to change the output format at runtime
67+
func (fb *Feedback) SetFormat(f OutputFormat) {
68+
fb.format = f
4569
}
4670

4771
// OutputWriter returns the underlying io.Writer to be used when the Print*
@@ -88,3 +112,16 @@ func (fb *Feedback) PrintJSON(v interface{}) {
88112
fb.Print(string(d))
89113
}
90114
}
115+
116+
// PrintResult is a convenient wrapper...
117+
func (fb *Feedback) PrintResult(res Result) {
118+
if fb.format == JSON {
119+
if d, err := json.MarshalIndent(res.Data(), "", " "); err != nil {
120+
fb.Errorf("Error during JSON encoding of the output: %v", err)
121+
} else {
122+
fb.Print(string(d))
123+
}
124+
} else {
125+
fb.Print(fmt.Sprintf("%s", res))
126+
}
127+
}

0 commit comments

Comments
 (0)