summaryrefslogtreecommitdiff
path: root/vendor/github.com/pborman/getopt/getopt.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pborman/getopt/getopt.go')
-rw-r--r--vendor/github.com/pborman/getopt/getopt.go537
1 files changed, 537 insertions, 0 deletions
diff --git a/vendor/github.com/pborman/getopt/getopt.go b/vendor/github.com/pborman/getopt/getopt.go
new file mode 100644
index 0000000..e3279ab
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/getopt.go
@@ -0,0 +1,537 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package getopt (v1) provides traditional getopt processing for implementing
+// commands that use traditional command lines. The standard Go flag package
+// cannot be used to write a program that parses flags the way ls or ssh does,
+// for example.
+//
+// A new version of this package (v2) (whose package name is also getopt) is
+// available as:
+//
+// "github.com/pborman/getopt/v2"
+//
+// Getopt supports functionality found in both the standard BSD getopt as well
+// as (one of the many versions of) the GNU getopt_long. Being a Go package,
+// this package makes common usage easy, but still enables more controlled usage
+// if needed.
+//
+// Typical usage:
+//
+// // Declare the flags to be used
+// helpFlag := getopt.Bool('?', "display help")
+// cmdFlag := getopt.StringLong("command", 'c', "", "the command)
+//
+// func main() {
+// // Parse the program arguments
+// getopt.Parse()
+// // Get the remaining positional parameters
+// args := getopt.Args()
+//
+// If you don't want the program to exit on error, use getopt.Getopt:
+//
+// err := getopt.Getopt(nil)
+// if err != nil {
+// // code to handle error
+// fmt.Fprintln(os.Stderr, err)
+// }
+//
+// Support is provided for both short (-f) and long (--flag) options. A single
+// option may have both a short and a long name. Each option may be a flag or a
+// value. A value takes an argument.
+//
+// Declaring no long names causes this package to process arguments like the
+// traditional BSD getopt.
+//
+// Short flags may be combined into a single parameter. For example, "-a -b -c"
+// may also be expressed "-abc". Long flags must stand on their own "--alpha
+// --beta"
+//
+// Values require an argument. For short options the argument may either be
+// immediately following the short name or as the next argument. Only one short
+// value may be combined with short flags in a single argument; the short value
+// must be after all short flags. For example, if f is a flag and v is a value,
+// then:
+//
+// -vvalue (sets v to "value")
+// -v value (sets v to "value")
+// -fvvalue (sets f, and sets v to "value")
+// -fv value (sets f, and sets v to "value")
+// -vf value (set v to "f" and value is the first parameter)
+//
+// For the long value option val:
+//
+// --val value (sets val to "value")
+// --val=value (sets val to "value")
+// --valvalue (invalid option "valvalue")
+//
+// Values with an optional value only set the value if the value is part of the
+// same argument. In any event, the option count is increased and the option is
+// marked as seen.
+//
+// -v -f (sets v and f as being seen)
+// -vvalue -f (sets v to "value" and sets f)
+// --val -f (sets v and f as being seen)
+// --val=value -f (sets v to "value" and sets f)
+//
+// There is no convience function defined for making the value optional. The
+// SetOptional method must be called on the actual Option.
+//
+// v := String("val", 'v', "", "the optional v")
+// Lookup("v").SetOptional()
+//
+// var s string
+// StringVar(&s, "val", 'v', "the optional v).SetOptional()
+//
+// Parsing continues until the first non-option or "--" is encountered.
+//
+// The short name "-" can be used, but it either is specified as "-" or as part
+// of a group of options, for example "-f-". If there are no long options
+// specified then "--f" could also be used. If "-" is not declared as an option
+// then the single "-" will also terminate the option processing but unlike
+// "--", the "-" will be part of the remaining arguments.
+//
+// Normally the parsing is performed by calling the Parse function. If it is
+// important to see the order of the options then the Getopt function should be
+// used. The standard Parse function does the equivalent of:
+//
+// func Parse() {
+// if err := getopt.Getopt(os.Args, nil); err != nil {
+// fmt.Fprintln(os.Stderr, err)
+// s.usage()
+// os.Exit(1)
+// }
+//
+// When calling Getopt it is the responsibility of the caller to print any
+// errors.
+//
+// Normally the default option set, CommandLine, is used. Other option sets may
+// be created with New.
+//
+// After parsing, the sets Args will contain the non-option arguments. If an
+// error is encountered then Args will begin with argument that caused the
+// error.
+//
+// It is valid to call a set's Parse a second time to amend the current set of
+// flags or values. As an example:
+//
+// var a = getopt.Bool('a', "", "The a flag")
+// var b = getopt.Bool('b', "", "The a flag")
+// var cmd = ""
+//
+// var opts = getopt.CommandLine
+//
+// opts.Parse(os.Args)
+// if opts.NArgs() > 0 {
+// cmd = opts.Arg(0)
+// opts.Parse(opts.Args())
+// }
+//
+// If called with set to { "prog", "-a", "cmd", "-b", "arg" } then both and and
+// b would be set, cmd would be set to "cmd", and opts.Args() would return {
+// "arg" }.
+//
+// Unless an option type explicitly prohibits it, an option may appear more than
+// once in the arguments. The last value provided to the option is the value.
+//
+// SYNTAX
+//
+// For each option type there are an unfortunately large number of ways, 8, to
+// initialize the option. This number is derived from three attributes:
+//
+// 1) Short or Long name
+// 2) Normal vs Var
+// 3) Command Line vs Option Set
+//
+// The first two variations provide 4 signature:
+//
+// Option(name rune, [value type,] helpvalue... string)
+// OptionLong(name string, short rune, [value type,] helpvalue... string)
+// OptionVar(p *type, name rune, helpvalue... string)
+// OptionVarLong(p *type, name string, short rune, helpvalue... string)
+//
+// Foo can actually be expressed in terms of FooLong:
+//
+// func Foo(name rune, value type, helpvalue... string) *type {
+// return FooLong("", name, value, helpvalue...)
+// }
+//
+// Normally Foo is used, unless long options are needed. Setting short to 0
+// creates only a long option.
+//
+// The difference bentween Foo and FooVar is that you pass a pointer, p, to the
+// location of the value to FooVar. The default value is simply *p. The
+// initial value of *p is the defaut value of the option.
+//
+// Foo is actually a wrapper around FooVar:
+//
+// func Foo(name rune, value type, helpvalue... string) *type {
+// p := value
+// FooVar(&p, name, helpvalue... string)
+// return &p
+// }
+//
+//
+// The third variation provides a top-level function and a method on a Set:
+//
+// func Option(...)
+// func (s *Set) Option(...)
+//
+// The top-level function is simply:
+//
+// func Option(...) *type {
+// return CommandLine.Option(...) {
+// }
+//
+// To simplfy documentation, typically only the main top-level function is fully
+// documented. The others will have documentation when there is something
+// special about them.
+//
+// VALUEHELP
+//
+// All non-flag options are created with a "valuehelp" as the last parameter.
+// Valuehelp should be 0, 1, or 2 strings. The first string, if provided, is
+// the usage message for the option. If the second string, if provided, is the
+// name to use for the value when displaying the usage. If not provided the
+// term "value" is assumed.
+//
+// The usage message for the option created with
+//
+// StringLong("option", 'o', "defval", "a string of letters")
+//
+// is
+//
+// -o, -option=value
+//
+// StringLong("option", 'o', "defval", "a string of letters", "string")
+//
+// is
+//
+// -o, -option=string
+package getopt
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "path"
+ "sort"
+ "strings"
+)
+
+// stderr allows tests to capture output to standard error.
+var stderr io.Writer = os.Stderr
+
+// exit allows tests to capture an os.Exit call
+var exit = os.Exit
+
+// DisplayWidth is used to determine where to split usage long lines.
+var DisplayWidth = 80
+
+// HelpColumn is the maximum column position that help strings start to display
+// at. If the option usage is too long then the help string will be displayed
+// on the next line. For example:
+//
+// -a this is the a flag
+// -u, --under=location
+// the u flag's usage is quite long
+var HelpColumn = 20
+
+// PrintUsage prints the usage of the program to w.
+func (s *Set) PrintUsage(w io.Writer) {
+ sort.Sort(s.options)
+ flags := ""
+
+ // Build up the list of short flag names and also compute
+ // how to display the option in the longer help listing.
+ // We also keep track of the longest option usage string
+ // that is no more than HelpColumn-3 bytes (at which point
+ // we use two lines to display the help). The three
+ // is for the leading space and the two spaces before the
+ // help string.
+ for _, opt := range s.options {
+ if opt.name == "" {
+ opt.name = "value"
+ }
+ if opt.uname == "" {
+ opt.uname = opt.usageName()
+ }
+ if opt.flag && opt.short != 0 && opt.short != '-' {
+ flags += string(opt.short)
+ }
+ }
+
+ var opts []string
+
+ // The short option - is special
+ if s.shortOptions['-'] != nil {
+ opts = append(opts, "-")
+ }
+
+ // If we have a bundle of flags, add them to the list
+ if flags != "" {
+ opts = append(opts, "-"+flags)
+ }
+
+ // Now append all the long options and options that require
+ // values.
+ for _, opt := range s.options {
+ if opt.flag {
+ if opt.short != 0 {
+ continue
+ }
+ flags = "--" + opt.long
+ } else if opt.short != 0 {
+ flags = "-" + string(opt.short) + " " + opt.name
+ } else {
+ flags = "--" + string(opt.long) + " " + opt.name
+ }
+ opts = append(opts, flags)
+ }
+ flags = strings.Join(opts, "] [")
+ if flags != "" {
+ flags = " [" + flags + "]"
+ }
+ if s.parameters != "" {
+ flags += " " + s.parameters
+ }
+ fmt.Fprintf(w, "Usage: %s%s\n", s.program, flags)
+ s.PrintOptions(w)
+}
+
+// PrintOptions prints the list of options in s to w.
+func (s *Set) PrintOptions(w io.Writer) {
+ sort.Sort(s.options)
+ max := 4
+ for _, opt := range s.options {
+ if opt.name == "" {
+ opt.name = "value"
+ }
+ if opt.uname == "" {
+ opt.uname = opt.usageName()
+ }
+ if max < len(opt.uname) && len(opt.uname) <= HelpColumn-3 {
+ max = len(opt.uname)
+ }
+ }
+ // Now print one or more usage lines per option.
+ for _, opt := range s.options {
+ if opt.uname != "" {
+ opt.help = strings.TrimSpace(opt.help)
+ if len(opt.help) == 0 {
+ fmt.Fprintf(w, " %s\n", opt.uname)
+ continue
+ }
+ help := strings.Split(opt.help, "\n")
+ // If they did not put in newlines then we will insert
+ // them to keep the help messages from wrapping.
+ if len(help) == 1 {
+ help = breakup(help[0], DisplayWidth-HelpColumn)
+ }
+ if len(opt.uname) <= max {
+ fmt.Fprintf(w, " %-*s %s\n", max, opt.uname, help[0])
+ help = help[1:]
+ } else {
+ fmt.Fprintf(w, " %s\n", opt.uname)
+ }
+ for _, s := range help {
+ fmt.Fprintf(w, " %-*s %s\n", max, " ", s)
+ }
+ }
+ }
+}
+
+// breakup breaks s up into strings no longer than max bytes.
+func breakup(s string, max int) []string {
+ var a []string
+
+ for {
+ // strip leading spaces
+ for len(s) > 0 && s[0] == ' ' {
+ s = s[1:]
+ }
+ // If the option is no longer than the max just return it
+ if len(s) <= max {
+ if len(s) != 0 {
+ a = append(a, s)
+ }
+ return a
+ }
+ x := max
+ for s[x] != ' ' {
+ // the first word is too long?!
+ if x == 0 {
+ x = max
+ for x < len(s) && s[x] != ' ' {
+ x++
+ }
+ if x == len(s) {
+ x--
+ }
+ break
+ }
+ x--
+ }
+ for s[x] == ' ' {
+ x--
+ }
+ a = append(a, s[:x+1])
+ s = s[x+1:]
+ }
+ panic("unreachable")
+}
+
+// Parse uses Getopt to parse args using the options set for s. The first
+// element of args is used to assign the program for s if it is not yet set. On
+// error, Parse displays the error message as well as a usage message on
+// standard error and then exits the program.
+func (s *Set) Parse(args []string) {
+ if err := s.Getopt(args, nil); err != nil {
+ fmt.Fprintln(stderr, err)
+ s.usage()
+ exit(1)
+ }
+}
+
+// Parse uses Getopt to parse args using the options set for s. The first
+// element of args is used to assign the program for s if it is not yet set.
+// Getop calls fn, if not nil, for each option parsed.
+//
+// Getopt returns nil when all options have been processed (a non-option
+// argument was encountered, "--" was encountered, or fn returned false).
+//
+// On error getopt returns a refernce to an InvalidOption (which implements
+// the error interface).
+func (s *Set) Getopt(args []string, fn func(Option) bool) (err error) {
+ s.State = InProgress
+ defer func() {
+ if s.State == InProgress {
+ switch {
+ case err != nil:
+ s.State = Failure
+ case len(s.args) == 0:
+ s.State = EndOfArguments
+ default:
+ s.State = Unknown
+ }
+ }
+ }()
+ if fn == nil {
+ fn = func(Option) bool { return true }
+ }
+ if len(args) == 0 {
+ return nil
+ }
+
+ if s.program == "" {
+ s.program = path.Base(args[0])
+ }
+ args = args[1:]
+Parsing:
+ for len(args) > 0 {
+ arg := args[0]
+ s.args = args
+ args = args[1:]
+
+ // end of options?
+ if arg == "" || arg[0] != '-' {
+ s.State = EndOfOptions
+ return nil
+ }
+
+ if arg == "-" {
+ goto ShortParsing
+ }
+
+ // explicitly request end of options?
+ if arg == "--" {
+ s.args = args
+ s.State = DashDash
+ return nil
+ }
+
+ // Long option processing
+ if len(s.longOptions) > 0 && arg[1] == '-' {
+ e := strings.IndexRune(arg, '=')
+ var value string
+ if e > 0 {
+ value = arg[e+1:]
+ arg = arg[:e]
+ }
+ opt := s.longOptions[arg[2:]]
+ // If we are processing long options then --f is -f
+ // if f is not defined as a long option.
+ // This lets you say --f=false
+ if opt == nil && len(arg[2:]) == 1 {
+ opt = s.shortOptions[rune(arg[2])]
+ }
+ if opt == nil {
+ return unknownOption(arg[2:])
+ }
+ opt.isLong = true
+ // If we require an option and did not have an =
+ // then use the next argument as an option.
+ if !opt.flag && e < 0 && !opt.optional {
+ if len(args) == 0 {
+ return missingArg(opt)
+ }
+ value = args[0]
+ args = args[1:]
+ }
+ opt.count++
+
+ if err := opt.value.Set(value, opt); err != nil {
+ return setError(opt, value, err)
+ }
+
+ if !fn(opt) {
+ s.State = Terminated
+ return nil
+ }
+ continue Parsing
+ }
+
+ // Short option processing
+ arg = arg[1:] // strip -
+ ShortParsing:
+ for i, c := range arg {
+ opt := s.shortOptions[c]
+ if opt == nil {
+ // In traditional getopt, if - is not registered
+ // as an option, a lone - is treated as
+ // if there were a -- in front of it.
+ if arg == "-" {
+ s.State = Dash
+ return nil
+ }
+ return unknownOption(c)
+ }
+ opt.isLong = false
+ opt.count++
+ var value string
+ if !opt.flag {
+ value = arg[1+i:]
+ if value == "" && !opt.optional {
+ if len(args) == 0 {
+ return missingArg(opt)
+ }
+ value = args[0]
+ args = args[1:]
+ }
+ }
+ if err := opt.value.Set(value, opt); err != nil {
+ return setError(opt, value, err)
+ }
+ if !fn(opt) {
+ s.State = Terminated
+ return nil
+ }
+ if !opt.flag {
+ continue Parsing
+ }
+ }
+ }
+ s.args = []string{}
+ return nil
+}