Skip to content

Commit b5e986f

Browse files
committed
Add goagen commands command.
1 parent 996c344 commit b5e986f

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

goagen/main.go

+89
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"os"
67
"path/filepath"
@@ -165,8 +166,21 @@ package and tool and the Swagger specification for the API.
165166
files = append(prev, files...)
166167
},
167168
}
169+
bootCmd.Flags().AddFlagSet(appCmd.Flags())
170+
bootCmd.Flags().AddFlagSet(mainCmd.Flags())
171+
bootCmd.Flags().AddFlagSet(clientCmd.Flags())
172+
bootCmd.Flags().AddFlagSet(swaggerCmd.Flags())
168173
rootCmd.AddCommand(bootCmd)
169174

175+
// cmdsCmd implements the commands command
176+
// It lists all the commands and flags in JSON to enable shell integrations.
177+
cmdsCmd := &cobra.Command{
178+
Use: "commands",
179+
Short: "Lists all commands and flags in JSON",
180+
Run: func(c *cobra.Command, _ []string) { runCommands(rootCmd) },
181+
}
182+
rootCmd.AddCommand(cmdsCmd)
183+
170184
// Now proceed with code generation
171185
cleanup := func() {
172186
for _, f := range files {
@@ -250,3 +264,78 @@ func generate(pkgName, pkgPath string, c *cobra.Command) ([]string, error) {
250264
}
251265
return gen.Generate()
252266
}
267+
268+
type (
269+
rootCommand struct {
270+
Name string `json:"name"`
271+
Commands []*command `json:"commands"`
272+
Flags []*flag `json:"flags"`
273+
}
274+
275+
flag struct {
276+
Long string `json:"long,omitempty"`
277+
Short string `json:"short,omitempty"`
278+
Description string `json:"description,omitempty"`
279+
Argument string `json:"argument,omitempty"`
280+
Required bool `json:"required"`
281+
}
282+
283+
command struct {
284+
Name string `json:"name"`
285+
Flags []*flag `json:"flags,omitempty"`
286+
}
287+
)
288+
289+
func runCommands(root *cobra.Command) {
290+
var (
291+
gblFlags []*flag
292+
cmds []*command
293+
)
294+
root.Flags().VisitAll(func(fl *pflag.Flag) {
295+
gblFlags = append(gblFlags, flagJSON(fl))
296+
})
297+
cmds = make([]*command, len(root.Commands())-2)
298+
j := 0
299+
for _, cm := range root.Commands() {
300+
if cm.Name() == "help" || cm.Name() == "commands" {
301+
continue
302+
}
303+
cmds[j] = cmdJSON(cm, gblFlags)
304+
j++
305+
}
306+
rc := rootCommand{os.Args[0], cmds, gblFlags}
307+
b, _ := json.MarshalIndent(rc, "", " ")
308+
fmt.Println(string(b))
309+
}
310+
311+
// Lots of assumptions in here, it's OK for what we are doing
312+
// Remember to update as goagen commands and flags evolve
313+
//
314+
// The flag argument values use variable names that cary semantic:
315+
// $DIR for file system directories, $DESIGN_PKG for import path to Go goa design Go packages, $PKG
316+
// for import path to any Go package.
317+
func flagJSON(fl *pflag.Flag) *flag {
318+
f := &flag{Long: fl.Name, Short: fl.Shorthand, Description: fl.Usage}
319+
f.Required = fl.Name == "pkg-path" || fl.Name == "design"
320+
switch fl.Name {
321+
case "out":
322+
f.Argument = "$DIR"
323+
case "design":
324+
f.Argument = "$DESIGN_PKG"
325+
case "pkg-path":
326+
f.Argument = "$PKG"
327+
}
328+
return f
329+
}
330+
331+
func cmdJSON(cm *cobra.Command, flags []*flag) *command {
332+
res := make([]*flag, len(flags))
333+
for i, fl := range flags {
334+
f := *fl
335+
res[i] = &f
336+
}
337+
cm.Flags().VisitAll(func(fl *pflag.Flag) {
338+
res = append(res, flagJSON(fl))
339+
})
340+
return &command{cm.Name(), res}
341+
}

0 commit comments

Comments
 (0)