Documentation ¶
Overview ¶
Package claptrap processes the command-line arguments of getopt(3) syntax. claptrap has built-in support for sub-commands; long and short flag name combination (`--version`, `-v`); `--flag=<value>` syntax; automatic invertable boolean flags (`--clean` => `--no-clean`); short-flag combination (`-c -v -p` = `-cvp`); variadic arguments; typed arguments/flags (int, bool, string, float, Duration); global flags; mandatory arguments; positional arguments; command matching (`ls` = `list`); subcommands (`cmd help topic`); `Usage` *and* manpage generation; -- and **no external dependencies**. Vendoring is as easy as copying this file into your project and changing the package name.
Index ¶
- Variables
- type Arg
- type CommandConfig
- func (commandConfig *CommandConfig) Add(name string, params ...interface{}) *Arg
- func (c *CommandConfig) AddCommand(name, description string) *CommandConfig
- func (c CommandConfig) Bool(n string) bool
- func (c CommandConfig) Duration(n string) time.Duration
- func (c CommandConfig) Durations(n string) []time.Duration
- func (c CommandConfig) Float(n string) float64
- func (c CommandConfig) Floats(n string) []float64
- func (c CommandConfig) Int(n string) int
- func (c CommandConfig) Ints(n string) []int
- func (c *CommandConfig) Parse(values []string)
- func (c CommandConfig) String(n string) string
- func (c CommandConfig) Strings(n string) []string
Examples ¶
- CommandConfig.Add (Arguments)
- CommandConfig.Add (Autono)
- CommandConfig.Add (Variations)
- CommandConfig.AddCommand
- CommandConfig.Bool
- CommandConfig.Duration
- CommandConfig.Durations
- CommandConfig.Parse (ExitWithError)
- CommandConfig.Parse (Mandatory)
- CommandConfig.Parse (Usage)
- CommandConfig.Parse (ValidateArgs)
Constants ¶
This section is empty.
Variables ¶
var HandleErrors func(int, []error) = func(exitCode int, errors []error) { for _, e := range errors { fmt.Fprintf(os.Stderr, "%s\n", e) } os.Exit(exitCode) }
Override this if you want to handle parse errors on your own.
var HelpTemplate string = strings.Join([]string{`{{ define "defaults" }} ({{ if .IsMandatory }}!{{ end }}{{ .DefaultValue }}){{ end }}`, `{{ define "command" }}{{ $command := . }}{{ .Name }}{{ if .Args }} [args]{{ end }}{{ if .Commands }} [commands]{{ end }}`, ` {{ .Description }}{{ $padname := 17 }}{{ $padtype := 17 }}{{ $longpad := 34 }}`, ` Commands:`, `{{ range .Commands }} {{ PadOut $longpad .Name }}{{ .Description }}`, `{{ end }}`, ` Arguments:`, `{{ range .ArgNames }}{{ with (index $command.Args .) }} {{ PadOut $padname .Name }}{{ if .IsVariadic }}{{ PadOut $padtype (printf "<%s>..." .Type) }}{{ else }}{{ PadOut $padtype (printf "<%s> " .Type) }}{{ .Description }}{{if .Options }} {{.Options}}{{end}}{{ template "defaults" . }}`, `{{ end }}{{ end }}{{ end }}`, ` Flags:`, `{{ range .Args }}{{ if .IsFlag }} {{ $name := (printf "-%s" .ShortName) }}{{ if (and .Name (not .ShortName)) }}{{ $name = (printf "--%s" .Name) }}{{ else if .Name }}{{ $name = (printf "--%s / -%s" .Name .ShortName) }}{{ end }}{{ PadOut $padname $name }}{{ if (not (eq .Type "bool")) }}{{ if .IsVariadic }}{{ PadOut $padtype (printf "<%s>..." .Type) }}{{ else }}{{ PadOut $padtype (printf "<%s> " .Type) }}{{ end }}{{ else }}{{ PadOut $padtype "" }}{{ end }}{{ .Description }}{{if .Options }} {{.Options}}{{end}}{{ template "defaults" . }}{{ if (and (eq .Type "bool") .Name)}}`, ` {{ PadOut $padname (printf "--no-%s" .Name)}}{{ PadOut $padtype ""}}{{ .Description}} (false){{ end}}`, `{{ end }}{{ end }}{{ end }}USAGE: {{ template "command" . }}`}, "\n")
Set this to ManTempl to generate man pages, or to your own template
var Usage func() = func() { t := template.New("help") t.Funcs(template.FuncMap{"PadOut": func(i int, v string) string { v = strings.ReplaceAll(strings.ReplaceAll(v, "[]", ""), "time.", "") if len(v) > i { i = len(v) } return v + strings.Repeat(" ", i-len(v)) }}) if mp, err := t.Parse(HelpTemplate); err != nil { panic(err) } else { if err := mp.Execute(os.Stdout, RootCommand); err != nil { panic(err) } } }
Usage prints usage information for the flag set. To print usage for a subcommand, set the RootCommand to the command to be printed and call Usage.
Functions ¶
This section is empty.
Types ¶
type Arg ¶
type Arg struct { // name of the argument Name string ShortName string IsVariadic bool IsMandatory bool // Options is either nil, or a slice of type DefaultValue Options interface{} // DefaultValue is never nil, and it determines the type of Arg's value DefaultValue interface{} // Value is always either nil, or a slice of type DefaultValue Value interface{} Description string IsFlag bool // Type is the Go string representation of the type, minus the package. I.e., time.Duration is "Duration" Type string }
Arg holds the structured information about an argument.
func (Arg) IsSet ¶
IsSet returns true if the Argument was provided with a value in the Parsed data.
type CommandConfig ¶
type CommandConfig struct { // name of the sub-command ("" for the root command) Name string // Defined subcommands Commands map[string]*CommandConfig // The parsed subcommand, if any Command *CommandConfig // registered command argument values Args map[string]*Arg // list of the argument names (for ordered iteration) ArgNames []string Description string // contains filtered or unexported fields }
CommandConfig type holds the structure and values of the command-line arguments of command.
var RootCommand *CommandConfig
RootCommand is the first command, if any. It will be nil if no command was parsed.
func Command ¶
func Command(name, description string) *CommandConfig
Command creates the root command for the program. Usually, it will be called with os.Args[0] for the first argument.
func (*CommandConfig) Add ¶
func (commandConfig *CommandConfig) Add(name string, params ...interface{}) *Arg
Add adds a named (positional) argument, or a flag. it requires a minimum of two arguments: a name and description. For flags, a second argument can be added for the short flag, and for all, the default value can be provided. If no default value is provided, then arguments are default strings and flags are default bools. Flags are specified with double dashes with long names; short flags are single dash and a single character.
The order of arguments must be:
If a flag, then <[LONGNAME] [SHORTNAME]> [DEFAULT-OR-CHOICE] <DESCRIPTION>
If an argument, then: <NAME> [DEFAULT] <DESCRIPTION>
Named (positional) arguments do not have short names. The `shortName` argument should be a single character after the dash.
Arguments can be made mandatory with a ! prefix in the name. Because named arguments (non-flags) are consumed in order, this has the effect of making _all_ arguments before the mandatory argument required. Mandatory flags can appear in any order.
Variadic arguments can be created by appending "..." to the end of the name (the first argument). Only one amed (positional) argument may be variadic; any number of variadic flags can be created.
Arguments are strongly typed. The type of an argument is derived from the default value. The supported type
- int
- string
- float64
- bool
- time.Duration
If the provided defaultValue is an array of one of the above types, then that array defines a set of legal values; any provided parameter that doesn't match a value in the array will result in a parse error.
Boolean arguments differ from other types in that boolean Args may *not* be variadic, and will produce an error. Boolean Args may not have array defaults; the options are always `true` and `false`. Boolean flags also do not take arguments: they are merely provided, or not. Boolean flags with long names automatically get a `no-<longname>` option, which if provided, returns `false' for the flag. Regardless of the default, boolean flags are true if provided, and false if inverted.
On the command line, Flags are prefixed with dashes. With the exceptions above, Flags follow all the rules and features of arguments: mandatory, variadic, defaults, choices, and types.
Example (Arguments) ¶
rt := Command("args", "demonstrating arguments (vs flags)") rt.Add("first", "firstDefault", "the first argument") rt.Add("second", "secondDefault", "the second argument") rt.Add("rest...", "", "the rest of the arguments") rt.Parse([]string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "gamma"}) fmt.Printf("%s, %s, %+v\n", rt.String("first"), rt.String("second"), rt.Strings("rest"))
Output: alpha, bravo, [charlie delta echo foxtrot gamma]
Example (Autono) ¶
rt := Command("args", "demonstrating arguments (vs flags)") rt.Add("--flag", true, "a bool flag with a true default") rt.Parse([]string{"--no-flag"}) fmt.Printf("%t\n", rt.Bool("")) // Output false
Output:
Example (Variations) ¶
rt := Command("args", "demonstrating arguments (vs flags)") rt.Add("namedarg", "a string argument") rt.Add("--longname", "a bool long-name flag") rt.Add("-s", "a bool short-name flag") rt.Add("boolarg", false, "a boolean argument") rt.Add("--string", "default", "a string flag") rt.Add("-i", 10, "an int short flag") rt.Add("--time", "-t", 5*time.Minute, "a Duration flag with short and long names") rt.Add("--options", "-o", []string{"one", "of", "these"}, "a string flag with limited legal values") rt.Add("!--mandatory", 0.0, "a mandatory float flag") rt.Add("-m...", "", "a variadic flag") rt.Add("remainder...", "all of the rest of the arguments, if any") rt.Parse([]string{"--mandatory", "6.2831853070"}) fmt.Printf("%f %s\n", rt.Float("mandatory"), rt.Duration("time")) // Output 6.283185 5m0s
Output:
func (*CommandConfig) AddCommand ¶
func (c *CommandConfig) AddCommand(name, description string) *CommandConfig
AddCommand creates a command. If the command name is an empty string, the command created is the root command. Commands may have zero or more subcommands. Commands have their own, distinct sets of flags, arguments, and commands.
Example ¶
rt := Command("jabberwocky", "a poem") rt.Add("-v", true, "a bool flag that defaults to true") m := rt.AddCommand("mome", "word one") m.Add("-v", -1, "an int flag") r := m.AddCommand("raths", "word two") r.Add("-v", "dflt", "a string flag") o := r.AddCommand("outgrabe", "word three") o.Add("-v", "another, different, bool flag") m.Parse([]string{"mome", "rath", "-v", "6", "outgrabe"}) fmt.Printf("(%t), %s(%d), %s(%q), %s(%t)", rt.Command.Bool("v"), rt.Command.Name, rt.Command.Int("v"), rt.Command.Name, rt.Command.String("v"), rt.Command.Name, rt.Command.Bool("v")) // Output true, mome(true), rath(6), outgrabe(false)
Output:
func (CommandConfig) Bool ¶
func (c CommandConfig) Bool(n string) bool
Bool finds a set Arg or Flag by name and returns its first value, or the value of the default, as an bool. See documentation for Int() for the rules
Example ¶
rt := Command("args", "demonstrating booleans") rt.Add("--correct", "correct type") rt.Add("--incorrect", 4, "correct type") rt.Add("--default", true, "default values") rt.Parse([]string{"--correct"}) fmt.Printf("%t %t %t", rt.Bool("correct"), rt.Bool("incorrect"), rt.Bool("default"))
Output: true false true
func (CommandConfig) Duration ¶
func (c CommandConfig) Duration(n string) time.Duration
Duration finds a set Arg or Flag by name and returns its first value, or the value of the default, as an duration. See documentation for Int() for the rules
Example ¶
rt := Command("args", "demonstrating booleans") rt.Add("--time", time.Second, "correct type") rt.Parse([]string{"--time", "5h"}) fmt.Printf("%s\n", rt.Duration("time"))
Output: 5h0m0s
func (CommandConfig) Durations ¶ added in v4.1.0
func (c CommandConfig) Durations(n string) []time.Duration
Durations returns the Arg value as an array of type duration, or the defaults if no argument was given. It returns an empty array if the Arg was declared as a different type.
Example ¶
rt := Command("args", "demonstrating booleans") rt.Add("--time", time.Second, "correct type") rt.Add("--times...", time.Second, "correct type") rt.Parse([]string{"--time", "5h", "--times", "1s", "--times", "2m"}) fmt.Printf("%s %v\n", rt.Duration("time"), rt.Durations("times"))
Output: 5h0m0s [1s 2m0s]
func (CommandConfig) Float ¶
func (c CommandConfig) Float(n string) float64
Float finds a set Arg or Flag by name and returns its first value, or the value of the default, as an float. See documentation for Int() for the rules
func (CommandConfig) Floats ¶ added in v4.1.0
func (c CommandConfig) Floats(n string) []float64
Floats returns the Arg value as an array of type float, or the defaults if no argument was given. It returns an empty array if the Arg was declared as a different type.
func (CommandConfig) Int ¶
func (c CommandConfig) Int(n string) int
Ints finds a set Arg or Flag by name and returns its first value, or the value of the default, as an int.
func (CommandConfig) Ints ¶ added in v4.1.0
func (c CommandConfig) Ints(n string) []int
Ints returns the Arg value as an array of type int, or the defaults if no argument was given. It returns an empty array if the Arg was declared as a different type.
func (*CommandConfig) Parse ¶
func (c *CommandConfig) Parse(values []string)
Parse parses an array of arguments and returns a command object, or an error if any of the parameter validations fail. If no root command is registered, the first array item must be a registered command.
See the rules for `AddArg()` and `AddFlag()` for specific parse rules.
Example (ExitWithError) ¶
HandleErrors = func(i int, es []error) { for _, e := range es { fmt.Println(e) } } rt := Command("args", "demonstrating arguments (vs flags)") rt.Add("first", "firstDefault", "the first argument") rt.Add("!second", "secondDefault", "the second argument") rt.Parse([]string{"alpha"})
Output: args -- missing mandatory option: second /
Example (Mandatory) ¶
HandleErrors = func(i int, es []error) { for _, e := range es { fmt.Println(e) } } rt := Command("args", "demonstrating arguments (vs flags)") rt.Add("first", "firstDefault", "the first argument") rt.Add("!second", "secondDefault", "the second argument") rt.Parse([]string{"alpha", "beta"}) fmt.Printf("%s, %s\n", rt.String("first"), rt.String("second"))
Output: alpha, beta
Example (Usage) ¶
HelpTemplate = "I am {{.Name}}, and I have {{len .Commands}} subcommand and {{len .Args}} args" rt := Command("args", "demonstrating booleans") rt.Add("name", "your name") rt.Add("age", 21, "your age") rt.AddCommand("help", "show the usage") Usage() fmt.Println() // Output I am args, and I have 1 subcommand and 2 args
Output:
Example (ValidateArgs) ¶
HandleErrors = func(i int, es []error) { for _, e := range es { fmt.Println(e) } } rt := Command("args", "demonstrating arguments (vs flags)") rt.Add("first", "firstDefault", "the first argument") rt.Add("second", "secondDefault", "the second argument") rt.Parse([]string{"alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "gamma"})
Output: got more parameters than defined arguments: charlie
func (CommandConfig) String ¶
func (c CommandConfig) String(n string) string
String finds a set Arg or Flag by name and returns its first value, or the value of the default, as an string. See documentation for Int() for the rules
func (CommandConfig) Strings ¶ added in v4.1.0
func (c CommandConfig) Strings(n string) []string
Strings returns the Arg value as an array of type string, or the defaults if no argument was given. It returns an empty array if the Arg was declared as a different type.