Documentation
¶
Overview ¶
Package modalflag is a wrapper for the flag package in the Go standard library. It provides a convenient method of handling program modes (and sub-modes) and allows different flags for each mode.
At it's simplest it can be used as a replacement for the flag package, with some differences. Whereas, with flag.FlagSet you call Parse() with the array of strings as the only argument, with modalflag you first NewArgs() with the array of arguments and then Parse() with no arguments. For example (note that no error handling of the Parse() function is shown here):
md = Modes{Output: os.Stdout} md.NewArgs(os.Args[1:]) _, _ = md.Parse()
The reason for his difference is to allow effective parsing of modes and sub-modes. We'll come to program modes in a short while.
In the above example, once the arguments have been parsed, non-flag arguments can be retrieved with the RemainingArgs() or GetArg() function. For example, handling exactly one argument:
switch len(md.RemainingArgs()) { case 0: return fmt.Errorf("argument required") case 1: Process(md.GetArg(0)) default: return fmt.Errorf("too many arguments") }
Adding flags is similar to the flag package. Adding a boolean flag:
verbose := md.AddBool("verbose", false, "print additional log messages")
These flag functions return a pointer to a variable of the specified type. The initial value of these variables if the default value, the second argument in the function call above. The Parse() function will set these values appropriately according what the user has requested, for example:
if *verbose { fmt.Println(additionalLogMessage) }
The most important difference between the standard flag package and the modalflag package is the ability of the latter to handle "modes". In this context, a mode is a special command line argument that when specified, puts the program into a different mode of operation. The best and most relevant example I can think of is the go command. The go command has many different modes: build, doc, get, test, etc. Each of these modes are different enough to require a different set of flags and expected arguments.
The modalflag package handles sub-modes with the AddSubModes() function. This function takes any number of string arguments, each one the name of a mode.
md.AddSubModes("run", "test", "debug")
For simplicity, all sub-mode comparisons are case insensitive.
Subsequent calls to Parse() will then process flags in the normal way but unlike the regular flag.Parse() function will check to see if the first argument after the flags is one of these modes. If it is, then the RemainingArgs() function will return all the arguments after the flags AND the mode selector.
So, for example:
md.Parse() switch md.Mode() { case "RUN": runMode(*verbose) default: fmt.Printf("%s not yet implemented", md.Mode()) }
Now that we've decided on what mode we're in, we can again call Parse() to process the remaining arguments. This example shows how we can handle return state and errors from the Parse() function:
func runMode(verbose bool) { md.NewMode() md.AddDuration("runtime", time.ParseDuration("10s"), "max run time") p, err := md.Parse switch p { case ParseError: fmt.Println(err) return case ParseHelp: return } doRun(md.RemainingArguments) }
This second call to Parse() will check for any additional flags and any further sub-modes (none in this example).
We can chain modes together as deep as we want. For example, the "test" mode added above could be divided into several different modes:
md = Modes{Output: os.Stdout} md.NewArgs(os.Args[1:]) md.AddSubModes("run", "test", "debug") _, _ = md.Parse() switch md.Mode() { case "TEST": md.NewMode() md.AddSubModes("A", "B", "C") _, _ = md.Parse() switch md.Mode() { case "A": testA() case "B": testB() case "C": testC() } default: fmt.Printf("%s not yet implemented", md.Mode()) }
Index ¶
- type Modes
- func (md *Modes) AddBool(name string, value bool, usage string) *bool
- func (md *Modes) AddDefaultSubMode(defSubMode string)
- func (md *Modes) AddDuration(name string, value time.Duration, usage string) *time.Duration
- func (md *Modes) AddFloat64(name string, value float64, usage string) *float64
- func (md *Modes) AddInt(name string, value int, usage string) *int
- func (md *Modes) AddInt64(name string, value int64, usage string) *int64
- func (md *Modes) AddString(name string, value string, usage string) *string
- func (md *Modes) AddSubModes(submodes ...string)
- func (md *Modes) AddUint(name string, value uint, usage string) *uint
- func (md *Modes) AddUint64(name string, value uint64, usage string) *uint64
- func (md *Modes) AdditionalHelp(help string)
- func (md *Modes) GetArg(i int) string
- func (md *Modes) MinMax(min int, max int)
- func (md *Modes) Mode() string
- func (md *Modes) NewArgs(args []string)
- func (md *Modes) NewMode()
- func (md *Modes) Parse() (ParseResult, error)
- func (md *Modes) Parsed() bool
- func (md *Modes) Path() string
- func (md *Modes) RemainingArgs() []string
- func (md *Modes) String() string
- func (md *Modes) Visit(fn func(flag string))
- type ParseResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Modes ¶
type Modes struct { // where to print output (help messages etc). defaults to os.Stdout Output io.Writer // contains filtered or unexported fields }
Modes provides an easy way of handling command line arguments. The Output field should be specified before calling Parse() or you will not see any help messages.
func (*Modes) AddDefaultSubMode ¶
AddDefaultSubMode to list of sub-modes.
func (*Modes) AddDuration ¶
AddDuration flag for next call to Parse().
func (*Modes) AddFloat64 ¶
AddFloat64 flag for next call to Parse().
func (*Modes) AddSubModes ¶
AddSubModes to list of submodes for next parse. The first sub-mode in the list is considered to be the default sub-mode. If you need more control over this, AddDefaultSubMode() can be used.
Note that sub-mode comparisons are case insensitive.
func (*Modes) AdditionalHelp ¶
AdditionalHelp allows you to add extensive help text to be displayed in addition to the regular help on available flags.
func (*Modes) MinMax ¶ added in v0.12.1
MinMax specifies the minimum and maximum number of non-flags arguments that are required.
func (*Modes) NewMode ¶
func (md *Modes) NewMode()
NewMode indicates that further arguments should be considered part of a new mode.
func (*Modes) Parse ¶
func (md *Modes) Parse() (ParseResult, error)
Parse the top level layer of arguments. Returns a value of ParseResult. The idiomatic usage is as follows:
p, err := md.Parse() switch p { case modalflag.ParseHelp: // help message has already been printed return case modalflag.ParseError: printError(err) return }
Help messages are handled automatically by the function. The return value ParseHelp is to help you guide your program appropriately. The above pattern suggests it should be treated similarly to an error and without the need to display anything further to the user.
Note that the Output field of the Modes struct *must* be specified in order for any help messages to be visible. The most common and useful value of the field is os.Stdout.
func (*Modes) Parsed ¶
Parsed returns false if Parse() has not yet been called since either a call to NewArgs() or NewMode(). Note that, a Modes struct is considered to be Parsed() even if Parse() results in an error.
func (*Modes) RemainingArgs ¶
RemainingArgs after a call to Parse() ie. arguments that aren't flags or a listed sub-mode.
type ParseResult ¶
type ParseResult int
ParseResult is returned from the Parse() function.
const ( // Continue with command line processing. How this result should be // interpreted depends on the context, which the caller of the Parse() // function knows best. However, generally we can say that if sub-modes // were specified in the preceding call to NewMode() then the Mode field // of the Modes struct should be checked. ParseContinue ParseResult = iota // The wrong number of non-flag arguments have been specified. ParseTooFewArgs ParseTooManyArgs // Help was requested and has been printed. ParseHelp // an error has occurred and is returned as the second return value. ParseError )
a list of valid ParseResult values.