Reputation: 29468
I'm using this library https://github.com/jessevdk/go-flags
A command for my app might be like:
ex list events
So I have my wrapper command
type ExCommand struct {
List list.ListCommand `command:"list" description:"list events" subcommands-optional:"true"`
}
List command
type ListCommand struct {
ExCommand ExCommand `command:"events" description:"list events"`
Config string `short:"c" long:"config" description:"config file" optional:"yes"`
}
Ex command
type EventsCommand struct {
}
func (c *ListCommand) Execute(args []string) error {
fmt.Println("execute list")
for _, val := range args {
fmt.Println(val)
}
fmt.Printf("c: %s\n", c.Config)
return nil
}
func (c *ExCommand) Execute(args []string) error {
fmt.Println("list events")
for _, val := range args {
fmt.Println(val)
}
return nil
}
So what I'd like to do, is to have a few options like
verbose
config
terse
that are global options that can be run on any commands. I can't seem to figure out if there's a way to do this though with this library. Does anyone have experience with that? I can add Config
to each individual low level command, list in this case the EventsCommand, but it seems like I'm repeating myself by adding at each low level command instead of the higher up ListCommand or ExCommand.
Upvotes: 2
Views: 1620
Reputation: 194
You can use NewParser to create a new parser. You'll notice from the documentation that the first argument is a pointer to a struct that will be "Application Options." I'll start with an explanation and follow with a working example. Pretend you have the following struct that contains your application wide options:
type Defaults struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
Terse bool `short:"t" long:"terse" description:"Shows terse output"`
}
You can pass this into the NewParser function as mentioned before like so:
defaultOptions = Defaults{}
parser = flags.NewParser(&defaultOptions, flags.Default)
Your additional commands can be added with the parser.AddCommand function. For example:
list := ListCommand{}
parser.AddCommand("list", "lists something", "", &list)
Finish up by calling parser. Parse and enjoy!
parser.Parse()
fmt.Printf("Verbose: %v\n", defaultOptions.Verbose)
fmt.Printf("Terse: %v\n", defaultOptions.Terse)
Here's a small fully-working example:
package main
import (
"fmt"
flags "github.com/jessevdk/go-flags"
)
type Defaults struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
Terse bool `short:"t" long:"terse" description:"Shows terse output"`
}
type ListCommand struct {
Config string `short:"c" long:"config" description:"config file" optional:"yes"`
}
func main() {
defaultOptions := Defaults{}
listCmd := ListCommand{}
parser := flags.NewParser(&defaultOptions, flags.Default)
parser.AddCommand("list", "lists something", "", &listCmd)
parser.Parse()
}
You can also achieve exactly what you're asking for by including the Defaults struct as an anonymous struct in your Command structs. Notice how I am referencing the Defaults type in my ListCommand struct but am not providing a name for the field. This allows me to access the fields of Defaults as if they were part of the ListCommand struct. The following example code allows me to provide the Verbose and Terse flags when using <prog> list -h
:
package main
import flags "github.com/jessevdk/go-flags"
type Defaults struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
Terse bool `short:"t" long:"terse" description:"Shows terse output"`
}
type ListCommand struct {
Config string `short:"c" long:"config" description:"config file" optional:"yes"`
Defaults
}
func main() {
listCmd := ListCommand{}
parser := flags.NewParser(nil, flags.Default)
parser.AddCommand("list", "lists something", "", &listCmd)
parser.Parse()
}
Upvotes: 4