forked from External/ergo
fix #782 (bring vendor into the main tree)
This commit is contained in:
parent
702c7b1e7c
commit
d0aa7cc860
616 changed files with 359667 additions and 31 deletions
25
vendor/github.com/docopt/docopt-go/.gitignore
generated
vendored
Normal file
25
vendor/github.com/docopt/docopt-go/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
|
||||
# coverage droppings
|
||||
profile.cov
|
||||
32
vendor/github.com/docopt/docopt-go/.travis.yml
generated
vendored
Normal file
32
vendor/github.com/docopt/docopt-go/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Travis CI (http://travis-ci.org/) is a continuous integration
|
||||
# service for open source projects. This file configures it
|
||||
# to run unit tests for docopt-go.
|
||||
|
||||
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/cover
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
install:
|
||||
- go get -d -v ./... && go build -v ./...
|
||||
|
||||
script:
|
||||
- go vet -x ./...
|
||||
- go test -v ./...
|
||||
- go test -covermode=count -coverprofile=profile.cov .
|
||||
|
||||
after_script:
|
||||
- $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci
|
||||
21
vendor/github.com/docopt/docopt-go/LICENSE
generated
vendored
Normal file
21
vendor/github.com/docopt/docopt-go/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
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
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
116
vendor/github.com/docopt/docopt-go/README.md
generated
vendored
Normal file
116
vendor/github.com/docopt/docopt-go/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
docopt-go
|
||||
=========
|
||||
|
||||
[](https://travis-ci.org/docopt/docopt.go)
|
||||
[](https://coveralls.io/github/docopt/docopt.go)
|
||||
[](https://godoc.org/github.com/docopt/docopt.go)
|
||||
|
||||
An implementation of [docopt](http://docopt.org/) in the [Go](http://golang.org/) programming language.
|
||||
|
||||
**docopt** helps you create *beautiful* command-line interfaces easily:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/docopt/docopt-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
usage := `Naval Fate.
|
||||
|
||||
Usage:
|
||||
naval_fate ship new <name>...
|
||||
naval_fate ship <name> move <x> <y> [--speed=<kn>]
|
||||
naval_fate ship shoot <x> <y>
|
||||
naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
|
||||
naval_fate -h | --help
|
||||
naval_fate --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Show version.
|
||||
--speed=<kn> Speed in knots [default: 10].
|
||||
--moored Moored (anchored) mine.
|
||||
--drifting Drifting mine.`
|
||||
|
||||
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.
|
||||
|
||||
## Installation
|
||||
|
||||
⚠ Use the alias "docopt-go". To use docopt in your Go code:
|
||||
|
||||
```go
|
||||
import "github.com/docopt/docopt-go"
|
||||
```
|
||||
|
||||
To install docopt in your `$GOPATH`:
|
||||
|
||||
```console
|
||||
$ 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
|
||||
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:
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
```go
|
||||
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:
|
||||
|
||||
```go
|
||||
flag, _ := opts.Bool("--flag")
|
||||
secs, _ := opts.Int("<seconds>")
|
||||
```
|
||||
|
||||
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:"<cmd>"`
|
||||
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`.
|
||||
49
vendor/github.com/docopt/docopt-go/doc.go
generated
vendored
Normal file
49
vendor/github.com/docopt/docopt-go/doc.go
generated
vendored
Normal file
|
|
@ -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("<seconds>")
|
||||
|
||||
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:"<cmd>"`
|
||||
Tries int `docopt:"-n"`
|
||||
Force bool // Gets the value of --force
|
||||
}
|
||||
opts.Bind(&config)
|
||||
*/
|
||||
package docopt
|
||||
575
vendor/github.com/docopt/docopt-go/docopt.go
generated
vendored
Normal file
575
vendor/github.com/docopt/docopt-go/docopt.go
generated
vendored
Normal file
|
|
@ -0,0 +1,575 @@
|
|||
// Licensed under terms of MIT license (see LICENSE-MIT)
|
||||
// Copyright (c) 2013 Keith Batten, kbatten@gmail.com
|
||||
// Copyright (c) 2016 David Irvine
|
||||
|
||||
package docopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
var PrintHelpOnly = func(err error, usage string) {
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, usage)
|
||||
} else {
|
||||
fmt.Println(usage)
|
||||
}
|
||||
}
|
||||
|
||||
var NoHelpHandler = func(err error, usage string) {}
|
||||
|
||||
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]
|
||||
}
|
||||
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
|
||||
p.HelpHandler(err, output)
|
||||
} else if len(output) > 0 && err == nil {
|
||||
// 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 {
|
||||
argv = os.Args[1:]
|
||||
}
|
||||
|
||||
usageSections := parseSection("usage:", doc)
|
||||
|
||||
if len(usageSections) == 0 {
|
||||
err = newLanguageError("\"usage:\" (case-insensitive) not found.")
|
||||
return
|
||||
}
|
||||
if len(usageSections) > 1 {
|
||||
err = newLanguageError("More than one \"usage:\" (case-insensitive).")
|
||||
return
|
||||
}
|
||||
usage := usageSections[0]
|
||||
|
||||
options := parseDefaults(doc)
|
||||
formal, err := formalUsage(usage)
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
|
||||
pat, err := parsePattern(formal, &options)
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
|
||||
patternArgv, err := parseArgv(newTokenList(argv, errorUser), &options, optionsFirst)
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
patFlat, err := pat.flat(patternOption)
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
patternOptions := patFlat.unique()
|
||||
|
||||
patFlat, err = pat.flat(patternOptionSSHORTCUT)
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
for _, optionsShortcut := range patFlat {
|
||||
docOptions := parseDefaults(doc)
|
||||
optionsShortcut.children = docOptions.unique().diff(patternOptions)
|
||||
}
|
||||
|
||||
if output = extras(help, version, patternArgv, doc); len(output) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
err = pat.fix()
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
matched, left, collected := pat.match(&patternArgv, nil)
|
||||
if matched && len(*left) == 0 {
|
||||
patFlat, err = pat.flat(patternDefault)
|
||||
if err != nil {
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
args = append(patFlat, *collected...).dictionary()
|
||||
return
|
||||
}
|
||||
|
||||
err = newUserError("")
|
||||
output = handleError(err, usage)
|
||||
return
|
||||
}
|
||||
|
||||
func handleError(err error, usage string) string {
|
||||
if _, ok := err.(*UserError); ok {
|
||||
return strings.TrimSpace(fmt.Sprintf("%s\n%s", err, usage))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func parseSection(name, source string) []string {
|
||||
p := regexp.MustCompile(`(?im)^([^\n]*` + name + `[^\n]*\n?(?:[ \t].*?(?:\n|$))*)`)
|
||||
s := p.FindAllString(source, -1)
|
||||
if s == nil {
|
||||
s = []string{}
|
||||
}
|
||||
for i, v := range s {
|
||||
s[i] = strings.TrimSpace(v)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func parseDefaults(doc string) patternList {
|
||||
defaults := patternList{}
|
||||
p := regexp.MustCompile(`\n[ \t]*(-\S+?)`)
|
||||
for _, s := range parseSection("options:", doc) {
|
||||
// FIXME corner case "bla: options: --foo"
|
||||
_, _, s = stringPartition(s, ":") // get rid of "options:"
|
||||
split := p.Split("\n"+s, -1)[1:]
|
||||
match := p.FindAllStringSubmatch("\n"+s, -1)
|
||||
for i := range split {
|
||||
optionDescription := match[i][1] + split[i]
|
||||
if strings.HasPrefix(optionDescription, "-") {
|
||||
defaults = append(defaults, parseOption(optionDescription))
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaults
|
||||
}
|
||||
|
||||
func parsePattern(source string, options *patternList) (*pattern, error) {
|
||||
tokens := tokenListFromPattern(source)
|
||||
result, err := parseExpr(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tokens.current() != nil {
|
||||
return nil, tokens.errorFunc("unexpected ending: %s" + strings.Join(tokens.tokens, " "))
|
||||
}
|
||||
return newRequired(result...), nil
|
||||
}
|
||||
|
||||
func parseArgv(tokens *tokenList, options *patternList, optionsFirst bool) (patternList, error) {
|
||||
/*
|
||||
Parse command-line argument vector.
|
||||
|
||||
If options_first:
|
||||
argv ::= [ long | shorts ]* [ argument ]* [ '--' [ argument ]* ] ;
|
||||
else:
|
||||
argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ;
|
||||
*/
|
||||
parsed := patternList{}
|
||||
for tokens.current() != nil {
|
||||
if tokens.current().eq("--") {
|
||||
for _, v := range tokens.tokens {
|
||||
parsed = append(parsed, newArgument("", v))
|
||||
}
|
||||
return parsed, nil
|
||||
} else if tokens.current().hasPrefix("--") {
|
||||
pl, err := parseLong(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed = append(parsed, pl...)
|
||||
} else if tokens.current().hasPrefix("-") && !tokens.current().eq("-") {
|
||||
ps, err := parseShorts(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsed = append(parsed, ps...)
|
||||
} else if optionsFirst {
|
||||
for _, v := range tokens.tokens {
|
||||
parsed = append(parsed, newArgument("", v))
|
||||
}
|
||||
return parsed, nil
|
||||
} else {
|
||||
parsed = append(parsed, newArgument("", tokens.move().String()))
|
||||
}
|
||||
}
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
func parseOption(optionDescription string) *pattern {
|
||||
optionDescription = strings.TrimSpace(optionDescription)
|
||||
options, _, description := stringPartition(optionDescription, " ")
|
||||
options = strings.Replace(options, ",", " ", -1)
|
||||
options = strings.Replace(options, "=", " ", -1)
|
||||
|
||||
short := ""
|
||||
long := ""
|
||||
argcount := 0
|
||||
var value interface{}
|
||||
value = false
|
||||
|
||||
reDefault := regexp.MustCompile(`(?i)\[default: (.*)\]`)
|
||||
for _, s := range strings.Fields(options) {
|
||||
if strings.HasPrefix(s, "--") {
|
||||
long = s
|
||||
} else if strings.HasPrefix(s, "-") {
|
||||
short = s
|
||||
} else {
|
||||
argcount = 1
|
||||
}
|
||||
if argcount > 0 {
|
||||
matched := reDefault.FindAllStringSubmatch(description, -1)
|
||||
if len(matched) > 0 {
|
||||
value = matched[0][1]
|
||||
} else {
|
||||
value = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return newOption(short, long, argcount, value)
|
||||
}
|
||||
|
||||
func parseExpr(tokens *tokenList, options *patternList) (patternList, error) {
|
||||
// expr ::= seq ( '|' seq )* ;
|
||||
seq, err := parseSeq(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !tokens.current().eq("|") {
|
||||
return seq, nil
|
||||
}
|
||||
var result patternList
|
||||
if len(seq) > 1 {
|
||||
result = patternList{newRequired(seq...)}
|
||||
} else {
|
||||
result = seq
|
||||
}
|
||||
for tokens.current().eq("|") {
|
||||
tokens.move()
|
||||
seq, err = parseSeq(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(seq) > 1 {
|
||||
result = append(result, newRequired(seq...))
|
||||
} else {
|
||||
result = append(result, seq...)
|
||||
}
|
||||
}
|
||||
if len(result) > 1 {
|
||||
return patternList{newEither(result...)}, nil
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func parseSeq(tokens *tokenList, options *patternList) (patternList, error) {
|
||||
// seq ::= ( atom [ '...' ] )* ;
|
||||
result := patternList{}
|
||||
for !tokens.current().match(true, "]", ")", "|") {
|
||||
atom, err := parseAtom(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tokens.current().eq("...") {
|
||||
atom = patternList{newOneOrMore(atom...)}
|
||||
tokens.move()
|
||||
}
|
||||
result = append(result, atom...)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func parseAtom(tokens *tokenList, options *patternList) (patternList, error) {
|
||||
// atom ::= '(' expr ')' | '[' expr ']' | 'options' | long | shorts | argument | command ;
|
||||
tok := tokens.current()
|
||||
result := patternList{}
|
||||
if tokens.current().match(false, "(", "[") {
|
||||
tokens.move()
|
||||
var matching string
|
||||
pl, err := parseExpr(tokens, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tok.eq("(") {
|
||||
matching = ")"
|
||||
result = patternList{newRequired(pl...)}
|
||||
} else if tok.eq("[") {
|
||||
matching = "]"
|
||||
result = patternList{newOptional(pl...)}
|
||||
}
|
||||
moved := tokens.move()
|
||||
if !moved.eq(matching) {
|
||||
return nil, tokens.errorFunc("unmatched '%s', expected: '%s' got: '%s'", tok, matching, moved)
|
||||
}
|
||||
return result, nil
|
||||
} else if tok.eq("options") {
|
||||
tokens.move()
|
||||
return patternList{newOptionsShortcut()}, nil
|
||||
} else if tok.hasPrefix("--") && !tok.eq("--") {
|
||||
return parseLong(tokens, options)
|
||||
} else if tok.hasPrefix("-") && !tok.eq("-") && !tok.eq("--") {
|
||||
return parseShorts(tokens, options)
|
||||
} else if tok.hasPrefix("<") && tok.hasSuffix(">") || tok.isUpper() {
|
||||
return patternList{newArgument(tokens.move().String(), nil)}, nil
|
||||
}
|
||||
return patternList{newCommand(tokens.move().String(), false)}, nil
|
||||
}
|
||||
|
||||
func parseLong(tokens *tokenList, options *patternList) (patternList, error) {
|
||||
// long ::= '--' chars [ ( ' ' | '=' ) chars ] ;
|
||||
long, eq, v := stringPartition(tokens.move().String(), "=")
|
||||
var value interface{}
|
||||
var opt *pattern
|
||||
if eq == "" && v == "" {
|
||||
value = nil
|
||||
} else {
|
||||
value = v
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(long, "--") {
|
||||
return nil, newError("long option '%s' doesn't start with --", long)
|
||||
}
|
||||
similar := patternList{}
|
||||
for _, o := range *options {
|
||||
if o.long == long {
|
||||
similar = append(similar, o)
|
||||
}
|
||||
}
|
||||
if tokens.err == errorUser && len(similar) == 0 { // if no exact match
|
||||
similar = patternList{}
|
||||
for _, o := range *options {
|
||||
if strings.HasPrefix(o.long, long) {
|
||||
similar = append(similar, o)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(similar) > 1 { // might be simply specified ambiguously 2+ times?
|
||||
similarLong := make([]string, len(similar))
|
||||
for i, s := range similar {
|
||||
similarLong[i] = s.long
|
||||
}
|
||||
return nil, tokens.errorFunc("%s is not a unique prefix: %s?", long, strings.Join(similarLong, ", "))
|
||||
} else if len(similar) < 1 {
|
||||
argcount := 0
|
||||
if eq == "=" {
|
||||
argcount = 1
|
||||
}
|
||||
opt = newOption("", long, argcount, false)
|
||||
*options = append(*options, opt)
|
||||
if tokens.err == errorUser {
|
||||
var val interface{}
|
||||
if argcount > 0 {
|
||||
val = value
|
||||
} else {
|
||||
val = true
|
||||
}
|
||||
opt = newOption("", long, argcount, val)
|
||||
}
|
||||
} else {
|
||||
opt = newOption(similar[0].short, similar[0].long, similar[0].argcount, similar[0].value)
|
||||
if opt.argcount == 0 {
|
||||
if value != nil {
|
||||
return nil, tokens.errorFunc("%s must not have an argument", opt.long)
|
||||
}
|
||||
} else {
|
||||
if value == nil {
|
||||
if tokens.current().match(true, "--") {
|
||||
return nil, tokens.errorFunc("%s requires argument", opt.long)
|
||||
}
|
||||
moved := tokens.move()
|
||||
if moved != nil {
|
||||
value = moved.String() // only set as string if not nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if tokens.err == errorUser {
|
||||
if value != nil {
|
||||
opt.value = value
|
||||
} else {
|
||||
opt.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return patternList{opt}, nil
|
||||
}
|
||||
|
||||
func parseShorts(tokens *tokenList, options *patternList) (patternList, error) {
|
||||
// shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;
|
||||
tok := tokens.move()
|
||||
if !tok.hasPrefix("-") || tok.hasPrefix("--") {
|
||||
return nil, newError("short option '%s' doesn't start with -", tok)
|
||||
}
|
||||
left := strings.TrimLeft(tok.String(), "-")
|
||||
parsed := patternList{}
|
||||
for left != "" {
|
||||
var opt *pattern
|
||||
short := "-" + left[0:1]
|
||||
left = left[1:]
|
||||
similar := patternList{}
|
||||
for _, o := range *options {
|
||||
if o.short == short {
|
||||
similar = append(similar, o)
|
||||
}
|
||||
}
|
||||
if len(similar) > 1 {
|
||||
return nil, tokens.errorFunc("%s is specified ambiguously %d times", short, len(similar))
|
||||
} else if len(similar) < 1 {
|
||||
opt = newOption(short, "", 0, false)
|
||||
*options = append(*options, opt)
|
||||
if tokens.err == errorUser {
|
||||
opt = newOption(short, "", 0, true)
|
||||
}
|
||||
} else { // why copying is necessary here?
|
||||
opt = newOption(short, similar[0].long, similar[0].argcount, similar[0].value)
|
||||
var value interface{}
|
||||
if opt.argcount > 0 {
|
||||
if left == "" {
|
||||
if tokens.current().match(true, "--") {
|
||||
return nil, tokens.errorFunc("%s requires argument", short)
|
||||
}
|
||||
value = tokens.move().String()
|
||||
} else {
|
||||
value = left
|
||||
left = ""
|
||||
}
|
||||
}
|
||||
if tokens.err == errorUser {
|
||||
if value != nil {
|
||||
opt.value = value
|
||||
} else {
|
||||
opt.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
parsed = append(parsed, opt)
|
||||
}
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
func formalUsage(section string) (string, error) {
|
||||
_, _, section = stringPartition(section, ":") // drop "usage:"
|
||||
pu := strings.Fields(section)
|
||||
|
||||
if len(pu) == 0 {
|
||||
return "", newLanguageError("no fields found in usage (perhaps a spacing error).")
|
||||
}
|
||||
|
||||
result := "( "
|
||||
for _, s := range pu[1:] {
|
||||
if s == pu[0] {
|
||||
result += ") | ( "
|
||||
} else {
|
||||
result += s + " "
|
||||
}
|
||||
}
|
||||
result += ")"
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func extras(help bool, version string, options patternList, doc string) string {
|
||||
if help {
|
||||
for _, o := range options {
|
||||
if (o.name == "-h" || o.name == "--help") && o.value == true {
|
||||
return strings.Trim(doc, "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
if version != "" {
|
||||
for _, o := range options {
|
||||
if (o.name == "--version") && o.value == true {
|
||||
return version
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func stringPartition(s, sep string) (string, string, string) {
|
||||
sepPos := strings.Index(s, sep)
|
||||
if sepPos == -1 { // no seperator found
|
||||
return s, "", ""
|
||||
}
|
||||
split := strings.SplitN(s, sep, 2)
|
||||
return split[0], sep, split[1]
|
||||
}
|
||||
49
vendor/github.com/docopt/docopt-go/error.go
generated
vendored
Normal file
49
vendor/github.com/docopt/docopt-go/error.go
generated
vendored
Normal file
|
|
@ -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
|
||||
264
vendor/github.com/docopt/docopt-go/opts.go
generated
vendored
Normal file
264
vendor/github.com/docopt/docopt-go/opts.go
generated
vendored
Normal file
|
|
@ -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 <seconds>")
|
||||
// secs, _ := opts.Int("<seconds>")
|
||||
//
|
||||
// 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["<binary>"].(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`, `<abc>`, or `abc`
|
||||
// // (case insensitive)
|
||||
// A string // Mapped from `-a`, `<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))
|
||||
}
|
||||
550
vendor/github.com/docopt/docopt-go/pattern.go
generated
vendored
Normal file
550
vendor/github.com/docopt/docopt-go/pattern.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
9
vendor/github.com/docopt/docopt-go/test_golang.docopt
generated
vendored
Normal file
9
vendor/github.com/docopt/docopt-go/test_golang.docopt
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
r"""usage: prog [NAME_-2]..."""
|
||||
$ prog 10 20
|
||||
{"NAME_-2": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME_-2": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME_-2": []}
|
||||
957
vendor/github.com/docopt/docopt-go/testcases.docopt
generated
vendored
Normal file
957
vendor/github.com/docopt/docopt-go/testcases.docopt
generated
vendored
Normal file
|
|
@ -0,0 +1,957 @@
|
|||
r"""Usage: prog
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{}
|
||||
|
||||
$ prog --xxx
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -a All.
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"-a": false}
|
||||
|
||||
$ prog -a
|
||||
{"-a": true}
|
||||
|
||||
$ prog -x
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: --all All.
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--all": false}
|
||||
|
||||
$ prog --all
|
||||
{"--all": true}
|
||||
|
||||
$ prog --xxx
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -v, --verbose Verbose.
|
||||
|
||||
"""
|
||||
$ prog --verbose
|
||||
{"--verbose": true}
|
||||
|
||||
$ prog --ver
|
||||
{"--verbose": true}
|
||||
|
||||
$ prog -v
|
||||
{"--verbose": true}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -p PATH
|
||||
|
||||
"""
|
||||
$ prog -p home/
|
||||
{"-p": "home/"}
|
||||
|
||||
$ prog -phome/
|
||||
{"-p": "home/"}
|
||||
|
||||
$ prog -p
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: --path <path>
|
||||
|
||||
"""
|
||||
$ prog --path home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --path=home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --pa home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --pa=home/
|
||||
{"--path": "home/"}
|
||||
|
||||
$ prog --path
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -p PATH, --path=<path> Path to files.
|
||||
|
||||
"""
|
||||
$ prog -proot
|
||||
{"--path": "root"}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: -p --path PATH Path to files.
|
||||
|
||||
"""
|
||||
$ prog -p root
|
||||
{"--path": "root"}
|
||||
|
||||
$ prog --path root
|
||||
{"--path": "root"}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options:
|
||||
-p PATH Path to files [default: ./]
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"-p": "./"}
|
||||
|
||||
$ prog -phome
|
||||
{"-p": "home"}
|
||||
|
||||
|
||||
r"""UsAgE: prog [options]
|
||||
|
||||
OpTiOnS: --path=<files> Path to files
|
||||
[dEfAuLt: /root]
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--path": "/root"}
|
||||
|
||||
$ prog --path=home
|
||||
{"--path": "home"}
|
||||
|
||||
|
||||
r"""usage: prog [options]
|
||||
|
||||
options:
|
||||
-a Add
|
||||
-r Remote
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -a -r -m Hello
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "Hello"}
|
||||
|
||||
$ prog -armyourass
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "yourass"}
|
||||
|
||||
$ prog -a -r
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": null}
|
||||
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
Options: --version
|
||||
--verbose
|
||||
|
||||
"""
|
||||
$ prog --version
|
||||
{"--version": true,
|
||||
"--verbose": false}
|
||||
|
||||
$ prog --verbose
|
||||
{"--version": false,
|
||||
"--verbose": true}
|
||||
|
||||
$ prog --ver
|
||||
"user-error"
|
||||
|
||||
$ prog --verb
|
||||
{"--version": false,
|
||||
"--verbose": true}
|
||||
|
||||
|
||||
r"""usage: prog [-a -r -m <msg>]
|
||||
|
||||
options:
|
||||
-a Add
|
||||
-r Remote
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -armyourass
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "yourass"}
|
||||
|
||||
|
||||
r"""usage: prog [-armmsg]
|
||||
|
||||
options: -a Add
|
||||
-r Remote
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -a -r -m Hello
|
||||
{"-a": true,
|
||||
"-r": true,
|
||||
"-m": "Hello"}
|
||||
|
||||
|
||||
r"""usage: prog -a -b
|
||||
|
||||
options:
|
||||
-a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog (-a -b)
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [-a] -b
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog -b
|
||||
{"-a": false, "-b": true}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [(-a -b)]
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -b -a
|
||||
{"-a": true, "-b": true}
|
||||
|
||||
$ prog -a
|
||||
"user-error"
|
||||
|
||||
$ prog -b
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"-a": false, "-b": false}
|
||||
|
||||
|
||||
r"""usage: prog (-a|-b)
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
$ prog -a
|
||||
{"-a": true, "-b": false}
|
||||
|
||||
$ prog -b
|
||||
{"-a": false, "-b": true}
|
||||
|
||||
|
||||
r"""usage: prog [ -a | -b ]
|
||||
|
||||
options: -a
|
||||
-b
|
||||
|
||||
"""
|
||||
$ prog -a -b
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"-a": false, "-b": false}
|
||||
|
||||
$ prog -a
|
||||
{"-a": true, "-b": false}
|
||||
|
||||
$ prog -b
|
||||
{"-a": false, "-b": true}
|
||||
|
||||
|
||||
r"""usage: prog <arg>"""
|
||||
$ prog 10
|
||||
{"<arg>": "10"}
|
||||
|
||||
$ prog 10 20
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [<arg>]"""
|
||||
$ prog 10
|
||||
{"<arg>": "10"}
|
||||
|
||||
$ prog 10 20
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"<arg>": null}
|
||||
|
||||
|
||||
r"""usage: prog <kind> <name> <type>"""
|
||||
$ prog 10 20 40
|
||||
{"<kind>": "10", "<name>": "20", "<type>": "40"}
|
||||
|
||||
$ prog 10 20
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog <kind> [<name> <type>]"""
|
||||
$ prog 10 20 40
|
||||
{"<kind>": "10", "<name>": "20", "<type>": "40"}
|
||||
|
||||
$ prog 10 20
|
||||
{"<kind>": "10", "<name>": "20", "<type>": null}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [<kind> | <name> <type>]"""
|
||||
$ prog 10 20 40
|
||||
"user-error"
|
||||
|
||||
$ prog 20 40
|
||||
{"<kind>": null, "<name>": "20", "<type>": "40"}
|
||||
|
||||
$ prog
|
||||
{"<kind>": null, "<name>": null, "<type>": null}
|
||||
|
||||
|
||||
r"""usage: prog (<kind> --all | <name>)
|
||||
|
||||
options:
|
||||
--all
|
||||
|
||||
"""
|
||||
$ prog 10 --all
|
||||
{"<kind>": "10", "--all": true, "<name>": null}
|
||||
|
||||
$ prog 10
|
||||
{"<kind>": null, "--all": false, "<name>": "10"}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [<name> <name>]"""
|
||||
$ prog 10 20
|
||||
{"<name>": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"<name>": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"<name>": []}
|
||||
|
||||
|
||||
r"""usage: prog [(<name> <name>)]"""
|
||||
$ prog 10 20
|
||||
{"<name>": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
"user-error"
|
||||
|
||||
$ prog
|
||||
{"<name>": []}
|
||||
|
||||
|
||||
r"""usage: prog NAME..."""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [NAME]..."""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
|
||||
r"""usage: prog [NAME...]"""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
|
||||
r"""usage: prog [NAME [NAME ...]]"""
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"]}
|
||||
|
||||
$ prog 10
|
||||
{"NAME": ["10"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
|
||||
r"""usage: prog (NAME | --foo NAME)
|
||||
|
||||
options: --foo
|
||||
|
||||
"""
|
||||
$ prog 10
|
||||
{"NAME": "10", "--foo": false}
|
||||
|
||||
$ prog --foo 10
|
||||
{"NAME": "10", "--foo": true}
|
||||
|
||||
$ prog --foo=10
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog (NAME | --foo) [--bar | NAME]
|
||||
|
||||
options: --foo
|
||||
options: --bar
|
||||
|
||||
"""
|
||||
$ prog 10
|
||||
{"NAME": ["10"], "--foo": false, "--bar": false}
|
||||
|
||||
$ prog 10 20
|
||||
{"NAME": ["10", "20"], "--foo": false, "--bar": false}
|
||||
|
||||
$ prog --foo --bar
|
||||
{"NAME": [], "--foo": true, "--bar": true}
|
||||
|
||||
|
||||
r"""Naval Fate.
|
||||
|
||||
Usage:
|
||||
prog ship new <name>...
|
||||
prog ship [<name>] move <x> <y> [--speed=<kn>]
|
||||
prog ship shoot <x> <y>
|
||||
prog mine (set|remove) <x> <y> [--moored|--drifting]
|
||||
prog -h | --help
|
||||
prog --version
|
||||
|
||||
Options:
|
||||
-h --help Show this screen.
|
||||
--version Show version.
|
||||
--speed=<kn> Speed in knots [default: 10].
|
||||
--moored Mored (anchored) mine.
|
||||
--drifting Drifting mine.
|
||||
|
||||
"""
|
||||
$ prog ship Guardian move 150 300 --speed=20
|
||||
{"--drifting": false,
|
||||
"--help": false,
|
||||
"--moored": false,
|
||||
"--speed": "20",
|
||||
"--version": false,
|
||||
"<name>": ["Guardian"],
|
||||
"<x>": "150",
|
||||
"<y>": "300",
|
||||
"mine": false,
|
||||
"move": true,
|
||||
"new": false,
|
||||
"remove": false,
|
||||
"set": false,
|
||||
"ship": true,
|
||||
"shoot": false}
|
||||
|
||||
|
||||
r"""usage: prog --hello"""
|
||||
$ prog --hello
|
||||
{"--hello": true}
|
||||
|
||||
|
||||
r"""usage: prog [--hello=<world>]"""
|
||||
$ prog
|
||||
{"--hello": null}
|
||||
|
||||
$ prog --hello wrld
|
||||
{"--hello": "wrld"}
|
||||
|
||||
|
||||
r"""usage: prog [-o]"""
|
||||
$ prog
|
||||
{"-o": false}
|
||||
|
||||
$ prog -o
|
||||
{"-o": true}
|
||||
|
||||
|
||||
r"""usage: prog [-opr]"""
|
||||
$ prog -op
|
||||
{"-o": true, "-p": true, "-r": false}
|
||||
|
||||
|
||||
r"""usage: prog --aabb | --aa"""
|
||||
$ prog --aa
|
||||
{"--aabb": false, "--aa": true}
|
||||
|
||||
$ prog --a
|
||||
"user-error" # not a unique prefix
|
||||
|
||||
#
|
||||
# Counting number of flags
|
||||
#
|
||||
|
||||
r"""Usage: prog -v"""
|
||||
$ prog -v
|
||||
{"-v": true}
|
||||
|
||||
|
||||
r"""Usage: prog [-v -v]"""
|
||||
$ prog
|
||||
{"-v": 0}
|
||||
|
||||
$ prog -v
|
||||
{"-v": 1}
|
||||
|
||||
$ prog -vv
|
||||
{"-v": 2}
|
||||
|
||||
|
||||
r"""Usage: prog -v ..."""
|
||||
$ prog
|
||||
"user-error"
|
||||
|
||||
$ prog -v
|
||||
{"-v": 1}
|
||||
|
||||
$ prog -vv
|
||||
{"-v": 2}
|
||||
|
||||
$ prog -vvvvvv
|
||||
{"-v": 6}
|
||||
|
||||
|
||||
r"""Usage: prog [-v | -vv | -vvv]
|
||||
|
||||
This one is probably most readable user-friednly variant.
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"-v": 0}
|
||||
|
||||
$ prog -v
|
||||
{"-v": 1}
|
||||
|
||||
$ prog -vv
|
||||
{"-v": 2}
|
||||
|
||||
$ prog -vvvv
|
||||
"user-error"
|
||||
|
||||
|
||||
r"""usage: prog [--ver --ver]"""
|
||||
$ prog --ver --ver
|
||||
{"--ver": 2}
|
||||
|
||||
|
||||
#
|
||||
# Counting commands
|
||||
#
|
||||
|
||||
r"""usage: prog [go]"""
|
||||
$ prog go
|
||||
{"go": true}
|
||||
|
||||
|
||||
r"""usage: prog [go go]"""
|
||||
$ prog
|
||||
{"go": 0}
|
||||
|
||||
$ prog go
|
||||
{"go": 1}
|
||||
|
||||
$ prog go go
|
||||
{"go": 2}
|
||||
|
||||
$ prog go go go
|
||||
"user-error"
|
||||
|
||||
r"""usage: prog go..."""
|
||||
$ prog go go go go go
|
||||
{"go": 5}
|
||||
|
||||
#
|
||||
# [options] does not include options from usage-pattern
|
||||
#
|
||||
r"""usage: prog [options] [-a]
|
||||
|
||||
options: -a
|
||||
-b
|
||||
"""
|
||||
$ prog -a
|
||||
{"-a": true, "-b": false}
|
||||
|
||||
$ prog -aa
|
||||
"user-error"
|
||||
|
||||
#
|
||||
# Test [options] shourtcut
|
||||
#
|
||||
|
||||
r"""Usage: prog [options] A
|
||||
Options:
|
||||
-q Be quiet
|
||||
-v Be verbose.
|
||||
|
||||
"""
|
||||
$ prog arg
|
||||
{"A": "arg", "-v": false, "-q": false}
|
||||
|
||||
$ prog -v arg
|
||||
{"A": "arg", "-v": true, "-q": false}
|
||||
|
||||
$ prog -q arg
|
||||
{"A": "arg", "-v": false, "-q": true}
|
||||
|
||||
#
|
||||
# Test single dash
|
||||
#
|
||||
|
||||
r"""usage: prog [-]"""
|
||||
|
||||
$ prog -
|
||||
{"-": true}
|
||||
|
||||
$ prog
|
||||
{"-": false}
|
||||
|
||||
#
|
||||
# If argument is repeated, its value should always be a list
|
||||
#
|
||||
|
||||
r"""usage: prog [NAME [NAME ...]]"""
|
||||
|
||||
$ prog a b
|
||||
{"NAME": ["a", "b"]}
|
||||
|
||||
$ prog
|
||||
{"NAME": []}
|
||||
|
||||
#
|
||||
# Option's argument defaults to null/None
|
||||
#
|
||||
|
||||
r"""usage: prog [options]
|
||||
options:
|
||||
-a Add
|
||||
-m <msg> Message
|
||||
|
||||
"""
|
||||
$ prog -a
|
||||
{"-m": null, "-a": true}
|
||||
|
||||
#
|
||||
# Test options without description
|
||||
#
|
||||
|
||||
r"""usage: prog --hello"""
|
||||
$ prog --hello
|
||||
{"--hello": true}
|
||||
|
||||
r"""usage: prog [--hello=<world>]"""
|
||||
$ prog
|
||||
{"--hello": null}
|
||||
|
||||
$ prog --hello wrld
|
||||
{"--hello": "wrld"}
|
||||
|
||||
r"""usage: prog [-o]"""
|
||||
$ prog
|
||||
{"-o": false}
|
||||
|
||||
$ prog -o
|
||||
{"-o": true}
|
||||
|
||||
r"""usage: prog [-opr]"""
|
||||
$ prog -op
|
||||
{"-o": true, "-p": true, "-r": false}
|
||||
|
||||
r"""usage: git [-v | --verbose]"""
|
||||
$ prog -v
|
||||
{"-v": true, "--verbose": false}
|
||||
|
||||
r"""usage: git remote [-v | --verbose]"""
|
||||
$ prog remote -v
|
||||
{"remote": true, "-v": true, "--verbose": false}
|
||||
|
||||
#
|
||||
# Test empty usage pattern
|
||||
#
|
||||
|
||||
r"""usage: prog"""
|
||||
$ prog
|
||||
{}
|
||||
|
||||
r"""usage: prog
|
||||
prog <a> <b>
|
||||
"""
|
||||
$ prog 1 2
|
||||
{"<a>": "1", "<b>": "2"}
|
||||
|
||||
$ prog
|
||||
{"<a>": null, "<b>": null}
|
||||
|
||||
r"""usage: prog <a> <b>
|
||||
prog
|
||||
"""
|
||||
$ prog
|
||||
{"<a>": null, "<b>": null}
|
||||
|
||||
#
|
||||
# Option's argument should not capture default value from usage pattern
|
||||
#
|
||||
|
||||
r"""usage: prog [--file=<f>]"""
|
||||
$ prog
|
||||
{"--file": null}
|
||||
|
||||
r"""usage: prog [--file=<f>]
|
||||
|
||||
options: --file <a>
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--file": null}
|
||||
|
||||
r"""Usage: prog [-a <host:port>]
|
||||
|
||||
Options: -a, --address <host:port> TCP address [default: localhost:6283].
|
||||
|
||||
"""
|
||||
$ prog
|
||||
{"--address": "localhost:6283"}
|
||||
|
||||
#
|
||||
# If option with argument could be repeated,
|
||||
# its arguments should be accumulated into a list
|
||||
#
|
||||
|
||||
r"""usage: prog --long=<arg> ..."""
|
||||
|
||||
$ prog --long one
|
||||
{"--long": ["one"]}
|
||||
|
||||
$ prog --long one --long two
|
||||
{"--long": ["one", "two"]}
|
||||
|
||||
#
|
||||
# Test multiple elements repeated at once
|
||||
#
|
||||
|
||||
r"""usage: prog (go <direction> --speed=<km/h>)..."""
|
||||
$ prog go left --speed=5 go right --speed=9
|
||||
{"go": 2, "<direction>": ["left", "right"], "--speed": ["5", "9"]}
|
||||
|
||||
#
|
||||
# Required options should work with option shortcut
|
||||
#
|
||||
|
||||
r"""usage: prog [options] -a
|
||||
|
||||
options: -a
|
||||
|
||||
"""
|
||||
$ prog -a
|
||||
{"-a": true}
|
||||
|
||||
#
|
||||
# If option could be repeated its defaults should be split into a list
|
||||
#
|
||||
|
||||
r"""usage: prog [-o <o>]...
|
||||
|
||||
options: -o <o> [default: x]
|
||||
|
||||
"""
|
||||
$ prog -o this -o that
|
||||
{"-o": ["this", "that"]}
|
||||
|
||||
$ prog
|
||||
{"-o": ["x"]}
|
||||
|
||||
r"""usage: prog [-o <o>]...
|
||||
|
||||
options: -o <o> [default: x y]
|
||||
|
||||
"""
|
||||
$ prog -o this
|
||||
{"-o": ["this"]}
|
||||
|
||||
$ prog
|
||||
{"-o": ["x", "y"]}
|
||||
|
||||
#
|
||||
# Test stacked option's argument
|
||||
#
|
||||
|
||||
r"""usage: prog -pPATH
|
||||
|
||||
options: -p PATH
|
||||
|
||||
"""
|
||||
$ prog -pHOME
|
||||
{"-p": "HOME"}
|
||||
|
||||
#
|
||||
# Issue 56: Repeated mutually exclusive args give nested lists sometimes
|
||||
#
|
||||
|
||||
r"""Usage: foo (--xx=x|--yy=y)..."""
|
||||
$ prog --xx=1 --yy=2
|
||||
{"--xx": ["1"], "--yy": ["2"]}
|
||||
|
||||
#
|
||||
# POSIXly correct tokenization
|
||||
#
|
||||
|
||||
r"""usage: prog [<input file>]"""
|
||||
$ prog f.txt
|
||||
{"<input file>": "f.txt"}
|
||||
|
||||
r"""usage: prog [--input=<file name>]..."""
|
||||
$ prog --input a.txt --input=b.txt
|
||||
{"--input": ["a.txt", "b.txt"]}
|
||||
|
||||
#
|
||||
# Issue 85: `[options]` shourtcut with multiple subcommands
|
||||
#
|
||||
|
||||
r"""usage: prog good [options]
|
||||
prog fail [options]
|
||||
|
||||
options: --loglevel=N
|
||||
|
||||
"""
|
||||
$ prog fail --loglevel 5
|
||||
{"--loglevel": "5", "fail": true, "good": false}
|
||||
|
||||
#
|
||||
# Usage-section syntax
|
||||
#
|
||||
|
||||
r"""usage:prog --foo"""
|
||||
$ prog --foo
|
||||
{"--foo": true}
|
||||
|
||||
r"""PROGRAM USAGE: prog --foo"""
|
||||
$ prog --foo
|
||||
{"--foo": true}
|
||||
|
||||
r"""Usage: prog --foo
|
||||
prog --bar
|
||||
NOT PART OF SECTION"""
|
||||
$ prog --foo
|
||||
{"--foo": true, "--bar": false}
|
||||
|
||||
r"""Usage:
|
||||
prog --foo
|
||||
prog --bar
|
||||
|
||||
NOT PART OF SECTION"""
|
||||
$ prog --foo
|
||||
{"--foo": true, "--bar": false}
|
||||
|
||||
r"""Usage:
|
||||
prog --foo
|
||||
prog --bar
|
||||
NOT PART OF SECTION"""
|
||||
$ prog --foo
|
||||
{"--foo": true, "--bar": false}
|
||||
|
||||
#
|
||||
# Options-section syntax
|
||||
#
|
||||
|
||||
r"""Usage: prog [options]
|
||||
|
||||
global options: --foo
|
||||
local options: --baz
|
||||
--bar
|
||||
other options:
|
||||
--egg
|
||||
--spam
|
||||
-not-an-option-
|
||||
|
||||
"""
|
||||
$ prog --baz --egg
|
||||
{"--foo": false, "--baz": true, "--bar": false, "--egg": true, "--spam": false}
|
||||
126
vendor/github.com/docopt/docopt-go/token.go
generated
vendored
Normal file
126
vendor/github.com/docopt/docopt-go/token.go
generated
vendored
Normal file
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue