Documentation ¶
Overview ¶
Package cmd is a minimalistic library that enables easy sub commands with the standard `flag` library.
This library extends the standard library `flag` package to support sub commands and more features in a minimalistic and idiomatic API.
Features:
- [x] Sub commands.
- [x] Automatic bash completion.
- [x] Flag values definition and check.
- [x] Explicit positional arguments definition.
- [x] Automatic usage text.
Usage ¶
Define a root command object using the `New` function. This object exposes the standard library's `flag.FlagSet` API, which enables adding flags in the standard way. Additionally, this object exposes the `SubCommand` method, which returns another command object. This objects also exposing the same API, enabling definition of flags and nested sub commands. The root object then have to be called with the `Parse` method, similarly to the `flag.Parse` call.
Principles ¶
* Minimalistic and `flag`-like.
* Any flag that is defined in the base command will be reflected in all of its sub commands.
* When user types the command, it starts from the command and sub commands, only then types the flags and then the positional arguments:
[command] [sub commands...] [flags...] [positional args...]
* When a command defines positional arguments, all its sub commands has these positional arguments and thus can't define their own positional arguments.
* When flag configuration is wrong, the program will panic.
Example ¶
Definition and usage of sub commands and sub commands flags.
package main import ( "fmt" "github.com/posener/cmd" ) var ( // Define root command with a single string flag. This object the familiar standard library // `*flag.FlagSet` API, so it can be used similarly. root = cmd.New() flag0 = root.String("flag0", "", "root string flag") // Define a sub command from the root command with a single string flag. The sub command object // also have the same API as the root command object. sub1 = root.SubCommand("sub1", "first sub command") flag1 = sub1.String("flag1", "", "sub1 string flag") // Define a second sub command from the root command with an int flag. sub2 = root.SubCommand("sub2", "second sub command") flag2 = sub1.Int("flag2", 0, "sub2 int flag") ) // Definition and usage of sub commands and sub commands flags. func main() { // Parse command line arguments. root.ParseArgs("cmd", "sub1", "-flag1", "value") // Check which sub command was choses by the user. switch { case sub1.Parsed(): fmt.Printf("Called sub1 with flag: %s", *flag1) case sub2.Parsed(): fmt.Printf("Called sub2 with flag: %d", *flag2) } }
Output: Called sub1 with flag: value
Example (Args) ¶
In the cmd package, positional arguments should be explicitly defined. They are defined using the `Args` or `ArgsVar` methods.
package main import ( "fmt" "github.com/posener/cmd" ) func main() { // Should be defined in global `var`. var ( root = cmd.New() // Positional arguments should be defined as any other flag. args = root.Args("[args...]", "positional arguments for command line") ) // Parse fake command line arguments. root.ParseArgs("cmd", "v1", "v2", "v3") // Test: fmt.Println(*args) }
Output: [v1 v2 v3]
Example (ArgsFn) ¶
An example of how to parse positional arguments using a custom function. It enables the advantage of using named variables such as `src` and `dst` as opposed to args[0] and args[1].
package main import ( "fmt" "github.com/posener/cmd" ) func main() { // Should be defined in global `var`. var ( root = cmd.New() // Define variables that will hold the command line positional arguments. src, dst string ) // Define an `ArgsFn` that converts a list of positional arguments to the named variables. It // should return an error when the arguments are invalid. argsFn := cmd.ArgsFn(func(args []string) error { if len(args) != 2 { return fmt.Errorf("expected src and dst, got %d arguments", len(args)) } src, dst = args[0], args[1] return nil }) // Should be in `init()`. // Register the function in the root command using the `ArgsVar` method. root.ArgsVar(argsFn, "[src] [dst]", "positional arguments for command line") // Should be in `main()`. root.ParseArgs("cmd", "from.txt", "to.txt") // Test: fmt.Println(src, dst) }
Output: from.txt to.txt
Example (ArgsInt) ¶
An example of defining int positional arguments.
package main import ( "fmt" "github.com/posener/cmd" ) func main() { // Should be defined in global `var`. var ( root = cmd.New() // Define a variable that will hold the positional arguments values. Use the `ArgsInt` type // to parse them as int. args cmd.ArgsInt ) // Should be in `init()`. // Register the positional argument variable in the root command using the `ArgsVar` method. root.ArgsVar(&args, "[int...]", "numbers to sum") // Should be in `main()`. // Parse fake command line arguments. root.ParseArgs("cmd", "10", "20", "30") // Test: sum := 0 for _, n := range args { sum += n } fmt.Println(sum) }
Output: 60
Example (ArgsN) ¶
An example of defining an exact number of positional arguments.
package main import ( "fmt" "github.com/posener/cmd" ) func main() { // Should be defined in global `var`. var ( root = cmd.New() // Define a variable that will hold positional arguments. Create the `ArgsStr` object with // cap=2 to ensure that the number of arguments is exactly 2. args = make(cmd.ArgsStr, 2) ) // Should be in `init()`. // Register the positional argument variable in the root command using the `ArgsVar` method // (similar to the Var methods of the standard library). root.ArgsVar(&args, "[src] [dst]", "positional arguments for command line") // Should be in `main()`. // Parse fake command line arguments. root.ParseArgs("cmd", "from.txt", "to.txt") // Test: fmt.Println(args) }
Output: [from.txt to.txt]
Example (Values) ¶
An example that shows how to use advanced configuration of flags and positional arguments using the predict package.
package main import ( "fmt" "github.com/posener/cmd" "github.com/posener/complete/v2/predict" ) func main() { // Should be defined in global `var`. var ( root = cmd.New() // Define a flag with valid values 'foo' and 'bar', and enforce the values by `OptCheck()`. // The defined values will be used for bash completion, and since the OptCheck was set, the // flag value will be checked during the parse call. flag1 = root.String("flag1", "", "first flag", predict.OptValues("foo", "bar"), predict.OptCheck()) // Define a flag to accept a valid Go file path. Choose to enforce the valid path using the // `OptCheck` function. The file name will also be completed in the bash completion // processes. file = root.String("file", "", "file path", predict.OptPredictor(predict.Files("*.go")), predict.OptCheck()) // Positional arguments should be explicitly defined. Define positional arguments with valid // values of 'baz' and 'buzz', and choose not to enforce these values by not calling // `OptCheck`. These values will also be completed in the bash completion process. args = root.Args("[args...]", "positional arguments", predict.OptValues("baz", "buzz")) ) // Parse fake command line arguments. root.ParseArgs("cmd", "-flag1", "foo", "-file", "cmd.go", "buz", "bazz") // Test: fmt.Println(*flag1, *file, *args) }
Output: foo cmd.go [buz bazz]
Index ¶
- func OptDetails(details string) optionFn
- func OptErrorHandling(errorHandling flag.ErrorHandling) optionRootFn
- func OptName(name string) optionRootFn
- func OptOutput(w io.Writer) optionRootFn
- func OptSynopsis(synopsis string) optionRootFn
- type ArgsFn
- type ArgsInt
- type ArgsStr
- type ArgsValue
- type Cmd
- type SubCmd
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func OptDetails ¶
func OptDetails(details string) optionFn
OptDetails sets a detailed description to the root command.
func OptErrorHandling ¶
func OptErrorHandling(errorHandling flag.ErrorHandling) optionRootFn
OptErrorHandling defines the behavior in case of an error in the `Parse` function.
func OptName ¶
func OptName(name string) optionRootFn
OptName sets a predefined name to the root command.
func OptSynopsis ¶
func OptSynopsis(synopsis string) optionRootFn
OptSynopsis sets a description to the root command.
Types ¶
type ArgsFn ¶
ArgsFn is a function that implements Args. Usage example:
var ( root = cmd.Root() src, dst string ) func setArgs(args []string) error { if len(args) != 2 { return fmt.Errorf("expected src and dst, got %d arguments", len(args)) } src, dst = args[0], args[1] return nil } func init() { root.ArgsVar(cmd.ArgsFn(setArgs), "[src] [dst]", "define source and destination") }
type ArgsInt ¶
type ArgsInt []int
ArgsInt are int positional arguments. If it is created with cap > 0, it will be used to define the number of required arguments.
Usage ¶
To get a list of arbitrary number of integers:
root := cmd.Root() var cmd.ArgsInt args root.ArgsVar(&args, "[int...]", "list of integer args")
To get a list of specific number of integers:
root := cmd.Root() args := make(cmd.ArgsInt, 3) root.ArgsVar(&args, "[int1] [int2] [int3]", "list of 3 integers")
type ArgsStr ¶
type ArgsStr []string
ArgsStr are string positional arguments. If it is created with cap > 0, it will be used to define the number of required arguments.
Usage ¶
To get a list of arbitrary number of arguments:
root := cmd.Root() var cmd.ArgsStr args root.ArgsVar(&args, "[arg...]", "list of arguments")
To get a list of specific number of arguments:
root := cmd.Root() args := make(cmd.ArgsStr, 3) root.ArgsVar(&args, "[arg1] [arg2] [arg3]", "list of 3 arguments")
type ArgsValue ¶
type ArgsValue interface { // Set should assign values to the positional arguments variable from list of positional // arguments from the command line. It should return an error if the given list does not fit // the requirements. Set([]string) error }
ArgsValue is interface for positional arguments variable. It can be used with the `(*Cmd).ArgsVar` method. For examples of objects that implement this interface see ./args.go.
type Cmd ¶
type Cmd struct {
*SubCmd
}
Cmd is a command that can have set of flags and sub commands.
type SubCmd ¶
type SubCmd struct { // flagsSet holds the flags of the command. *compflag.FlagSet // contains filtered or unexported fields }
SubCmd is a sub command that can have a set of flags and sub commands.
func (*SubCmd) Args ¶
Args returns the positional arguments for the command and enable defining options. Only a sub command that called this method accepts positional arguments. Calling a sub command with positional arguments where they were not defined result in parsing error. The provided options can be nil for default values.
func (*SubCmd) ArgsVar ¶
ArgsVar should be used to parse arguments with specific requirements or to specific object/s. For example, accept only 3 positional arguments:
var ( root = cmd.Root() args = make(cmd.ArgsStr, 3) ) func init() { root.ArgsVar(args, "[arg1] [arg2] [arg3]", "provide 3 positional arguments") }
The value argument can optionally implement `github.com/posener/complete.Predictor` interface. Then, command completion for the predictor will apply.
func (*SubCmd) SubCommand ¶
SubCommand creates a new sub command to the given command.