Documentation ¶
Overview ¶
Package options provides a command line option parser.
This package is meant as an alternative to the core flag package. It is more powerful without attempting to support every possible feature some parsing library ever introduced. It is arguably easier to use.
Usage:
Create an OptionSpec that documents your program's allowed flags. This begins with a free-text synopsis of your command line interface, then a line containing only two dashes, then a series of option specifications:
import "github.com/gaal/go-options/options" s := options.NewOptions(` cat - concatenate files to standard input Usage: cat [OPTIONS] file... This version of cat supports character set conversion. Fancifully, you can say "-r 3" and have everything told you three times. -- n,numerate,number number input lines e,escape escape nonprintable characters i,input-encoding= charset input is encoded in [utf-8] o,output-encoding= charset output is encoded in [utf-8] r,repeat= repeat every line some number of times [1] v,verbose be verbose `)
Then parse the command line:
opt := s.Parse(os.Args[1:])
This return value is of Options type and has the parsed command line (for an alternate way of parsing the command line, see the "Callback interface" descibed below).
Options may have any number of aliases; the last one is the "canonical" name and the one your program must use when reading values.
opt.Get("input-encoding") // Returns "utf-8", or whatever user set. opt.Get("i") // Error! No option with that canonical name. opt.Get("number") // Returns "" if the user didn't specify it.
Get returns a string. Several very simple conversions are provided but you are encouraged to write your own if you need more.
opt.GetBool("escape") // false (by default) opt.GetBool("number") // false (by default) opt.GetInt("repeat") // 1 (by default)
Options either take a required argument or take no argument. Non-argument options have useful values exposed as bool and ints.
// cat -v -v -v, or alternatively, // cat -vvv opt.GetBool("verbose") // true opt.GetInt("verbose") // 3
The user can say either "--foo=bar" or "--foo bar". Short options may be clustered; "-abc foo" means the same as "-a -b -c=foo".
Parsing stops if "--" is given on the command line.
The "Extra" field of the returned Options contains all non-option command line input. In the case of a cat command, this would be the filenames to concat.
By default, options permits such extra values. Setting UnknownValuesFatal causes it to panic when it enconters them instead.
The "Flags" field of the returned Options contains the series of flags as given on the command line, including repeated ones (which are suppressed in opt -- it only contains the last value). This allows you to do your own handling of repeated options easily.
By default, options does not permit unknown flags. Setting UnknownOptionsFatal to false causes them to be recorded in "flags" instead. Note that since they have no canonical name, they cannot be accessed via opt. Also note that since options does not know about the meaning of these flags, it has to guess whether they consume the next argument or not. This is currently done naively by peeking at the first character of the next argument.
Callback interface:
If you prefer a more type-safe, static interface to your options, you can use options to get that too. Instead of looking at opt and friends, set OptionSpec.ParseCallback:
var (foo string; bar int; baz float64; lst []string; verbose bool) func myParseCallback(spec *OptionSpec, option string, argument *string) { if argument != nil { switch option { case "string-option": foo = *argument case "int-option": fmt.Sscanf(*argument, "%d", &bar) case "decimal-option": fmt.Sscanf(*argument, "%f", &baz) case "list-option": lst = append(lst, *argument) default: spec.PrintUsageAndExit("Unknown option: " + option) } } else { switch option { case "verbose": verbose = true case "help": spec.PrintUsageAndExit("") // No error default: spec.PrintUsageAndExit("Unknown option: " + option) } } spec.ParseCallback = myParseCallback opt := spec.Parse(os.Args[1:]) // Note that the opt.Get won't work when using a custom parse callback.
Index ¶
- Constants
- func GetAll(flag string, flags [][]string) []string
- type OptionSpec
- func (s *OptionSpec) GetCanonical(option string) string
- func (s *OptionSpec) Parse(args []string) Options
- func (s *OptionSpec) PrintUsageAndExit(err string)
- func (s *OptionSpec) SetParseCallback(callback func(*OptionSpec, string, *string)) *OptionSpec
- func (s *OptionSpec) SetUnknownOptionsFatal(val bool) *OptionSpec
- func (s *OptionSpec) SetUnknownValuesFatal(val bool) *OptionSpec
- type Options
- Bugs
Constants ¶
const EX_USAGE = 64 // Exit status for incorrect command lines.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type OptionSpec ¶
type OptionSpec struct { Usage string // Formatted usage string UnknownOptionsFatal bool // Whether to die on unknown flags [true] UnknownValuesFatal bool // Whether to die on extra nonflags [false] ParseCallback func(*OptionSpec, string, *string) // Custom callback function Exit func(code int) // Function to use for exiting [os.Exit] ErrorWriter io.Writer // Alternate Writer for usage writing // contains filtered or unexported fields }
OptionSpec represents the specification of a command line interface.
func NewOptions ¶
func NewOptions(spec string) *OptionSpec
NewOptions takes a string speficiation of a command line interface and returns an OptionSpec for you to call Parse on.
func (*OptionSpec) GetCanonical ¶
func (s *OptionSpec) GetCanonical(option string) string
GetCanonical returns the canonical name of an option, or the empty string if the option is unkown. Useful to tidy up switch statements when using the custom callback interface.
func (*OptionSpec) Parse ¶
func (s *OptionSpec) Parse(args []string) Options
Parse performs the actual parsing of a command line according to an OptionSpec. It returns an Options value; see the package description for an overview of what it means and how to use it. In case of parse error, a panic is thrown. TODO(gaal): decide if gentler error signalling is more useful.
func (*OptionSpec) PrintUsageAndExit ¶
func (s *OptionSpec) PrintUsageAndExit(err string)
PrintUsageAndExit writes the usage string and exits the program. If an error message is given, usage is written to standard error. Otherwise, it is written to standard output; this makes invocations such as "myprog --help | less" work as the user expects. Likewise, the status code is zero when no error was given.
func (*OptionSpec) SetParseCallback ¶
func (s *OptionSpec) SetParseCallback(callback func(*OptionSpec, string, *string)) *OptionSpec
SetParseCallback is a convencience function designed to be chained after NewOptions.
func (*OptionSpec) SetUnknownOptionsFatal ¶
func (s *OptionSpec) SetUnknownOptionsFatal(val bool) *OptionSpec
SetUnknownOptionsFatal is a conveience function designed to be chained after NewOptions.
func (*OptionSpec) SetUnknownValuesFatal ¶
func (s *OptionSpec) SetUnknownValuesFatal(val bool) *OptionSpec
SetUnknownValuesFatal is a conveience function designed to be chained after NewOptions.
type Options ¶
type Options struct { Flags [][]string // Original flags presented on the command line Extra []string // Non-option command line arguments left on the command line Leftover []string // Untouched arguments (after "--") // contains filtered or unexported fields }
Options represents the known formal options provided on the command line.
func (*Options) Get ¶
Get returns the value of an option, which must be known to this parse. Options that take an argument return the argument. Options with no argument return values hinting whether they were specified or not; GetInt or GetBool may be more suited for looking them up.
func (*Options) GetBool ¶
GetBool returns the value of an option as a bool. All values are treated as true except for the following which yield false:
"" (empty), "0", "false", "off", "nil", "null", "no"
Notes ¶
Bugs ¶
Option groups are not yet supported.
The usage string is not yet formatted prettily. It should consider tty width, etc.
Negated options ("--no-frobulate") are not yet supported.