Skip to content

Commit 94a5eeb

Browse files
author
Massimiliano Pippi
authored
Make commands output agnostic (#391)
1 parent 63da3d8 commit 94a5eeb

File tree

16 files changed

+217
-185
lines changed

16 files changed

+217
-185
lines changed

cli/board/details.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func runDetailsCommand(cmd *cobra.Command, args []string) {
5454
feedback.PrintResult(detailsResult{details: res})
5555
}
5656

57-
// ouput from this command requires special formatting, let's create a dedicated
57+
// output from this command requires special formatting, let's create a dedicated
5858
// feedback.Result implementation
5959
type detailsResult struct {
6060
details *rpc.BoardDetailsResp

cli/board/list.go

+19-14
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import (
2626
"github.com/arduino/arduino-cli/arduino/cores"
2727
"github.com/arduino/arduino-cli/cli/errorcodes"
2828
"github.com/arduino/arduino-cli/cli/feedback"
29-
"github.com/arduino/arduino-cli/cli/globals"
3029
"github.com/arduino/arduino-cli/cli/instance"
3130
"github.com/arduino/arduino-cli/commands/board"
3231
rpc "github.com/arduino/arduino-cli/rpc/commands"
@@ -68,27 +67,33 @@ func runListCommand(cmd *cobra.Command, args []string) {
6867
os.Exit(errorcodes.ErrNetwork)
6968
}
7069

71-
if globals.OutputFormat == "json" {
72-
feedback.PrintJSON(ports)
73-
} else {
74-
outputListResp(ports)
75-
}
70+
feedback.PrintResult(result{ports})
71+
}
72+
73+
// output from this command requires special formatting, let's create a dedicated
74+
// feedback.Result implementation
75+
type result struct {
76+
ports []*rpc.DetectedPort
7677
}
7778

78-
func outputListResp(ports []*rpc.DetectedPort) {
79-
if len(ports) == 0 {
80-
feedback.Print("No boards found.")
81-
return
79+
func (dr result) Data() interface{} {
80+
return dr.ports
81+
}
82+
83+
func (dr result) String() string {
84+
if len(dr.ports) == 0 {
85+
return "No boards found."
8286
}
83-
sort.Slice(ports, func(i, j int) bool {
84-
x, y := ports[i], ports[j]
87+
88+
sort.Slice(dr.ports, func(i, j int) bool {
89+
x, y := dr.ports[i], dr.ports[j]
8590
return x.GetProtocol() < y.GetProtocol() ||
8691
(x.GetProtocol() == y.GetProtocol() && x.GetAddress() < y.GetAddress())
8792
})
8893

8994
t := table.New()
9095
t.SetHeader("Port", "Type", "Board Name", "FQBN", "Core")
91-
for _, port := range ports {
96+
for _, port := range dr.ports {
9297
address := port.GetProtocol() + "://" + port.GetAddress()
9398
if port.GetProtocol() == "serial" {
9499
address = port.GetAddress()
@@ -123,5 +128,5 @@ func outputListResp(ports []*rpc.DetectedPort) {
123128
t.AddRow(address, protocol, board, fqbn, coreName)
124129
}
125130
}
126-
feedback.Print(t.Render())
131+
return t.Render()
127132
}

cli/board/listall.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424

2525
"github.com/arduino/arduino-cli/cli/errorcodes"
2626
"github.com/arduino/arduino-cli/cli/feedback"
27-
"github.com/arduino/arduino-cli/cli/globals"
2827
"github.com/arduino/arduino-cli/cli/instance"
2928
"github.com/arduino/arduino-cli/commands/board"
3029
rpc "github.com/arduino/arduino-cli/rpc/commands"
@@ -58,22 +57,28 @@ func runListAllCommand(cmd *cobra.Command, args []string) {
5857
os.Exit(errorcodes.ErrGeneric)
5958
}
6059

61-
if globals.OutputFormat == "json" {
62-
feedback.PrintJSON(list)
63-
} else {
64-
outputBoardListAll(list)
65-
}
60+
feedback.PrintResult(resultAll{list})
61+
}
62+
63+
// output from this command requires special formatting, let's create a dedicated
64+
// feedback.Result implementation
65+
type resultAll struct {
66+
list *rpc.BoardListAllResp
67+
}
68+
69+
func (dr resultAll) Data() interface{} {
70+
return dr.list
6671
}
6772

68-
func outputBoardListAll(list *rpc.BoardListAllResp) {
69-
sort.Slice(list.Boards, func(i, j int) bool {
70-
return list.Boards[i].GetName() < list.Boards[j].GetName()
73+
func (dr resultAll) String() string {
74+
sort.Slice(dr.list.Boards, func(i, j int) bool {
75+
return dr.list.Boards[i].GetName() < dr.list.Boards[j].GetName()
7176
})
7277

7378
t := table.New()
7479
t.SetHeader("Board Name", "FQBN")
75-
for _, item := range list.GetBoards() {
80+
for _, item := range dr.list.GetBoards() {
7681
t.AddRow(item.GetName(), item.GetFQBN())
7782
}
78-
feedback.Print(t.Render())
83+
return t.Render()
7984
}

cli/cli.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/arduino/arduino-cli/cli/generatedocs"
3434
"github.com/arduino/arduino-cli/cli/globals"
3535
"github.com/arduino/arduino-cli/cli/lib"
36+
"github.com/arduino/arduino-cli/cli/output"
3637
"github.com/arduino/arduino-cli/cli/sketch"
3738
"github.com/arduino/arduino-cli/cli/upload"
3839
"github.com/arduino/arduino-cli/cli/version"
@@ -52,9 +53,10 @@ var (
5253
PersistentPreRun: preRun,
5354
}
5455

55-
verbose bool
56-
logFile string
57-
logFormat string
56+
verbose bool
57+
logFile string
58+
logFormat string
59+
outputFormat string
5860
)
5961

6062
const (
@@ -83,7 +85,7 @@ func createCliCommandTree(cmd *cobra.Command) {
8385
cmd.PersistentFlags().StringVar(&globals.LogLevel, "log-level", defaultLogLevel, "Messages with this level and above will be logged.")
8486
cmd.PersistentFlags().StringVar(&logFile, "log-file", "", "Path to the file where logs will be written.")
8587
cmd.PersistentFlags().StringVar(&logFormat, "log-format", "text", "The output format for the logs, can be [text|json].")
86-
cmd.PersistentFlags().StringVar(&globals.OutputFormat, "format", "text", "The output format, can be [text|json].")
88+
cmd.PersistentFlags().StringVar(&outputFormat, "format", "text", "The output format, can be [text|json].")
8789
cmd.PersistentFlags().StringVar(&globals.YAMLConfigFile, "config-file", "", "The custom config file (if not specified the default will be used).")
8890
cmd.PersistentFlags().StringSliceVar(&globals.AdditionalUrls, "additional-urls", []string{}, "Additional URLs for the board manager.")
8991
}
@@ -115,7 +117,9 @@ func parseFormatString(arg string) (feedback.OutputFormat, bool) {
115117

116118
func preRun(cmd *cobra.Command, args []string) {
117119
// normalize the format strings
118-
globals.OutputFormat = strings.ToLower(globals.OutputFormat)
120+
outputFormat = strings.ToLower(outputFormat)
121+
// configure the output package
122+
output.OutputFormat = outputFormat
119123
logFormat = strings.ToLower(logFormat)
120124

121125
// should we log to file?
@@ -159,9 +163,9 @@ func preRun(cmd *cobra.Command, args []string) {
159163
}
160164

161165
// check the right output format was passed
162-
format, found := parseFormatString(globals.OutputFormat)
166+
format, found := parseFormatString(outputFormat)
163167
if !found {
164-
feedback.Error("Invalid output format: " + globals.OutputFormat)
168+
feedback.Error("Invalid output format: " + outputFormat)
165169
os.Exit(errorcodes.ErrBadCall)
166170
}
167171

@@ -174,7 +178,7 @@ func preRun(cmd *cobra.Command, args []string) {
174178
logrus.Info("Starting root command preparation (`arduino`)")
175179

176180
logrus.Info("Formatter set")
177-
if globals.OutputFormat != "text" {
181+
if outputFormat != "text" {
178182
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
179183
logrus.Warn("Calling help on JSON format")
180184
feedback.Error("Invalid Call : should show Help, but it is available only in TEXT mode.")

cli/config/dump.go

+32-18
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ var dumpCmd = &cobra.Command{
5858
Run: runDumpCommand,
5959
}
6060

61+
// output from this command requires special formatting, let's create a dedicated
62+
// feedback.Result implementation
63+
type dumpResult struct {
64+
structured *jsonConfig
65+
plain string
66+
}
67+
68+
func (dr dumpResult) Data() interface{} {
69+
return dr.structured
70+
}
71+
72+
func (dr dumpResult) String() string {
73+
return dr.plain
74+
}
75+
6176
func runDumpCommand(cmd *cobra.Command, args []string) {
6277
logrus.Info("Executing `arduino config dump`")
6378

@@ -69,23 +84,23 @@ func runDumpCommand(cmd *cobra.Command, args []string) {
6984

7085
c := globals.Config
7186

72-
if globals.OutputFormat == "json" {
73-
sketchbookDir := ""
74-
if c.SketchbookDir != nil {
75-
sketchbookDir = c.SketchbookDir.String()
76-
}
87+
sketchbookDir := ""
88+
if c.SketchbookDir != nil {
89+
sketchbookDir = c.SketchbookDir.String()
90+
}
7791

78-
arduinoDataDir := ""
79-
if c.DataDir != nil {
80-
arduinoDataDir = c.DataDir.String()
81-
}
92+
arduinoDataDir := ""
93+
if c.DataDir != nil {
94+
arduinoDataDir = c.DataDir.String()
95+
}
8296

83-
arduinoDownloadsDir := ""
84-
if c.ArduinoDownloadsDir != nil {
85-
arduinoDownloadsDir = c.ArduinoDownloadsDir.String()
86-
}
97+
arduinoDownloadsDir := ""
98+
if c.ArduinoDownloadsDir != nil {
99+
arduinoDownloadsDir = c.ArduinoDownloadsDir.String()
100+
}
87101

88-
feedback.PrintJSON(jsonConfig{
102+
feedback.PrintResult(&dumpResult{
103+
structured: &jsonConfig{
89104
ProxyType: c.ProxyType,
90105
ProxyManualConfig: &jsonProxyConfig{
91106
Hostname: c.ProxyHostname,
@@ -98,8 +113,7 @@ func runDumpCommand(cmd *cobra.Command, args []string) {
98113
BoardsManager: &jsonBoardsManagerConfig{
99114
AdditionalURLS: c.BoardManagerAdditionalUrls,
100115
},
101-
})
102-
} else {
103-
feedback.Print(string(data))
104-
}
116+
},
117+
plain: string(data),
118+
})
105119
}

cli/config/init.go

-9
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ func initInitCommand() *cobra.Command {
4040
Args: cobra.NoArgs,
4141
Run: runInitCommand,
4242
}
43-
initCommand.Flags().BoolVar(&initFlags._default, "default", false,
44-
"If omitted, ask questions to the user about setting configuration properties, otherwise use default configuration.")
4543
initCommand.Flags().StringVar(&initFlags.location, "save-as", "",
4644
"Sets where to save the configuration file [default is ./arduino-cli.yaml].")
4745
return initCommand
@@ -55,13 +53,6 @@ var initFlags struct {
5553
func runInitCommand(cmd *cobra.Command, args []string) {
5654
logrus.Info("Executing `arduino config init`")
5755

58-
if !initFlags._default {
59-
if globals.OutputFormat != "text" {
60-
feedback.Error("The interactive mode is supported only in text mode.")
61-
os.Exit(errorcodes.ErrBadCall)
62-
}
63-
}
64-
6556
filepath := initFlags.location
6657
if filepath == "" {
6758
filepath = globals.Config.ConfigFile.String()

cli/core/list.go

+18-13
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/arduino/arduino-cli/arduino/cores"
2525
"github.com/arduino/arduino-cli/cli/errorcodes"
2626
"github.com/arduino/arduino-cli/cli/feedback"
27-
"github.com/arduino/arduino-cli/cli/globals"
2827
"github.com/arduino/arduino-cli/cli/instance"
2928
"github.com/arduino/arduino-cli/commands/core"
3029
"github.com/arduino/arduino-cli/table"
@@ -59,26 +58,32 @@ func runListCommand(cmd *cobra.Command, args []string) {
5958
os.Exit(errorcodes.ErrGeneric)
6059
}
6160

62-
if globals.OutputFormat == "json" {
63-
feedback.PrintJSON(platforms)
64-
} else {
65-
outputInstalledCores(platforms)
66-
}
61+
feedback.PrintResult(installedResult{platforms})
62+
}
63+
64+
// output from this command requires special formatting, let's create a dedicated
65+
// feedback.Result implementation
66+
type installedResult struct {
67+
platforms []*cores.PlatformRelease
68+
}
69+
70+
func (ir installedResult) Data() interface{} {
71+
return ir.platforms
6772
}
6873

69-
func outputInstalledCores(platforms []*cores.PlatformRelease) {
70-
if platforms == nil || len(platforms) == 0 {
71-
return
74+
func (ir installedResult) String() string {
75+
if ir.platforms == nil || len(ir.platforms) == 0 {
76+
return ""
7277
}
7378

7479
t := table.New()
7580
t.SetHeader("ID", "Installed", "Latest", "Name")
76-
sort.Slice(platforms, func(i, j int) bool {
77-
return platforms[i].Platform.String() < platforms[j].Platform.String()
81+
sort.Slice(ir.platforms, func(i, j int) bool {
82+
return ir.platforms[i].Platform.String() < ir.platforms[j].Platform.String()
7883
})
79-
for _, p := range platforms {
84+
for _, p := range ir.platforms {
8085
t.AddRow(p.Platform.String(), p.Version.String(), p.Platform.GetLatestRelease().Version.String(), p.Platform.Name)
8186
}
8287

83-
feedback.Print(t.Render())
88+
return t.Render()
8489
}

cli/core/search.go

+18-19
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525

2626
"github.com/arduino/arduino-cli/cli/errorcodes"
2727
"github.com/arduino/arduino-cli/cli/feedback"
28-
"github.com/arduino/arduino-cli/cli/globals"
2928
"github.com/arduino/arduino-cli/cli/instance"
3029
"github.com/arduino/arduino-cli/commands/core"
3130
rpc "github.com/arduino/arduino-cli/rpc/commands"
@@ -51,11 +50,6 @@ func runSearchCommand(cmd *cobra.Command, args []string) {
5150
logrus.Info("Executing `arduino core search`")
5251

5352
arguments := strings.ToLower(strings.Join(args, " "))
54-
55-
if globals.OutputFormat != "json" {
56-
feedback.Printf("Searching for platforms matching '%s'", arguments)
57-
}
58-
5953
resp, err := core.PlatformSearch(context.Background(), &rpc.PlatformSearchReq{
6054
Instance: instance,
6155
SearchArgs: arguments,
@@ -66,25 +60,30 @@ func runSearchCommand(cmd *cobra.Command, args []string) {
6660
}
6761

6862
coreslist := resp.GetSearchOutput()
69-
if globals.OutputFormat == "json" {
70-
feedback.PrintJSON(coreslist)
71-
} else {
72-
outputSearchCores(coreslist)
73-
}
63+
feedback.PrintResult(searchResults{coreslist})
64+
}
65+
66+
// output from this command requires special formatting, let's create a dedicated
67+
// feedback.Result implementation
68+
type searchResults struct {
69+
platforms []*rpc.Platform
70+
}
71+
72+
func (sr searchResults) Data() interface{} {
73+
return sr.platforms
7474
}
7575

76-
func outputSearchCores(cores []*rpc.Platform) {
77-
if len(cores) > 0 {
76+
func (sr searchResults) String() string {
77+
if len(sr.platforms) > 0 {
7878
t := table.New()
7979
t.SetHeader("ID", "Version", "Name")
80-
sort.Slice(cores, func(i, j int) bool {
81-
return cores[i].ID < cores[j].ID
80+
sort.Slice(sr.platforms, func(i, j int) bool {
81+
return sr.platforms[i].ID < sr.platforms[j].ID
8282
})
83-
for _, item := range cores {
83+
for _, item := range sr.platforms {
8484
t.AddRow(item.GetID(), item.GetLatest(), item.GetName())
8585
}
86-
feedback.Print(t.Render())
87-
} else {
88-
feedback.Print("No platforms matching your search.")
86+
return t.Render()
8987
}
88+
return "No platforms matching your search."
9089
}

0 commit comments

Comments
 (0)