|
1 | 1 | package main
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "encoding/json" |
4 | 5 | "fmt"
|
5 | 6 | "os"
|
6 | 7 | "path/filepath"
|
@@ -165,8 +166,21 @@ package and tool and the Swagger specification for the API.
|
165 | 166 | files = append(prev, files...)
|
166 | 167 | },
|
167 | 168 | }
|
| 169 | + bootCmd.Flags().AddFlagSet(appCmd.Flags()) |
| 170 | + bootCmd.Flags().AddFlagSet(mainCmd.Flags()) |
| 171 | + bootCmd.Flags().AddFlagSet(clientCmd.Flags()) |
| 172 | + bootCmd.Flags().AddFlagSet(swaggerCmd.Flags()) |
168 | 173 | rootCmd.AddCommand(bootCmd)
|
169 | 174 |
|
| 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 | + |
170 | 184 | // Now proceed with code generation
|
171 | 185 | cleanup := func() {
|
172 | 186 | for _, f := range files {
|
@@ -250,3 +264,78 @@ func generate(pkgName, pkgPath string, c *cobra.Command) ([]string, error) {
|
250 | 264 | }
|
251 | 265 | return gen.Generate()
|
252 | 266 | }
|
| 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