Documentation ¶
Overview ¶
Package subcmd provides types and functions for creating command-line interfaces with subcommands and flags.
Example ¶
package main import ( "context" "flag" "fmt" "io/ioutil" "strconv" "github.com/bobg/subcmd" ) func main() { // First, parse global flags normally. var ( verbose = flag.Bool("verbose", false, "be verbose") config = flag.String("config", ".config", "path to config file") ) flag.Parse() confData, err := ioutil.ReadFile(*config) if err != nil { panic(err) } // Stash the relevant info into an object that implements the subcmd.Cmd interface. cmd := command{ conf: string(confData), verbose: *verbose, } // Pass that object to subcmd.Run, // which will parse a subcommand and its flags // from the remaining command-line arguments // and run them. err = subcmd.Run(context.Background(), cmd, flag.Args()) if err != nil { panic(err) } } // Type command implements the subcmd.Cmd interface, // meaning that it can report its subcommands, // their names, // and their parameters and types // via the Subcmds method. type command struct { conf string verbose bool } func (c command) Subcmds() subcmd.Map { // There are two subcommands: // hello, which takes -name and -spanish flags, // and add, which takes no flags. return subcmd.Commands( "hello", hello, subcmd.Params( "name", subcmd.String, "", "name to greet", "spanish", subcmd.Bool, false, "greet in Spanish", ), "add", c.add, nil, ) } // The implementation of a subcommand takes a context object, // the values of its parsed flags, // and a slice of remaining command-line arguments // (which could be used in another call to subcmd.Run // to implement a sub-subcommand). // It can optionally return an error. func hello(_ context.Context, name string, spanish bool, _ []string) { if spanish { fmt.Print("Hola") } else { fmt.Print("Hello") } if name != "" { fmt.Printf(" %s", name) } fmt.Print("\n") } func (c command) add(_ context.Context, args []string) error { if c.verbose { fmt.Printf("adding %d value(s)\n", len(args)) } var result float64 for _, arg := range args { aval, err := strconv.ParseFloat(arg, 64) if err != nil { return err } result += aval } fmt.Println(result) return nil }
Output:
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoArgs is the error when Run is called with an empty list of args. ErrNoArgs = errors.New("no arguments") // ErrUnknown is the error when Run is called with an unknown subcommand as args[0]. ErrUnknown = errors.New("unknown subcommand") )
Functions ¶
func Run ¶
Run runs the subcommand of c named in args[0]. The remaining args are parsed with a new flag.FlagSet, populated according to the parameters of the named Subcmd. The Subcmd's function is invoked with a context object, the parameter values parsed by the FlagSet, and a slice of the args left over after FlagSet parsing. The FlagSet is placed in the context object that's passed to the Subcmd's function, and can be retrieved if needed with the FlagSet function. No FlagSet is present if the subcommand takes no parameters.
Types ¶
type Cmd ¶
type Cmd interface { // Subcmds returns this Cmd's subcommands as a map, // whose keys are subcommand names and values are Subcmd objects. // Implementations may use the Commands function to build this map. Subcmds() Map }
Cmd is the way a command tells Run how to parse and run its subcommands.
type Map ¶
Map is the type of the data structure returned by Cmd.Subcmds and by Commands. It maps a subcommand name to its Subcmd structure.
func Commands ¶
func Commands(args ...interface{}) Map
Commands is a convenience function for producing the map needed by a Cmd. It takes 3n arguments, where n is the number of subcommands. Each group of three is: - the subcommand name, a string; - the function implementing the subcommand; - the list of parameters for the function, a slice of Param (which can be produced with Params).
A call like this:
Commands( "foo", foo, Params( "verbose", Bool, false, "be verbose", ), "bar", bar, Params( "level", Int, 0, "barness level", ), )
is equivalent to:
Map{ "foo": Subcmd{ F: foo, Params: []Param{ { Name: "verbose", Type: Bool, Default: false, Doc: "be verbose", }, }, }, "bar": Subcmd{ F: bar, Params: []Param{ { Name: "level", Type: Int, Default: 0, Doc: "barness level", }, }, }, }
This function panics if the number or types of the arguments are wrong.
type Param ¶
type Param struct { // Name is the flag name for the parameter // (e.g., "verbose" for a -verbose flag). Name string // Type is the type of the parameter. Type Type // Default is a default value for the parameter. // Its type must be suitable for Type. Default interface{} // Doc is a docstring for the parameter. Doc string }
Param is one parameter of a Subcmd.
func Params ¶
func Params(a ...interface{}) []Param
Params is a convenience function for producing the list of parameters needed by a Subcmd. It takes 4n arguments, where n is the number of parameters. Each group of four is: - the flag name for the parameter, a string (e.g. "verbose" for a -verbose flag); - the type of the parameter, a Type constant; - the default value of the parameter, - the doc string for the parameter.
This function panics if the number or types of the arguments are wrong.
type Subcmd ¶
type Subcmd struct { // F is the function implementing the subcommand. // Its signature must be func(context.Context, ..., []string) error, // where the number and types of parameters between the context and the string slice // is given by Params. // The error return is optional. F interface{} // Params describes the parameters to F // (excluding the initial context.Context that F takes, and the final []string). Params []Param }
Subcmd is one subcommand of a Cmd.