diff options
Diffstat (limited to 'vendor/modernc.org/opt/opt.go')
-rw-r--r-- | vendor/modernc.org/opt/opt.go | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/vendor/modernc.org/opt/opt.go b/vendor/modernc.org/opt/opt.go new file mode 100644 index 00000000..0085e9f2 --- /dev/null +++ b/vendor/modernc.org/opt/opt.go @@ -0,0 +1,152 @@ +// Package opt implements command-line flag parsing. +package opt // import "modernc.org/opt" + +import ( + "fmt" + "strings" +) + +type opt struct { + handler func(opt, arg string) error + name string + + arg bool // Enable argument, e.g. `-I foo` or `-I=foo` +} + +// A Set represents a set of defined options. +type Set struct { + cfg map[string]*opt + imm []*opt +} + +// NewSet returns a new, empty option set. +func NewSet() *Set { return &Set{cfg: map[string]*opt{}} } + +// Opt defines a simple option, e.g. `-f`. When the option is found during +// Parse, the handler is called with the value of the option, e.g. "-f". +func (p *Set) Opt(name string, handler func(opt string) error) { + p.cfg[name] = &opt{ + handler: func(opt, arg string) error { return handler(opt) }, + } +} + +// Arg defines a simple option with an argument, e.g. `-I foo` or `-I=foo`. +// Setting imm argument enables additionally `-Ifoo`. When the option is found +// during Parse, the handler is called with the values of the option and the +// argument, e.g. "-I" and "foo" for all of the variants. +func (p *Set) Arg(name string, imm bool, handler func(opt, arg string) error) { + switch { + case imm: + p.imm = append(p.imm, &opt{ + handler: handler, + name: name, + }) + default: + p.cfg[name] = &opt{ + arg: true, + handler: handler, + name: name, + } + } +} + +// Parse parses opts. Must be called after all options are defined. The handler +// is called for all items in opts that were not defined before using Opt or +// Arg. +// +// If any handler returns a non-nil error, Parse will stop. If the error is of +// type Skip, the error returned by Parse will contain all the unprocessed +// items of opts. +// +// The opts slice must not be modified by any handler while Parser is +// executing. +func (p *Set) Parse(opts []string, handler func(string) error) (err error) { + defer func() { + switch err.(type) { + case Skip: + err = Skip(opts) + } + }() + + for len(opts) != 0 { + opt := opts[0] + opts = opts[1:] + var arg string + out: + switch { + case strings.HasPrefix(opt, "-"): + name := opt[1:] + for _, cfg := range p.imm { + if strings.HasPrefix(name, cfg.name) { + switch { + case name == cfg.name: + if len(opts) == 0 { + return fmt.Errorf("missing argument of %s", opt) + } + + if err = cfg.handler(opt, opts[0]); err != nil { + return err + } + + opts = opts[1:] + default: + if err = cfg.handler(opt[:len(cfg.name)+1], name[len(cfg.name):]); err != nil { + return err + } + } + break out + } + } + + if n := strings.IndexByte(opt, '='); n > 0 { + arg = opt[n+1:] + name = opt[1:n] + opt = opt[:n] + } + switch cfg := p.cfg[name]; { + case cfg == nil: + if err = handler(opt); err != nil { + return err + } + default: + switch { + case cfg.arg: + switch { + case arg != "": + if err = cfg.handler(opt, arg); err != nil { + return err + } + default: + if len(opts) == 0 { + return fmt.Errorf("missing argument of %s", opt) + } + + if err = cfg.handler(opt, opts[0]); err != nil { + return err + } + + opts = opts[1:] + } + default: + if err = cfg.handler(opt, ""); err != nil { + return err + } + } + } + default: + if opt == "" { + break + } + + if err = handler(opt); err != nil { + return err + } + } + } + return nil +} + +// Skip is an error that contains all unprocessed items passed to Parse. +type Skip []string + +func (s Skip) Error() string { return fmt.Sprint([]string(s)) } |