Fixed docopt dep version issue
This commit is contained in:
parent
da98e5421b
commit
3cc1e4ebfc
6
Gopkg.lock
generated
6
Gopkg.lock
generated
|
@ -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
|
||||
|
|
29
Gopkg.toml
29
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"
|
||||
|
|
7
vendor/github.com/docopt/docopt-go/.travis.yml
generated
vendored
7
vendor/github.com/docopt/docopt-go/.travis.yml
generated
vendored
|
@ -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 .
|
||||
|
||||
|
|
1
vendor/github.com/docopt/docopt-go/LICENSE
generated
vendored
1
vendor/github.com/docopt/docopt-go/LICENSE
generated
vendored
|
@ -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
|
||||
|
|
80
vendor/github.com/docopt/docopt-go/README.md
generated
vendored
80
vendor/github.com/docopt/docopt-go/README.md
generated
vendored
|
@ -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("<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
|
830
vendor/github.com/docopt/docopt-go/docopt.go
generated
vendored
830
vendor/github.com/docopt/docopt-go/docopt.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
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
|
||||
}
|
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…
Reference in New Issue
Block a user