|
1 | 1 | [](https://github.com/bep/simplecobra/actions?query=workflow:Test) |
2 | 2 | [](https://goreportcard.com/report/github.com/bep/simplecobra) |
3 | | -[](https://godoc.org/github.com/bep/simplecobra) |
| 3 | +[](https://godoc.org/github.com/bep/simplecobra) |
| 4 | + |
| 5 | +So, [Cobra](https://github.com/spf13/cobra) is a Go CLI library with a feature set that's hard to resist for bigger applications (autocomplete, docs auto generation etc.). But it's also rather complex to use beyond the simplest of applications. This package is built to aid rewriting [Hugo's](https://github.com/gohugoio/hugo) commands package to something that's easier to understand and maintain. |
| 6 | + |
| 7 | +I welcome suggestions to improve/simplify this further, but the core idea is that the command graph gets built in one go with a tree of struct pointers implementing a simple `Commander` interface: |
| 8 | + |
| 9 | +```go |
| 10 | +type Commander interface { |
| 11 | + // The name of the command. |
| 12 | + Name() string |
| 13 | + |
| 14 | + // The command execution. |
| 15 | + Run(ctx context.Context, args []string) error |
| 16 | + |
| 17 | + // Init called on all commands in this tree, before execution, starting from the root. |
| 18 | + // This is the place to evaluate flags and set up the command. |
| 19 | + Init(*Commandeer) error |
| 20 | + |
| 21 | + // WithCobraCommand is called when the cobra command is created. |
| 22 | + // This is where the flags, short and long description etc. are added. |
| 23 | + WithCobraCommand(*cobra.Command) error |
| 24 | + |
| 25 | + // Commands returns the sub commands, if any. |
| 26 | + Commands() []Commander |
| 27 | +} |
| 28 | +``` |
| 29 | + |
| 30 | +The `Init` method allows for flag compilation, referencing the parent and root etc. If needed, the full Cobra command is still available for configuration in `WithCobraCommand`. |
| 31 | + |
| 32 | +There's a runnable [example](https://pkg.go.dev/github.com/bep/simplecobra#example-package) in the documentation, but the gist of it is: |
| 33 | + |
| 34 | +```go |
| 35 | +func main() { |
| 36 | + rootCmd := &rootCommand{name: "root", |
| 37 | + commands: []simplecobra.Commander{ |
| 38 | + &lvl1Command{name: "foo"}, |
| 39 | + &lvl1Command{name: "bar", |
| 40 | + commands: []simplecobra.Commander{ |
| 41 | + &lvl2Command{name: "baz"}, |
| 42 | + }, |
| 43 | + }, |
| 44 | + }, |
| 45 | + } |
| 46 | + |
| 47 | + x, err := simplecobra.New(rootCmd) |
| 48 | + if err != nil { |
| 49 | + log.Fatal(err) |
| 50 | + } |
| 51 | + cd, err := x.Execute(context.Background(), []string{"bar", "baz", "--localFlagName", "baz_local", "--persistentFlagName", "baz_persistent"}) |
| 52 | + if err != nil { |
| 53 | + log.Fatal(err) |
| 54 | + } |
| 55 | + |
| 56 | + // These are wired up in Init(). |
| 57 | + lvl2 := cd.Command.(*lvl2Command) |
| 58 | + lvl1 := lvl2.parentCmd |
| 59 | + root := lvl1.rootCmd |
| 60 | + |
| 61 | + fmt.Printf("Executed %s.%s.%s with localFlagName %s and and persistentFlagName %s.\n", root.name, lvl1.name, lvl2.name, lvl2.localFlagName, root.persistentFlagName) |
| 62 | +} |
| 63 | +``` |
0 commit comments