Documentation
¶
Overview ¶
subcmd is a minimalistic library that enables easy sub commands with the standard `flag` library.
Define a `root` command object using the `Root` 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` or `ParseArgs` methods, similarly to the `flag.Parse` call.
The usage is automatically configured to show both sub commands and flags.
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.
* Positional arguments are as any other flag: their number and type should be enforced and checked.
* When a command that defined positional arguments, all its sub commands has these positional arguments and thus can't define their own positional arguments.
* Usage format is standard, programs can't define their own format.
* When flag configuration is wrong, the program will panic when starts. Most of them in flag definition stage, and not after flag parsing stage.
Example ¶
Definition and usage of sub commands and sub commands flags.
package main
import (
"fmt"
"github.com/posener/subcmd"
)
var (
// Define a root command. Some options can be set using the `Opt*` functions. It returns a
// `*Cmd` object.
root = subcmd.Root()
// The `*Cmd` object can be used as the standard library `flag.FlagSet`.
flag0 = root.String("flag0", "", "root stringflag")
// From each command object, a sub command can be created. This can be done recursively.
sub1 = root.SubCommand("sub1", "first sub command")
// Each sub command can have flags attached.
flag1 = sub1.String("flag1", "", "sub1 string 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() {
// In the example we use `Parse()` for a given list of command line arguments. This is useful
// for testing, but should be replaced with `root.ParseArgs()` in `main()`
root.Parse([]string{"cmd", "sub1", "-flag1", "value"})
// Usually the program should switch over the sub commands. The chosen sub command will return
// true for the `Parsed()` method.
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) ¶
Usage of positional arguments. If a program accepts positional arguments it must declare it using the `Args()` or the `ArgsVar()` methods. Positional arguments can be also defined on sub commands.
package main
import (
"fmt"
"github.com/posener/subcmd"
)
func main() {
// Should be defined in global `var`.
var (
root = subcmd.Root()
// Positional arguments can be defined as any other flag.
args = root.Args("[args...]", "positional arguments for command line")
)
// Should be in `main()`.
root.Parse([]string{"cmd", "v1", "v2", "v3"})
// Test:
fmt.Println(*args)
}
Output: [v1 v2 v3]
Example (ArgsFn) ¶
Usage of positional arguments with a conversion function.
package main
import (
"fmt"
"github.com/posener/subcmd"
)
func main() {
// Should be defined in global `var`.
var (
root = subcmd.Root()
src, dst string
)
// A function that convert the positional arguments to the program variables.
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()`.
root.ArgsVar(subcmd.ArgsFn(argsFn), "[src] [dst]", "positional arguments for command line")
// Should be in `main()`.
root.Parse([]string{"cmd", "from.txt", "to.txt"})
// Test:
fmt.Println(src, dst)
}
Output: from.txt to.txt
Example (ArgsInt) ¶
Usage of positional arguments of a specific type.
package main
import (
"fmt"
"github.com/posener/subcmd"
)
func main() {
// Should be defined in global `var`.
var (
root = subcmd.Root()
// Define positional arguments of type integer.
args subcmd.ArgsInt
)
// Should be in `init()`.
root.ArgsVar(&args, "[int...]", "numbers to sum")
// Should be in `main()`.
root.Parse([]string{"cmd", "10", "20", "30"})
// Test:
sum := 0
for _, n := range args {
sum += n
}
fmt.Println(sum)
}
Output: 60
Example (ArgsN) ¶
Usage of positional arguments with exact number of arguments.
package main
import (
"fmt"
"github.com/posener/subcmd"
)
func main() {
// Should be defined in global `var`.
var (
root = subcmd.Root()
// Define arguments with cap=2 will ensure that the number of arguments is always 2.
args = make(subcmd.ArgsStr, 2)
)
// Should be in `init()`.
root.ArgsVar(&args, "[src] [dst]", "positional arguments for command line")
// Should be in `main()`.
root.Parse([]string{"cmd", "from.txt", "to.txt"})
// Test:
fmt.Println(args)
}
Output: [from.txt to.txt]
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
- func (c *SubCmd) Args(usage, details string) *[]string
- func (c *SubCmd) ArgsVar(value ArgsValue, usage, details string)
- func (c *SubCmd) Bool(name string, value bool, usage string) *bool
- func (c *SubCmd) BoolVar(p *bool, name string, value bool, usage string)
- func (c *SubCmd) Duration(name string, value time.Duration, usage string) *time.Duration
- func (c *SubCmd) DurationVar(p *time.Duration, name string, value time.Duration, usage string)
- func (c *SubCmd) Float64(name string, value float64, usage string) *float64
- func (c *SubCmd) Float64Var(p *float64, name string, value float64, usage string)
- func (c *SubCmd) Int(name string, value int, usage string) *int
- func (c *SubCmd) Int64(name string, value int64, usage string) *int64
- func (c *SubCmd) Int64Var(p *int64, name string, value int64, usage string)
- func (c *SubCmd) IntVar(p *int, name string, value int, usage string)
- func (c *SubCmd) Parsed() bool
- func (c *SubCmd) Set(name, value string) error
- func (c *SubCmd) String(name string, value string, usage string) *string
- func (c *SubCmd) StringVar(p *string, name string, value string, usage string)
- func (c *SubCmd) SubCommand(name string, synopsis string, options ...option) *SubCmd
- func (c *SubCmd) Uint(name string, value uint, usage string) *uint
- func (c *SubCmd) Uint64(name string, value uint64, usage string) *uint64
- func (c *SubCmd) UintVar(p *uint, name string, value uint, usage string)
- func (c *SubCmd) UintVar64(p *uint64, name string, value uint64, usage string)
- func (c *SubCmd) Usage()
- func (c *SubCmd) Var(value flag.Value, name string, usage string)
- func (c *SubCmd) Visit(fn func(*flag.Flag))
- func (c *SubCmd) VisitAll(fn func(*flag.Flag))
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func OptDetails ¶ added in v1.1.0
func OptDetails(details string) optionFn
OptSynopsis sets a 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 ¶ added in v1.1.0
func OptSynopsis(synopsis string) optionRootFn
OptSynopsis sets a description to the root command.
Types ¶
type ArgsFn ¶ added in v1.1.0
ArgsFn is a function that implements Args. Usage example:
var (
cmd = subcmd.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() {
cmd.ArgsVar(subcmd.ArgsFn(setArgs), "[src] [dst]", "define source and destination")
}
type ArgsInt ¶ added in v1.1.0
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 := subcmd.Root() var subcmd.ArgsInt args root.ArgsVar(&args, "[int...]", "list of integer args")
To get a list of specific number of integers:
root := subcmd.Root() args := make(subcmd.ArgsInt, 3) root.ArgsVar(&args, "[int1] [int2] [int3]", "list of 3 integers")
type ArgsStr ¶ added in v1.1.0
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 := subcmd.Root() var subcmd.ArgsStr args root.ArgsVar(&args, "[arg...]", "list of arguments")
To get a list of specific number of arguments:
root := subcmd.Root() args := make(subcmd.ArgsStr, 3) root.ArgsVar(&args, "[arg1] [arg2] [arg3]", "list of 3 arguments")
type ArgsValue ¶ added in v1.1.0
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 ¶ added in v1.2.0
type SubCmd struct {
// contains filtered or unexported fields
}
SubCmd is a sub command that can have a set of flags and sub commands.
func (*SubCmd) Args ¶ added in v1.2.0
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 ¶ added in v1.2.0
ArgsVar should be used to parse arguments with specific requirements or to specific object/s. For example, accept only 3 positional arguments:
var (
cmd = subcmd.Root()
args = make(subcmd.ArgsStr, 3)
)
func init() {
cmd.ArgsVar(args, "[arg1] [arg2] [arg3]", "provide 3 positional arguments")
}
func (*SubCmd) DurationVar ¶ added in v1.2.0
func (*SubCmd) Float64Var ¶ added in v1.2.0
func (*SubCmd) SubCommand ¶ added in v1.2.0
SubCommand creates a new sub command to the given command.