mirror of
https://github.com/rumanzo/bt2qbt.git
synced 2024-11-22 10:22:38 +01:00
vendor update
This commit is contained in:
parent
7e57318c2e
commit
4002b2ad4e
44
vendor/github.com/jessevdk/go-flags/.travis.yml
generated
vendored
Normal file
44
vendor/github.com/jessevdk/go-flags/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
language: go
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
go:
|
||||
- 1.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
|
||||
install:
|
||||
# go-flags
|
||||
- go get -d -v ./...
|
||||
- go build -v ./...
|
||||
|
||||
# linting
|
||||
- go get github.com/golang/lint/golint
|
||||
|
||||
# code coverage
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/onsi/ginkgo/ginkgo
|
||||
- go get github.com/modocache/gover
|
||||
- if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi
|
||||
|
||||
script:
|
||||
# go-flags
|
||||
- $(exit $(gofmt -l . | wc -l))
|
||||
- go test -v ./...
|
||||
|
||||
# linting
|
||||
- go tool vet -all=true -v=true . || true
|
||||
- $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./...
|
||||
|
||||
# code coverage
|
||||
- $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/ginkgo -r -cover
|
||||
- $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/gover
|
||||
- if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi
|
||||
|
||||
env:
|
||||
# coveralls.io
|
||||
secure: "RCYbiB4P0RjQRIoUx/vG/AjP3mmYCbzOmr86DCww1Z88yNcy3hYr3Cq8rpPtYU5v0g7wTpu4adaKIcqRE9xknYGbqj3YWZiCoBP1/n4Z+9sHW3Dsd9D/GRGeHUus0laJUGARjWoCTvoEtOgTdGQDoX7mH+pUUY0FBltNYUdOiiU="
|
26
vendor/github.com/jessevdk/go-flags/LICENSE
generated
vendored
Normal file
26
vendor/github.com/jessevdk/go-flags/LICENSE
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
Copyright (c) 2012 Jesse van den Kieboom. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
134
vendor/github.com/jessevdk/go-flags/README.md
generated
vendored
Normal file
134
vendor/github.com/jessevdk/go-flags/README.md
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
go-flags: a go library for parsing command line arguments
|
||||
=========================================================
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/jessevdk/go-flags?status.png)](https://godoc.org/github.com/jessevdk/go-flags) [![Build Status](https://travis-ci.org/jessevdk/go-flags.svg?branch=master)](https://travis-ci.org/jessevdk/go-flags) [![Coverage Status](https://img.shields.io/coveralls/jessevdk/go-flags.svg)](https://coveralls.io/r/jessevdk/go-flags?branch=master)
|
||||
|
||||
This library provides similar functionality to the builtin flag library of
|
||||
go, but provides much more functionality and nicer formatting. From the
|
||||
documentation:
|
||||
|
||||
Package flags provides an extensive command line option parser.
|
||||
The flags package is similar in functionality to the go builtin flag package
|
||||
but provides more options and uses reflection to provide a convenient and
|
||||
succinct way of specifying command line options.
|
||||
|
||||
Supported features:
|
||||
* Options with short names (-v)
|
||||
* Options with long names (--verbose)
|
||||
* Options with and without arguments (bool v.s. other type)
|
||||
* Options with optional arguments and default values
|
||||
* Multiple option groups each containing a set of options
|
||||
* Generate and print well-formatted help message
|
||||
* Passing remaining command line arguments after -- (optional)
|
||||
* Ignoring unknown command line options (optional)
|
||||
* Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification
|
||||
* Supports multiple short options -aux
|
||||
* Supports all primitive go types (string, int{8..64}, uint{8..64}, float)
|
||||
* Supports same option multiple times (can store in slice or last option counts)
|
||||
* Supports maps
|
||||
* Supports function callbacks
|
||||
* Supports namespaces for (nested) option groups
|
||||
|
||||
The flags package uses structs, reflection and struct field tags
|
||||
to allow users to specify command line options. This results in very simple
|
||||
and concise specification of your application options. For example:
|
||||
|
||||
```go
|
||||
type Options struct {
|
||||
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
|
||||
}
|
||||
```
|
||||
|
||||
This specifies one option with a short name -v and a long name --verbose.
|
||||
When either -v or --verbose is found on the command line, a 'true' value
|
||||
will be appended to the Verbose field. e.g. when specifying -vvv, the
|
||||
resulting value of Verbose will be {[true, true, true]}.
|
||||
|
||||
Example:
|
||||
--------
|
||||
```go
|
||||
var opts struct {
|
||||
// Slice of bool will append 'true' each time the option
|
||||
// is encountered (can be set multiple times, like -vvv)
|
||||
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
|
||||
|
||||
// Example of automatic marshalling to desired type (uint)
|
||||
Offset uint `long:"offset" description:"Offset"`
|
||||
|
||||
// Example of a callback, called each time the option is found.
|
||||
Call func(string) `short:"c" description:"Call phone number"`
|
||||
|
||||
// Example of a required flag
|
||||
Name string `short:"n" long:"name" description:"A name" required:"true"`
|
||||
|
||||
// Example of a value name
|
||||
File string `short:"f" long:"file" description:"A file" value-name:"FILE"`
|
||||
|
||||
// Example of a pointer
|
||||
Ptr *int `short:"p" description:"A pointer to an integer"`
|
||||
|
||||
// Example of a slice of strings
|
||||
StringSlice []string `short:"s" description:"A slice of strings"`
|
||||
|
||||
// Example of a slice of pointers
|
||||
PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"`
|
||||
|
||||
// Example of a map
|
||||
IntMap map[string]int `long:"intmap" description:"A map from string to int"`
|
||||
}
|
||||
|
||||
// Callback which will invoke callto:<argument> to call a number.
|
||||
// Note that this works just on OS X (and probably only with
|
||||
// Skype) but it shows the idea.
|
||||
opts.Call = func(num string) {
|
||||
cmd := exec.Command("open", "callto:"+num)
|
||||
cmd.Start()
|
||||
cmd.Process.Release()
|
||||
}
|
||||
|
||||
// Make some fake arguments to parse.
|
||||
args := []string{
|
||||
"-vv",
|
||||
"--offset=5",
|
||||
"-n", "Me",
|
||||
"-p", "3",
|
||||
"-s", "hello",
|
||||
"-s", "world",
|
||||
"--ptrslice", "hello",
|
||||
"--ptrslice", "world",
|
||||
"--intmap", "a:1",
|
||||
"--intmap", "b:5",
|
||||
"arg1",
|
||||
"arg2",
|
||||
"arg3",
|
||||
}
|
||||
|
||||
// Parse flags from `args'. Note that here we use flags.ParseArgs for
|
||||
// the sake of making a working example. Normally, you would simply use
|
||||
// flags.Parse(&opts) which uses os.Args
|
||||
args, err := flags.ParseArgs(&opts, args)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Verbosity: %v\n", opts.Verbose)
|
||||
fmt.Printf("Offset: %d\n", opts.Offset)
|
||||
fmt.Printf("Name: %s\n", opts.Name)
|
||||
fmt.Printf("Ptr: %d\n", *opts.Ptr)
|
||||
fmt.Printf("StringSlice: %v\n", opts.StringSlice)
|
||||
fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1])
|
||||
fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"])
|
||||
fmt.Printf("Remaining args: %s\n", strings.Join(args, " "))
|
||||
|
||||
// Output: Verbosity: [true true]
|
||||
// Offset: 5
|
||||
// Name: Me
|
||||
// Ptr: 3
|
||||
// StringSlice: [hello world]
|
||||
// PtrSlice: [hello world]
|
||||
// IntMap: [a:1 b:5]
|
||||
// Remaining args: arg1 arg2 arg3
|
||||
```
|
||||
|
||||
More information can be found in the godocs: <http://godoc.org/github.com/jessevdk/go-flags>
|
27
vendor/github.com/jessevdk/go-flags/arg.go
generated
vendored
Normal file
27
vendor/github.com/jessevdk/go-flags/arg.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Arg represents a positional argument on the command line.
|
||||
type Arg struct {
|
||||
// The name of the positional argument (used in the help)
|
||||
Name string
|
||||
|
||||
// A description of the positional argument (used in the help)
|
||||
Description string
|
||||
|
||||
// The minimal number of required positional arguments
|
||||
Required int
|
||||
|
||||
// The maximum number of required positional arguments
|
||||
RequiredMaximum int
|
||||
|
||||
value reflect.Value
|
||||
tag multiTag
|
||||
}
|
||||
|
||||
func (a *Arg) isRemaining() bool {
|
||||
return a.value.Type().Kind() == reflect.Slice
|
||||
}
|
16
vendor/github.com/jessevdk/go-flags/check_crosscompile.sh
generated
vendored
Normal file
16
vendor/github.com/jessevdk/go-flags/check_crosscompile.sh
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo '# linux arm7'
|
||||
GOARM=7 GOARCH=arm GOOS=linux go build
|
||||
echo '# linux arm5'
|
||||
GOARM=5 GOARCH=arm GOOS=linux go build
|
||||
echo '# windows 386'
|
||||
GOARCH=386 GOOS=windows go build
|
||||
echo '# windows amd64'
|
||||
GOARCH=amd64 GOOS=windows go build
|
||||
echo '# darwin'
|
||||
GOARCH=amd64 GOOS=darwin go build
|
||||
echo '# freebsd'
|
||||
GOARCH=amd64 GOOS=freebsd go build
|
59
vendor/github.com/jessevdk/go-flags/closest.go
generated
vendored
Normal file
59
vendor/github.com/jessevdk/go-flags/closest.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
package flags
|
||||
|
||||
func levenshtein(s string, t string) int {
|
||||
if len(s) == 0 {
|
||||
return len(t)
|
||||
}
|
||||
|
||||
if len(t) == 0 {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
dists := make([][]int, len(s)+1)
|
||||
for i := range dists {
|
||||
dists[i] = make([]int, len(t)+1)
|
||||
dists[i][0] = i
|
||||
}
|
||||
|
||||
for j := range t {
|
||||
dists[0][j] = j
|
||||
}
|
||||
|
||||
for i, sc := range s {
|
||||
for j, tc := range t {
|
||||
if sc == tc {
|
||||
dists[i+1][j+1] = dists[i][j]
|
||||
} else {
|
||||
dists[i+1][j+1] = dists[i][j] + 1
|
||||
if dists[i+1][j] < dists[i+1][j+1] {
|
||||
dists[i+1][j+1] = dists[i+1][j] + 1
|
||||
}
|
||||
if dists[i][j+1] < dists[i+1][j+1] {
|
||||
dists[i+1][j+1] = dists[i][j+1] + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dists[len(s)][len(t)]
|
||||
}
|
||||
|
||||
func closestChoice(cmd string, choices []string) (string, int) {
|
||||
if len(choices) == 0 {
|
||||
return "", 0
|
||||
}
|
||||
|
||||
mincmd := -1
|
||||
mindist := -1
|
||||
|
||||
for i, c := range choices {
|
||||
l := levenshtein(cmd, c)
|
||||
|
||||
if mincmd < 0 || l < mindist {
|
||||
mindist = l
|
||||
mincmd = i
|
||||
}
|
||||
}
|
||||
|
||||
return choices[mincmd], mindist
|
||||
}
|
465
vendor/github.com/jessevdk/go-flags/command.go
generated
vendored
Normal file
465
vendor/github.com/jessevdk/go-flags/command.go
generated
vendored
Normal file
@ -0,0 +1,465 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Command represents an application command. Commands can be added to the
|
||||
// parser (which itself is a command) and are selected/executed when its name
|
||||
// is specified on the command line. The Command type embeds a Group and
|
||||
// therefore also carries a set of command specific options.
|
||||
type Command struct {
|
||||
// Embedded, see Group for more information
|
||||
*Group
|
||||
|
||||
// The name by which the command can be invoked
|
||||
Name string
|
||||
|
||||
// The active sub command (set by parsing) or nil
|
||||
Active *Command
|
||||
|
||||
// Whether subcommands are optional
|
||||
SubcommandsOptional bool
|
||||
|
||||
// Aliases for the command
|
||||
Aliases []string
|
||||
|
||||
// Whether positional arguments are required
|
||||
ArgsRequired bool
|
||||
|
||||
commands []*Command
|
||||
hasBuiltinHelpGroup bool
|
||||
args []*Arg
|
||||
}
|
||||
|
||||
// Commander is an interface which can be implemented by any command added in
|
||||
// the options. When implemented, the Execute method will be called for the last
|
||||
// specified (sub)command providing the remaining command line arguments.
|
||||
type Commander interface {
|
||||
// Execute will be called for the last active (sub)command. The
|
||||
// args argument contains the remaining command line arguments. The
|
||||
// error that Execute returns will be eventually passed out of the
|
||||
// Parse method of the Parser.
|
||||
Execute(args []string) error
|
||||
}
|
||||
|
||||
// Usage is an interface which can be implemented to show a custom usage string
|
||||
// in the help message shown for a command.
|
||||
type Usage interface {
|
||||
// Usage is called for commands to allow customized printing of command
|
||||
// usage in the generated help message.
|
||||
Usage() string
|
||||
}
|
||||
|
||||
type lookup struct {
|
||||
shortNames map[string]*Option
|
||||
longNames map[string]*Option
|
||||
|
||||
commands map[string]*Command
|
||||
}
|
||||
|
||||
// AddCommand adds a new command to the parser with the given name and data. The
|
||||
// data needs to be a pointer to a struct from which the fields indicate which
|
||||
// options are in the command. The provided data can implement the Command and
|
||||
// Usage interfaces.
|
||||
func (c *Command) AddCommand(command string, shortDescription string, longDescription string, data interface{}) (*Command, error) {
|
||||
cmd := newCommand(command, shortDescription, longDescription, data)
|
||||
|
||||
cmd.parent = c
|
||||
|
||||
if err := cmd.scan(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.commands = append(c.commands, cmd)
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// AddGroup adds a new group to the command with the given name and data. The
|
||||
// data needs to be a pointer to a struct from which the fields indicate which
|
||||
// options are in the group.
|
||||
func (c *Command) AddGroup(shortDescription string, longDescription string, data interface{}) (*Group, error) {
|
||||
group := newGroup(shortDescription, longDescription, data)
|
||||
|
||||
group.parent = c
|
||||
|
||||
if err := group.scanType(c.scanSubcommandHandler(group)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.groups = append(c.groups, group)
|
||||
return group, nil
|
||||
}
|
||||
|
||||
// Commands returns a list of subcommands of this command.
|
||||
func (c *Command) Commands() []*Command {
|
||||
return c.commands
|
||||
}
|
||||
|
||||
// Find locates the subcommand with the given name and returns it. If no such
|
||||
// command can be found Find will return nil.
|
||||
func (c *Command) Find(name string) *Command {
|
||||
for _, cc := range c.commands {
|
||||
if cc.match(name) {
|
||||
return cc
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindOptionByLongName finds an option that is part of the command, or any of
|
||||
// its parent commands, by matching its long name (including the option
|
||||
// namespace).
|
||||
func (c *Command) FindOptionByLongName(longName string) (option *Option) {
|
||||
for option == nil && c != nil {
|
||||
option = c.Group.FindOptionByLongName(longName)
|
||||
|
||||
c, _ = c.parent.(*Command)
|
||||
}
|
||||
|
||||
return option
|
||||
}
|
||||
|
||||
// FindOptionByShortName finds an option that is part of the command, or any of
|
||||
// its parent commands, by matching its long name (including the option
|
||||
// namespace).
|
||||
func (c *Command) FindOptionByShortName(shortName rune) (option *Option) {
|
||||
for option == nil && c != nil {
|
||||
option = c.Group.FindOptionByShortName(shortName)
|
||||
|
||||
c, _ = c.parent.(*Command)
|
||||
}
|
||||
|
||||
return option
|
||||
}
|
||||
|
||||
// Args returns a list of positional arguments associated with this command.
|
||||
func (c *Command) Args() []*Arg {
|
||||
ret := make([]*Arg, len(c.args))
|
||||
copy(ret, c.args)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func newCommand(name string, shortDescription string, longDescription string, data interface{}) *Command {
|
||||
return &Command{
|
||||
Group: newGroup(shortDescription, longDescription, data),
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Command) scanSubcommandHandler(parentg *Group) scanHandler {
|
||||
f := func(realval reflect.Value, sfield *reflect.StructField) (bool, error) {
|
||||
mtag := newMultiTag(string(sfield.Tag))
|
||||
|
||||
if err := mtag.Parse(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
positional := mtag.Get("positional-args")
|
||||
|
||||
if len(positional) != 0 {
|
||||
stype := realval.Type()
|
||||
|
||||
for i := 0; i < stype.NumField(); i++ {
|
||||
field := stype.Field(i)
|
||||
|
||||
m := newMultiTag((string(field.Tag)))
|
||||
|
||||
if err := m.Parse(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
name := m.Get("positional-arg-name")
|
||||
|
||||
if len(name) == 0 {
|
||||
name = field.Name
|
||||
}
|
||||
|
||||
required := -1
|
||||
requiredMaximum := -1
|
||||
|
||||
sreq := m.Get("required")
|
||||
|
||||
if sreq != "" {
|
||||
required = 1
|
||||
|
||||
rng := strings.SplitN(sreq, "-", 2)
|
||||
|
||||
if len(rng) > 1 {
|
||||
if preq, err := strconv.ParseInt(rng[0], 10, 32); err == nil {
|
||||
required = int(preq)
|
||||
}
|
||||
|
||||
if preq, err := strconv.ParseInt(rng[1], 10, 32); err == nil {
|
||||
requiredMaximum = int(preq)
|
||||
}
|
||||
} else {
|
||||
if preq, err := strconv.ParseInt(sreq, 10, 32); err == nil {
|
||||
required = int(preq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg := &Arg{
|
||||
Name: name,
|
||||
Description: m.Get("description"),
|
||||
Required: required,
|
||||
RequiredMaximum: requiredMaximum,
|
||||
|
||||
value: realval.Field(i),
|
||||
tag: m,
|
||||
}
|
||||
|
||||
c.args = append(c.args, arg)
|
||||
|
||||
if len(mtag.Get("required")) != 0 {
|
||||
c.ArgsRequired = true
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
subcommand := mtag.Get("command")
|
||||
|
||||
if len(subcommand) != 0 {
|
||||
var ptrval reflect.Value
|
||||
|
||||
if realval.Kind() == reflect.Ptr {
|
||||
ptrval = realval
|
||||
|
||||
if ptrval.IsNil() {
|
||||
ptrval.Set(reflect.New(ptrval.Type().Elem()))
|
||||
}
|
||||
} else {
|
||||
ptrval = realval.Addr()
|
||||
}
|
||||
|
||||
shortDescription := mtag.Get("description")
|
||||
longDescription := mtag.Get("long-description")
|
||||
subcommandsOptional := mtag.Get("subcommands-optional")
|
||||
aliases := mtag.GetMany("alias")
|
||||
|
||||
subc, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface())
|
||||
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
subc.Hidden = mtag.Get("hidden") != ""
|
||||
|
||||
if len(subcommandsOptional) > 0 {
|
||||
subc.SubcommandsOptional = true
|
||||
}
|
||||
|
||||
if len(aliases) > 0 {
|
||||
subc.Aliases = aliases
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return parentg.scanSubGroupHandler(realval, sfield)
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (c *Command) scan() error {
|
||||
return c.scanType(c.scanSubcommandHandler(c.Group))
|
||||
}
|
||||
|
||||
func (c *Command) eachOption(f func(*Command, *Group, *Option)) {
|
||||
c.eachCommand(func(c *Command) {
|
||||
c.eachGroup(func(g *Group) {
|
||||
for _, option := range g.options {
|
||||
f(c, g, option)
|
||||
}
|
||||
})
|
||||
}, true)
|
||||
}
|
||||
|
||||
func (c *Command) eachCommand(f func(*Command), recurse bool) {
|
||||
f(c)
|
||||
|
||||
for _, cc := range c.commands {
|
||||
if recurse {
|
||||
cc.eachCommand(f, true)
|
||||
} else {
|
||||
f(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Command) eachActiveGroup(f func(cc *Command, g *Group)) {
|
||||
c.eachGroup(func(g *Group) {
|
||||
f(c, g)
|
||||
})
|
||||
|
||||
if c.Active != nil {
|
||||
c.Active.eachActiveGroup(f)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Command) addHelpGroups(showHelp func() error) {
|
||||
if !c.hasBuiltinHelpGroup {
|
||||
c.addHelpGroup(showHelp)
|
||||
c.hasBuiltinHelpGroup = true
|
||||
}
|
||||
|
||||
for _, cc := range c.commands {
|
||||
cc.addHelpGroups(showHelp)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Command) makeLookup() lookup {
|
||||
ret := lookup{
|
||||
shortNames: make(map[string]*Option),
|
||||
longNames: make(map[string]*Option),
|
||||
commands: make(map[string]*Command),
|
||||
}
|
||||
|
||||
parent := c.parent
|
||||
|
||||
var parents []*Command
|
||||
|
||||
for parent != nil {
|
||||
if cmd, ok := parent.(*Command); ok {
|
||||
parents = append(parents, cmd)
|
||||
parent = cmd.parent
|
||||
} else {
|
||||
parent = nil
|
||||
}
|
||||
}
|
||||
|
||||
for i := len(parents) - 1; i >= 0; i-- {
|
||||
parents[i].fillLookup(&ret, true)
|
||||
}
|
||||
|
||||
c.fillLookup(&ret, false)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Command) fillLookup(ret *lookup, onlyOptions bool) {
|
||||
c.eachGroup(func(g *Group) {
|
||||
for _, option := range g.options {
|
||||
if option.ShortName != 0 {
|
||||
ret.shortNames[string(option.ShortName)] = option
|
||||
}
|
||||
|
||||
if len(option.LongName) > 0 {
|
||||
ret.longNames[option.LongNameWithNamespace()] = option
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if onlyOptions {
|
||||
return
|
||||
}
|
||||
|
||||
for _, subcommand := range c.commands {
|
||||
ret.commands[subcommand.Name] = subcommand
|
||||
|
||||
for _, a := range subcommand.Aliases {
|
||||
ret.commands[a] = subcommand
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Command) groupByName(name string) *Group {
|
||||
if grp := c.Group.groupByName(name); grp != nil {
|
||||
return grp
|
||||
}
|
||||
|
||||
for _, subc := range c.commands {
|
||||
prefix := subc.Name + "."
|
||||
|
||||
if strings.HasPrefix(name, prefix) {
|
||||
if grp := subc.groupByName(name[len(prefix):]); grp != nil {
|
||||
return grp
|
||||
}
|
||||
} else if name == subc.Name {
|
||||
return subc.Group
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type commandList []*Command
|
||||
|
||||
func (c commandList) Less(i, j int) bool {
|
||||
return c[i].Name < c[j].Name
|
||||
}
|
||||
|
||||
func (c commandList) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
|
||||
func (c commandList) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
||||
|
||||
func (c *Command) sortedVisibleCommands() []*Command {
|
||||
ret := commandList(c.visibleCommands())
|
||||
sort.Sort(ret)
|
||||
|
||||
return []*Command(ret)
|
||||
}
|
||||
|
||||
func (c *Command) visibleCommands() []*Command {
|
||||
ret := make([]*Command, 0, len(c.commands))
|
||||
|
||||
for _, cmd := range c.commands {
|
||||
if !cmd.Hidden {
|
||||
ret = append(ret, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Command) match(name string) bool {
|
||||
if c.Name == name {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, v := range c.Aliases {
|
||||
if v == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Command) hasCliOptions() bool {
|
||||
ret := false
|
||||
|
||||
c.eachGroup(func(g *Group) {
|
||||
if g.isBuiltinHelp {
|
||||
return
|
||||
}
|
||||
|
||||
for _, opt := range g.options {
|
||||
if opt.canCli() {
|
||||
ret = true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *Command) fillParseState(s *parseState) {
|
||||
s.positional = make([]*Arg, len(c.args))
|
||||
copy(s.positional, c.args)
|
||||
|
||||
s.lookup = c.makeLookup()
|
||||
s.command = c
|
||||
}
|
309
vendor/github.com/jessevdk/go-flags/completion.go
generated
vendored
Normal file
309
vendor/github.com/jessevdk/go-flags/completion.go
generated
vendored
Normal file
@ -0,0 +1,309 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Completion is a type containing information of a completion.
|
||||
type Completion struct {
|
||||
// The completed item
|
||||
Item string
|
||||
|
||||
// A description of the completed item (optional)
|
||||
Description string
|
||||
}
|
||||
|
||||
type completions []Completion
|
||||
|
||||
func (c completions) Len() int {
|
||||
return len(c)
|
||||
}
|
||||
|
||||
func (c completions) Less(i, j int) bool {
|
||||
return c[i].Item < c[j].Item
|
||||
}
|
||||
|
||||
func (c completions) Swap(i, j int) {
|
||||
c[i], c[j] = c[j], c[i]
|
||||
}
|
||||
|
||||
// Completer is an interface which can be implemented by types
|
||||
// to provide custom command line argument completion.
|
||||
type Completer interface {
|
||||
// Complete receives a prefix representing a (partial) value
|
||||
// for its type and should provide a list of possible valid
|
||||
// completions.
|
||||
Complete(match string) []Completion
|
||||
}
|
||||
|
||||
type completion struct {
|
||||
parser *Parser
|
||||
}
|
||||
|
||||
// Filename is a string alias which provides filename completion.
|
||||
type Filename string
|
||||
|
||||
func completionsWithoutDescriptions(items []string) []Completion {
|
||||
ret := make([]Completion, len(items))
|
||||
|
||||
for i, v := range items {
|
||||
ret[i].Item = v
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Complete returns a list of existing files with the given
|
||||
// prefix.
|
||||
func (f *Filename) Complete(match string) []Completion {
|
||||
ret, _ := filepath.Glob(match + "*")
|
||||
return completionsWithoutDescriptions(ret)
|
||||
}
|
||||
|
||||
func (c *completion) skipPositional(s *parseState, n int) {
|
||||
if n >= len(s.positional) {
|
||||
s.positional = nil
|
||||
} else {
|
||||
s.positional = s.positional[n:]
|
||||
}
|
||||
}
|
||||
|
||||
func (c *completion) completeOptionNames(s *parseState, prefix string, match string, short bool) []Completion {
|
||||
if short && len(match) != 0 {
|
||||
return []Completion{
|
||||
Completion{
|
||||
Item: prefix + match,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var results []Completion
|
||||
repeats := map[string]bool{}
|
||||
|
||||
for name, opt := range s.lookup.longNames {
|
||||
if strings.HasPrefix(name, match) && !opt.Hidden {
|
||||
results = append(results, Completion{
|
||||
Item: defaultLongOptDelimiter + name,
|
||||
Description: opt.Description,
|
||||
})
|
||||
|
||||
if short {
|
||||
repeats[string(opt.ShortName)] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if short {
|
||||
for name, opt := range s.lookup.shortNames {
|
||||
if _, exist := repeats[name]; !exist && strings.HasPrefix(name, match) && !opt.Hidden {
|
||||
results = append(results, Completion{
|
||||
Item: string(defaultShortOptDelimiter) + name,
|
||||
Description: opt.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func (c *completion) completeNamesForLongPrefix(s *parseState, prefix string, match string) []Completion {
|
||||
return c.completeOptionNames(s, prefix, match, false)
|
||||
}
|
||||
|
||||
func (c *completion) completeNamesForShortPrefix(s *parseState, prefix string, match string) []Completion {
|
||||
return c.completeOptionNames(s, prefix, match, true)
|
||||
}
|
||||
|
||||
func (c *completion) completeCommands(s *parseState, match string) []Completion {
|
||||
n := make([]Completion, 0, len(s.command.commands))
|
||||
|
||||
for _, cmd := range s.command.commands {
|
||||
if cmd.data != c && strings.HasPrefix(cmd.Name, match) {
|
||||
n = append(n, Completion{
|
||||
Item: cmd.Name,
|
||||
Description: cmd.ShortDescription,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (c *completion) completeValue(value reflect.Value, prefix string, match string) []Completion {
|
||||
if value.Kind() == reflect.Slice {
|
||||
value = reflect.New(value.Type().Elem())
|
||||
}
|
||||
i := value.Interface()
|
||||
|
||||
var ret []Completion
|
||||
|
||||
if cmp, ok := i.(Completer); ok {
|
||||
ret = cmp.Complete(match)
|
||||
} else if value.CanAddr() {
|
||||
if cmp, ok = value.Addr().Interface().(Completer); ok {
|
||||
ret = cmp.Complete(match)
|
||||
}
|
||||
}
|
||||
|
||||
for i, v := range ret {
|
||||
ret[i].Item = prefix + v.Item
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *completion) complete(args []string) []Completion {
|
||||
if len(args) == 0 {
|
||||
args = []string{""}
|
||||
}
|
||||
|
||||
s := &parseState{
|
||||
args: args,
|
||||
}
|
||||
|
||||
c.parser.fillParseState(s)
|
||||
|
||||
var opt *Option
|
||||
|
||||
for len(s.args) > 1 {
|
||||
arg := s.pop()
|
||||
|
||||
if (c.parser.Options&PassDoubleDash) != None && arg == "--" {
|
||||
opt = nil
|
||||
c.skipPositional(s, len(s.args)-1)
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if argumentIsOption(arg) {
|
||||
prefix, optname, islong := stripOptionPrefix(arg)
|
||||
optname, _, argument := splitOption(prefix, optname, islong)
|
||||
|
||||
if argument == nil {
|
||||
var o *Option
|
||||
canarg := true
|
||||
|
||||
if islong {
|
||||
o = s.lookup.longNames[optname]
|
||||
} else {
|
||||
for i, r := range optname {
|
||||
sname := string(r)
|
||||
o = s.lookup.shortNames[sname]
|
||||
|
||||
if o == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if i == 0 && o.canArgument() && len(optname) != len(sname) {
|
||||
canarg = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if o == nil && (c.parser.Options&PassAfterNonOption) != None {
|
||||
opt = nil
|
||||
c.skipPositional(s, len(s.args)-1)
|
||||
|
||||
break
|
||||
} else if o != nil && o.canArgument() && !o.OptionalArgument && canarg {
|
||||
if len(s.args) > 1 {
|
||||
s.pop()
|
||||
} else {
|
||||
opt = o
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(s.positional) > 0 {
|
||||
if !s.positional[0].isRemaining() {
|
||||
// Don't advance beyond a remaining positional arg (because
|
||||
// it consumes all subsequent args).
|
||||
s.positional = s.positional[1:]
|
||||
}
|
||||
} else if cmd, ok := s.lookup.commands[arg]; ok {
|
||||
cmd.fillParseState(s)
|
||||
}
|
||||
|
||||
opt = nil
|
||||
}
|
||||
}
|
||||
|
||||
lastarg := s.args[len(s.args)-1]
|
||||
var ret []Completion
|
||||
|
||||
if opt != nil {
|
||||
// Completion for the argument of 'opt'
|
||||
ret = c.completeValue(opt.value, "", lastarg)
|
||||
} else if argumentStartsOption(lastarg) {
|
||||
// Complete the option
|
||||
prefix, optname, islong := stripOptionPrefix(lastarg)
|
||||
optname, split, argument := splitOption(prefix, optname, islong)
|
||||
|
||||
if argument == nil && !islong {
|
||||
rname, n := utf8.DecodeRuneInString(optname)
|
||||
sname := string(rname)
|
||||
|
||||
if opt := s.lookup.shortNames[sname]; opt != nil && opt.canArgument() {
|
||||
ret = c.completeValue(opt.value, prefix+sname, optname[n:])
|
||||
} else {
|
||||
ret = c.completeNamesForShortPrefix(s, prefix, optname)
|
||||
}
|
||||
} else if argument != nil {
|
||||
if islong {
|
||||
opt = s.lookup.longNames[optname]
|
||||
} else {
|
||||
opt = s.lookup.shortNames[optname]
|
||||
}
|
||||
|
||||
if opt != nil {
|
||||
ret = c.completeValue(opt.value, prefix+optname+split, *argument)
|
||||
}
|
||||
} else if islong {
|
||||
ret = c.completeNamesForLongPrefix(s, prefix, optname)
|
||||
} else {
|
||||
ret = c.completeNamesForShortPrefix(s, prefix, optname)
|
||||
}
|
||||
} else if len(s.positional) > 0 {
|
||||
// Complete for positional argument
|
||||
ret = c.completeValue(s.positional[0].value, "", lastarg)
|
||||
} else if len(s.command.commands) > 0 {
|
||||
// Complete for command
|
||||
ret = c.completeCommands(s, lastarg)
|
||||
}
|
||||
|
||||
sort.Sort(completions(ret))
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *completion) print(items []Completion, showDescriptions bool) {
|
||||
if showDescriptions && len(items) > 1 {
|
||||
maxl := 0
|
||||
|
||||
for _, v := range items {
|
||||
if len(v.Item) > maxl {
|
||||
maxl = len(v.Item)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range items {
|
||||
fmt.Printf("%s", v.Item)
|
||||
|
||||
if len(v.Description) > 0 {
|
||||
fmt.Printf("%s # %s", strings.Repeat(" ", maxl-len(v.Item)), v.Description)
|
||||
}
|
||||
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
} else {
|
||||
for _, v := range items {
|
||||
fmt.Println(v.Item)
|
||||
}
|
||||
}
|
||||
}
|
348
vendor/github.com/jessevdk/go-flags/convert.go
generated
vendored
Normal file
348
vendor/github.com/jessevdk/go-flags/convert.go
generated
vendored
Normal file
@ -0,0 +1,348 @@
|
||||
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Marshaler is the interface implemented by types that can marshal themselves
|
||||
// to a string representation of the flag.
|
||||
type Marshaler interface {
|
||||
// MarshalFlag marshals a flag value to its string representation.
|
||||
MarshalFlag() (string, error)
|
||||
}
|
||||
|
||||
// Unmarshaler is the interface implemented by types that can unmarshal a flag
|
||||
// argument to themselves. The provided value is directly passed from the
|
||||
// command line.
|
||||
type Unmarshaler interface {
|
||||
// UnmarshalFlag unmarshals a string value representation to the flag
|
||||
// value (which therefore needs to be a pointer receiver).
|
||||
UnmarshalFlag(value string) error
|
||||
}
|
||||
|
||||
func getBase(options multiTag, base int) (int, error) {
|
||||
sbase := options.Get("base")
|
||||
|
||||
var err error
|
||||
var ivbase int64
|
||||
|
||||
if sbase != "" {
|
||||
ivbase, err = strconv.ParseInt(sbase, 10, 32)
|
||||
base = int(ivbase)
|
||||
}
|
||||
|
||||
return base, err
|
||||
}
|
||||
|
||||
func convertMarshal(val reflect.Value) (bool, string, error) {
|
||||
// Check first for the Marshaler interface
|
||||
if val.Type().NumMethod() > 0 && val.CanInterface() {
|
||||
if marshaler, ok := val.Interface().(Marshaler); ok {
|
||||
ret, err := marshaler.MarshalFlag()
|
||||
return true, ret, err
|
||||
}
|
||||
}
|
||||
|
||||
return false, "", nil
|
||||
}
|
||||
|
||||
func convertToString(val reflect.Value, options multiTag) (string, error) {
|
||||
if ok, ret, err := convertMarshal(val); ok {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
tp := val.Type()
|
||||
|
||||
// Support for time.Duration
|
||||
if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() {
|
||||
stringer := val.Interface().(fmt.Stringer)
|
||||
return stringer.String(), nil
|
||||
}
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.String:
|
||||
return val.String(), nil
|
||||
case reflect.Bool:
|
||||
if val.Bool() {
|
||||
return "true", nil
|
||||
}
|
||||
|
||||
return "false", nil
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
base, err := getBase(options, 10)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strconv.FormatInt(val.Int(), base), nil
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
base, err := getBase(options, 10)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strconv.FormatUint(val.Uint(), base), nil
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return strconv.FormatFloat(val.Float(), 'g', -1, tp.Bits()), nil
|
||||
case reflect.Slice:
|
||||
if val.Len() == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
ret := "["
|
||||
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
if i != 0 {
|
||||
ret += ", "
|
||||
}
|
||||
|
||||
item, err := convertToString(val.Index(i), options)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ret += item
|
||||
}
|
||||
|
||||
return ret + "]", nil
|
||||
case reflect.Map:
|
||||
ret := "{"
|
||||
|
||||
for i, key := range val.MapKeys() {
|
||||
if i != 0 {
|
||||
ret += ", "
|
||||
}
|
||||
|
||||
keyitem, err := convertToString(key, options)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
item, err := convertToString(val.MapIndex(key), options)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ret += keyitem + ":" + item
|
||||
}
|
||||
|
||||
return ret + "}", nil
|
||||
case reflect.Ptr:
|
||||
return convertToString(reflect.Indirect(val), options)
|
||||
case reflect.Interface:
|
||||
if !val.IsNil() {
|
||||
return convertToString(val.Elem(), options)
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func convertUnmarshal(val string, retval reflect.Value) (bool, error) {
|
||||
if retval.Type().NumMethod() > 0 && retval.CanInterface() {
|
||||
if unmarshaler, ok := retval.Interface().(Unmarshaler); ok {
|
||||
if retval.IsNil() {
|
||||
retval.Set(reflect.New(retval.Type().Elem()))
|
||||
|
||||
// Re-assign from the new value
|
||||
unmarshaler = retval.Interface().(Unmarshaler)
|
||||
}
|
||||
|
||||
return true, unmarshaler.UnmarshalFlag(val)
|
||||
}
|
||||
}
|
||||
|
||||
if retval.Type().Kind() != reflect.Ptr && retval.CanAddr() {
|
||||
return convertUnmarshal(val, retval.Addr())
|
||||
}
|
||||
|
||||
if retval.Type().Kind() == reflect.Interface && !retval.IsNil() {
|
||||
return convertUnmarshal(val, retval.Elem())
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func convert(val string, retval reflect.Value, options multiTag) error {
|
||||
if ok, err := convertUnmarshal(val, retval); ok {
|
||||
return err
|
||||
}
|
||||
|
||||
tp := retval.Type()
|
||||
|
||||
// Support for time.Duration
|
||||
if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() {
|
||||
parsed, err := time.ParseDuration(val)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval.SetInt(int64(parsed))
|
||||
return nil
|
||||
}
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.String:
|
||||
retval.SetString(val)
|
||||
case reflect.Bool:
|
||||
if val == "" {
|
||||
retval.SetBool(true)
|
||||
} else {
|
||||
b, err := strconv.ParseBool(val)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval.SetBool(b)
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
base, err := getBase(options, 10)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsed, err := strconv.ParseInt(val, base, tp.Bits())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval.SetInt(parsed)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
base, err := getBase(options, 10)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parsed, err := strconv.ParseUint(val, base, tp.Bits())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval.SetUint(parsed)
|
||||
case reflect.Float32, reflect.Float64:
|
||||
parsed, err := strconv.ParseFloat(val, tp.Bits())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval.SetFloat(parsed)
|
||||
case reflect.Slice:
|
||||
elemtp := tp.Elem()
|
||||
|
||||
elemvalptr := reflect.New(elemtp)
|
||||
elemval := reflect.Indirect(elemvalptr)
|
||||
|
||||
if err := convert(val, elemval, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval.Set(reflect.Append(retval, elemval))
|
||||
case reflect.Map:
|
||||
parts := strings.SplitN(val, ":", 2)
|
||||
|
||||
key := parts[0]
|
||||
var value string
|
||||
|
||||
if len(parts) == 2 {
|
||||
value = parts[1]
|
||||
}
|
||||
|
||||
keytp := tp.Key()
|
||||
keyval := reflect.New(keytp)
|
||||
|
||||
if err := convert(key, keyval, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valuetp := tp.Elem()
|
||||
valueval := reflect.New(valuetp)
|
||||
|
||||
if err := convert(value, valueval, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if retval.IsNil() {
|
||||
retval.Set(reflect.MakeMap(tp))
|
||||
}
|
||||
|
||||
retval.SetMapIndex(reflect.Indirect(keyval), reflect.Indirect(valueval))
|
||||
case reflect.Ptr:
|
||||
if retval.IsNil() {
|
||||
retval.Set(reflect.New(retval.Type().Elem()))
|
||||
}
|
||||
|
||||
return convert(val, reflect.Indirect(retval), options)
|
||||
case reflect.Interface:
|
||||
if !retval.IsNil() {
|
||||
return convert(val, retval.Elem(), options)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func isPrint(s string) bool {
|
||||
for _, c := range s {
|
||||
if !strconv.IsPrint(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func quoteIfNeeded(s string) string {
|
||||
if !isPrint(s) {
|
||||
return strconv.Quote(s)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func quoteIfNeededV(s []string) []string {
|
||||
ret := make([]string, len(s))
|
||||
|
||||
for i, v := range s {
|
||||
ret[i] = quoteIfNeeded(v)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func quoteV(s []string) []string {
|
||||
ret := make([]string, len(s))
|
||||
|
||||
for i, v := range s {
|
||||
ret[i] = strconv.Quote(v)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func unquoteIfPossible(s string) (string, error) {
|
||||
if len(s) == 0 || s[0] != '"' {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
return strconv.Unquote(s)
|
||||
}
|
134
vendor/github.com/jessevdk/go-flags/error.go
generated
vendored
Normal file
134
vendor/github.com/jessevdk/go-flags/error.go
generated
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrorType represents the type of error.
|
||||
type ErrorType uint
|
||||
|
||||
const (
|
||||
// ErrUnknown indicates a generic error.
|
||||
ErrUnknown ErrorType = iota
|
||||
|
||||
// ErrExpectedArgument indicates that an argument was expected.
|
||||
ErrExpectedArgument
|
||||
|
||||
// ErrUnknownFlag indicates an unknown flag.
|
||||
ErrUnknownFlag
|
||||
|
||||
// ErrUnknownGroup indicates an unknown group.
|
||||
ErrUnknownGroup
|
||||
|
||||
// ErrMarshal indicates a marshalling error while converting values.
|
||||
ErrMarshal
|
||||
|
||||
// ErrHelp indicates that the built-in help was shown (the error
|
||||
// contains the help message).
|
||||
ErrHelp
|
||||
|
||||
// ErrNoArgumentForBool indicates that an argument was given for a
|
||||
// boolean flag (which don't not take any arguments).
|
||||
ErrNoArgumentForBool
|
||||
|
||||
// ErrRequired indicates that a required flag was not provided.
|
||||
ErrRequired
|
||||
|
||||
// ErrShortNameTooLong indicates that a short flag name was specified,
|
||||
// longer than one character.
|
||||
ErrShortNameTooLong
|
||||
|
||||
// ErrDuplicatedFlag indicates that a short or long flag has been
|
||||
// defined more than once
|
||||
ErrDuplicatedFlag
|
||||
|
||||
// ErrTag indicates an error while parsing flag tags.
|
||||
ErrTag
|
||||
|
||||
// ErrCommandRequired indicates that a command was required but not
|
||||
// specified
|
||||
ErrCommandRequired
|
||||
|
||||
// ErrUnknownCommand indicates that an unknown command was specified.
|
||||
ErrUnknownCommand
|
||||
|
||||
// ErrInvalidChoice indicates an invalid option value which only allows
|
||||
// a certain number of choices.
|
||||
ErrInvalidChoice
|
||||
|
||||
// ErrInvalidTag indicates an invalid tag or invalid use of an existing tag
|
||||
ErrInvalidTag
|
||||
)
|
||||
|
||||
func (e ErrorType) String() string {
|
||||
switch e {
|
||||
case ErrUnknown:
|
||||
return "unknown"
|
||||
case ErrExpectedArgument:
|
||||
return "expected argument"
|
||||
case ErrUnknownFlag:
|
||||
return "unknown flag"
|
||||
case ErrUnknownGroup:
|
||||
return "unknown group"
|
||||
case ErrMarshal:
|
||||
return "marshal"
|
||||
case ErrHelp:
|
||||
return "help"
|
||||
case ErrNoArgumentForBool:
|
||||
return "no argument for bool"
|
||||
case ErrRequired:
|
||||
return "required"
|
||||
case ErrShortNameTooLong:
|
||||
return "short name too long"
|
||||
case ErrDuplicatedFlag:
|
||||
return "duplicated flag"
|
||||
case ErrTag:
|
||||
return "tag"
|
||||
case ErrCommandRequired:
|
||||
return "command required"
|
||||
case ErrUnknownCommand:
|
||||
return "unknown command"
|
||||
case ErrInvalidChoice:
|
||||
return "invalid choice"
|
||||
case ErrInvalidTag:
|
||||
return "invalid tag"
|
||||
}
|
||||
|
||||
return "unrecognized error type"
|
||||
}
|
||||
|
||||
// Error represents a parser error. The error returned from Parse is of this
|
||||
// type. The error contains both a Type and Message.
|
||||
type Error struct {
|
||||
// The type of error
|
||||
Type ErrorType
|
||||
|
||||
// The error message
|
||||
Message string
|
||||
}
|
||||
|
||||
// Error returns the error's message
|
||||
func (e *Error) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func newError(tp ErrorType, message string) *Error {
|
||||
return &Error{
|
||||
Type: tp,
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
func newErrorf(tp ErrorType, format string, args ...interface{}) *Error {
|
||||
return newError(tp, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func wrapError(err error) *Error {
|
||||
ret, ok := err.(*Error)
|
||||
|
||||
if !ok {
|
||||
return newError(ErrUnknown, err.Error())
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
258
vendor/github.com/jessevdk/go-flags/flags.go
generated
vendored
Normal file
258
vendor/github.com/jessevdk/go-flags/flags.go
generated
vendored
Normal file
@ -0,0 +1,258 @@
|
||||
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package flags provides an extensive command line option parser.
|
||||
The flags package is similar in functionality to the go built-in flag package
|
||||
but provides more options and uses reflection to provide a convenient and
|
||||
succinct way of specifying command line options.
|
||||
|
||||
|
||||
Supported features
|
||||
|
||||
The following features are supported in go-flags:
|
||||
|
||||
Options with short names (-v)
|
||||
Options with long names (--verbose)
|
||||
Options with and without arguments (bool v.s. other type)
|
||||
Options with optional arguments and default values
|
||||
Option default values from ENVIRONMENT_VARIABLES, including slice and map values
|
||||
Multiple option groups each containing a set of options
|
||||
Generate and print well-formatted help message
|
||||
Passing remaining command line arguments after -- (optional)
|
||||
Ignoring unknown command line options (optional)
|
||||
Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification
|
||||
Supports multiple short options -aux
|
||||
Supports all primitive go types (string, int{8..64}, uint{8..64}, float)
|
||||
Supports same option multiple times (can store in slice or last option counts)
|
||||
Supports maps
|
||||
Supports function callbacks
|
||||
Supports namespaces for (nested) option groups
|
||||
|
||||
Additional features specific to Windows:
|
||||
Options with short names (/v)
|
||||
Options with long names (/verbose)
|
||||
Windows-style options with arguments use a colon as the delimiter
|
||||
Modify generated help message with Windows-style / options
|
||||
Windows style options can be disabled at build time using the "forceposix"
|
||||
build tag
|
||||
|
||||
|
||||
Basic usage
|
||||
|
||||
The flags package uses structs, reflection and struct field tags
|
||||
to allow users to specify command line options. This results in very simple
|
||||
and concise specification of your application options. For example:
|
||||
|
||||
type Options struct {
|
||||
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
|
||||
}
|
||||
|
||||
This specifies one option with a short name -v and a long name --verbose.
|
||||
When either -v or --verbose is found on the command line, a 'true' value
|
||||
will be appended to the Verbose field. e.g. when specifying -vvv, the
|
||||
resulting value of Verbose will be {[true, true, true]}.
|
||||
|
||||
Slice options work exactly the same as primitive type options, except that
|
||||
whenever the option is encountered, a value is appended to the slice.
|
||||
|
||||
Map options from string to primitive type are also supported. On the command
|
||||
line, you specify the value for such an option as key:value. For example
|
||||
|
||||
type Options struct {
|
||||
AuthorInfo string[string] `short:"a"`
|
||||
}
|
||||
|
||||
Then, the AuthorInfo map can be filled with something like
|
||||
-a name:Jesse -a "surname:van den Kieboom".
|
||||
|
||||
Finally, for full control over the conversion between command line argument
|
||||
values and options, user defined types can choose to implement the Marshaler
|
||||
and Unmarshaler interfaces.
|
||||
|
||||
|
||||
Available field tags
|
||||
|
||||
The following is a list of tags for struct fields supported by go-flags:
|
||||
|
||||
short: the short name of the option (single character)
|
||||
long: the long name of the option
|
||||
required: if non empty, makes the option required to appear on the command
|
||||
line. If a required option is not present, the parser will
|
||||
return ErrRequired (optional)
|
||||
description: the description of the option (optional)
|
||||
long-description: the long description of the option. Currently only
|
||||
displayed in generated man pages (optional)
|
||||
no-flag: if non-empty, this field is ignored as an option (optional)
|
||||
|
||||
optional: if non-empty, makes the argument of the option optional. When an
|
||||
argument is optional it can only be specified using
|
||||
--option=argument (optional)
|
||||
optional-value: the value of an optional option when the option occurs
|
||||
without an argument. This tag can be specified multiple
|
||||
times in the case of maps or slices (optional)
|
||||
default: the default value of an option. This tag can be specified
|
||||
multiple times in the case of slices or maps (optional)
|
||||
default-mask: when specified, this value will be displayed in the help
|
||||
instead of the actual default value. This is useful
|
||||
mostly for hiding otherwise sensitive information from
|
||||
showing up in the help. If default-mask takes the special
|
||||
value "-", then no default value will be shown at all
|
||||
(optional)
|
||||
env: the default value of the option is overridden from the
|
||||
specified environment variable, if one has been defined.
|
||||
(optional)
|
||||
env-delim: the 'env' default value from environment is split into
|
||||
multiple values with the given delimiter string, use with
|
||||
slices and maps (optional)
|
||||
value-name: the name of the argument value (to be shown in the help)
|
||||
(optional)
|
||||
choice: limits the values for an option to a set of values.
|
||||
This tag can be specified multiple times (optional)
|
||||
hidden: if non-empty, the option is not visible in the help or man page.
|
||||
|
||||
base: a base (radix) used to convert strings to integer values, the
|
||||
default base is 10 (i.e. decimal) (optional)
|
||||
|
||||
ini-name: the explicit ini option name (optional)
|
||||
no-ini: if non-empty this field is ignored as an ini option
|
||||
(optional)
|
||||
|
||||
group: when specified on a struct field, makes the struct
|
||||
field a separate group with the given name (optional)
|
||||
namespace: when specified on a group struct field, the namespace
|
||||
gets prepended to every option's long name and
|
||||
subgroup's namespace of this group, separated by
|
||||
the parser's namespace delimiter (optional)
|
||||
command: when specified on a struct field, makes the struct
|
||||
field a (sub)command with the given name (optional)
|
||||
subcommands-optional: when specified on a command struct field, makes
|
||||
any subcommands of that command optional (optional)
|
||||
alias: when specified on a command struct field, adds the
|
||||
specified name as an alias for the command. Can be
|
||||
be specified multiple times to add more than one
|
||||
alias (optional)
|
||||
positional-args: when specified on a field with a struct type,
|
||||
uses the fields of that struct to parse remaining
|
||||
positional command line arguments into (in order
|
||||
of the fields). If a field has a slice type,
|
||||
then all remaining arguments will be added to it.
|
||||
Positional arguments are optional by default,
|
||||
unless the "required" tag is specified together
|
||||
with the "positional-args" tag. The "required" tag
|
||||
can also be set on the individual rest argument
|
||||
fields, to require only the first N positional
|
||||
arguments. If the "required" tag is set on the
|
||||
rest arguments slice, then its value determines
|
||||
the minimum amount of rest arguments that needs to
|
||||
be provided (e.g. `required:"2"`) (optional)
|
||||
positional-arg-name: used on a field in a positional argument struct; name
|
||||
of the positional argument placeholder to be shown in
|
||||
the help (optional)
|
||||
|
||||
Either the `short:` tag or the `long:` must be specified to make the field eligible as an
|
||||
option.
|
||||
|
||||
|
||||
Option groups
|
||||
|
||||
Option groups are a simple way to semantically separate your options. All
|
||||
options in a particular group are shown together in the help under the name
|
||||
of the group. Namespaces can be used to specify option long names more
|
||||
precisely and emphasize the options affiliation to their group.
|
||||
|
||||
There are currently three ways to specify option groups.
|
||||
|
||||
1. Use NewNamedParser specifying the various option groups.
|
||||
2. Use AddGroup to add a group to an existing parser.
|
||||
3. Add a struct field to the top-level options annotated with the
|
||||
group:"group-name" tag.
|
||||
|
||||
|
||||
|
||||
Commands
|
||||
|
||||
The flags package also has basic support for commands. Commands are often
|
||||
used in monolithic applications that support various commands or actions.
|
||||
Take git for example, all of the add, commit, checkout, etc. are called
|
||||
commands. Using commands you can easily separate multiple functions of your
|
||||
application.
|
||||
|
||||
There are currently two ways to specify a command.
|
||||
|
||||
1. Use AddCommand on an existing parser.
|
||||
2. Add a struct field to your options struct annotated with the
|
||||
command:"command-name" tag.
|
||||
|
||||
The most common, idiomatic way to implement commands is to define a global
|
||||
parser instance and implement each command in a separate file. These
|
||||
command files should define a go init function which calls AddCommand on
|
||||
the global parser.
|
||||
|
||||
When parsing ends and there is an active command and that command implements
|
||||
the Commander interface, then its Execute method will be run with the
|
||||
remaining command line arguments.
|
||||
|
||||
Command structs can have options which become valid to parse after the
|
||||
command has been specified on the command line, in addition to the options
|
||||
of all the parent commands. I.e. considering a -v flag on the parser and an
|
||||
add command, the following are equivalent:
|
||||
|
||||
./app -v add
|
||||
./app add -v
|
||||
|
||||
However, if the -v flag is defined on the add command, then the first of
|
||||
the two examples above would fail since the -v flag is not defined before
|
||||
the add command.
|
||||
|
||||
|
||||
Completion
|
||||
|
||||
go-flags has builtin support to provide bash completion of flags, commands
|
||||
and argument values. To use completion, the binary which uses go-flags
|
||||
can be invoked in a special environment to list completion of the current
|
||||
command line argument. It should be noted that this `executes` your application,
|
||||
and it is up to the user to make sure there are no negative side effects (for
|
||||
example from init functions).
|
||||
|
||||
Setting the environment variable `GO_FLAGS_COMPLETION=1` enables completion
|
||||
by replacing the argument parsing routine with the completion routine which
|
||||
outputs completions for the passed arguments. The basic invocation to
|
||||
complete a set of arguments is therefore:
|
||||
|
||||
GO_FLAGS_COMPLETION=1 ./completion-example arg1 arg2 arg3
|
||||
|
||||
where `completion-example` is the binary, `arg1` and `arg2` are
|
||||
the current arguments, and `arg3` (the last argument) is the argument
|
||||
to be completed. If the GO_FLAGS_COMPLETION is set to "verbose", then
|
||||
descriptions of possible completion items will also be shown, if there
|
||||
are more than 1 completion items.
|
||||
|
||||
To use this with bash completion, a simple file can be written which
|
||||
calls the binary which supports go-flags completion:
|
||||
|
||||
_completion_example() {
|
||||
# All arguments except the first one
|
||||
args=("${COMP_WORDS[@]:1:$COMP_CWORD}")
|
||||
|
||||
# Only split on newlines
|
||||
local IFS=$'\n'
|
||||
|
||||
# Call completion (note that the first element of COMP_WORDS is
|
||||
# the executable itself)
|
||||
COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}"))
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -F _completion_example completion-example
|
||||
|
||||
Completion requires the parser option PassDoubleDash and is therefore enforced if the environment variable GO_FLAGS_COMPLETION is set.
|
||||
|
||||
Customized completion for argument values is supported by implementing
|
||||
the flags.Completer interface for the argument value type. An example
|
||||
of a type which does so is the flags.Filename type, an alias of string
|
||||
allowing simple filename completion. A slice or array argument value
|
||||
whose element type implements flags.Completer will also be completed.
|
||||
*/
|
||||
package flags
|
406
vendor/github.com/jessevdk/go-flags/group.go
generated
vendored
Normal file
406
vendor/github.com/jessevdk/go-flags/group.go
generated
vendored
Normal file
@ -0,0 +1,406 @@
|
||||
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// ErrNotPointerToStruct indicates that a provided data container is not
|
||||
// a pointer to a struct. Only pointers to structs are valid data containers
|
||||
// for options.
|
||||
var ErrNotPointerToStruct = errors.New("provided data is not a pointer to struct")
|
||||
|
||||
// Group represents an option group. Option groups can be used to logically
|
||||
// group options together under a description. Groups are only used to provide
|
||||
// more structure to options both for the user (as displayed in the help message)
|
||||
// and for you, since groups can be nested.
|
||||
type Group struct {
|
||||
// A short description of the group. The
|
||||
// short description is primarily used in the built-in generated help
|
||||
// message
|
||||
ShortDescription string
|
||||
|
||||
// A long description of the group. The long
|
||||
// description is primarily used to present information on commands
|
||||
// (Command embeds Group) in the built-in generated help and man pages.
|
||||
LongDescription string
|
||||
|
||||
// The namespace of the group
|
||||
Namespace string
|
||||
|
||||
// If true, the group is not displayed in the help or man page
|
||||
Hidden bool
|
||||
|
||||
// The parent of the group or nil if it has no parent
|
||||
parent interface{}
|
||||
|
||||
// All the options in the group
|
||||
options []*Option
|
||||
|
||||
// All the subgroups
|
||||
groups []*Group
|
||||
|
||||
// Whether the group represents the built-in help group
|
||||
isBuiltinHelp bool
|
||||
|
||||
data interface{}
|
||||
}
|
||||
|
||||
type scanHandler func(reflect.Value, *reflect.StructField) (bool, error)
|
||||
|
||||
// AddGroup adds a new group to the command with the given name and data. The
|
||||
// data needs to be a pointer to a struct from which the fields indicate which
|
||||
// options are in the group.
|
||||
func (g *Group) AddGroup(shortDescription string, longDescription string, data interface{}) (*Group, error) {
|
||||
group := newGroup(shortDescription, longDescription, data)
|
||||
|
||||
group.parent = g
|
||||
|
||||
if err := group.scan(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g.groups = append(g.groups, group)
|
||||
return group, nil
|
||||
}
|
||||
|
||||
// Groups returns the list of groups embedded in this group.
|
||||
func (g *Group) Groups() []*Group {
|
||||
return g.groups
|
||||
}
|
||||
|
||||
// Options returns the list of options in this group.
|
||||
func (g *Group) Options() []*Option {
|
||||
return g.options
|
||||
}
|
||||
|
||||
// Find locates the subgroup with the given short description and returns it.
|
||||
// If no such group can be found Find will return nil. Note that the description
|
||||
// is matched case insensitively.
|
||||
func (g *Group) Find(shortDescription string) *Group {
|
||||
lshortDescription := strings.ToLower(shortDescription)
|
||||
|
||||
var ret *Group
|
||||
|
||||
g.eachGroup(func(gg *Group) {
|
||||
if gg != g && strings.ToLower(gg.ShortDescription) == lshortDescription {
|
||||
ret = gg
|
||||
}
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (g *Group) findOption(matcher func(*Option) bool) (option *Option) {
|
||||
g.eachGroup(func(g *Group) {
|
||||
for _, opt := range g.options {
|
||||
if option == nil && matcher(opt) {
|
||||
option = opt
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return option
|
||||
}
|
||||
|
||||
// FindOptionByLongName finds an option that is part of the group, or any of its
|
||||
// subgroups, by matching its long name (including the option namespace).
|
||||
func (g *Group) FindOptionByLongName(longName string) *Option {
|
||||
return g.findOption(func(option *Option) bool {
|
||||
return option.LongNameWithNamespace() == longName
|
||||
})
|
||||
}
|
||||
|
||||
// FindOptionByShortName finds an option that is part of the group, or any of
|
||||
// its subgroups, by matching its short name.
|
||||
func (g *Group) FindOptionByShortName(shortName rune) *Option {
|
||||
return g.findOption(func(option *Option) bool {
|
||||
return option.ShortName == shortName
|
||||
})
|
||||
}
|
||||
|
||||
func newGroup(shortDescription string, longDescription string, data interface{}) *Group {
|
||||
return &Group{
|
||||
ShortDescription: shortDescription,
|
||||
LongDescription: longDescription,
|
||||
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Group) optionByName(name string, namematch func(*Option, string) bool) *Option {
|
||||
prio := 0
|
||||
var retopt *Option
|
||||
|
||||
g.eachGroup(func(g *Group) {
|
||||
for _, opt := range g.options {
|
||||
if namematch != nil && namematch(opt, name) && prio < 4 {
|
||||
retopt = opt
|
||||
prio = 4
|
||||
}
|
||||
|
||||
if name == opt.field.Name && prio < 3 {
|
||||
retopt = opt
|
||||
prio = 3
|
||||
}
|
||||
|
||||
if name == opt.LongNameWithNamespace() && prio < 2 {
|
||||
retopt = opt
|
||||
prio = 2
|
||||
}
|
||||
|
||||
if opt.ShortName != 0 && name == string(opt.ShortName) && prio < 1 {
|
||||
retopt = opt
|
||||
prio = 1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return retopt
|
||||
}
|
||||
|
||||
func (g *Group) eachGroup(f func(*Group)) {
|
||||
f(g)
|
||||
|
||||
for _, gg := range g.groups {
|
||||
gg.eachGroup(f)
|
||||
}
|
||||
}
|
||||
|
||||
func isStringFalsy(s string) bool {
|
||||
return s == "" || s == "false" || s == "no" || s == "0"
|
||||
}
|
||||
|
||||
func (g *Group) scanStruct(realval reflect.Value, sfield *reflect.StructField, handler scanHandler) error {
|
||||
stype := realval.Type()
|
||||
|
||||
if sfield != nil {
|
||||
if ok, err := handler(realval, sfield); err != nil {
|
||||
return err
|
||||
} else if ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < stype.NumField(); i++ {
|
||||
field := stype.Field(i)
|
||||
|
||||
// PkgName is set only for non-exported fields, which we ignore
|
||||
if field.PkgPath != "" && !field.Anonymous {
|
||||
continue
|
||||
}
|
||||
|
||||
mtag := newMultiTag(string(field.Tag))
|
||||
|
||||
if err := mtag.Parse(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip fields with the no-flag tag
|
||||
if mtag.Get("no-flag") != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Dive deep into structs or pointers to structs
|
||||
kind := field.Type.Kind()
|
||||
fld := realval.Field(i)
|
||||
|
||||
if kind == reflect.Struct {
|
||||
if err := g.scanStruct(fld, &field, handler); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if kind == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
|
||||
flagCountBefore := len(g.options) + len(g.groups)
|
||||
|
||||
if fld.IsNil() {
|
||||
fld = reflect.New(fld.Type().Elem())
|
||||
}
|
||||
|
||||
if err := g.scanStruct(reflect.Indirect(fld), &field, handler); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(g.options)+len(g.groups) != flagCountBefore {
|
||||
realval.Field(i).Set(fld)
|
||||
}
|
||||
}
|
||||
|
||||
longname := mtag.Get("long")
|
||||
shortname := mtag.Get("short")
|
||||
|
||||
// Need at least either a short or long name
|
||||
if longname == "" && shortname == "" && mtag.Get("ini-name") == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
short := rune(0)
|
||||
rc := utf8.RuneCountInString(shortname)
|
||||
|
||||
if rc > 1 {
|
||||
return newErrorf(ErrShortNameTooLong,
|
||||
"short names can only be 1 character long, not `%s'",
|
||||
shortname)
|
||||
|
||||
} else if rc == 1 {
|
||||
short, _ = utf8.DecodeRuneInString(shortname)
|
||||
}
|
||||
|
||||
description := mtag.Get("description")
|
||||
def := mtag.GetMany("default")
|
||||
|
||||
optionalValue := mtag.GetMany("optional-value")
|
||||
valueName := mtag.Get("value-name")
|
||||
defaultMask := mtag.Get("default-mask")
|
||||
|
||||
optional := !isStringFalsy(mtag.Get("optional"))
|
||||
required := !isStringFalsy(mtag.Get("required"))
|
||||
choices := mtag.GetMany("choice")
|
||||
hidden := !isStringFalsy(mtag.Get("hidden"))
|
||||
|
||||
option := &Option{
|
||||
Description: description,
|
||||
ShortName: short,
|
||||
LongName: longname,
|
||||
Default: def,
|
||||
EnvDefaultKey: mtag.Get("env"),
|
||||
EnvDefaultDelim: mtag.Get("env-delim"),
|
||||
OptionalArgument: optional,
|
||||
OptionalValue: optionalValue,
|
||||
Required: required,
|
||||
ValueName: valueName,
|
||||
DefaultMask: defaultMask,
|
||||
Choices: choices,
|
||||
Hidden: hidden,
|
||||
|
||||
group: g,
|
||||
|
||||
field: field,
|
||||
value: realval.Field(i),
|
||||
tag: mtag,
|
||||
}
|
||||
|
||||
if option.isBool() && option.Default != nil {
|
||||
return newErrorf(ErrInvalidTag,
|
||||
"boolean flag `%s' may not have default values, they always default to `false' and can only be turned on",
|
||||
option.shortAndLongName())
|
||||
}
|
||||
|
||||
g.options = append(g.options, option)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Group) checkForDuplicateFlags() *Error {
|
||||
shortNames := make(map[rune]*Option)
|
||||
longNames := make(map[string]*Option)
|
||||
|
||||
var duplicateError *Error
|
||||
|
||||
g.eachGroup(func(g *Group) {
|
||||
for _, option := range g.options {
|
||||
if option.LongName != "" {
|
||||
longName := option.LongNameWithNamespace()
|
||||
|
||||
if otherOption, ok := longNames[longName]; ok {
|
||||
duplicateError = newErrorf(ErrDuplicatedFlag, "option `%s' uses the same long name as option `%s'", option, otherOption)
|
||||
return
|
||||
}
|
||||
longNames[longName] = option
|
||||
}
|
||||
if option.ShortName != 0 {
|
||||
if otherOption, ok := shortNames[option.ShortName]; ok {
|
||||
duplicateError = newErrorf(ErrDuplicatedFlag, "option `%s' uses the same short name as option `%s'", option, otherOption)
|
||||
return
|
||||
}
|
||||
shortNames[option.ShortName] = option
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return duplicateError
|
||||
}
|
||||
|
||||
func (g *Group) scanSubGroupHandler(realval reflect.Value, sfield *reflect.StructField) (bool, error) {
|
||||
mtag := newMultiTag(string(sfield.Tag))
|
||||
|
||||
if err := mtag.Parse(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
subgroup := mtag.Get("group")
|
||||
|
||||
if len(subgroup) != 0 {
|
||||
var ptrval reflect.Value
|
||||
|
||||
if realval.Kind() == reflect.Ptr {
|
||||
ptrval = realval
|
||||
|
||||
if ptrval.IsNil() {
|
||||
ptrval.Set(reflect.New(ptrval.Type()))
|
||||
}
|
||||
} else {
|
||||
ptrval = realval.Addr()
|
||||
}
|
||||
|
||||
description := mtag.Get("description")
|
||||
|
||||
group, err := g.AddGroup(subgroup, description, ptrval.Interface())
|
||||
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
group.Namespace = mtag.Get("namespace")
|
||||
group.Hidden = mtag.Get("hidden") != ""
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (g *Group) scanType(handler scanHandler) error {
|
||||
// Get all the public fields in the data struct
|
||||
ptrval := reflect.ValueOf(g.data)
|
||||
|
||||
if ptrval.Type().Kind() != reflect.Ptr {
|
||||
panic(ErrNotPointerToStruct)
|
||||
}
|
||||
|
||||
stype := ptrval.Type().Elem()
|
||||
|
||||
if stype.Kind() != reflect.Struct {
|
||||
panic(ErrNotPointerToStruct)
|
||||
}
|
||||
|
||||
realval := reflect.Indirect(ptrval)
|
||||
|
||||
if err := g.scanStruct(realval, nil, handler); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := g.checkForDuplicateFlags(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Group) scan() error {
|
||||
return g.scanType(g.scanSubGroupHandler)
|
||||
}
|
||||
|
||||
func (g *Group) groupByName(name string) *Group {
|
||||
if len(name) == 0 {
|
||||
return g
|
||||
}
|
||||
|
||||
return g.Find(name)
|
||||
}
|
491
vendor/github.com/jessevdk/go-flags/help.go
generated
vendored
Normal file
491
vendor/github.com/jessevdk/go-flags/help.go
generated
vendored
Normal file
@ -0,0 +1,491 @@
|
||||
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type alignmentInfo struct {
|
||||
maxLongLen int
|
||||
hasShort bool
|
||||
hasValueName bool
|
||||
terminalColumns int
|
||||
indent bool
|
||||
}
|
||||
|
||||
const (
|
||||
paddingBeforeOption = 2
|
||||
distanceBetweenOptionAndDescription = 2
|
||||
)
|
||||
|
||||
func (a *alignmentInfo) descriptionStart() int {
|
||||
ret := a.maxLongLen + distanceBetweenOptionAndDescription
|
||||
|
||||
if a.hasShort {
|
||||
ret += 2
|
||||
}
|
||||
|
||||
if a.maxLongLen > 0 {
|
||||
ret += 4
|
||||
}
|
||||
|
||||
if a.hasValueName {
|
||||
ret += 3
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *alignmentInfo) updateLen(name string, indent bool) {
|
||||
l := utf8.RuneCountInString(name)
|
||||
|
||||
if indent {
|
||||
l = l + 4
|
||||
}
|
||||
|
||||
if l > a.maxLongLen {
|
||||
a.maxLongLen = l
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) getAlignmentInfo() alignmentInfo {
|
||||
ret := alignmentInfo{
|
||||
maxLongLen: 0,
|
||||
hasShort: false,
|
||||
hasValueName: false,
|
||||
terminalColumns: getTerminalColumns(),
|
||||
}
|
||||
|
||||
if ret.terminalColumns <= 0 {
|
||||
ret.terminalColumns = 80
|
||||
}
|
||||
|
||||
var prevcmd *Command
|
||||
|
||||
p.eachActiveGroup(func(c *Command, grp *Group) {
|
||||
if c != prevcmd {
|
||||
for _, arg := range c.args {
|
||||
ret.updateLen(arg.Name, c != p.Command)
|
||||
}
|
||||
}
|
||||
|
||||
for _, info := range grp.options {
|
||||
if !info.canCli() {
|
||||
continue
|
||||
}
|
||||
|
||||
if info.ShortName != 0 {
|
||||
ret.hasShort = true
|
||||
}
|
||||
|
||||
if len(info.ValueName) > 0 {
|
||||
ret.hasValueName = true
|
||||
}
|
||||
|
||||
l := info.LongNameWithNamespace() + info.ValueName
|
||||
|
||||
if len(info.Choices) != 0 {
|
||||
l += "[" + strings.Join(info.Choices, "|") + "]"
|
||||
}
|
||||
|
||||
ret.updateLen(l, c != p.Command)
|
||||
}
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func wrapText(s string, l int, prefix string) string {
|
||||
var ret string
|
||||
|
||||
if l < 10 {
|
||||
l = 10
|
||||
}
|
||||
|
||||
// Basic text wrapping of s at spaces to fit in l
|
||||
lines := strings.Split(s, "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
var retline string
|
||||
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
for len(line) > l {
|
||||
// Try to split on space
|
||||
suffix := ""
|
||||
|
||||
pos := strings.LastIndex(line[:l], " ")
|
||||
|
||||
if pos < 0 {
|
||||
pos = l - 1
|
||||
suffix = "-\n"
|
||||
}
|
||||
|
||||
if len(retline) != 0 {
|
||||
retline += "\n" + prefix
|
||||
}
|
||||
|
||||
retline += strings.TrimSpace(line[:pos]) + suffix
|
||||
line = strings.TrimSpace(line[pos:])
|
||||
}
|
||||
|
||||
if len(line) > 0 {
|
||||
if len(retline) != 0 {
|
||||
retline += "\n" + prefix
|
||||
}
|
||||
|
||||
retline += line
|
||||
}
|
||||
|
||||
if len(ret) > 0 {
|
||||
ret += "\n"
|
||||
|
||||
if len(retline) > 0 {
|
||||
ret += prefix
|
||||
}
|
||||
}
|
||||
|
||||
ret += retline
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alignmentInfo) {
|
||||
line := &bytes.Buffer{}
|
||||
|
||||
prefix := paddingBeforeOption
|
||||
|
||||
if info.indent {
|
||||
prefix += 4
|
||||
}
|
||||
|
||||
if option.Hidden {
|
||||
return
|
||||
}
|
||||
|
||||
line.WriteString(strings.Repeat(" ", prefix))
|
||||
|
||||
if option.ShortName != 0 {
|
||||
line.WriteRune(defaultShortOptDelimiter)
|
||||
line.WriteRune(option.ShortName)
|
||||
} else if info.hasShort {
|
||||
line.WriteString(" ")
|
||||
}
|
||||
|
||||
descstart := info.descriptionStart() + paddingBeforeOption
|
||||
|
||||
if len(option.LongName) > 0 {
|
||||
if option.ShortName != 0 {
|
||||
line.WriteString(", ")
|
||||
} else if info.hasShort {
|
||||
line.WriteString(" ")
|
||||
}
|
||||
|
||||
line.WriteString(defaultLongOptDelimiter)
|
||||
line.WriteString(option.LongNameWithNamespace())
|
||||
}
|
||||
|
||||
if option.canArgument() {
|
||||
line.WriteRune(defaultNameArgDelimiter)
|
||||
|
||||
if len(option.ValueName) > 0 {
|
||||
line.WriteString(option.ValueName)
|
||||
}
|
||||
|
||||
if len(option.Choices) > 0 {
|
||||
line.WriteString("[" + strings.Join(option.Choices, "|") + "]")
|
||||
}
|
||||
}
|
||||
|
||||
written := line.Len()
|
||||
line.WriteTo(writer)
|
||||
|
||||
if option.Description != "" {
|
||||
dw := descstart - written
|
||||
writer.WriteString(strings.Repeat(" ", dw))
|
||||
|
||||
var def string
|
||||
|
||||
if len(option.DefaultMask) != 0 {
|
||||
if option.DefaultMask != "-" {
|
||||
def = option.DefaultMask
|
||||
}
|
||||
} else {
|
||||
def = option.defaultLiteral
|
||||
}
|
||||
|
||||
var envDef string
|
||||
if option.EnvDefaultKey != "" {
|
||||
var envPrintable string
|
||||
if runtime.GOOS == "windows" {
|
||||
envPrintable = "%" + option.EnvDefaultKey + "%"
|
||||
} else {
|
||||
envPrintable = "$" + option.EnvDefaultKey
|
||||
}
|
||||
envDef = fmt.Sprintf(" [%s]", envPrintable)
|
||||
}
|
||||
|
||||
var desc string
|
||||
|
||||
if def != "" {
|
||||
desc = fmt.Sprintf("%s (default: %v)%s", option.Description, def, envDef)
|
||||
} else {
|
||||
desc = option.Description + envDef
|
||||
}
|
||||
|
||||
writer.WriteString(wrapText(desc,
|
||||
info.terminalColumns-descstart,
|
||||
strings.Repeat(" ", descstart)))
|
||||
}
|
||||
|
||||
writer.WriteString("\n")
|
||||
}
|
||||
|
||||
func maxCommandLength(s []*Command) int {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
ret := len(s[0].Name)
|
||||
|
||||
for _, v := range s[1:] {
|
||||
l := len(v.Name)
|
||||
|
||||
if l > ret {
|
||||
ret = l
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// WriteHelp writes a help message containing all the possible options and
|
||||
// their descriptions to the provided writer. Note that the HelpFlag parser
|
||||
// option provides a convenient way to add a -h/--help option group to the
|
||||
// command line parser which will automatically show the help messages using
|
||||
// this method.
|
||||
func (p *Parser) WriteHelp(writer io.Writer) {
|
||||
if writer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
wr := bufio.NewWriter(writer)
|
||||
aligninfo := p.getAlignmentInfo()
|
||||
|
||||
cmd := p.Command
|
||||
|
||||
for cmd.Active != nil {
|
||||
cmd = cmd.Active
|
||||
}
|
||||
|
||||
if p.Name != "" {
|
||||
wr.WriteString("Usage:\n")
|
||||
wr.WriteString(" ")
|
||||
|
||||
allcmd := p.Command
|
||||
|
||||
for allcmd != nil {
|
||||
var usage string
|
||||
|
||||
if allcmd == p.Command {
|
||||
if len(p.Usage) != 0 {
|
||||
usage = p.Usage
|
||||
} else if p.Options&HelpFlag != 0 {
|
||||
usage = "[OPTIONS]"
|
||||
}
|
||||
} else if us, ok := allcmd.data.(Usage); ok {
|
||||
usage = us.Usage()
|
||||
} else if allcmd.hasCliOptions() {
|
||||
usage = fmt.Sprintf("[%s-OPTIONS]", allcmd.Name)
|
||||
}
|
||||
|
||||
if len(usage) != 0 {
|
||||
fmt.Fprintf(wr, " %s %s", allcmd.Name, usage)
|
||||
} else {
|
||||
fmt.Fprintf(wr, " %s", allcmd.Name)
|
||||
}
|
||||
|
||||
if len(allcmd.args) > 0 {
|
||||
fmt.Fprintf(wr, " ")
|
||||
}
|
||||
|
||||
for i, arg := range allcmd.args {
|
||||
if i != 0 {
|
||||
fmt.Fprintf(wr, " ")
|
||||
}
|
||||
|
||||
name := arg.Name
|
||||
|
||||
if arg.isRemaining() {
|
||||
name = name + "..."
|
||||
}
|
||||
|
||||
if !allcmd.ArgsRequired {
|
||||
fmt.Fprintf(wr, "[%s]", name)
|
||||
} else {
|
||||
fmt.Fprintf(wr, "%s", name)
|
||||
}
|
||||
}
|
||||
|
||||
if allcmd.Active == nil && len(allcmd.commands) > 0 {
|
||||
var co, cc string
|
||||
|
||||
if allcmd.SubcommandsOptional {
|
||||
co, cc = "[", "]"
|
||||
} else {
|
||||
co, cc = "<", ">"
|
||||
}
|
||||
|
||||
visibleCommands := allcmd.visibleCommands()
|
||||
|
||||
if len(visibleCommands) > 3 {
|
||||
fmt.Fprintf(wr, " %scommand%s", co, cc)
|
||||
} else {
|
||||
subcommands := allcmd.sortedVisibleCommands()
|
||||
names := make([]string, len(subcommands))
|
||||
|
||||
for i, subc := range subcommands {
|
||||
names[i] = subc.Name
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, " %s%s%s", co, strings.Join(names, " | "), cc)
|
||||
}
|
||||
}
|
||||
|
||||
allcmd = allcmd.Active
|
||||
}
|
||||
|
||||
fmt.Fprintln(wr)
|
||||
|
||||
if len(cmd.LongDescription) != 0 {
|
||||
fmt.Fprintln(wr)
|
||||
|
||||
t := wrapText(cmd.LongDescription,
|
||||
aligninfo.terminalColumns,
|
||||
"")
|
||||
|
||||
fmt.Fprintln(wr, t)
|
||||
}
|
||||
}
|
||||
|
||||
c := p.Command
|
||||
|
||||
for c != nil {
|
||||
printcmd := c != p.Command
|
||||
|
||||
c.eachGroup(func(grp *Group) {
|
||||
first := true
|
||||
|
||||
// Skip built-in help group for all commands except the top-level
|
||||
// parser
|
||||
if grp.Hidden || (grp.isBuiltinHelp && c != p.Command) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, info := range grp.options {
|
||||
if !info.canCli() || info.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
if printcmd {
|
||||
fmt.Fprintf(wr, "\n[%s command options]\n", c.Name)
|
||||
aligninfo.indent = true
|
||||
printcmd = false
|
||||
}
|
||||
|
||||
if first && cmd.Group != grp {
|
||||
fmt.Fprintln(wr)
|
||||
|
||||
if aligninfo.indent {
|
||||
wr.WriteString(" ")
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "%s:\n", grp.ShortDescription)
|
||||
first = false
|
||||
}
|
||||
|
||||
p.writeHelpOption(wr, info, aligninfo)
|
||||
}
|
||||
})
|
||||
|
||||
var args []*Arg
|
||||
for _, arg := range c.args {
|
||||
if arg.Description != "" {
|
||||
args = append(args, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
if c == p.Command {
|
||||
fmt.Fprintf(wr, "\nArguments:\n")
|
||||
} else {
|
||||
fmt.Fprintf(wr, "\n[%s command arguments]\n", c.Name)
|
||||
}
|
||||
|
||||
descStart := aligninfo.descriptionStart() + paddingBeforeOption
|
||||
|
||||
for _, arg := range args {
|
||||
argPrefix := strings.Repeat(" ", paddingBeforeOption)
|
||||
argPrefix += arg.Name
|
||||
|
||||
if len(arg.Description) > 0 {
|
||||
argPrefix += ":"
|
||||
wr.WriteString(argPrefix)
|
||||
|
||||
// Space between "arg:" and the description start
|
||||
descPadding := strings.Repeat(" ", descStart-len(argPrefix))
|
||||
// How much space the description gets before wrapping
|
||||
descWidth := aligninfo.terminalColumns - 1 - descStart
|
||||
// Whitespace to which we can indent new description lines
|
||||
descPrefix := strings.Repeat(" ", descStart)
|
||||
|
||||
wr.WriteString(descPadding)
|
||||
wr.WriteString(wrapText(arg.Description, descWidth, descPrefix))
|
||||
} else {
|
||||
wr.WriteString(argPrefix)
|
||||
}
|
||||
|
||||
fmt.Fprintln(wr)
|
||||
}
|
||||
}
|
||||
|
||||
c = c.Active
|
||||
}
|
||||
|
||||
scommands := cmd.sortedVisibleCommands()
|
||||
|
||||
if len(scommands) > 0 {
|
||||
maxnamelen := maxCommandLength(scommands)
|
||||
|
||||
fmt.Fprintln(wr)
|
||||
fmt.Fprintln(wr, "Available commands:")
|
||||
|
||||
for _, c := range scommands {
|
||||
fmt.Fprintf(wr, " %s", c.Name)
|
||||
|
||||
if len(c.ShortDescription) > 0 {
|
||||
pad := strings.Repeat(" ", maxnamelen-len(c.Name))
|
||||
fmt.Fprintf(wr, "%s %s", pad, c.ShortDescription)
|
||||
|
||||
if len(c.Aliases) > 0 {
|
||||
fmt.Fprintf(wr, " (aliases: %s)", strings.Join(c.Aliases, ", "))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fmt.Fprintln(wr)
|
||||
}
|
||||
}
|
||||
|
||||
wr.Flush()
|
||||
}
|
597
vendor/github.com/jessevdk/go-flags/ini.go
generated
vendored
Normal file
597
vendor/github.com/jessevdk/go-flags/ini.go
generated
vendored
Normal file
@ -0,0 +1,597 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IniError contains location information on where an error occurred.
|
||||
type IniError struct {
|
||||
// The error message.
|
||||
Message string
|
||||
|
||||
// The filename of the file in which the error occurred.
|
||||
File string
|
||||
|
||||
// The line number at which the error occurred.
|
||||
LineNumber uint
|
||||
}
|
||||
|
||||
// Error provides a "file:line: message" formatted message of the ini error.
|
||||
func (x *IniError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"%s:%d: %s",
|
||||
x.File,
|
||||
x.LineNumber,
|
||||
x.Message,
|
||||
)
|
||||
}
|
||||
|
||||
// IniOptions for writing
|
||||
type IniOptions uint
|
||||
|
||||
const (
|
||||
// IniNone indicates no options.
|
||||
IniNone IniOptions = 0
|
||||
|
||||
// IniIncludeDefaults indicates that default values should be written.
|
||||
IniIncludeDefaults = 1 << iota
|
||||
|
||||
// IniCommentDefaults indicates that if IniIncludeDefaults is used
|
||||
// options with default values are written but commented out.
|
||||
IniCommentDefaults
|
||||
|
||||
// IniIncludeComments indicates that comments containing the description
|
||||
// of an option should be written.
|
||||
IniIncludeComments
|
||||
|
||||
// IniDefault provides a default set of options.
|
||||
IniDefault = IniIncludeComments
|
||||
)
|
||||
|
||||
// IniParser is a utility to read and write flags options from and to ini
|
||||
// formatted strings.
|
||||
type IniParser struct {
|
||||
ParseAsDefaults bool // override default flags
|
||||
|
||||
parser *Parser
|
||||
}
|
||||
|
||||
type iniValue struct {
|
||||
Name string
|
||||
Value string
|
||||
Quoted bool
|
||||
LineNumber uint
|
||||
}
|
||||
|
||||
type iniSection []iniValue
|
||||
|
||||
type ini struct {
|
||||
File string
|
||||
Sections map[string]iniSection
|
||||
}
|
||||
|
||||
// NewIniParser creates a new ini parser for a given Parser.
|
||||
func NewIniParser(p *Parser) *IniParser {
|
||||
return &IniParser{
|
||||
parser: p,
|
||||
}
|
||||
}
|
||||
|
||||
// IniParse is a convenience function to parse command line options with default
|
||||
// settings from an ini formatted file. The provided data is a pointer to a struct
|
||||
// representing the default option group (named "Application Options"). For
|
||||
// more control, use flags.NewParser.
|
||||
func IniParse(filename string, data interface{}) error {
|
||||
p := NewParser(data, Default)
|
||||
|
||||
return NewIniParser(p).ParseFile(filename)
|
||||
}
|
||||
|
||||
// ParseFile parses flags from an ini formatted file. See Parse for more
|
||||
// information on the ini file format. The returned errors can be of the type
|
||||
// flags.Error or flags.IniError.
|
||||
func (i *IniParser) ParseFile(filename string) error {
|
||||
ini, err := readIniFromFile(filename)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return i.parse(ini)
|
||||
}
|
||||
|
||||
// Parse parses flags from an ini format. You can use ParseFile as a
|
||||
// convenience function to parse from a filename instead of a general
|
||||
// io.Reader.
|
||||
//
|
||||
// The format of the ini file is as follows:
|
||||
//
|
||||
// [Option group name]
|
||||
// option = value
|
||||
//
|
||||
// Each section in the ini file represents an option group or command in the
|
||||
// flags parser. The default flags parser option group (i.e. when using
|
||||
// flags.Parse) is named 'Application Options'. The ini option name is matched
|
||||
// in the following order:
|
||||
//
|
||||
// 1. Compared to the ini-name tag on the option struct field (if present)
|
||||
// 2. Compared to the struct field name
|
||||
// 3. Compared to the option long name (if present)
|
||||
// 4. Compared to the option short name (if present)
|
||||
//
|
||||
// Sections for nested groups and commands can be addressed using a dot `.'
|
||||
// namespacing notation (i.e [subcommand.Options]). Group section names are
|
||||
// matched case insensitive.
|
||||
//
|
||||
// The returned errors can be of the type flags.Error or flags.IniError.
|
||||
func (i *IniParser) Parse(reader io.Reader) error {
|
||||
ini, err := readIni(reader, "")
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return i.parse(ini)
|
||||
}
|
||||
|
||||
// WriteFile writes the flags as ini format into a file. See Write
|
||||
// for more information. The returned error occurs when the specified file
|
||||
// could not be opened for writing.
|
||||
func (i *IniParser) WriteFile(filename string, options IniOptions) error {
|
||||
return writeIniToFile(i, filename, options)
|
||||
}
|
||||
|
||||
// Write writes the current values of all the flags to an ini format.
|
||||
// See Parse for more information on the ini file format. You typically
|
||||
// call this only after settings have been parsed since the default values of each
|
||||
// option are stored just before parsing the flags (this is only relevant when
|
||||
// IniIncludeDefaults is _not_ set in options).
|
||||
func (i *IniParser) Write(writer io.Writer, options IniOptions) {
|
||||
writeIni(i, writer, options)
|
||||
}
|
||||
|
||||
func readFullLine(reader *bufio.Reader) (string, error) {
|
||||
var line []byte
|
||||
|
||||
for {
|
||||
l, more, err := reader.ReadLine()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if line == nil && !more {
|
||||
return string(l), nil
|
||||
}
|
||||
|
||||
line = append(line, l...)
|
||||
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return string(line), nil
|
||||
}
|
||||
|
||||
func optionIniName(option *Option) string {
|
||||
name := option.tag.Get("_read-ini-name")
|
||||
|
||||
if len(name) != 0 {
|
||||
return name
|
||||
}
|
||||
|
||||
name = option.tag.Get("ini-name")
|
||||
|
||||
if len(name) != 0 {
|
||||
return name
|
||||
}
|
||||
|
||||
return option.field.Name
|
||||
}
|
||||
|
||||
func writeGroupIni(cmd *Command, group *Group, namespace string, writer io.Writer, options IniOptions) {
|
||||
var sname string
|
||||
|
||||
if len(namespace) != 0 {
|
||||
sname = namespace
|
||||
}
|
||||
|
||||
if cmd.Group != group && len(group.ShortDescription) != 0 {
|
||||
if len(sname) != 0 {
|
||||
sname += "."
|
||||
}
|
||||
|
||||
sname += group.ShortDescription
|
||||
}
|
||||
|
||||
sectionwritten := false
|
||||
comments := (options & IniIncludeComments) != IniNone
|
||||
|
||||
for _, option := range group.options {
|
||||
if option.isFunc() || option.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(option.tag.Get("no-ini")) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
val := option.value
|
||||
|
||||
if (options&IniIncludeDefaults) == IniNone && option.valueIsDefault() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !sectionwritten {
|
||||
fmt.Fprintf(writer, "[%s]\n", sname)
|
||||
sectionwritten = true
|
||||
}
|
||||
|
||||
if comments && len(option.Description) != 0 {
|
||||
fmt.Fprintf(writer, "; %s\n", option.Description)
|
||||
}
|
||||
|
||||
oname := optionIniName(option)
|
||||
|
||||
commentOption := (options&(IniIncludeDefaults|IniCommentDefaults)) == IniIncludeDefaults|IniCommentDefaults && option.valueIsDefault()
|
||||
|
||||
kind := val.Type().Kind()
|
||||
switch kind {
|
||||
case reflect.Slice:
|
||||
kind = val.Type().Elem().Kind()
|
||||
|
||||
if val.Len() == 0 {
|
||||
writeOption(writer, oname, kind, "", "", true, option.iniQuote)
|
||||
} else {
|
||||
for idx := 0; idx < val.Len(); idx++ {
|
||||
v, _ := convertToString(val.Index(idx), option.tag)
|
||||
|
||||
writeOption(writer, oname, kind, "", v, commentOption, option.iniQuote)
|
||||
}
|
||||
}
|
||||
case reflect.Map:
|
||||
kind = val.Type().Elem().Kind()
|
||||
|
||||
if val.Len() == 0 {
|
||||
writeOption(writer, oname, kind, "", "", true, option.iniQuote)
|
||||
} else {
|
||||
mkeys := val.MapKeys()
|
||||
keys := make([]string, len(val.MapKeys()))
|
||||
kkmap := make(map[string]reflect.Value)
|
||||
|
||||
for i, k := range mkeys {
|
||||
keys[i], _ = convertToString(k, option.tag)
|
||||
kkmap[keys[i]] = k
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, k := range keys {
|
||||
v, _ := convertToString(val.MapIndex(kkmap[k]), option.tag)
|
||||
|
||||
writeOption(writer, oname, kind, k, v, commentOption, option.iniQuote)
|
||||
}
|
||||
}
|
||||
default:
|
||||
v, _ := convertToString(val, option.tag)
|
||||
|
||||
writeOption(writer, oname, kind, "", v, commentOption, option.iniQuote)
|
||||
}
|
||||
|
||||
if comments {
|
||||
fmt.Fprintln(writer)
|
||||
}
|
||||
}
|
||||
|
||||
if sectionwritten && !comments {
|
||||
fmt.Fprintln(writer)
|
||||
}
|
||||
}
|
||||
|
||||
func writeOption(writer io.Writer, optionName string, optionType reflect.Kind, optionKey string, optionValue string, commentOption bool, forceQuote bool) {
|
||||
if forceQuote || (optionType == reflect.String && !isPrint(optionValue)) {
|
||||
optionValue = strconv.Quote(optionValue)
|
||||
}
|
||||
|
||||
comment := ""
|
||||
if commentOption {
|
||||
comment = "; "
|
||||
}
|
||||
|
||||
fmt.Fprintf(writer, "%s%s =", comment, optionName)
|
||||
|
||||
if optionKey != "" {
|
||||
fmt.Fprintf(writer, " %s:%s", optionKey, optionValue)
|
||||
} else if optionValue != "" {
|
||||
fmt.Fprintf(writer, " %s", optionValue)
|
||||
}
|
||||
|
||||
fmt.Fprintln(writer)
|
||||
}
|
||||
|
||||
func writeCommandIni(command *Command, namespace string, writer io.Writer, options IniOptions) {
|
||||
command.eachGroup(func(group *Group) {
|
||||
if !group.Hidden {
|
||||
writeGroupIni(command, group, namespace, writer, options)
|
||||
}
|
||||
})
|
||||
|
||||
for _, c := range command.commands {
|
||||
var nns string
|
||||
|
||||
if c.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(namespace) != 0 {
|
||||
nns = c.Name + "." + nns
|
||||
} else {
|
||||
nns = c.Name
|
||||
}
|
||||
|
||||
writeCommandIni(c, nns, writer, options)
|
||||
}
|
||||
}
|
||||
|
||||
func writeIni(parser *IniParser, writer io.Writer, options IniOptions) {
|
||||
writeCommandIni(parser.parser.Command, "", writer, options)
|
||||
}
|
||||
|
||||
func writeIniToFile(parser *IniParser, filename string, options IniOptions) error {
|
||||
file, err := os.Create(filename)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
writeIni(parser, file, options)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func readIniFromFile(filename string) (*ini, error) {
|
||||
file, err := os.Open(filename)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
return readIni(file, filename)
|
||||
}
|
||||
|
||||
func readIni(contents io.Reader, filename string) (*ini, error) {
|
||||
ret := &ini{
|
||||
File: filename,
|
||||
Sections: make(map[string]iniSection),
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(contents)
|
||||
|
||||
// Empty global section
|
||||
section := make(iniSection, 0, 10)
|
||||
sectionname := ""
|
||||
|
||||
ret.Sections[sectionname] = section
|
||||
|
||||
var lineno uint
|
||||
|
||||
for {
|
||||
line, err := readFullLine(reader)
|
||||
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lineno++
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
// Skip empty lines and lines starting with ; (comments)
|
||||
if len(line) == 0 || line[0] == ';' || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
|
||||
if line[0] == '[' {
|
||||
if line[0] != '[' || line[len(line)-1] != ']' {
|
||||
return nil, &IniError{
|
||||
Message: "malformed section header",
|
||||
File: filename,
|
||||
LineNumber: lineno,
|
||||
}
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(line[1 : len(line)-1])
|
||||
|
||||
if len(name) == 0 {
|
||||
return nil, &IniError{
|
||||
Message: "empty section name",
|
||||
File: filename,
|
||||
LineNumber: lineno,
|
||||
}
|
||||
}
|
||||
|
||||
sectionname = name
|
||||
section = ret.Sections[name]
|
||||
|
||||
if section == nil {
|
||||
section = make(iniSection, 0, 10)
|
||||
ret.Sections[name] = section
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Parse option here
|
||||
keyval := strings.SplitN(line, "=", 2)
|
||||
|
||||
if len(keyval) != 2 {
|
||||
return nil, &IniError{
|
||||
Message: fmt.Sprintf("malformed key=value (%s)", line),
|
||||
File: filename,
|
||||
LineNumber: lineno,
|
||||
}
|
||||
}
|
||||
|
||||
name := strings.TrimSpace(keyval[0])
|
||||
value := strings.TrimSpace(keyval[1])
|
||||
quoted := false
|
||||
|
||||
if len(value) != 0 && value[0] == '"' {
|
||||
if v, err := strconv.Unquote(value); err == nil {
|
||||
value = v
|
||||
|
||||
quoted = true
|
||||
} else {
|
||||
return nil, &IniError{
|
||||
Message: err.Error(),
|
||||
File: filename,
|
||||
LineNumber: lineno,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section = append(section, iniValue{
|
||||
Name: name,
|
||||
Value: value,
|
||||
Quoted: quoted,
|
||||
LineNumber: lineno,
|
||||
})
|
||||
|
||||
ret.Sections[sectionname] = section
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (i *IniParser) matchingGroups(name string) []*Group {
|
||||
if len(name) == 0 {
|
||||
var ret []*Group
|
||||
|
||||
i.parser.eachGroup(func(g *Group) {
|
||||
ret = append(ret, g)
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
g := i.parser.groupByName(name)
|
||||
|
||||
if g != nil {
|
||||
return []*Group{g}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IniParser) parse(ini *ini) error {
|
||||
p := i.parser
|
||||
|
||||
var quotesLookup = make(map[*Option]bool)
|
||||
|
||||
for name, section := range ini.Sections {
|
||||
groups := i.matchingGroups(name)
|
||||
|
||||
if len(groups) == 0 {
|
||||
return newErrorf(ErrUnknownGroup, "could not find option group `%s'", name)
|
||||
}
|
||||
|
||||
for _, inival := range section {
|
||||
var opt *Option
|
||||
|
||||
for _, group := range groups {
|
||||
opt = group.optionByName(inival.Name, func(o *Option, n string) bool {
|
||||
return strings.ToLower(o.tag.Get("ini-name")) == strings.ToLower(n)
|
||||
})
|
||||
|
||||
if opt != nil && len(opt.tag.Get("no-ini")) != 0 {
|
||||
opt = nil
|
||||
}
|
||||
|
||||
if opt != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if opt == nil {
|
||||
if (p.Options & IgnoreUnknown) == None {
|
||||
return &IniError{
|
||||
Message: fmt.Sprintf("unknown option: %s", inival.Name),
|
||||
File: ini.File,
|
||||
LineNumber: inival.LineNumber,
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// ini value is ignored if override is set and
|
||||
// value was previously set from non default
|
||||
if i.ParseAsDefaults && !opt.isSetDefault {
|
||||
continue
|
||||
}
|
||||
|
||||
pval := &inival.Value
|
||||
|
||||
if !opt.canArgument() && len(inival.Value) == 0 {
|
||||
pval = nil
|
||||
} else {
|
||||
if opt.value.Type().Kind() == reflect.Map {
|
||||
parts := strings.SplitN(inival.Value, ":", 2)
|
||||
|
||||
// only handle unquoting
|
||||
if len(parts) == 2 && parts[1][0] == '"' {
|
||||
if v, err := strconv.Unquote(parts[1]); err == nil {
|
||||
parts[1] = v
|
||||
|
||||
inival.Quoted = true
|
||||
} else {
|
||||
return &IniError{
|
||||
Message: err.Error(),
|
||||
File: ini.File,
|
||||
LineNumber: inival.LineNumber,
|
||||
}
|
||||
}
|
||||
|
||||
s := parts[0] + ":" + parts[1]
|
||||
|
||||
pval = &s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := opt.set(pval); err != nil {
|
||||
return &IniError{
|
||||
Message: err.Error(),
|
||||
File: ini.File,
|
||||
LineNumber: inival.LineNumber,
|
||||
}
|
||||
}
|
||||
|
||||
// either all INI values are quoted or only values who need quoting
|
||||
if _, ok := quotesLookup[opt]; !inival.Quoted || !ok {
|
||||
quotesLookup[opt] = inival.Quoted
|
||||
}
|
||||
|
||||
opt.tag.Set("_read-ini-name", inival.Name)
|
||||
}
|
||||
}
|
||||
|
||||
for opt, quoted := range quotesLookup {
|
||||
opt.iniQuote = quoted
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
205
vendor/github.com/jessevdk/go-flags/man.go
generated
vendored
Normal file
205
vendor/github.com/jessevdk/go-flags/man.go
generated
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func manQuote(s string) string {
|
||||
return strings.Replace(s, "\\", "\\\\", -1)
|
||||
}
|
||||
|
||||
func formatForMan(wr io.Writer, s string) {
|
||||
for {
|
||||
idx := strings.IndexRune(s, '`')
|
||||
|
||||
if idx < 0 {
|
||||
fmt.Fprintf(wr, "%s", manQuote(s))
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "%s", manQuote(s[:idx]))
|
||||
|
||||
s = s[idx+1:]
|
||||
idx = strings.IndexRune(s, '\'')
|
||||
|
||||
if idx < 0 {
|
||||
fmt.Fprintf(wr, "%s", manQuote(s))
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "\\fB%s\\fP", manQuote(s[:idx]))
|
||||
s = s[idx+1:]
|
||||
}
|
||||
}
|
||||
|
||||
func writeManPageOptions(wr io.Writer, grp *Group) {
|
||||
grp.eachGroup(func(group *Group) {
|
||||
if group.Hidden || len(group.options) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// If the parent (grp) has any subgroups, display their descriptions as
|
||||
// subsection headers similar to the output of --help.
|
||||
if group.ShortDescription != "" && len(grp.groups) > 0 {
|
||||
fmt.Fprintf(wr, ".SS %s\n", group.ShortDescription)
|
||||
|
||||
if group.LongDescription != "" {
|
||||
formatForMan(wr, group.LongDescription)
|
||||
fmt.Fprintln(wr, "")
|
||||
}
|
||||
}
|
||||
|
||||
for _, opt := range group.options {
|
||||
if !opt.canCli() || opt.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintln(wr, ".TP")
|
||||
fmt.Fprintf(wr, "\\fB")
|
||||
|
||||
if opt.ShortName != 0 {
|
||||
fmt.Fprintf(wr, "\\fB\\-%c\\fR", opt.ShortName)
|
||||
}
|
||||
|
||||
if len(opt.LongName) != 0 {
|
||||
if opt.ShortName != 0 {
|
||||
fmt.Fprintf(wr, ", ")
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "\\fB\\-\\-%s\\fR", manQuote(opt.LongNameWithNamespace()))
|
||||
}
|
||||
|
||||
if len(opt.ValueName) != 0 || opt.OptionalArgument {
|
||||
if opt.OptionalArgument {
|
||||
fmt.Fprintf(wr, " [\\fI%s=%s\\fR]", manQuote(opt.ValueName), manQuote(strings.Join(quoteV(opt.OptionalValue), ", ")))
|
||||
} else {
|
||||
fmt.Fprintf(wr, " \\fI%s\\fR", manQuote(opt.ValueName))
|
||||
}
|
||||
}
|
||||
|
||||
if len(opt.Default) != 0 {
|
||||
fmt.Fprintf(wr, " <default: \\fI%s\\fR>", manQuote(strings.Join(quoteV(opt.Default), ", ")))
|
||||
} else if len(opt.EnvDefaultKey) != 0 {
|
||||
if runtime.GOOS == "windows" {
|
||||
fmt.Fprintf(wr, " <default: \\fI%%%s%%\\fR>", manQuote(opt.EnvDefaultKey))
|
||||
} else {
|
||||
fmt.Fprintf(wr, " <default: \\fI$%s\\fR>", manQuote(opt.EnvDefaultKey))
|
||||
}
|
||||
}
|
||||
|
||||
if opt.Required {
|
||||
fmt.Fprintf(wr, " (\\fIrequired\\fR)")
|
||||
}
|
||||
|
||||
fmt.Fprintln(wr, "\\fP")
|
||||
|
||||
if len(opt.Description) != 0 {
|
||||
formatForMan(wr, opt.Description)
|
||||
fmt.Fprintln(wr, "")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func writeManPageSubcommands(wr io.Writer, name string, root *Command) {
|
||||
commands := root.sortedVisibleCommands()
|
||||
|
||||
for _, c := range commands {
|
||||
var nn string
|
||||
|
||||
if c.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(name) != 0 {
|
||||
nn = name + " " + c.Name
|
||||
} else {
|
||||
nn = c.Name
|
||||
}
|
||||
|
||||
writeManPageCommand(wr, nn, root, c)
|
||||
}
|
||||
}
|
||||
|
||||
func writeManPageCommand(wr io.Writer, name string, root *Command, command *Command) {
|
||||
fmt.Fprintf(wr, ".SS %s\n", name)
|
||||
fmt.Fprintln(wr, command.ShortDescription)
|
||||
|
||||
if len(command.LongDescription) > 0 {
|
||||
fmt.Fprintln(wr, "")
|
||||
|
||||
cmdstart := fmt.Sprintf("The %s command", manQuote(command.Name))
|
||||
|
||||
if strings.HasPrefix(command.LongDescription, cmdstart) {
|
||||
fmt.Fprintf(wr, "The \\fI%s\\fP command", manQuote(command.Name))
|
||||
|
||||
formatForMan(wr, command.LongDescription[len(cmdstart):])
|
||||
fmt.Fprintln(wr, "")
|
||||
} else {
|
||||
formatForMan(wr, command.LongDescription)
|
||||
fmt.Fprintln(wr, "")
|
||||
}
|
||||
}
|
||||
|
||||
var usage string
|
||||
if us, ok := command.data.(Usage); ok {
|
||||
usage = us.Usage()
|
||||
} else if command.hasCliOptions() {
|
||||
usage = fmt.Sprintf("[%s-OPTIONS]", command.Name)
|
||||
}
|
||||
|
||||
var pre string
|
||||
if root.hasCliOptions() {
|
||||
pre = fmt.Sprintf("%s [OPTIONS] %s", root.Name, command.Name)
|
||||
} else {
|
||||
pre = fmt.Sprintf("%s %s", root.Name, command.Name)
|
||||
}
|
||||
|
||||
if len(usage) > 0 {
|
||||
fmt.Fprintf(wr, "\n\\fBUsage\\fP: %s %s\n.TP\n", manQuote(pre), manQuote(usage))
|
||||
}
|
||||
|
||||
if len(command.Aliases) > 0 {
|
||||
fmt.Fprintf(wr, "\n\\fBAliases\\fP: %s\n\n", manQuote(strings.Join(command.Aliases, ", ")))
|
||||
}
|
||||
|
||||
writeManPageOptions(wr, command.Group)
|
||||
writeManPageSubcommands(wr, name, command)
|
||||
}
|
||||
|
||||
// WriteManPage writes a basic man page in groff format to the specified
|
||||
// writer.
|
||||
func (p *Parser) WriteManPage(wr io.Writer) {
|
||||
t := time.Now()
|
||||
|
||||
fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", manQuote(p.Name), t.Format("2 January 2006"))
|
||||
fmt.Fprintln(wr, ".SH NAME")
|
||||
fmt.Fprintf(wr, "%s \\- %s\n", manQuote(p.Name), manQuote(p.ShortDescription))
|
||||
fmt.Fprintln(wr, ".SH SYNOPSIS")
|
||||
|
||||
usage := p.Usage
|
||||
|
||||
if len(usage) == 0 {
|
||||
usage = "[OPTIONS]"
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "\\fB%s\\fP %s\n", manQuote(p.Name), manQuote(usage))
|
||||
fmt.Fprintln(wr, ".SH DESCRIPTION")
|
||||
|
||||
formatForMan(wr, p.LongDescription)
|
||||
fmt.Fprintln(wr, "")
|
||||
|
||||
fmt.Fprintln(wr, ".SH OPTIONS")
|
||||
|
||||
writeManPageOptions(wr, p.Command.Group)
|
||||
|
||||
if len(p.visibleCommands()) > 0 {
|
||||
fmt.Fprintln(wr, ".SH COMMANDS")
|
||||
|
||||
writeManPageSubcommands(wr, "", p.Command)
|
||||
}
|
||||
}
|
140
vendor/github.com/jessevdk/go-flags/multitag.go
generated
vendored
Normal file
140
vendor/github.com/jessevdk/go-flags/multitag.go
generated
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type multiTag struct {
|
||||
value string
|
||||
cache map[string][]string
|
||||
}
|
||||
|
||||
func newMultiTag(v string) multiTag {
|
||||
return multiTag{
|
||||
value: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (x *multiTag) scan() (map[string][]string, error) {
|
||||
v := x.value
|
||||
|
||||
ret := make(map[string][]string)
|
||||
|
||||
// This is mostly copied from reflect.StructTag.Get
|
||||
for v != "" {
|
||||
i := 0
|
||||
|
||||
// Skip whitespace
|
||||
for i < len(v) && v[i] == ' ' {
|
||||
i++
|
||||
}
|
||||
|
||||
v = v[i:]
|
||||
|
||||
if v == "" {
|
||||
break
|
||||
}
|
||||
|
||||
// Scan to colon to find key
|
||||
i = 0
|
||||
|
||||
for i < len(v) && v[i] != ' ' && v[i] != ':' && v[i] != '"' {
|
||||
i++
|
||||
}
|
||||
|
||||
if i >= len(v) {
|
||||
return nil, newErrorf(ErrTag, "expected `:' after key name, but got end of tag (in `%v`)", x.value)
|
||||
}
|
||||
|
||||
if v[i] != ':' {
|
||||
return nil, newErrorf(ErrTag, "expected `:' after key name, but got `%v' (in `%v`)", v[i], x.value)
|
||||
}
|
||||
|
||||
if i+1 >= len(v) {
|
||||
return nil, newErrorf(ErrTag, "expected `\"' to start tag value at end of tag (in `%v`)", x.value)
|
||||
}
|
||||
|
||||
if v[i+1] != '"' {
|
||||
return nil, newErrorf(ErrTag, "expected `\"' to start tag value, but got `%v' (in `%v`)", v[i+1], x.value)
|
||||
}
|
||||
|
||||
name := v[:i]
|
||||
v = v[i+1:]
|
||||
|
||||
// Scan quoted string to find value
|
||||
i = 1
|
||||
|
||||
for i < len(v) && v[i] != '"' {
|
||||
if v[i] == '\n' {
|
||||
return nil, newErrorf(ErrTag, "unexpected newline in tag value `%v' (in `%v`)", name, x.value)
|
||||
}
|
||||
|
||||
if v[i] == '\\' {
|
||||
i++
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
if i >= len(v) {
|
||||
return nil, newErrorf(ErrTag, "expected end of tag value `\"' at end of tag (in `%v`)", x.value)
|
||||
}
|
||||
|
||||
val, err := strconv.Unquote(v[:i+1])
|
||||
|
||||
if err != nil {
|
||||
return nil, newErrorf(ErrTag, "Malformed value of tag `%v:%v` => %v (in `%v`)", name, v[:i+1], err, x.value)
|
||||
}
|
||||
|
||||
v = v[i+1:]
|
||||
|
||||
ret[name] = append(ret[name], val)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (x *multiTag) Parse() error {
|
||||
vals, err := x.scan()
|
||||
x.cache = vals
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (x *multiTag) cached() map[string][]string {
|
||||
if x.cache == nil {
|
||||
cache, _ := x.scan()
|
||||
|
||||
if cache == nil {
|
||||
cache = make(map[string][]string)
|
||||
}
|
||||
|
||||
x.cache = cache
|
||||
}
|
||||
|
||||
return x.cache
|
||||
}
|
||||
|
||||
func (x *multiTag) Get(key string) string {
|
||||
c := x.cached()
|
||||
|
||||
if v, ok := c[key]; ok {
|
||||
return v[len(v)-1]
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *multiTag) GetMany(key string) []string {
|
||||
c := x.cached()
|
||||
return c[key]
|
||||
}
|
||||
|
||||
func (x *multiTag) Set(key string, value string) {
|
||||
c := x.cached()
|
||||
c[key] = []string{value}
|
||||
}
|
||||
|
||||
func (x *multiTag) SetMany(key string, value []string) {
|
||||
c := x.cached()
|
||||
c[key] = value
|
||||
}
|
459
vendor/github.com/jessevdk/go-flags/option.go
generated
vendored
Normal file
459
vendor/github.com/jessevdk/go-flags/option.go
generated
vendored
Normal file
@ -0,0 +1,459 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Option flag information. Contains a description of the option, short and
|
||||
// long name as well as a default value and whether an argument for this
|
||||
// flag is optional.
|
||||
type Option struct {
|
||||
// The description of the option flag. This description is shown
|
||||
// automatically in the built-in help.
|
||||
Description string
|
||||
|
||||
// The short name of the option (a single character). If not 0, the
|
||||
// option flag can be 'activated' using -<ShortName>. Either ShortName
|
||||
// or LongName needs to be non-empty.
|
||||
ShortName rune
|
||||
|
||||
// The long name of the option. If not "", the option flag can be
|
||||
// activated using --<LongName>. Either ShortName or LongName needs
|
||||
// to be non-empty.
|
||||
LongName string
|
||||
|
||||
// The default value of the option.
|
||||
Default []string
|
||||
|
||||
// The optional environment default value key name.
|
||||
EnvDefaultKey string
|
||||
|
||||
// The optional delimiter string for EnvDefaultKey values.
|
||||
EnvDefaultDelim string
|
||||
|
||||
// If true, specifies that the argument to an option flag is optional.
|
||||
// When no argument to the flag is specified on the command line, the
|
||||
// value of OptionalValue will be set in the field this option represents.
|
||||
// This is only valid for non-boolean options.
|
||||
OptionalArgument bool
|
||||
|
||||
// The optional value of the option. The optional value is used when
|
||||
// the option flag is marked as having an OptionalArgument. This means
|
||||
// that when the flag is specified, but no option argument is given,
|
||||
// the value of the field this option represents will be set to
|
||||
// OptionalValue. This is only valid for non-boolean options.
|
||||
OptionalValue []string
|
||||
|
||||
// If true, the option _must_ be specified on the command line. If the
|
||||
// option is not specified, the parser will generate an ErrRequired type
|
||||
// error.
|
||||
Required bool
|
||||
|
||||
// A name for the value of an option shown in the Help as --flag [ValueName]
|
||||
ValueName string
|
||||
|
||||
// A mask value to show in the help instead of the default value. This
|
||||
// is useful for hiding sensitive information in the help, such as
|
||||
// passwords.
|
||||
DefaultMask string
|
||||
|
||||
// If non empty, only a certain set of values is allowed for an option.
|
||||
Choices []string
|
||||
|
||||
// If true, the option is not displayed in the help or man page
|
||||
Hidden bool
|
||||
|
||||
// The group which the option belongs to
|
||||
group *Group
|
||||
|
||||
// The struct field which the option represents.
|
||||
field reflect.StructField
|
||||
|
||||
// The struct field value which the option represents.
|
||||
value reflect.Value
|
||||
|
||||
// Determines if the option will be always quoted in the INI output
|
||||
iniQuote bool
|
||||
|
||||
tag multiTag
|
||||
isSet bool
|
||||
isSetDefault bool
|
||||
preventDefault bool
|
||||
|
||||
defaultLiteral string
|
||||
}
|
||||
|
||||
// LongNameWithNamespace returns the option's long name with the group namespaces
|
||||
// prepended by walking up the option's group tree. Namespaces and the long name
|
||||
// itself are separated by the parser's namespace delimiter. If the long name is
|
||||
// empty an empty string is returned.
|
||||
func (option *Option) LongNameWithNamespace() string {
|
||||
if len(option.LongName) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// fetch the namespace delimiter from the parser which is always at the
|
||||
// end of the group hierarchy
|
||||
namespaceDelimiter := ""
|
||||
g := option.group
|
||||
|
||||
for {
|
||||
if p, ok := g.parent.(*Parser); ok {
|
||||
namespaceDelimiter = p.NamespaceDelimiter
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
switch i := g.parent.(type) {
|
||||
case *Command:
|
||||
g = i.Group
|
||||
case *Group:
|
||||
g = i
|
||||
}
|
||||
}
|
||||
|
||||
// concatenate long name with namespace
|
||||
longName := option.LongName
|
||||
g = option.group
|
||||
|
||||
for g != nil {
|
||||
if g.Namespace != "" {
|
||||
longName = g.Namespace + namespaceDelimiter + longName
|
||||
}
|
||||
|
||||
switch i := g.parent.(type) {
|
||||
case *Command:
|
||||
g = i.Group
|
||||
case *Group:
|
||||
g = i
|
||||
case *Parser:
|
||||
g = nil
|
||||
}
|
||||
}
|
||||
|
||||
return longName
|
||||
}
|
||||
|
||||
// String converts an option to a human friendly readable string describing the
|
||||
// option.
|
||||
func (option *Option) String() string {
|
||||
var s string
|
||||
var short string
|
||||
|
||||
if option.ShortName != 0 {
|
||||
data := make([]byte, utf8.RuneLen(option.ShortName))
|
||||
utf8.EncodeRune(data, option.ShortName)
|
||||
short = string(data)
|
||||
|
||||
if len(option.LongName) != 0 {
|
||||
s = fmt.Sprintf("%s%s, %s%s",
|
||||
string(defaultShortOptDelimiter), short,
|
||||
defaultLongOptDelimiter, option.LongNameWithNamespace())
|
||||
} else {
|
||||
s = fmt.Sprintf("%s%s", string(defaultShortOptDelimiter), short)
|
||||
}
|
||||
} else if len(option.LongName) != 0 {
|
||||
s = fmt.Sprintf("%s%s", defaultLongOptDelimiter, option.LongNameWithNamespace())
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Value returns the option value as an interface{}.
|
||||
func (option *Option) Value() interface{} {
|
||||
return option.value.Interface()
|
||||
}
|
||||
|
||||
// Field returns the reflect struct field of the option.
|
||||
func (option *Option) Field() reflect.StructField {
|
||||
return option.field
|
||||
}
|
||||
|
||||
// IsSet returns true if option has been set
|
||||
func (option *Option) IsSet() bool {
|
||||
return option.isSet
|
||||
}
|
||||
|
||||
// IsSetDefault returns true if option has been set via the default option tag
|
||||
func (option *Option) IsSetDefault() bool {
|
||||
return option.isSetDefault
|
||||
}
|
||||
|
||||
// Set the value of an option to the specified value. An error will be returned
|
||||
// if the specified value could not be converted to the corresponding option
|
||||
// value type.
|
||||
func (option *Option) set(value *string) error {
|
||||
kind := option.value.Type().Kind()
|
||||
|
||||
if (kind == reflect.Map || kind == reflect.Slice) && !option.isSet {
|
||||
option.empty()
|
||||
}
|
||||
|
||||
option.isSet = true
|
||||
option.preventDefault = true
|
||||
|
||||
if len(option.Choices) != 0 {
|
||||
found := false
|
||||
|
||||
for _, choice := range option.Choices {
|
||||
if choice == *value {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
allowed := strings.Join(option.Choices[0:len(option.Choices)-1], ", ")
|
||||
|
||||
if len(option.Choices) > 1 {
|
||||
allowed += " or " + option.Choices[len(option.Choices)-1]
|
||||
}
|
||||
|
||||
return newErrorf(ErrInvalidChoice,
|
||||
"Invalid value `%s' for option `%s'. Allowed values are: %s",
|
||||
*value, option, allowed)
|
||||
}
|
||||
}
|
||||
|
||||
if option.isFunc() {
|
||||
return option.call(value)
|
||||
} else if value != nil {
|
||||
return convert(*value, option.value, option.tag)
|
||||
}
|
||||
|
||||
return convert("", option.value, option.tag)
|
||||
}
|
||||
|
||||
func (option *Option) canCli() bool {
|
||||
return option.ShortName != 0 || len(option.LongName) != 0
|
||||
}
|
||||
|
||||
func (option *Option) canArgument() bool {
|
||||
if u := option.isUnmarshaler(); u != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return !option.isBool()
|
||||
}
|
||||
|
||||
func (option *Option) emptyValue() reflect.Value {
|
||||
tp := option.value.Type()
|
||||
|
||||
if tp.Kind() == reflect.Map {
|
||||
return reflect.MakeMap(tp)
|
||||
}
|
||||
|
||||
return reflect.Zero(tp)
|
||||
}
|
||||
|
||||
func (option *Option) empty() {
|
||||
if !option.isFunc() {
|
||||
option.value.Set(option.emptyValue())
|
||||
}
|
||||
}
|
||||
|
||||
func (option *Option) clearDefault() {
|
||||
usedDefault := option.Default
|
||||
|
||||
if envKey := option.EnvDefaultKey; envKey != "" {
|
||||
if value, ok := os.LookupEnv(envKey); ok {
|
||||
if option.EnvDefaultDelim != "" {
|
||||
usedDefault = strings.Split(value,
|
||||
option.EnvDefaultDelim)
|
||||
} else {
|
||||
usedDefault = []string{value}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
option.isSetDefault = true
|
||||
|
||||
if len(usedDefault) > 0 {
|
||||
option.empty()
|
||||
|
||||
for _, d := range usedDefault {
|
||||
option.set(&d)
|
||||
option.isSetDefault = true
|
||||
}
|
||||
} else {
|
||||
tp := option.value.Type()
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Map:
|
||||
if option.value.IsNil() {
|
||||
option.empty()
|
||||
}
|
||||
case reflect.Slice:
|
||||
if option.value.IsNil() {
|
||||
option.empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (option *Option) valueIsDefault() bool {
|
||||
// Check if the value of the option corresponds to its
|
||||
// default value
|
||||
emptyval := option.emptyValue()
|
||||
|
||||
checkvalptr := reflect.New(emptyval.Type())
|
||||
checkval := reflect.Indirect(checkvalptr)
|
||||
|
||||
checkval.Set(emptyval)
|
||||
|
||||
if len(option.Default) != 0 {
|
||||
for _, v := range option.Default {
|
||||
convert(v, checkval, option.tag)
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(option.value.Interface(), checkval.Interface())
|
||||
}
|
||||
|
||||
func (option *Option) isUnmarshaler() Unmarshaler {
|
||||
v := option.value
|
||||
|
||||
for {
|
||||
if !v.CanInterface() {
|
||||
break
|
||||
}
|
||||
|
||||
i := v.Interface()
|
||||
|
||||
if u, ok := i.(Unmarshaler); ok {
|
||||
return u
|
||||
}
|
||||
|
||||
if !v.CanAddr() {
|
||||
break
|
||||
}
|
||||
|
||||
v = v.Addr()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (option *Option) isBool() bool {
|
||||
tp := option.value.Type()
|
||||
|
||||
for {
|
||||
switch tp.Kind() {
|
||||
case reflect.Slice, reflect.Ptr:
|
||||
tp = tp.Elem()
|
||||
case reflect.Bool:
|
||||
return true
|
||||
case reflect.Func:
|
||||
return tp.NumIn() == 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (option *Option) isSignedNumber() bool {
|
||||
tp := option.value.Type()
|
||||
|
||||
for {
|
||||
switch tp.Kind() {
|
||||
case reflect.Slice, reflect.Ptr:
|
||||
tp = tp.Elem()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (option *Option) isFunc() bool {
|
||||
return option.value.Type().Kind() == reflect.Func
|
||||
}
|
||||
|
||||
func (option *Option) call(value *string) error {
|
||||
var retval []reflect.Value
|
||||
|
||||
if value == nil {
|
||||
retval = option.value.Call(nil)
|
||||
} else {
|
||||
tp := option.value.Type().In(0)
|
||||
|
||||
val := reflect.New(tp)
|
||||
val = reflect.Indirect(val)
|
||||
|
||||
if err := convert(*value, val, option.tag); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
retval = option.value.Call([]reflect.Value{val})
|
||||
}
|
||||
|
||||
if len(retval) == 1 && retval[0].Type() == reflect.TypeOf((*error)(nil)).Elem() {
|
||||
if retval[0].Interface() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return retval[0].Interface().(error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (option *Option) updateDefaultLiteral() {
|
||||
defs := option.Default
|
||||
def := ""
|
||||
|
||||
if len(defs) == 0 && option.canArgument() {
|
||||
var showdef bool
|
||||
|
||||
switch option.field.Type.Kind() {
|
||||
case reflect.Func, reflect.Ptr:
|
||||
showdef = !option.value.IsNil()
|
||||
case reflect.Slice, reflect.String, reflect.Array:
|
||||
showdef = option.value.Len() > 0
|
||||
case reflect.Map:
|
||||
showdef = !option.value.IsNil() && option.value.Len() > 0
|
||||
default:
|
||||
zeroval := reflect.Zero(option.field.Type)
|
||||
showdef = !reflect.DeepEqual(zeroval.Interface(), option.value.Interface())
|
||||
}
|
||||
|
||||
if showdef {
|
||||
def, _ = convertToString(option.value, option.tag)
|
||||
}
|
||||
} else if len(defs) != 0 {
|
||||
l := len(defs) - 1
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
def += quoteIfNeeded(defs[i]) + ", "
|
||||
}
|
||||
|
||||
def += quoteIfNeeded(defs[l])
|
||||
}
|
||||
|
||||
option.defaultLiteral = def
|
||||
}
|
||||
|
||||
func (option *Option) shortAndLongName() string {
|
||||
ret := &bytes.Buffer{}
|
||||
|
||||
if option.ShortName != 0 {
|
||||
ret.WriteRune(defaultShortOptDelimiter)
|
||||
ret.WriteRune(option.ShortName)
|
||||
}
|
||||
|
||||
if len(option.LongName) != 0 {
|
||||
if option.ShortName != 0 {
|
||||
ret.WriteRune('/')
|
||||
}
|
||||
|
||||
ret.WriteString(option.LongName)
|
||||
}
|
||||
|
||||
return ret.String()
|
||||
}
|
67
vendor/github.com/jessevdk/go-flags/optstyle_other.go
generated
vendored
Normal file
67
vendor/github.com/jessevdk/go-flags/optstyle_other.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// +build !windows forceposix
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultShortOptDelimiter = '-'
|
||||
defaultLongOptDelimiter = "--"
|
||||
defaultNameArgDelimiter = '='
|
||||
)
|
||||
|
||||
func argumentStartsOption(arg string) bool {
|
||||
return len(arg) > 0 && arg[0] == '-'
|
||||
}
|
||||
|
||||
func argumentIsOption(arg string) bool {
|
||||
if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(arg) > 2 && arg[0] == '-' && arg[1] == '-' && arg[2] != '-' {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// stripOptionPrefix returns the option without the prefix and whether or
|
||||
// not the option is a long option or not.
|
||||
func stripOptionPrefix(optname string) (prefix string, name string, islong bool) {
|
||||
if strings.HasPrefix(optname, "--") {
|
||||
return "--", optname[2:], true
|
||||
} else if strings.HasPrefix(optname, "-") {
|
||||
return "-", optname[1:], false
|
||||
}
|
||||
|
||||
return "", optname, false
|
||||
}
|
||||
|
||||
// splitOption attempts to split the passed option into a name and an argument.
|
||||
// When there is no argument specified, nil will be returned for it.
|
||||
func splitOption(prefix string, option string, islong bool) (string, string, *string) {
|
||||
pos := strings.Index(option, "=")
|
||||
|
||||
if (islong && pos >= 0) || (!islong && pos == 1) {
|
||||
rest := option[pos+1:]
|
||||
return option[:pos], "=", &rest
|
||||
}
|
||||
|
||||
return option, "", nil
|
||||
}
|
||||
|
||||
// addHelpGroup adds a new group that contains default help parameters.
|
||||
func (c *Command) addHelpGroup(showHelp func() error) *Group {
|
||||
var help struct {
|
||||
ShowHelp func() error `short:"h" long:"help" description:"Show this help message"`
|
||||
}
|
||||
|
||||
help.ShowHelp = showHelp
|
||||
ret, _ := c.AddGroup("Help Options", "", &help)
|
||||
ret.isBuiltinHelp = true
|
||||
|
||||
return ret
|
||||
}
|
108
vendor/github.com/jessevdk/go-flags/optstyle_windows.go
generated
vendored
Normal file
108
vendor/github.com/jessevdk/go-flags/optstyle_windows.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
// +build !forceposix
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Windows uses a front slash for both short and long options. Also it uses
|
||||
// a colon for name/argument delimter.
|
||||
const (
|
||||
defaultShortOptDelimiter = '/'
|
||||
defaultLongOptDelimiter = "/"
|
||||
defaultNameArgDelimiter = ':'
|
||||
)
|
||||
|
||||
func argumentStartsOption(arg string) bool {
|
||||
return len(arg) > 0 && (arg[0] == '-' || arg[0] == '/')
|
||||
}
|
||||
|
||||
func argumentIsOption(arg string) bool {
|
||||
// Windows-style options allow front slash for the option
|
||||
// delimiter.
|
||||
if len(arg) > 1 && arg[0] == '/' {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(arg) > 2 && arg[0] == '-' && arg[1] == '-' && arg[2] != '-' {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// stripOptionPrefix returns the option without the prefix and whether or
|
||||
// not the option is a long option or not.
|
||||
func stripOptionPrefix(optname string) (prefix string, name string, islong bool) {
|
||||
// Determine if the argument is a long option or not. Windows
|
||||
// typically supports both long and short options with a single
|
||||
// front slash as the option delimiter, so handle this situation
|
||||
// nicely.
|
||||
possplit := 0
|
||||
|
||||
if strings.HasPrefix(optname, "--") {
|
||||
possplit = 2
|
||||
islong = true
|
||||
} else if strings.HasPrefix(optname, "-") {
|
||||
possplit = 1
|
||||
islong = false
|
||||
} else if strings.HasPrefix(optname, "/") {
|
||||
possplit = 1
|
||||
islong = len(optname) > 2
|
||||
}
|
||||
|
||||
return optname[:possplit], optname[possplit:], islong
|
||||
}
|
||||
|
||||
// splitOption attempts to split the passed option into a name and an argument.
|
||||
// When there is no argument specified, nil will be returned for it.
|
||||
func splitOption(prefix string, option string, islong bool) (string, string, *string) {
|
||||
if len(option) == 0 {
|
||||
return option, "", nil
|
||||
}
|
||||
|
||||
// Windows typically uses a colon for the option name and argument
|
||||
// delimiter while POSIX typically uses an equals. Support both styles,
|
||||
// but don't allow the two to be mixed. That is to say /foo:bar and
|
||||
// --foo=bar are acceptable, but /foo=bar and --foo:bar are not.
|
||||
var pos int
|
||||
var sp string
|
||||
|
||||
if prefix == "/" {
|
||||
sp = ":"
|
||||
pos = strings.Index(option, sp)
|
||||
} else if len(prefix) > 0 {
|
||||
sp = "="
|
||||
pos = strings.Index(option, sp)
|
||||
}
|
||||
|
||||
if (islong && pos >= 0) || (!islong && pos == 1) {
|
||||
rest := option[pos+1:]
|
||||
return option[:pos], sp, &rest
|
||||
}
|
||||
|
||||
return option, "", nil
|
||||
}
|
||||
|
||||
// addHelpGroup adds a new group that contains default help parameters.
|
||||
func (c *Command) addHelpGroup(showHelp func() error) *Group {
|
||||
// Windows CLI applications typically use /? for help, so make both
|
||||
// that available as well as the POSIX style h and help.
|
||||
var help struct {
|
||||
ShowHelpWindows func() error `short:"?" description:"Show this help message"`
|
||||
ShowHelpPosix func() error `short:"h" long:"help" description:"Show this help message"`
|
||||
}
|
||||
|
||||
help.ShowHelpWindows = showHelp
|
||||
help.ShowHelpPosix = showHelp
|
||||
|
||||
ret, _ := c.AddGroup("Help Options", "", &help)
|
||||
ret.isBuiltinHelp = true
|
||||
|
||||
return ret
|
||||
}
|
700
vendor/github.com/jessevdk/go-flags/parser.go
generated
vendored
Normal file
700
vendor/github.com/jessevdk/go-flags/parser.go
generated
vendored
Normal file
@ -0,0 +1,700 @@
|
||||
// Copyright 2012 Jesse van den Kieboom. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A Parser provides command line option parsing. It can contain several
|
||||
// option groups each with their own set of options.
|
||||
type Parser struct {
|
||||
// Embedded, see Command for more information
|
||||
*Command
|
||||
|
||||
// A usage string to be displayed in the help message.
|
||||
Usage string
|
||||
|
||||
// Option flags changing the behavior of the parser.
|
||||
Options Options
|
||||
|
||||
// NamespaceDelimiter separates group namespaces and option long names
|
||||
NamespaceDelimiter string
|
||||
|
||||
// UnknownOptionsHandler is a function which gets called when the parser
|
||||
// encounters an unknown option. The function receives the unknown option
|
||||
// name, a SplitArgument which specifies its value if set with an argument
|
||||
// separator, and the remaining command line arguments.
|
||||
// It should return a new list of remaining arguments to continue parsing,
|
||||
// or an error to indicate a parse failure.
|
||||
UnknownOptionHandler func(option string, arg SplitArgument, args []string) ([]string, error)
|
||||
|
||||
// CompletionHandler is a function gets called to handle the completion of
|
||||
// items. By default, the items are printed and the application is exited.
|
||||
// You can override this default behavior by specifying a custom CompletionHandler.
|
||||
CompletionHandler func(items []Completion)
|
||||
|
||||
// CommandHandler is a function that gets called to handle execution of a
|
||||
// command. By default, the command will simply be executed. This can be
|
||||
// overridden to perform certain actions (such as applying global flags)
|
||||
// just before the command is executed. Note that if you override the
|
||||
// handler it is your responsibility to call the command.Execute function.
|
||||
//
|
||||
// The command passed into CommandHandler may be nil in case there is no
|
||||
// command to be executed when parsing has finished.
|
||||
CommandHandler func(command Commander, args []string) error
|
||||
|
||||
internalError error
|
||||
}
|
||||
|
||||
// SplitArgument represents the argument value of an option that was passed using
|
||||
// an argument separator.
|
||||
type SplitArgument interface {
|
||||
// String returns the option's value as a string, and a boolean indicating
|
||||
// if the option was present.
|
||||
Value() (string, bool)
|
||||
}
|
||||
|
||||
type strArgument struct {
|
||||
value *string
|
||||
}
|
||||
|
||||
func (s strArgument) Value() (string, bool) {
|
||||
if s.value == nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return *s.value, true
|
||||
}
|
||||
|
||||
// Options provides parser options that change the behavior of the option
|
||||
// parser.
|
||||
type Options uint
|
||||
|
||||
const (
|
||||
// None indicates no options.
|
||||
None Options = 0
|
||||
|
||||
// HelpFlag adds a default Help Options group to the parser containing
|
||||
// -h and --help options. When either -h or --help is specified on the
|
||||
// command line, the parser will return the special error of type
|
||||
// ErrHelp. When PrintErrors is also specified, then the help message
|
||||
// will also be automatically printed to os.Stdout.
|
||||
HelpFlag = 1 << iota
|
||||
|
||||
// PassDoubleDash passes all arguments after a double dash, --, as
|
||||
// remaining command line arguments (i.e. they will not be parsed for
|
||||
// flags).
|
||||
PassDoubleDash
|
||||
|
||||
// IgnoreUnknown ignores any unknown options and passes them as
|
||||
// remaining command line arguments instead of generating an error.
|
||||
IgnoreUnknown
|
||||
|
||||
// PrintErrors prints any errors which occurred during parsing to
|
||||
// os.Stderr. In the special case of ErrHelp, the message will be printed
|
||||
// to os.Stdout.
|
||||
PrintErrors
|
||||
|
||||
// PassAfterNonOption passes all arguments after the first non option
|
||||
// as remaining command line arguments. This is equivalent to strict
|
||||
// POSIX processing.
|
||||
PassAfterNonOption
|
||||
|
||||
// Default is a convenient default set of options which should cover
|
||||
// most of the uses of the flags package.
|
||||
Default = HelpFlag | PrintErrors | PassDoubleDash
|
||||
)
|
||||
|
||||
type parseState struct {
|
||||
arg string
|
||||
args []string
|
||||
retargs []string
|
||||
positional []*Arg
|
||||
err error
|
||||
|
||||
command *Command
|
||||
lookup lookup
|
||||
}
|
||||
|
||||
// Parse is a convenience function to parse command line options with default
|
||||
// settings. The provided data is a pointer to a struct representing the
|
||||
// default option group (named "Application Options"). For more control, use
|
||||
// flags.NewParser.
|
||||
func Parse(data interface{}) ([]string, error) {
|
||||
return NewParser(data, Default).Parse()
|
||||
}
|
||||
|
||||
// ParseArgs is a convenience function to parse command line options with default
|
||||
// settings. The provided data is a pointer to a struct representing the
|
||||
// default option group (named "Application Options"). The args argument is
|
||||
// the list of command line arguments to parse. If you just want to parse the
|
||||
// default program command line arguments (i.e. os.Args), then use flags.Parse
|
||||
// instead. For more control, use flags.NewParser.
|
||||
func ParseArgs(data interface{}, args []string) ([]string, error) {
|
||||
return NewParser(data, Default).ParseArgs(args)
|
||||
}
|
||||
|
||||
// NewParser creates a new parser. It uses os.Args[0] as the application
|
||||
// name and then calls Parser.NewNamedParser (see Parser.NewNamedParser for
|
||||
// more details). The provided data is a pointer to a struct representing the
|
||||
// default option group (named "Application Options"), or nil if the default
|
||||
// group should not be added. The options parameter specifies a set of options
|
||||
// for the parser.
|
||||
func NewParser(data interface{}, options Options) *Parser {
|
||||
p := NewNamedParser(path.Base(os.Args[0]), options)
|
||||
|
||||
if data != nil {
|
||||
g, err := p.AddGroup("Application Options", "", data)
|
||||
|
||||
if err == nil {
|
||||
g.parent = p
|
||||
}
|
||||
|
||||
p.internalError = err
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// NewNamedParser creates a new parser. The appname is used to display the
|
||||
// executable name in the built-in help message. Option groups and commands can
|
||||
// be added to this parser by using AddGroup and AddCommand.
|
||||
func NewNamedParser(appname string, options Options) *Parser {
|
||||
p := &Parser{
|
||||
Command: newCommand(appname, "", "", nil),
|
||||
Options: options,
|
||||
NamespaceDelimiter: ".",
|
||||
}
|
||||
|
||||
p.Command.parent = p
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// Parse parses the command line arguments from os.Args using Parser.ParseArgs.
|
||||
// For more detailed information see ParseArgs.
|
||||
func (p *Parser) Parse() ([]string, error) {
|
||||
return p.ParseArgs(os.Args[1:])
|
||||
}
|
||||
|
||||
// ParseArgs parses the command line arguments according to the option groups that
|
||||
// were added to the parser. On successful parsing of the arguments, the
|
||||
// remaining, non-option, arguments (if any) are returned. The returned error
|
||||
// indicates a parsing error and can be used with PrintError to display
|
||||
// contextual information on where the error occurred exactly.
|
||||
//
|
||||
// When the common help group has been added (AddHelp) and either -h or --help
|
||||
// was specified in the command line arguments, a help message will be
|
||||
// automatically printed if the PrintErrors option is enabled.
|
||||
// Furthermore, the special error type ErrHelp is returned.
|
||||
// It is up to the caller to exit the program if so desired.
|
||||
func (p *Parser) ParseArgs(args []string) ([]string, error) {
|
||||
if p.internalError != nil {
|
||||
return nil, p.internalError
|
||||
}
|
||||
|
||||
p.eachOption(func(c *Command, g *Group, option *Option) {
|
||||
option.isSet = false
|
||||
option.isSetDefault = false
|
||||
option.updateDefaultLiteral()
|
||||
})
|
||||
|
||||
// Add built-in help group to all commands if necessary
|
||||
if (p.Options & HelpFlag) != None {
|
||||
p.addHelpGroups(p.showBuiltinHelp)
|
||||
}
|
||||
|
||||
compval := os.Getenv("GO_FLAGS_COMPLETION")
|
||||
|
||||
if len(compval) != 0 {
|
||||
comp := &completion{parser: p}
|
||||
items := comp.complete(args)
|
||||
|
||||
if p.CompletionHandler != nil {
|
||||
p.CompletionHandler(items)
|
||||
} else {
|
||||
comp.print(items, compval == "verbose")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
s := &parseState{
|
||||
args: args,
|
||||
retargs: make([]string, 0, len(args)),
|
||||
}
|
||||
|
||||
p.fillParseState(s)
|
||||
|
||||
for !s.eof() {
|
||||
arg := s.pop()
|
||||
|
||||
// When PassDoubleDash is set and we encounter a --, then
|
||||
// simply append all the rest as arguments and break out
|
||||
if (p.Options&PassDoubleDash) != None && arg == "--" {
|
||||
s.addArgs(s.args...)
|
||||
break
|
||||
}
|
||||
|
||||
if !argumentIsOption(arg) {
|
||||
// Note: this also sets s.err, so we can just check for
|
||||
// nil here and use s.err later
|
||||
if p.parseNonOption(s) != nil {
|
||||
break
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
prefix, optname, islong := stripOptionPrefix(arg)
|
||||
optname, _, argument := splitOption(prefix, optname, islong)
|
||||
|
||||
if islong {
|
||||
err = p.parseLong(s, optname, argument)
|
||||
} else {
|
||||
err = p.parseShort(s, optname, argument)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ignoreUnknown := (p.Options & IgnoreUnknown) != None
|
||||
parseErr := wrapError(err)
|
||||
|
||||
if parseErr.Type != ErrUnknownFlag || (!ignoreUnknown && p.UnknownOptionHandler == nil) {
|
||||
s.err = parseErr
|
||||
break
|
||||
}
|
||||
|
||||
if ignoreUnknown {
|
||||
s.addArgs(arg)
|
||||
} else if p.UnknownOptionHandler != nil {
|
||||
modifiedArgs, err := p.UnknownOptionHandler(optname, strArgument{argument}, s.args)
|
||||
|
||||
if err != nil {
|
||||
s.err = err
|
||||
break
|
||||
}
|
||||
|
||||
s.args = modifiedArgs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.err == nil {
|
||||
p.eachOption(func(c *Command, g *Group, option *Option) {
|
||||
if option.preventDefault {
|
||||
return
|
||||
}
|
||||
|
||||
option.clearDefault()
|
||||
})
|
||||
|
||||
s.checkRequired(p)
|
||||
}
|
||||
|
||||
var reterr error
|
||||
|
||||
if s.err != nil {
|
||||
reterr = s.err
|
||||
} else if len(s.command.commands) != 0 && !s.command.SubcommandsOptional {
|
||||
reterr = s.estimateCommand()
|
||||
} else if cmd, ok := s.command.data.(Commander); ok {
|
||||
if p.CommandHandler != nil {
|
||||
reterr = p.CommandHandler(cmd, s.retargs)
|
||||
} else {
|
||||
reterr = cmd.Execute(s.retargs)
|
||||
}
|
||||
} else if p.CommandHandler != nil {
|
||||
reterr = p.CommandHandler(nil, s.retargs)
|
||||
}
|
||||
|
||||
if reterr != nil {
|
||||
var retargs []string
|
||||
|
||||
if ourErr, ok := reterr.(*Error); !ok || ourErr.Type != ErrHelp {
|
||||
retargs = append([]string{s.arg}, s.args...)
|
||||
} else {
|
||||
retargs = s.args
|
||||
}
|
||||
|
||||
return retargs, p.printError(reterr)
|
||||
}
|
||||
|
||||
return s.retargs, nil
|
||||
}
|
||||
|
||||
func (p *parseState) eof() bool {
|
||||
return len(p.args) == 0
|
||||
}
|
||||
|
||||
func (p *parseState) pop() string {
|
||||
if p.eof() {
|
||||
return ""
|
||||
}
|
||||
|
||||
p.arg = p.args[0]
|
||||
p.args = p.args[1:]
|
||||
|
||||
return p.arg
|
||||
}
|
||||
|
||||
func (p *parseState) peek() string {
|
||||
if p.eof() {
|
||||
return ""
|
||||
}
|
||||
|
||||
return p.args[0]
|
||||
}
|
||||
|
||||
func (p *parseState) checkRequired(parser *Parser) error {
|
||||
c := parser.Command
|
||||
|
||||
var required []*Option
|
||||
|
||||
for c != nil {
|
||||
c.eachGroup(func(g *Group) {
|
||||
for _, option := range g.options {
|
||||
if !option.isSet && option.Required {
|
||||
required = append(required, option)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
c = c.Active
|
||||
}
|
||||
|
||||
if len(required) == 0 {
|
||||
if len(p.positional) > 0 {
|
||||
var reqnames []string
|
||||
|
||||
for _, arg := range p.positional {
|
||||
argRequired := (!arg.isRemaining() && p.command.ArgsRequired) || arg.Required != -1 || arg.RequiredMaximum != -1
|
||||
|
||||
if !argRequired {
|
||||
continue
|
||||
}
|
||||
|
||||
if arg.isRemaining() {
|
||||
if arg.value.Len() < arg.Required {
|
||||
var arguments string
|
||||
|
||||
if arg.Required > 1 {
|
||||
arguments = "arguments, but got only " + fmt.Sprintf("%d", arg.value.Len())
|
||||
} else {
|
||||
arguments = "argument"
|
||||
}
|
||||
|
||||
reqnames = append(reqnames, "`"+arg.Name+" (at least "+fmt.Sprintf("%d", arg.Required)+" "+arguments+")`")
|
||||
} else if arg.RequiredMaximum != -1 && arg.value.Len() > arg.RequiredMaximum {
|
||||
if arg.RequiredMaximum == 0 {
|
||||
reqnames = append(reqnames, "`"+arg.Name+" (zero arguments)`")
|
||||
} else {
|
||||
var arguments string
|
||||
|
||||
if arg.RequiredMaximum > 1 {
|
||||
arguments = "arguments, but got " + fmt.Sprintf("%d", arg.value.Len())
|
||||
} else {
|
||||
arguments = "argument"
|
||||
}
|
||||
|
||||
reqnames = append(reqnames, "`"+arg.Name+" (at most "+fmt.Sprintf("%d", arg.RequiredMaximum)+" "+arguments+")`")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reqnames = append(reqnames, "`"+arg.Name+"`")
|
||||
}
|
||||
}
|
||||
|
||||
if len(reqnames) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var msg string
|
||||
|
||||
if len(reqnames) == 1 {
|
||||
msg = fmt.Sprintf("the required argument %s was not provided", reqnames[0])
|
||||
} else {
|
||||
msg = fmt.Sprintf("the required arguments %s and %s were not provided",
|
||||
strings.Join(reqnames[:len(reqnames)-1], ", "), reqnames[len(reqnames)-1])
|
||||
}
|
||||
|
||||
p.err = newError(ErrRequired, msg)
|
||||
return p.err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(required))
|
||||
|
||||
for _, k := range required {
|
||||
names = append(names, "`"+k.String()+"'")
|
||||
}
|
||||
|
||||
sort.Strings(names)
|
||||
|
||||
var msg string
|
||||
|
||||
if len(names) == 1 {
|
||||
msg = fmt.Sprintf("the required flag %s was not specified", names[0])
|
||||
} else {
|
||||
msg = fmt.Sprintf("the required flags %s and %s were not specified",
|
||||
strings.Join(names[:len(names)-1], ", "), names[len(names)-1])
|
||||
}
|
||||
|
||||
p.err = newError(ErrRequired, msg)
|
||||
return p.err
|
||||
}
|
||||
|
||||
func (p *parseState) estimateCommand() error {
|
||||
commands := p.command.sortedVisibleCommands()
|
||||
cmdnames := make([]string, len(commands))
|
||||
|
||||
for i, v := range commands {
|
||||
cmdnames[i] = v.Name
|
||||
}
|
||||
|
||||
var msg string
|
||||
var errtype ErrorType
|
||||
|
||||
if len(p.retargs) != 0 {
|
||||
c, l := closestChoice(p.retargs[0], cmdnames)
|
||||
msg = fmt.Sprintf("Unknown command `%s'", p.retargs[0])
|
||||
errtype = ErrUnknownCommand
|
||||
|
||||
if float32(l)/float32(len(c)) < 0.5 {
|
||||
msg = fmt.Sprintf("%s, did you mean `%s'?", msg, c)
|
||||
} else if len(cmdnames) == 1 {
|
||||
msg = fmt.Sprintf("%s. You should use the %s command",
|
||||
msg,
|
||||
cmdnames[0])
|
||||
} else if len(cmdnames) > 1 {
|
||||
msg = fmt.Sprintf("%s. Please specify one command of: %s or %s",
|
||||
msg,
|
||||
strings.Join(cmdnames[:len(cmdnames)-1], ", "),
|
||||
cmdnames[len(cmdnames)-1])
|
||||
}
|
||||
} else {
|
||||
errtype = ErrCommandRequired
|
||||
|
||||
if len(cmdnames) == 1 {
|
||||
msg = fmt.Sprintf("Please specify the %s command", cmdnames[0])
|
||||
} else if len(cmdnames) > 1 {
|
||||
msg = fmt.Sprintf("Please specify one command of: %s or %s",
|
||||
strings.Join(cmdnames[:len(cmdnames)-1], ", "),
|
||||
cmdnames[len(cmdnames)-1])
|
||||
}
|
||||
}
|
||||
|
||||
return newError(errtype, msg)
|
||||
}
|
||||
|
||||
func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (err error) {
|
||||
if !option.canArgument() {
|
||||
if argument != nil {
|
||||
return newErrorf(ErrNoArgumentForBool, "bool flag `%s' cannot have an argument", option)
|
||||
}
|
||||
|
||||
err = option.set(nil)
|
||||
} else if argument != nil || (canarg && !s.eof()) {
|
||||
var arg string
|
||||
|
||||
if argument != nil {
|
||||
arg = *argument
|
||||
} else {
|
||||
arg = s.pop()
|
||||
|
||||
if argumentIsOption(arg) && !(option.isSignedNumber() && len(arg) > 1 && arg[0] == '-' && arg[1] >= '0' && arg[1] <= '9') {
|
||||
return newErrorf(ErrExpectedArgument, "expected argument for flag `%s', but got option `%s'", option, arg)
|
||||
} else if p.Options&PassDoubleDash != 0 && arg == "--" {
|
||||
return newErrorf(ErrExpectedArgument, "expected argument for flag `%s', but got double dash `--'", option)
|
||||
}
|
||||
}
|
||||
|
||||
if option.tag.Get("unquote") != "false" {
|
||||
arg, err = unquoteIfPossible(arg)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = option.set(&arg)
|
||||
}
|
||||
} else if option.OptionalArgument {
|
||||
option.empty()
|
||||
|
||||
for _, v := range option.OptionalValue {
|
||||
err = option.set(&v)
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = newErrorf(ErrExpectedArgument, "expected argument for flag `%s'", option)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if _, ok := err.(*Error); !ok {
|
||||
err = newErrorf(ErrMarshal, "invalid argument for flag `%s' (expected %s): %s",
|
||||
option,
|
||||
option.value.Type(),
|
||||
err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Parser) parseLong(s *parseState, name string, argument *string) error {
|
||||
if option := s.lookup.longNames[name]; option != nil {
|
||||
// Only long options that are required can consume an argument
|
||||
// from the argument list
|
||||
canarg := !option.OptionalArgument
|
||||
|
||||
return p.parseOption(s, name, option, canarg, argument)
|
||||
}
|
||||
|
||||
return newErrorf(ErrUnknownFlag, "unknown flag `%s'", name)
|
||||
}
|
||||
|
||||
func (p *Parser) splitShortConcatArg(s *parseState, optname string) (string, *string) {
|
||||
c, n := utf8.DecodeRuneInString(optname)
|
||||
|
||||
if n == len(optname) {
|
||||
return optname, nil
|
||||
}
|
||||
|
||||
first := string(c)
|
||||
|
||||
if option := s.lookup.shortNames[first]; option != nil && option.canArgument() {
|
||||
arg := optname[n:]
|
||||
return first, &arg
|
||||
}
|
||||
|
||||
return optname, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseShort(s *parseState, optname string, argument *string) error {
|
||||
if argument == nil {
|
||||
optname, argument = p.splitShortConcatArg(s, optname)
|
||||
}
|
||||
|
||||
for i, c := range optname {
|
||||
shortname := string(c)
|
||||
|
||||
if option := s.lookup.shortNames[shortname]; option != nil {
|
||||
// Only the last short argument can consume an argument from
|
||||
// the arguments list, and only if it's non optional
|
||||
canarg := (i+utf8.RuneLen(c) == len(optname)) && !option.OptionalArgument
|
||||
|
||||
if err := p.parseOption(s, shortname, option, canarg, argument); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return newErrorf(ErrUnknownFlag, "unknown flag `%s'", shortname)
|
||||
}
|
||||
|
||||
// Only the first option can have a concatted argument, so just
|
||||
// clear argument here
|
||||
argument = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *parseState) addArgs(args ...string) error {
|
||||
for len(p.positional) > 0 && len(args) > 0 {
|
||||
arg := p.positional[0]
|
||||
|
||||
if err := convert(args[0], arg.value, arg.tag); err != nil {
|
||||
p.err = err
|
||||
return err
|
||||
}
|
||||
|
||||
if !arg.isRemaining() {
|
||||
p.positional = p.positional[1:]
|
||||
}
|
||||
|
||||
args = args[1:]
|
||||
}
|
||||
|
||||
p.retargs = append(p.retargs, args...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseNonOption(s *parseState) error {
|
||||
if len(s.positional) > 0 {
|
||||
return s.addArgs(s.arg)
|
||||
}
|
||||
|
||||
if len(s.command.commands) > 0 && len(s.retargs) == 0 {
|
||||
if cmd := s.lookup.commands[s.arg]; cmd != nil {
|
||||
s.command.Active = cmd
|
||||
cmd.fillParseState(s)
|
||||
|
||||
return nil
|
||||
} else if !s.command.SubcommandsOptional {
|
||||
s.addArgs(s.arg)
|
||||
return newErrorf(ErrUnknownCommand, "Unknown command `%s'", s.arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (p.Options & PassAfterNonOption) != None {
|
||||
// If PassAfterNonOption is set then all remaining arguments
|
||||
// are considered positional
|
||||
if err := s.addArgs(s.arg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.addArgs(s.args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.args = []string{}
|
||||
} else {
|
||||
return s.addArgs(s.arg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) showBuiltinHelp() error {
|
||||
var b bytes.Buffer
|
||||
|
||||
p.WriteHelp(&b)
|
||||
return newError(ErrHelp, b.String())
|
||||
}
|
||||
|
||||
func (p *Parser) printError(err error) error {
|
||||
if err != nil && (p.Options&PrintErrors) != None {
|
||||
flagsErr, ok := err.(*Error)
|
||||
|
||||
if ok && flagsErr.Type == ErrHelp {
|
||||
fmt.Fprintln(os.Stdout, err)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Parser) clearIsSet() {
|
||||
p.eachCommand(func(c *Command) {
|
||||
c.eachGroup(func(g *Group) {
|
||||
for _, option := range g.options {
|
||||
option.isSet = false
|
||||
}
|
||||
})
|
||||
}, true)
|
||||
}
|
28
vendor/github.com/jessevdk/go-flags/termsize.go
generated
vendored
Normal file
28
vendor/github.com/jessevdk/go-flags/termsize.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// +build !windows,!plan9,!solaris,!appengine
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type winsize struct {
|
||||
row, col uint16
|
||||
xpixel, ypixel uint16
|
||||
}
|
||||
|
||||
func getTerminalColumns() int {
|
||||
ws := winsize{}
|
||||
|
||||
if tIOCGWINSZ != 0 {
|
||||
syscall.Syscall(syscall.SYS_IOCTL,
|
||||
uintptr(0),
|
||||
uintptr(tIOCGWINSZ),
|
||||
uintptr(unsafe.Pointer(&ws)))
|
||||
|
||||
return int(ws.col)
|
||||
}
|
||||
|
||||
return 80
|
||||
}
|
7
vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go
generated
vendored
Normal file
7
vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// +build windows plan9 solaris appengine
|
||||
|
||||
package flags
|
||||
|
||||
func getTerminalColumns() int {
|
||||
return 80
|
||||
}
|
7
vendor/github.com/jessevdk/go-flags/tiocgwinsz_bsdish.go
generated
vendored
Normal file
7
vendor/github.com/jessevdk/go-flags/tiocgwinsz_bsdish.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
|
||||
package flags
|
||||
|
||||
const (
|
||||
tIOCGWINSZ = 0x40087468
|
||||
)
|
7
vendor/github.com/jessevdk/go-flags/tiocgwinsz_linux.go
generated
vendored
Normal file
7
vendor/github.com/jessevdk/go-flags/tiocgwinsz_linux.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// +build linux
|
||||
|
||||
package flags
|
||||
|
||||
const (
|
||||
tIOCGWINSZ = 0x5413
|
||||
)
|
7
vendor/github.com/jessevdk/go-flags/tiocgwinsz_other.go
generated
vendored
Normal file
7
vendor/github.com/jessevdk/go-flags/tiocgwinsz_other.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// +build !darwin,!freebsd,!netbsd,!openbsd,!linux
|
||||
|
||||
package flags
|
||||
|
||||
const (
|
||||
tIOCGWINSZ = 0
|
||||
)
|
Loading…
Reference in New Issue
Block a user