From 3cc1e4ebfc102a797b81bbffb4e221a2041e8b2a Mon Sep 17 00:00:00 2001 From: Caleb Bassi Date: Fri, 30 Mar 2018 12:41:15 -0700 Subject: [PATCH] Fixed docopt dep version issue --- Gopkg.lock | 6 +- Gopkg.toml | 29 +- .../github.com/docopt/docopt-go/.travis.yml | 7 +- vendor/github.com/docopt/docopt-go/LICENSE | 1 + vendor/github.com/docopt/docopt-go/README.md | 80 +- vendor/github.com/docopt/docopt-go/doc.go | 49 ++ vendor/github.com/docopt/docopt-go/docopt.go | 830 ++---------------- vendor/github.com/docopt/docopt-go/error.go | 49 ++ vendor/github.com/docopt/docopt-go/opts.go | 264 ++++++ vendor/github.com/docopt/docopt-go/pattern.go | 550 ++++++++++++ vendor/github.com/docopt/docopt-go/token.go | 126 +++ 11 files changed, 1184 insertions(+), 807 deletions(-) create mode 100644 vendor/github.com/docopt/docopt-go/doc.go create mode 100644 vendor/github.com/docopt/docopt-go/error.go create mode 100644 vendor/github.com/docopt/docopt-go/opts.go create mode 100644 vendor/github.com/docopt/docopt-go/pattern.go create mode 100644 vendor/github.com/docopt/docopt-go/token.go diff --git a/Gopkg.lock b/Gopkg.lock index 57de7f3..e557805 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -20,10 +20,10 @@ revision = "d8e7d6f2c53c6f045c1d95c9fa9968e4d2ba569e" [[projects]] + branch = "master" name = "github.com/docopt/docopt-go" packages = ["."] - revision = "784ddc588536785e7299f7272f39101f7faccc3f" - version = "0.6.2" + revision = "ee0de3bc6815ee19d4a46c7eb90f829db0e014b1" [[projects]] name = "github.com/go-ole/go-ole" @@ -78,6 +78,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "d2076f778d670ace1a8d4ddb709c3421637ec24b72e6e8502e5bbf41e93def62" + inputs-digest = "22a656ce826eed217bf58555e692a26e2d791e256a6f17b8b06b9c964bb30f11" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 939f0f9..817f8fd 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -1,37 +1,10 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - [[constraint]] branch = "master" name = "github.com/cjbassi/termui" [[constraint]] + branch = "master" name = "github.com/docopt/docopt-go" - version = "0.6.2" [[constraint]] name = "github.com/shirou/gopsutil" diff --git a/vendor/github.com/docopt/docopt-go/.travis.yml b/vendor/github.com/docopt/docopt-go/.travis.yml index 65fad59..db820dc 100644 --- a/vendor/github.com/docopt/docopt-go/.travis.yml +++ b/vendor/github.com/docopt/docopt-go/.travis.yml @@ -7,15 +7,17 @@ language: go go: - 1.4 - 1.5 + - 1.6 + - 1.7 + - 1.8 + - 1.9 - tip matrix: fast_finish: true before_install: - - go get golang.org/x/tools/cmd/vet - go get golang.org/x/tools/cmd/cover - - go get github.com/golang/lint/golint - go get github.com/mattn/goveralls install: @@ -23,7 +25,6 @@ install: script: - go vet -x ./... - - $HOME/gopath/bin/golint ./... - go test -v ./... - go test -covermode=count -coverprofile=profile.cov . diff --git a/vendor/github.com/docopt/docopt-go/LICENSE b/vendor/github.com/docopt/docopt-go/LICENSE index 8841af1..5e51f73 100644 --- a/vendor/github.com/docopt/docopt-go/LICENSE +++ b/vendor/github.com/docopt/docopt-go/LICENSE @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2013 Keith Batten +Copyright (c) 2016 David Irvine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/vendor/github.com/docopt/docopt-go/README.md b/vendor/github.com/docopt/docopt-go/README.md index 71c92aa..d03f8da 100644 --- a/vendor/github.com/docopt/docopt-go/README.md +++ b/vendor/github.com/docopt/docopt-go/README.md @@ -2,11 +2,10 @@ docopt-go ========= [![Build Status](https://travis-ci.org/docopt/docopt.go.svg?branch=master)](https://travis-ci.org/docopt/docopt.go) -[![Coverage Status](https://coveralls.io/repos/docopt/docopt.go/badge.png)](https://coveralls.io/r/docopt/docopt.go) -[![GoDoc](https://godoc.org/github.com/docopt/docopt.go?status.png)](https://godoc.org/github.com/docopt/docopt.go) +[![Coverage Status](https://coveralls.io/repos/github/docopt/docopt.go/badge.svg)](https://coveralls.io/github/docopt/docopt.go) +[![GoDoc](https://godoc.org/github.com/docopt/docopt.go?status.svg)](https://godoc.org/github.com/docopt/docopt.go) -An implementation of [docopt](http://docopt.org/) in the -[Go](http://golang.org/) programming language. +An implementation of [docopt](http://docopt.org/) in the [Go](http://golang.org/) programming language. **docopt** helps you create *beautiful* command-line interfaces easily: @@ -36,24 +35,22 @@ Options: --moored Moored (anchored) mine. --drifting Drifting mine.` - arguments, _ := docopt.Parse(usage, nil, true, "Naval Fate 2.0", false) + arguments, _ := docopt.ParseDoc(usage) fmt.Println(arguments) } ``` -**docopt** parses command-line arguments based on a help message. Don't -write parser code: a good help message already has all the necessary -information in it. +**docopt** parses command-line arguments based on a help message. Don't write parser code: a good help message already has all the necessary information in it. ## Installation -⚠ Use the alias “docopt-go”. To use docopt in your Go code: +⚠ Use the alias "docopt-go". To use docopt in your Go code: ```go import "github.com/docopt/docopt-go" ``` -To install docopt according to your `$GOPATH`: +To install docopt in your `$GOPATH`: ```console $ go get github.com/docopt/docopt-go @@ -61,28 +58,59 @@ $ go get github.com/docopt/docopt-go ## API +Given a conventional command-line help message, docopt processes the arguments. See https://github.com/docopt/docopt#help-message-format for a description of the help message format. + +This package exposes three different APIs, depending on the level of control required. The first, simplest way to parse your docopt usage is to just call: + ```go -func Parse(doc string, argv []string, help bool, version string, - optionsFirst bool, exit ...bool) (map[string]interface{}, error) +docopt.ParseDoc(usage) ``` -Parse `argv` based on the command-line interface described in `doc`. -Given a conventional command-line help message, docopt creates a parser and -processes the arguments. See -https://github.com/docopt/docopt#help-message-format for a description of the -help message format. If `argv` is `nil`, `os.Args[1:]` is used. +This will use `os.Args[1:]` as the argv slice, and use the default parser options. If you want to provide your own version string and args, then use: -docopt returns a map of option names to the values parsed from `argv`, and an -error or `nil`. +```go +docopt.ParseArgs(usage, argv, "1.2.3") +``` -More documentation for docopt is available at -[GoDoc.org](https://godoc.org/github.com/docopt/docopt.go). +If the last parameter (version) is a non-empty string, it will be printed when `--version` is given in the argv slice. Finally, we can instantiate our own `docopt.Parser` which gives us control over how things like help messages are printed and whether to exit after displaying usage messages, etc. -## Testing +```go +parser := &docopt.Parser{ + HelpHandler: docopt.PrintHelpOnly, + OptionsFirst: true, +} +opts, err := parser.ParseArgs(usage, argv, "") +``` -All tests from the Python version are implemented and passing -at [Travis CI](https://travis-ci.org/docopt/docopt.go). New -language-agnostic tests have been added -to [test_golang.docopt](test_golang.docopt). +In particular, setting your own custom `HelpHandler` function makes unit testing your own docs with example command line invocations much more enjoyable. + +All three of these return a map of option names to the values parsed from argv, and an error or nil. You can get the values using the helpers, or just treat it as a regular map: + +```go +flag, _ := opts.Bool("--flag") +secs, _ := opts.Int("") +``` + +Additionally, you can `Bind` these to a struct, assigning option values to the +exported fields of that struct, all at once. + +```go +var config struct { + Command string `docopt:""` + Tries int `docopt:"-n"` + Force bool // Gets the value of --force +} +opts.Bind(&config) +``` + +More documentation is available at [godoc.org](https://godoc.org/github.com/docopt/docopt-go). + +## Unit Testing + +Unit testing your own usage docs is recommended, so you can be sure that for a given command line invocation, the expected options are set. An example of how to do this is [in the examples folder](examples/unit_test/unit_test.go). + +## Tests + +All tests from the Python version are implemented and passing at [Travis CI](https://travis-ci.org/docopt/docopt-go). New language-agnostic tests have been added to [test_golang.docopt](test_golang.docopt). To run tests for docopt-go, use `go test`. diff --git a/vendor/github.com/docopt/docopt-go/doc.go b/vendor/github.com/docopt/docopt-go/doc.go new file mode 100644 index 0000000..c56ee12 --- /dev/null +++ b/vendor/github.com/docopt/docopt-go/doc.go @@ -0,0 +1,49 @@ +/* +Package docopt parses command-line arguments based on a help message. + +Given a conventional command-line help message, docopt processes the arguments. +See https://github.com/docopt/docopt#help-message-format for a description of +the help message format. + +This package exposes three different APIs, depending on the level of control +required. The first, simplest way to parse your docopt usage is to just call: + + docopt.ParseDoc(usage) + +This will use os.Args[1:] as the argv slice, and use the default parser +options. If you want to provide your own version string and args, then use: + + docopt.ParseArgs(usage, argv, "1.2.3") + +If the last parameter (version) is a non-empty string, it will be printed when +--version is given in the argv slice. Finally, we can instantiate our own +docopt.Parser which gives us control over how things like help messages are +printed and whether to exit after displaying usage messages, etc. + + parser := &docopt.Parser{ + HelpHandler: docopt.PrintHelpOnly, + OptionsFirst: true, + } + opts, err := parser.ParseArgs(usage, argv, "") + +In particular, setting your own custom HelpHandler function makes unit testing +your own docs with example command line invocations much more enjoyable. + +All three of these return a map of option names to the values parsed from argv, +and an error or nil. You can get the values using the helpers, or just treat it +as a regular map: + + flag, _ := opts.Bool("--flag") + secs, _ := opts.Int("") + +Additionally, you can `Bind` these to a struct, assigning option values to the +exported fields of that struct, all at once. + + var config struct { + Command string `docopt:""` + Tries int `docopt:"-n"` + Force bool // Gets the value of --force + } + opts.Bind(&config) +*/ +package docopt diff --git a/vendor/github.com/docopt/docopt-go/docopt.go b/vendor/github.com/docopt/docopt-go/docopt.go index d929fc3..c22feb7 100644 --- a/vendor/github.com/docopt/docopt-go/docopt.go +++ b/vendor/github.com/docopt/docopt-go/docopt.go @@ -1,71 +1,113 @@ // Licensed under terms of MIT license (see LICENSE-MIT) // Copyright (c) 2013 Keith Batten, kbatten@gmail.com +// Copyright (c) 2016 David Irvine -/* -Package docopt parses command-line arguments based on a help message. - -⚠ Use the alias “docopt-go”: - import "github.com/docopt/docopt-go" -or - $ go get github.com/docopt/docopt-go -*/ package docopt import ( "fmt" "os" - "reflect" "regexp" "strings" - "unicode" ) -/* -Parse `argv` based on the command-line interface described in `doc`. +type Parser struct { + // HelpHandler is called when we encounter bad user input, or when the user + // asks for help. + // By default, this calls os.Exit(0) if it handled a built-in option such + // as -h, --help or --version. If the user errored with a wrong command or + // options, we exit with a return code of 1. + HelpHandler func(err error, usage string) + // OptionsFirst requires that option flags always come before positional + // arguments; otherwise they can overlap. + OptionsFirst bool + // SkipHelpFlags tells the parser not to look for -h and --help flags and + // call the HelpHandler. + SkipHelpFlags bool +} -Given a conventional command-line help message, docopt creates a parser and -processes the arguments. See -https://github.com/docopt/docopt#help-message-format for a description of the -help message format. If `argv` is `nil`, `os.Args[1:]` is used. +var PrintHelpAndExit = func(err error, usage string) { + if err != nil { + fmt.Fprintln(os.Stderr, usage) + os.Exit(1) + } else { + fmt.Println(usage) + os.Exit(0) + } +} -docopt returns a map of option names to the values parsed from `argv`, and an -error or `nil`. +var PrintHelpOnly = func(err error, usage string) { + if err != nil { + fmt.Fprintln(os.Stderr, usage) + } else { + fmt.Println(usage) + } +} -Set `help` to `false` to disable automatic help messages on `-h` or `--help`. -If `version` is a non-empty string, it will be printed when `--version` is -specified. Set `optionsFirst` to `true` to require that options always come -before positional arguments; otherwise they can overlap. +var NoHelpHandler = func(err error, usage string) {} -By default, docopt calls `os.Exit(0)` if it handled a built-in option such as -`-h` or `--version`. If the user errored with a wrong command or options, -docopt exits with a return code of 1. To stop docopt from calling `os.Exit()` -and to handle your own return codes, pass an optional last parameter of `false` -for `exit`. -*/ -func Parse(doc string, argv []string, help bool, version string, - optionsFirst bool, exit ...bool) (map[string]interface{}, error) { - // if "false" was the (optional) last arg, don't call os.Exit() +var DefaultParser = &Parser{ + HelpHandler: PrintHelpAndExit, + OptionsFirst: false, + SkipHelpFlags: false, +} + +// ParseDoc parses os.Args[1:] based on the interface described in doc, using the default parser options. +func ParseDoc(doc string) (Opts, error) { + return ParseArgs(doc, nil, "") +} + +// ParseArgs parses custom arguments based on the interface described in doc. If you provide a non-empty version +// string, then this will be displayed when the --version flag is found. This method uses the default parser options. +func ParseArgs(doc string, argv []string, version string) (Opts, error) { + return DefaultParser.ParseArgs(doc, argv, version) +} + +// ParseArgs parses custom arguments based on the interface described in doc. If you provide a non-empty version +// string, then this will be displayed when the --version flag is found. +func (p *Parser) ParseArgs(doc string, argv []string, version string) (Opts, error) { + return p.parse(doc, argv, version) +} + +// Deprecated: Parse is provided for backward compatibility with the original docopt.go package. +// Please rather make use of ParseDoc, ParseArgs, or use your own custom Parser. +func Parse(doc string, argv []string, help bool, version string, optionsFirst bool, exit ...bool) (map[string]interface{}, error) { exitOk := true if len(exit) > 0 { exitOk = exit[0] } - args, output, err := parse(doc, argv, help, version, optionsFirst) + p := &Parser{ + OptionsFirst: optionsFirst, + SkipHelpFlags: !help, + } + if exitOk { + p.HelpHandler = PrintHelpAndExit + } else { + p.HelpHandler = PrintHelpOnly + } + return p.parse(doc, argv, version) +} + +func (p *Parser) parse(doc string, argv []string, version string) (map[string]interface{}, error) { + if argv == nil { + argv = os.Args[1:] + } + if p.HelpHandler == nil { + p.HelpHandler = DefaultParser.HelpHandler + } + args, output, err := parse(doc, argv, !p.SkipHelpFlags, version, p.OptionsFirst) if _, ok := err.(*UserError); ok { // the user gave us bad input - fmt.Fprintln(os.Stderr, output) - if exitOk { - os.Exit(1) - } + p.HelpHandler(err, output) } else if len(output) > 0 && err == nil { - // the user asked for help or `--version` - fmt.Println(output) - if exitOk { - os.Exit(0) - } + // the user asked for help or --version + p.HelpHandler(err, output) } return args, err } +// ----------------------------------------------------------------------------- + // parse and return a map of args, output and all errors func parse(doc string, argv []string, help bool, version string, optionsFirst bool) (args map[string]interface{}, output string, err error) { if argv == nil && len(os.Args) > 1 { @@ -484,39 +526,6 @@ func parseShorts(tokens *tokenList, options *patternList) (patternList, error) { return parsed, nil } -func newTokenList(source []string, err errorType) *tokenList { - errorFunc := newError - if err == errorUser { - errorFunc = newUserError - } else if err == errorLanguage { - errorFunc = newLanguageError - } - return &tokenList{source, errorFunc, err} -} - -func tokenListFromString(source string) *tokenList { - return newTokenList(strings.Fields(source), errorUser) -} - -func tokenListFromPattern(source string) *tokenList { - p := regexp.MustCompile(`([\[\]\(\)\|]|\.\.\.)`) - source = p.ReplaceAllString(source, ` $1 `) - p = regexp.MustCompile(`\s+|(\S*<.*?>)`) - split := p.Split(source, -1) - match := p.FindAllStringSubmatch(source, -1) - var result []string - l := len(split) - for i := 0; i < l; i++ { - if len(split[i]) > 0 { - result = append(result, split[i]) - } - if i < l-1 && len(match[i][1]) > 0 { - result = append(result, match[i][1]) - } - } - return newTokenList(result, errorLanguage) -} - func formalUsage(section string) (string, error) { _, _, section = stringPartition(section, ":") // drop "usage:" pu := strings.Fields(section) @@ -556,665 +565,6 @@ func extras(help bool, version string, options patternList, doc string) string { return "" } -type errorType int - -const ( - errorUser errorType = iota - errorLanguage -) - -func (e errorType) String() string { - switch e { - case errorUser: - return "errorUser" - case errorLanguage: - return "errorLanguage" - } - return "" -} - -// UserError records an error with program arguments. -type UserError struct { - msg string - Usage string -} - -func (e UserError) Error() string { - return e.msg -} -func newUserError(msg string, f ...interface{}) error { - return &UserError{fmt.Sprintf(msg, f...), ""} -} - -// LanguageError records an error with the doc string. -type LanguageError struct { - msg string -} - -func (e LanguageError) Error() string { - return e.msg -} -func newLanguageError(msg string, f ...interface{}) error { - return &LanguageError{fmt.Sprintf(msg, f...)} -} - -var newError = fmt.Errorf - -type tokenList struct { - tokens []string - errorFunc func(string, ...interface{}) error - err errorType -} -type token string - -func (t *token) eq(s string) bool { - if t == nil { - return false - } - return string(*t) == s -} -func (t *token) match(matchNil bool, tokenStrings ...string) bool { - if t == nil && matchNil { - return true - } else if t == nil && !matchNil { - return false - } - - for _, tok := range tokenStrings { - if tok == string(*t) { - return true - } - } - return false -} -func (t *token) hasPrefix(prefix string) bool { - if t == nil { - return false - } - return strings.HasPrefix(string(*t), prefix) -} -func (t *token) hasSuffix(suffix string) bool { - if t == nil { - return false - } - return strings.HasSuffix(string(*t), suffix) -} -func (t *token) isUpper() bool { - if t == nil { - return false - } - return isStringUppercase(string(*t)) -} -func (t *token) String() string { - if t == nil { - return "" - } - return string(*t) -} - -func (tl *tokenList) current() *token { - if len(tl.tokens) > 0 { - return (*token)(&(tl.tokens[0])) - } - return nil -} - -func (tl *tokenList) length() int { - return len(tl.tokens) -} - -func (tl *tokenList) move() *token { - if len(tl.tokens) > 0 { - t := tl.tokens[0] - tl.tokens = tl.tokens[1:] - return (*token)(&t) - } - return nil -} - -type patternType uint - -const ( - // leaf - patternArgument patternType = 1 << iota - patternCommand - patternOption - - // branch - patternRequired - patternOptionAL - patternOptionSSHORTCUT // Marker/placeholder for [options] shortcut. - patternOneOrMore - patternEither - - patternLeaf = patternArgument + - patternCommand + - patternOption - patternBranch = patternRequired + - patternOptionAL + - patternOptionSSHORTCUT + - patternOneOrMore + - patternEither - patternAll = patternLeaf + patternBranch - patternDefault = 0 -) - -func (pt patternType) String() string { - switch pt { - case patternArgument: - return "argument" - case patternCommand: - return "command" - case patternOption: - return "option" - case patternRequired: - return "required" - case patternOptionAL: - return "optional" - case patternOptionSSHORTCUT: - return "optionsshortcut" - case patternOneOrMore: - return "oneormore" - case patternEither: - return "either" - case patternLeaf: - return "leaf" - case patternBranch: - return "branch" - case patternAll: - return "all" - case patternDefault: - return "default" - } - return "" -} - -type pattern struct { - t patternType - - children patternList - - name string - value interface{} - - short string - long string - argcount int -} - -type patternList []*pattern - -func newBranchPattern(t patternType, pl ...*pattern) *pattern { - var p pattern - p.t = t - p.children = make(patternList, len(pl)) - copy(p.children, pl) - return &p -} - -func newRequired(pl ...*pattern) *pattern { - return newBranchPattern(patternRequired, pl...) -} - -func newEither(pl ...*pattern) *pattern { - return newBranchPattern(patternEither, pl...) -} - -func newOneOrMore(pl ...*pattern) *pattern { - return newBranchPattern(patternOneOrMore, pl...) -} - -func newOptional(pl ...*pattern) *pattern { - return newBranchPattern(patternOptionAL, pl...) -} - -func newOptionsShortcut() *pattern { - var p pattern - p.t = patternOptionSSHORTCUT - return &p -} - -func newLeafPattern(t patternType, name string, value interface{}) *pattern { - // default: value=nil - var p pattern - p.t = t - p.name = name - p.value = value - return &p -} - -func newArgument(name string, value interface{}) *pattern { - // default: value=nil - return newLeafPattern(patternArgument, name, value) -} - -func newCommand(name string, value interface{}) *pattern { - // default: value=false - var p pattern - p.t = patternCommand - p.name = name - p.value = value - return &p -} - -func newOption(short, long string, argcount int, value interface{}) *pattern { - // default: "", "", 0, false - var p pattern - p.t = patternOption - p.short = short - p.long = long - if long != "" { - p.name = long - } else { - p.name = short - } - p.argcount = argcount - if value == false && argcount > 0 { - p.value = nil - } else { - p.value = value - } - return &p -} - -func (p *pattern) flat(types patternType) (patternList, error) { - if p.t&patternLeaf != 0 { - if types == patternDefault { - types = patternAll - } - if p.t&types != 0 { - return patternList{p}, nil - } - return patternList{}, nil - } - - if p.t&patternBranch != 0 { - if p.t&types != 0 { - return patternList{p}, nil - } - result := patternList{} - for _, child := range p.children { - childFlat, err := child.flat(types) - if err != nil { - return nil, err - } - result = append(result, childFlat...) - } - return result, nil - } - return nil, newError("unknown pattern type: %d, %d", p.t, types) -} - -func (p *pattern) fix() error { - err := p.fixIdentities(nil) - if err != nil { - return err - } - p.fixRepeatingArguments() - return nil -} - -func (p *pattern) fixIdentities(uniq patternList) error { - // Make pattern-tree tips point to same object if they are equal. - if p.t&patternBranch == 0 { - return nil - } - if uniq == nil { - pFlat, err := p.flat(patternDefault) - if err != nil { - return err - } - uniq = pFlat.unique() - } - for i, child := range p.children { - if child.t&patternBranch == 0 { - ind, err := uniq.index(child) - if err != nil { - return err - } - p.children[i] = uniq[ind] - } else { - err := child.fixIdentities(uniq) - if err != nil { - return err - } - } - } - return nil -} - -func (p *pattern) fixRepeatingArguments() { - // Fix elements that should accumulate/increment values. - var either []patternList - - for _, child := range p.transform().children { - either = append(either, child.children) - } - for _, cas := range either { - casMultiple := patternList{} - for _, e := range cas { - if cas.count(e) > 1 { - casMultiple = append(casMultiple, e) - } - } - for _, e := range casMultiple { - if e.t == patternArgument || e.t == patternOption && e.argcount > 0 { - switch e.value.(type) { - case string: - e.value = strings.Fields(e.value.(string)) - case []string: - default: - e.value = []string{} - } - } - if e.t == patternCommand || e.t == patternOption && e.argcount == 0 { - e.value = 0 - } - } - } -} - -func (p *pattern) match(left *patternList, collected *patternList) (bool, *patternList, *patternList) { - if collected == nil { - collected = &patternList{} - } - if p.t&patternRequired != 0 { - l := left - c := collected - for _, p := range p.children { - var matched bool - matched, l, c = p.match(l, c) - if !matched { - return false, left, collected - } - } - return true, l, c - } else if p.t&patternOptionAL != 0 || p.t&patternOptionSSHORTCUT != 0 { - for _, p := range p.children { - _, left, collected = p.match(left, collected) - } - return true, left, collected - } else if p.t&patternOneOrMore != 0 { - if len(p.children) != 1 { - panic("OneOrMore.match(): assert len(p.children) == 1") - } - l := left - c := collected - var lAlt *patternList - matched := true - times := 0 - for matched { - // could it be that something didn't match but changed l or c? - matched, l, c = p.children[0].match(l, c) - if matched { - times++ - } - if lAlt == l { - break - } - lAlt = l - } - if times >= 1 { - return true, l, c - } - return false, left, collected - } else if p.t&patternEither != 0 { - type outcomeStruct struct { - matched bool - left *patternList - collected *patternList - length int - } - outcomes := []outcomeStruct{} - for _, p := range p.children { - matched, l, c := p.match(left, collected) - outcome := outcomeStruct{matched, l, c, len(*l)} - if matched { - outcomes = append(outcomes, outcome) - } - } - if len(outcomes) > 0 { - minLen := outcomes[0].length - minIndex := 0 - for i, v := range outcomes { - if v.length < minLen { - minIndex = i - } - } - return outcomes[minIndex].matched, outcomes[minIndex].left, outcomes[minIndex].collected - } - return false, left, collected - } else if p.t&patternLeaf != 0 { - pos, match := p.singleMatch(left) - var increment interface{} - if match == nil { - return false, left, collected - } - leftAlt := make(patternList, len((*left)[:pos]), len((*left)[:pos])+len((*left)[pos+1:])) - copy(leftAlt, (*left)[:pos]) - leftAlt = append(leftAlt, (*left)[pos+1:]...) - sameName := patternList{} - for _, a := range *collected { - if a.name == p.name { - sameName = append(sameName, a) - } - } - - switch p.value.(type) { - case int, []string: - switch p.value.(type) { - case int: - increment = 1 - case []string: - switch match.value.(type) { - case string: - increment = []string{match.value.(string)} - default: - increment = match.value - } - } - if len(sameName) == 0 { - match.value = increment - collectedMatch := make(patternList, len(*collected), len(*collected)+1) - copy(collectedMatch, *collected) - collectedMatch = append(collectedMatch, match) - return true, &leftAlt, &collectedMatch - } - switch sameName[0].value.(type) { - case int: - sameName[0].value = sameName[0].value.(int) + increment.(int) - case []string: - sameName[0].value = append(sameName[0].value.([]string), increment.([]string)...) - } - return true, &leftAlt, collected - } - collectedMatch := make(patternList, len(*collected), len(*collected)+1) - copy(collectedMatch, *collected) - collectedMatch = append(collectedMatch, match) - return true, &leftAlt, &collectedMatch - } - panic("unmatched type") -} - -func (p *pattern) singleMatch(left *patternList) (int, *pattern) { - if p.t&patternArgument != 0 { - for n, pat := range *left { - if pat.t&patternArgument != 0 { - return n, newArgument(p.name, pat.value) - } - } - return -1, nil - } else if p.t&patternCommand != 0 { - for n, pat := range *left { - if pat.t&patternArgument != 0 { - if pat.value == p.name { - return n, newCommand(p.name, true) - } - break - } - } - return -1, nil - } else if p.t&patternOption != 0 { - for n, pat := range *left { - if p.name == pat.name { - return n, pat - } - } - return -1, nil - } - panic("unmatched type") -} - -func (p *pattern) String() string { - if p.t&patternOption != 0 { - return fmt.Sprintf("%s(%s, %s, %d, %+v)", p.t, p.short, p.long, p.argcount, p.value) - } else if p.t&patternLeaf != 0 { - return fmt.Sprintf("%s(%s, %+v)", p.t, p.name, p.value) - } else if p.t&patternBranch != 0 { - result := "" - for i, child := range p.children { - if i > 0 { - result += ", " - } - result += child.String() - } - return fmt.Sprintf("%s(%s)", p.t, result) - } - panic("unmatched type") -} - -func (p *pattern) transform() *pattern { - /* - Expand pattern into an (almost) equivalent one, but with single Either. - - Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d) - Quirks: [-a] => (-a), (-a...) => (-a -a) - */ - result := []patternList{} - groups := []patternList{patternList{p}} - parents := patternRequired + - patternOptionAL + - patternOptionSSHORTCUT + - patternEither + - patternOneOrMore - for len(groups) > 0 { - children := groups[0] - groups = groups[1:] - var child *pattern - for _, c := range children { - if c.t&parents != 0 { - child = c - break - } - } - if child != nil { - children.remove(child) - if child.t&patternEither != 0 { - for _, c := range child.children { - r := patternList{} - r = append(r, c) - r = append(r, children...) - groups = append(groups, r) - } - } else if child.t&patternOneOrMore != 0 { - r := patternList{} - r = append(r, child.children.double()...) - r = append(r, children...) - groups = append(groups, r) - } else { - r := patternList{} - r = append(r, child.children...) - r = append(r, children...) - groups = append(groups, r) - } - } else { - result = append(result, children) - } - } - either := patternList{} - for _, e := range result { - either = append(either, newRequired(e...)) - } - return newEither(either...) -} - -func (p *pattern) eq(other *pattern) bool { - return reflect.DeepEqual(p, other) -} - -func (pl patternList) unique() patternList { - table := make(map[string]bool) - result := patternList{} - for _, v := range pl { - if !table[v.String()] { - table[v.String()] = true - result = append(result, v) - } - } - return result -} - -func (pl patternList) index(p *pattern) (int, error) { - for i, c := range pl { - if c.eq(p) { - return i, nil - } - } - return -1, newError("%s not in list", p) -} - -func (pl patternList) count(p *pattern) int { - count := 0 - for _, c := range pl { - if c.eq(p) { - count++ - } - } - return count -} - -func (pl patternList) diff(l patternList) patternList { - lAlt := make(patternList, len(l)) - copy(lAlt, l) - result := make(patternList, 0, len(pl)) - for _, v := range pl { - if v != nil { - match := false - for i, w := range lAlt { - if w.eq(v) { - match = true - lAlt[i] = nil - break - } - } - if match == false { - result = append(result, v) - } - } - } - return result -} - -func (pl patternList) double() patternList { - l := len(pl) - result := make(patternList, l*2) - copy(result, pl) - copy(result[l:2*l], pl) - return result -} - -func (pl *patternList) remove(p *pattern) { - (*pl) = pl.diff(patternList{p}) -} - -func (pl patternList) dictionary() map[string]interface{} { - dict := make(map[string]interface{}) - for _, a := range pl { - dict[a.name] = a.value - } - return dict -} - func stringPartition(s, sep string) (string, string, string) { sepPos := strings.Index(s, sep) if sepPos == -1 { // no seperator found @@ -1223,17 +573,3 @@ func stringPartition(s, sep string) (string, string, string) { split := strings.SplitN(s, sep, 2) return split[0], sep, split[1] } - -// returns true if all cased characters in the string are uppercase -// and there are there is at least one cased charcter -func isStringUppercase(s string) bool { - if strings.ToUpper(s) != s { - return false - } - for _, c := range []rune(s) { - if unicode.IsUpper(c) { - return true - } - } - return false -} diff --git a/vendor/github.com/docopt/docopt-go/error.go b/vendor/github.com/docopt/docopt-go/error.go new file mode 100644 index 0000000..bd26460 --- /dev/null +++ b/vendor/github.com/docopt/docopt-go/error.go @@ -0,0 +1,49 @@ +package docopt + +import ( + "fmt" +) + +type errorType int + +const ( + errorUser errorType = iota + errorLanguage +) + +func (e errorType) String() string { + switch e { + case errorUser: + return "errorUser" + case errorLanguage: + return "errorLanguage" + } + return "" +} + +// UserError records an error with program arguments. +type UserError struct { + msg string + Usage string +} + +func (e UserError) Error() string { + return e.msg +} +func newUserError(msg string, f ...interface{}) error { + return &UserError{fmt.Sprintf(msg, f...), ""} +} + +// LanguageError records an error with the doc string. +type LanguageError struct { + msg string +} + +func (e LanguageError) Error() string { + return e.msg +} +func newLanguageError(msg string, f ...interface{}) error { + return &LanguageError{fmt.Sprintf(msg, f...)} +} + +var newError = fmt.Errorf diff --git a/vendor/github.com/docopt/docopt-go/opts.go b/vendor/github.com/docopt/docopt-go/opts.go new file mode 100644 index 0000000..36320fb --- /dev/null +++ b/vendor/github.com/docopt/docopt-go/opts.go @@ -0,0 +1,264 @@ +package docopt + +import ( + "fmt" + "reflect" + "strconv" + "strings" + "unicode" +) + +func errKey(key string) error { + return fmt.Errorf("no such key: %q", key) +} +func errType(key string) error { + return fmt.Errorf("key: %q failed type conversion", key) +} +func errStrconv(key string, convErr error) error { + return fmt.Errorf("key: %q failed type conversion: %s", key, convErr) +} + +// Opts is a map of command line options to their values, with some convenience +// methods for value type conversion (bool, float64, int, string). For example, +// to get an option value as an int: +// +// opts, _ := docopt.ParseDoc("Usage: sleep ") +// secs, _ := opts.Int("") +// +// Additionally, Opts.Bind allows you easily populate a struct's fields with the +// values of each option value. See below for examples. +// +// Lastly, you can still treat Opts as a regular map, and do any type checking +// and conversion that you want to yourself. For example: +// +// if s, ok := opts[""].(string); ok { +// if val, err := strconv.ParseUint(s, 2, 64); err != nil { ... } +// } +// +// Note that any non-boolean option / flag will have a string value in the +// underlying map. +type Opts map[string]interface{} + +func (o Opts) String(key string) (s string, err error) { + v, ok := o[key] + if !ok { + err = errKey(key) + return + } + s, ok = v.(string) + if !ok { + err = errType(key) + } + return +} + +func (o Opts) Bool(key string) (b bool, err error) { + v, ok := o[key] + if !ok { + err = errKey(key) + return + } + b, ok = v.(bool) + if !ok { + err = errType(key) + } + return +} + +func (o Opts) Int(key string) (i int, err error) { + s, err := o.String(key) + if err != nil { + return + } + i, err = strconv.Atoi(s) + if err != nil { + err = errStrconv(key, err) + } + return +} + +func (o Opts) Float64(key string) (f float64, err error) { + s, err := o.String(key) + if err != nil { + return + } + f, err = strconv.ParseFloat(s, 64) + if err != nil { + err = errStrconv(key, err) + } + return +} + +// Bind populates the fields of a given struct with matching option values. +// Each key in Opts will be mapped to an exported field of the struct pointed +// to by `v`, as follows: +// +// abc int // Unexported field, ignored +// Abc string // Mapped from `--abc`, ``, or `abc` +// // (case insensitive) +// A string // Mapped from `-a`, `` or `a` +// // (case insensitive) +// Abc int `docopt:"XYZ"` // Mapped from `XYZ` +// Abc bool `docopt:"-"` // Mapped from `-` +// Abc bool `docopt:"-x,--xyz"` // Mapped from `-x` or `--xyz` +// // (first non-zero value found) +// +// Tagged (annotated) fields will always be mapped first. If no field is tagged +// with an option's key, Bind will try to map the option to an appropriately +// named field (as above). +// +// Bind also handles conversion to bool, float, int or string types. +func (o Opts) Bind(v interface{}) error { + structVal := reflect.ValueOf(v) + if structVal.Kind() != reflect.Ptr { + return newError("'v' argument is not pointer to struct type") + } + for structVal.Kind() == reflect.Ptr { + structVal = structVal.Elem() + } + if structVal.Kind() != reflect.Struct { + return newError("'v' argument is not pointer to struct type") + } + structType := structVal.Type() + + tagged := make(map[string]int) // Tagged field tags + untagged := make(map[string]int) // Untagged field names + + for i := 0; i < structType.NumField(); i++ { + field := structType.Field(i) + if isUnexportedField(field) || field.Anonymous { + continue + } + tag := field.Tag.Get("docopt") + if tag == "" { + untagged[field.Name] = i + continue + } + for _, t := range strings.Split(tag, ",") { + tagged[t] = i + } + } + + // Get the index of the struct field to use, based on the option key. + // Second argument is true/false on whether something was matched. + getFieldIndex := func(key string) (int, bool) { + if i, ok := tagged[key]; ok { + return i, true + } + if i, ok := untagged[guessUntaggedField(key)]; ok { + return i, true + } + return -1, false + } + + indexMap := make(map[string]int) // Option keys to field index + + // Pre-check that option keys are mapped to fields and fields are zero valued, before populating them. + for k := range o { + i, ok := getFieldIndex(k) + if !ok { + if k == "--help" || k == "--version" { // Don't require these to be mapped. + continue + } + return newError("mapping of %q is not found in given struct, or is an unexported field", k) + } + fieldVal := structVal.Field(i) + zeroVal := reflect.Zero(fieldVal.Type()) + if !reflect.DeepEqual(fieldVal.Interface(), zeroVal.Interface()) { + return newError("%q field is non-zero, will be overwritten by value of %q", structType.Field(i).Name, k) + } + indexMap[k] = i + } + + // Populate fields with option values. + for k, v := range o { + i, ok := indexMap[k] + if !ok { + continue // Not mapped. + } + field := structVal.Field(i) + if !reflect.DeepEqual(field.Interface(), reflect.Zero(field.Type()).Interface()) { + // The struct's field is already non-zero (by our doing), so don't change it. + // This happens with comma separated tags, e.g. `docopt:"-h,--help"` which is a + // convenient way of checking if one of multiple boolean flags are set. + continue + } + optVal := reflect.ValueOf(v) + // Option value is the zero Value, so we can't get its .Type(). No need to assign anyway, so move along. + if !optVal.IsValid() { + continue + } + if !field.CanSet() { + return newError("%q field cannot be set", structType.Field(i).Name) + } + // Try to assign now if able. bool and string values should be assignable already. + if optVal.Type().AssignableTo(field.Type()) { + field.Set(optVal) + continue + } + // Try to convert the value and assign if able. + switch field.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if x, err := o.Int(k); err == nil { + field.SetInt(int64(x)) + continue + } + case reflect.Float32, reflect.Float64: + if x, err := o.Float64(k); err == nil { + field.SetFloat(x) + continue + } + } + // TODO: Something clever (recursive?) with non-string slices. + // case reflect.Slice: + // if optVal.Kind() == reflect.Slice { + // for i := 0; i < optVal.Len(); i++ { + // sliceVal := optVal.Index(i) + // fmt.Printf("%v", sliceVal) + // } + // fmt.Printf("\n") + // } + return newError("value of %q is not assignable to %q field", k, structType.Field(i).Name) + } + + return nil +} + +// isUnexportedField returns whether the field is unexported. +// isUnexportedField is to avoid the bug in versions older than Go1.3. +// See following links: +// https://code.google.com/p/go/issues/detail?id=7247 +// http://golang.org/ref/spec#Exported_identifiers +func isUnexportedField(field reflect.StructField) bool { + return !(field.PkgPath == "" && unicode.IsUpper(rune(field.Name[0]))) +} + +// Convert a string like "--my-special-flag" to "MySpecialFlag". +func titleCaseDashes(key string) string { + nextToUpper := true + mapFn := func(r rune) rune { + if r == '-' { + nextToUpper = true + return -1 + } + if nextToUpper { + nextToUpper = false + return unicode.ToUpper(r) + } + return r + } + return strings.Map(mapFn, key) +} + +// Best guess which field.Name in a struct to assign for an option key. +func guessUntaggedField(key string) string { + switch { + case strings.HasPrefix(key, "--") && len(key[2:]) > 1: + return titleCaseDashes(key[2:]) + case strings.HasPrefix(key, "-") && len(key[1:]) == 1: + return titleCaseDashes(key[1:]) + case strings.HasPrefix(key, "<") && strings.HasSuffix(key, ">"): + key = key[1 : len(key)-1] + } + return strings.Title(strings.ToLower(key)) +} diff --git a/vendor/github.com/docopt/docopt-go/pattern.go b/vendor/github.com/docopt/docopt-go/pattern.go new file mode 100644 index 0000000..0a29667 --- /dev/null +++ b/vendor/github.com/docopt/docopt-go/pattern.go @@ -0,0 +1,550 @@ +package docopt + +import ( + "fmt" + "reflect" + "strings" +) + +type patternType uint + +const ( + // leaf + patternArgument patternType = 1 << iota + patternCommand + patternOption + + // branch + patternRequired + patternOptionAL + patternOptionSSHORTCUT // Marker/placeholder for [options] shortcut. + patternOneOrMore + patternEither + + patternLeaf = patternArgument + + patternCommand + + patternOption + patternBranch = patternRequired + + patternOptionAL + + patternOptionSSHORTCUT + + patternOneOrMore + + patternEither + patternAll = patternLeaf + patternBranch + patternDefault = 0 +) + +func (pt patternType) String() string { + switch pt { + case patternArgument: + return "argument" + case patternCommand: + return "command" + case patternOption: + return "option" + case patternRequired: + return "required" + case patternOptionAL: + return "optional" + case patternOptionSSHORTCUT: + return "optionsshortcut" + case patternOneOrMore: + return "oneormore" + case patternEither: + return "either" + case patternLeaf: + return "leaf" + case patternBranch: + return "branch" + case patternAll: + return "all" + case patternDefault: + return "default" + } + return "" +} + +type pattern struct { + t patternType + + children patternList + + name string + value interface{} + + short string + long string + argcount int +} + +type patternList []*pattern + +func newBranchPattern(t patternType, pl ...*pattern) *pattern { + var p pattern + p.t = t + p.children = make(patternList, len(pl)) + copy(p.children, pl) + return &p +} + +func newRequired(pl ...*pattern) *pattern { + return newBranchPattern(patternRequired, pl...) +} + +func newEither(pl ...*pattern) *pattern { + return newBranchPattern(patternEither, pl...) +} + +func newOneOrMore(pl ...*pattern) *pattern { + return newBranchPattern(patternOneOrMore, pl...) +} + +func newOptional(pl ...*pattern) *pattern { + return newBranchPattern(patternOptionAL, pl...) +} + +func newOptionsShortcut() *pattern { + var p pattern + p.t = patternOptionSSHORTCUT + return &p +} + +func newLeafPattern(t patternType, name string, value interface{}) *pattern { + // default: value=nil + var p pattern + p.t = t + p.name = name + p.value = value + return &p +} + +func newArgument(name string, value interface{}) *pattern { + // default: value=nil + return newLeafPattern(patternArgument, name, value) +} + +func newCommand(name string, value interface{}) *pattern { + // default: value=false + var p pattern + p.t = patternCommand + p.name = name + p.value = value + return &p +} + +func newOption(short, long string, argcount int, value interface{}) *pattern { + // default: "", "", 0, false + var p pattern + p.t = patternOption + p.short = short + p.long = long + if long != "" { + p.name = long + } else { + p.name = short + } + p.argcount = argcount + if value == false && argcount > 0 { + p.value = nil + } else { + p.value = value + } + return &p +} + +func (p *pattern) flat(types patternType) (patternList, error) { + if p.t&patternLeaf != 0 { + if types == patternDefault { + types = patternAll + } + if p.t&types != 0 { + return patternList{p}, nil + } + return patternList{}, nil + } + + if p.t&patternBranch != 0 { + if p.t&types != 0 { + return patternList{p}, nil + } + result := patternList{} + for _, child := range p.children { + childFlat, err := child.flat(types) + if err != nil { + return nil, err + } + result = append(result, childFlat...) + } + return result, nil + } + return nil, newError("unknown pattern type: %d, %d", p.t, types) +} + +func (p *pattern) fix() error { + err := p.fixIdentities(nil) + if err != nil { + return err + } + p.fixRepeatingArguments() + return nil +} + +func (p *pattern) fixIdentities(uniq patternList) error { + // Make pattern-tree tips point to same object if they are equal. + if p.t&patternBranch == 0 { + return nil + } + if uniq == nil { + pFlat, err := p.flat(patternDefault) + if err != nil { + return err + } + uniq = pFlat.unique() + } + for i, child := range p.children { + if child.t&patternBranch == 0 { + ind, err := uniq.index(child) + if err != nil { + return err + } + p.children[i] = uniq[ind] + } else { + err := child.fixIdentities(uniq) + if err != nil { + return err + } + } + } + return nil +} + +func (p *pattern) fixRepeatingArguments() { + // Fix elements that should accumulate/increment values. + var either []patternList + + for _, child := range p.transform().children { + either = append(either, child.children) + } + for _, cas := range either { + casMultiple := patternList{} + for _, e := range cas { + if cas.count(e) > 1 { + casMultiple = append(casMultiple, e) + } + } + for _, e := range casMultiple { + if e.t == patternArgument || e.t == patternOption && e.argcount > 0 { + switch e.value.(type) { + case string: + e.value = strings.Fields(e.value.(string)) + case []string: + default: + e.value = []string{} + } + } + if e.t == patternCommand || e.t == patternOption && e.argcount == 0 { + e.value = 0 + } + } + } +} + +func (p *pattern) match(left *patternList, collected *patternList) (bool, *patternList, *patternList) { + if collected == nil { + collected = &patternList{} + } + if p.t&patternRequired != 0 { + l := left + c := collected + for _, p := range p.children { + var matched bool + matched, l, c = p.match(l, c) + if !matched { + return false, left, collected + } + } + return true, l, c + } else if p.t&patternOptionAL != 0 || p.t&patternOptionSSHORTCUT != 0 { + for _, p := range p.children { + _, left, collected = p.match(left, collected) + } + return true, left, collected + } else if p.t&patternOneOrMore != 0 { + if len(p.children) != 1 { + panic("OneOrMore.match(): assert len(p.children) == 1") + } + l := left + c := collected + var lAlt *patternList + matched := true + times := 0 + for matched { + // could it be that something didn't match but changed l or c? + matched, l, c = p.children[0].match(l, c) + if matched { + times++ + } + if lAlt == l { + break + } + lAlt = l + } + if times >= 1 { + return true, l, c + } + return false, left, collected + } else if p.t&patternEither != 0 { + type outcomeStruct struct { + matched bool + left *patternList + collected *patternList + length int + } + outcomes := []outcomeStruct{} + for _, p := range p.children { + matched, l, c := p.match(left, collected) + outcome := outcomeStruct{matched, l, c, len(*l)} + if matched { + outcomes = append(outcomes, outcome) + } + } + if len(outcomes) > 0 { + minLen := outcomes[0].length + minIndex := 0 + for i, v := range outcomes { + if v.length < minLen { + minIndex = i + } + } + return outcomes[minIndex].matched, outcomes[minIndex].left, outcomes[minIndex].collected + } + return false, left, collected + } else if p.t&patternLeaf != 0 { + pos, match := p.singleMatch(left) + var increment interface{} + if match == nil { + return false, left, collected + } + leftAlt := make(patternList, len((*left)[:pos]), len((*left)[:pos])+len((*left)[pos+1:])) + copy(leftAlt, (*left)[:pos]) + leftAlt = append(leftAlt, (*left)[pos+1:]...) + sameName := patternList{} + for _, a := range *collected { + if a.name == p.name { + sameName = append(sameName, a) + } + } + + switch p.value.(type) { + case int, []string: + switch p.value.(type) { + case int: + increment = 1 + case []string: + switch match.value.(type) { + case string: + increment = []string{match.value.(string)} + default: + increment = match.value + } + } + if len(sameName) == 0 { + match.value = increment + collectedMatch := make(patternList, len(*collected), len(*collected)+1) + copy(collectedMatch, *collected) + collectedMatch = append(collectedMatch, match) + return true, &leftAlt, &collectedMatch + } + switch sameName[0].value.(type) { + case int: + sameName[0].value = sameName[0].value.(int) + increment.(int) + case []string: + sameName[0].value = append(sameName[0].value.([]string), increment.([]string)...) + } + return true, &leftAlt, collected + } + collectedMatch := make(patternList, len(*collected), len(*collected)+1) + copy(collectedMatch, *collected) + collectedMatch = append(collectedMatch, match) + return true, &leftAlt, &collectedMatch + } + panic("unmatched type") +} + +func (p *pattern) singleMatch(left *patternList) (int, *pattern) { + if p.t&patternArgument != 0 { + for n, pat := range *left { + if pat.t&patternArgument != 0 { + return n, newArgument(p.name, pat.value) + } + } + return -1, nil + } else if p.t&patternCommand != 0 { + for n, pat := range *left { + if pat.t&patternArgument != 0 { + if pat.value == p.name { + return n, newCommand(p.name, true) + } + break + } + } + return -1, nil + } else if p.t&patternOption != 0 { + for n, pat := range *left { + if p.name == pat.name { + return n, pat + } + } + return -1, nil + } + panic("unmatched type") +} + +func (p *pattern) String() string { + if p.t&patternOption != 0 { + return fmt.Sprintf("%s(%s, %s, %d, %+v)", p.t, p.short, p.long, p.argcount, p.value) + } else if p.t&patternLeaf != 0 { + return fmt.Sprintf("%s(%s, %+v)", p.t, p.name, p.value) + } else if p.t&patternBranch != 0 { + result := "" + for i, child := range p.children { + if i > 0 { + result += ", " + } + result += child.String() + } + return fmt.Sprintf("%s(%s)", p.t, result) + } + panic("unmatched type") +} + +func (p *pattern) transform() *pattern { + /* + Expand pattern into an (almost) equivalent one, but with single Either. + + Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d) + Quirks: [-a] => (-a), (-a...) => (-a -a) + */ + result := []patternList{} + groups := []patternList{patternList{p}} + parents := patternRequired + + patternOptionAL + + patternOptionSSHORTCUT + + patternEither + + patternOneOrMore + for len(groups) > 0 { + children := groups[0] + groups = groups[1:] + var child *pattern + for _, c := range children { + if c.t&parents != 0 { + child = c + break + } + } + if child != nil { + children.remove(child) + if child.t&patternEither != 0 { + for _, c := range child.children { + r := patternList{} + r = append(r, c) + r = append(r, children...) + groups = append(groups, r) + } + } else if child.t&patternOneOrMore != 0 { + r := patternList{} + r = append(r, child.children.double()...) + r = append(r, children...) + groups = append(groups, r) + } else { + r := patternList{} + r = append(r, child.children...) + r = append(r, children...) + groups = append(groups, r) + } + } else { + result = append(result, children) + } + } + either := patternList{} + for _, e := range result { + either = append(either, newRequired(e...)) + } + return newEither(either...) +} + +func (p *pattern) eq(other *pattern) bool { + return reflect.DeepEqual(p, other) +} + +func (pl patternList) unique() patternList { + table := make(map[string]bool) + result := patternList{} + for _, v := range pl { + if !table[v.String()] { + table[v.String()] = true + result = append(result, v) + } + } + return result +} + +func (pl patternList) index(p *pattern) (int, error) { + for i, c := range pl { + if c.eq(p) { + return i, nil + } + } + return -1, newError("%s not in list", p) +} + +func (pl patternList) count(p *pattern) int { + count := 0 + for _, c := range pl { + if c.eq(p) { + count++ + } + } + return count +} + +func (pl patternList) diff(l patternList) patternList { + lAlt := make(patternList, len(l)) + copy(lAlt, l) + result := make(patternList, 0, len(pl)) + for _, v := range pl { + if v != nil { + match := false + for i, w := range lAlt { + if w.eq(v) { + match = true + lAlt[i] = nil + break + } + } + if match == false { + result = append(result, v) + } + } + } + return result +} + +func (pl patternList) double() patternList { + l := len(pl) + result := make(patternList, l*2) + copy(result, pl) + copy(result[l:2*l], pl) + return result +} + +func (pl *patternList) remove(p *pattern) { + (*pl) = pl.diff(patternList{p}) +} + +func (pl patternList) dictionary() map[string]interface{} { + dict := make(map[string]interface{}) + for _, a := range pl { + dict[a.name] = a.value + } + return dict +} diff --git a/vendor/github.com/docopt/docopt-go/token.go b/vendor/github.com/docopt/docopt-go/token.go new file mode 100644 index 0000000..cc18ec9 --- /dev/null +++ b/vendor/github.com/docopt/docopt-go/token.go @@ -0,0 +1,126 @@ +package docopt + +import ( + "regexp" + "strings" + "unicode" +) + +type tokenList struct { + tokens []string + errorFunc func(string, ...interface{}) error + err errorType +} +type token string + +func newTokenList(source []string, err errorType) *tokenList { + errorFunc := newError + if err == errorUser { + errorFunc = newUserError + } else if err == errorLanguage { + errorFunc = newLanguageError + } + return &tokenList{source, errorFunc, err} +} + +func tokenListFromString(source string) *tokenList { + return newTokenList(strings.Fields(source), errorUser) +} + +func tokenListFromPattern(source string) *tokenList { + p := regexp.MustCompile(`([\[\]\(\)\|]|\.\.\.)`) + source = p.ReplaceAllString(source, ` $1 `) + p = regexp.MustCompile(`\s+|(\S*<.*?>)`) + split := p.Split(source, -1) + match := p.FindAllStringSubmatch(source, -1) + var result []string + l := len(split) + for i := 0; i < l; i++ { + if len(split[i]) > 0 { + result = append(result, split[i]) + } + if i < l-1 && len(match[i][1]) > 0 { + result = append(result, match[i][1]) + } + } + return newTokenList(result, errorLanguage) +} + +func (t *token) eq(s string) bool { + if t == nil { + return false + } + return string(*t) == s +} +func (t *token) match(matchNil bool, tokenStrings ...string) bool { + if t == nil && matchNil { + return true + } else if t == nil && !matchNil { + return false + } + + for _, tok := range tokenStrings { + if tok == string(*t) { + return true + } + } + return false +} +func (t *token) hasPrefix(prefix string) bool { + if t == nil { + return false + } + return strings.HasPrefix(string(*t), prefix) +} +func (t *token) hasSuffix(suffix string) bool { + if t == nil { + return false + } + return strings.HasSuffix(string(*t), suffix) +} +func (t *token) isUpper() bool { + if t == nil { + return false + } + return isStringUppercase(string(*t)) +} +func (t *token) String() string { + if t == nil { + return "" + } + return string(*t) +} + +func (tl *tokenList) current() *token { + if len(tl.tokens) > 0 { + return (*token)(&(tl.tokens[0])) + } + return nil +} + +func (tl *tokenList) length() int { + return len(tl.tokens) +} + +func (tl *tokenList) move() *token { + if len(tl.tokens) > 0 { + t := tl.tokens[0] + tl.tokens = tl.tokens[1:] + return (*token)(&t) + } + return nil +} + +// returns true if all cased characters in the string are uppercase +// and there are there is at least one cased charcter +func isStringUppercase(s string) bool { + if strings.ToUpper(s) != s { + return false + } + for _, c := range []rune(s) { + if unicode.IsUpper(c) { + return true + } + } + return false +}