Switch to dep for dependency management
This commit is contained in:
17
vendor/github.com/jessevdk/go-flags/.travis.yml
generated
vendored
17
vendor/github.com/jessevdk/go-flags/.travis.yml
generated
vendored
@@ -1,17 +1,26 @@
|
||||
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 code.google.com/p/go.tools/cmd/vet
|
||||
- go get github.com/golang/lint
|
||||
- go install github.com/golang/lint/golint
|
||||
- go get github.com/golang/lint/golint
|
||||
|
||||
# code coverage
|
||||
- go get code.google.com/p/go.tools/cmd/cover
|
||||
- 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
|
||||
|
||||
147
vendor/github.com/jessevdk/go-flags/README.md
generated
vendored
147
vendor/github.com/jessevdk/go-flags/README.md
generated
vendored
@@ -33,9 +33,11 @@ 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"`
|
||||
}
|
||||
```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
|
||||
@@ -44,88 +46,89 @@ resulting value of Verbose will be {[true, true, true]}.
|
||||
|
||||
Example:
|
||||
--------
|
||||
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"`
|
||||
```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 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 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 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 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 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 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 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"`
|
||||
}
|
||||
// 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()
|
||||
}
|
||||
// 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",
|
||||
}
|
||||
// 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)
|
||||
// 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)
|
||||
os.Exit(1)
|
||||
}
|
||||
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, " "))
|
||||
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
|
||||
// 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>
|
||||
|
||||
6
vendor/github.com/jessevdk/go-flags/arg.go
generated
vendored
6
vendor/github.com/jessevdk/go-flags/arg.go
generated
vendored
@@ -12,6 +12,12 @@ type Arg struct {
|
||||
// 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
|
||||
}
|
||||
|
||||
359
vendor/github.com/jessevdk/go-flags/command.go
generated
vendored
359
vendor/github.com/jessevdk/go-flags/command.go
generated
vendored
@@ -1,5 +1,12 @@
|
||||
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
|
||||
@@ -47,6 +54,13 @@ type Usage interface {
|
||||
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
|
||||
@@ -97,6 +111,32 @@ func (c *Command) Find(name string) *Command {
|
||||
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))
|
||||
@@ -104,3 +144,322 @@ func (c *Command) Args() []*Arg {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
250
vendor/github.com/jessevdk/go-flags/command_private.go
generated
vendored
250
vendor/github.com/jessevdk/go-flags/command_private.go
generated
vendored
@@ -1,250 +0,0 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type lookup struct {
|
||||
shortNames map[string]*Option
|
||||
longNames map[string]*Option
|
||||
|
||||
commands map[string]*Command
|
||||
}
|
||||
|
||||
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("name")
|
||||
|
||||
if len(name) == 0 {
|
||||
name = field.Name
|
||||
}
|
||||
|
||||
arg := &Arg{
|
||||
Name: name,
|
||||
Description: m.Get("description"),
|
||||
|
||||
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 {
|
||||
ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr()))
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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) 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),
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
for _, subcommand := range c.commands {
|
||||
ret.commands[subcommand.Name] = subcommand
|
||||
|
||||
for _, a := range subcommand.Aliases {
|
||||
ret.commands[a] = subcommand
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
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) sortedCommands() []*Command {
|
||||
ret := make(commandList, len(c.commands))
|
||||
copy(ret, c.commands)
|
||||
|
||||
sort.Sort(ret)
|
||||
return []*Command(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
|
||||
}
|
||||
95
vendor/github.com/jessevdk/go-flags/completion.go
generated
vendored
95
vendor/github.com/jessevdk/go-flags/completion.go
generated
vendored
@@ -43,8 +43,6 @@ type Completer interface {
|
||||
|
||||
type completion struct {
|
||||
parser *Parser
|
||||
|
||||
ShowDescriptions bool
|
||||
}
|
||||
|
||||
// Filename is a string alias which provides filename completion.
|
||||
@@ -75,27 +73,8 @@ func (c *completion) skipPositional(s *parseState, n int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *completion) completeOptionNames(names map[string]*Option, prefix string, match string) []Completion {
|
||||
n := make([]Completion, 0, len(names))
|
||||
|
||||
for k, opt := range names {
|
||||
if strings.HasPrefix(k, match) {
|
||||
n = append(n, Completion{
|
||||
Item: prefix + k,
|
||||
Description: opt.Description,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (c *completion) completeLongNames(s *parseState, prefix string, match string) []Completion {
|
||||
return c.completeOptionNames(s.lookup.longNames, prefix, match)
|
||||
}
|
||||
|
||||
func (c *completion) completeShortNames(s *parseState, prefix string, match string) []Completion {
|
||||
if len(match) != 0 {
|
||||
func (c *completion) completeOptionNames(s *parseState, prefix string, match string, short bool) []Completion {
|
||||
if short && len(match) != 0 {
|
||||
return []Completion{
|
||||
Completion{
|
||||
Item: prefix + match,
|
||||
@@ -103,7 +82,42 @@ func (c *completion) completeShortNames(s *parseState, prefix string, match stri
|
||||
}
|
||||
}
|
||||
|
||||
return c.completeOptionNames(s.lookup.shortNames, 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 {
|
||||
@@ -122,6 +136,9 @@ func (c *completion) completeCommands(s *parseState, match string) []Completion
|
||||
}
|
||||
|
||||
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
|
||||
@@ -141,16 +158,6 @@ func (c *completion) completeValue(value reflect.Value, prefix string, match str
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *completion) completeArg(arg *Arg, prefix string, match string) []Completion {
|
||||
if arg.isRemaining() {
|
||||
// For remaining positional args (that are parsed into a slice), complete
|
||||
// based on the element type.
|
||||
return c.completeValue(reflect.New(arg.value.Type().Elem()), prefix, match)
|
||||
}
|
||||
|
||||
return c.completeValue(arg.value, prefix, match)
|
||||
}
|
||||
|
||||
func (c *completion) complete(args []string) []Completion {
|
||||
if len(args) == 0 {
|
||||
args = []string{""}
|
||||
@@ -246,7 +253,7 @@ func (c *completion) complete(args []string) []Completion {
|
||||
if opt := s.lookup.shortNames[sname]; opt != nil && opt.canArgument() {
|
||||
ret = c.completeValue(opt.value, prefix+sname, optname[n:])
|
||||
} else {
|
||||
ret = c.completeShortNames(s, prefix, optname)
|
||||
ret = c.completeNamesForShortPrefix(s, prefix, optname)
|
||||
}
|
||||
} else if argument != nil {
|
||||
if islong {
|
||||
@@ -259,13 +266,13 @@ func (c *completion) complete(args []string) []Completion {
|
||||
ret = c.completeValue(opt.value, prefix+optname+split, *argument)
|
||||
}
|
||||
} else if islong {
|
||||
ret = c.completeLongNames(s, prefix, optname)
|
||||
ret = c.completeNamesForLongPrefix(s, prefix, optname)
|
||||
} else {
|
||||
ret = c.completeShortNames(s, prefix, optname)
|
||||
ret = c.completeNamesForShortPrefix(s, prefix, optname)
|
||||
}
|
||||
} else if len(s.positional) > 0 {
|
||||
// Complete for positional argument
|
||||
ret = c.completeArg(s.positional[0], "", lastarg)
|
||||
ret = c.completeValue(s.positional[0].value, "", lastarg)
|
||||
} else if len(s.command.commands) > 0 {
|
||||
// Complete for command
|
||||
ret = c.completeCommands(s, lastarg)
|
||||
@@ -275,19 +282,17 @@ func (c *completion) complete(args []string) []Completion {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *completion) execute(args []string) {
|
||||
ret := c.complete(args)
|
||||
|
||||
if c.ShowDescriptions && len(ret) > 1 {
|
||||
func (c *completion) print(items []Completion, showDescriptions bool) {
|
||||
if showDescriptions && len(items) > 1 {
|
||||
maxl := 0
|
||||
|
||||
for _, v := range ret {
|
||||
for _, v := range items {
|
||||
if len(v.Item) > maxl {
|
||||
maxl = len(v.Item)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range ret {
|
||||
for _, v := range items {
|
||||
fmt.Printf("%s", v.Item)
|
||||
|
||||
if len(v.Description) > 0 {
|
||||
@@ -297,7 +302,7 @@ func (c *completion) execute(args []string) {
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
} else {
|
||||
for _, v := range ret {
|
||||
for _, v := range items {
|
||||
fmt.Println(v.Item)
|
||||
}
|
||||
}
|
||||
|
||||
63
vendor/github.com/jessevdk/go-flags/convert.go
generated
vendored
63
vendor/github.com/jessevdk/go-flags/convert.go
generated
vendored
@@ -154,6 +154,13 @@ func convertToString(val reflect.Value, options multiTag) (string, error) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -312,6 +319,26 @@ func quoteIfNeeded(s string) string {
|
||||
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
|
||||
@@ -319,39 +346,3 @@ func unquoteIfPossible(s string) (string, error) {
|
||||
|
||||
return strconv.Unquote(s)
|
||||
}
|
||||
|
||||
func wrapText(s string, l int, prefix string) string {
|
||||
// Basic text wrapping of s at spaces to fit in l
|
||||
var ret string
|
||||
|
||||
s = strings.TrimSpace(s)
|
||||
|
||||
for len(s) > l {
|
||||
// Try to split on space
|
||||
suffix := ""
|
||||
|
||||
pos := strings.LastIndex(s[:l], " ")
|
||||
|
||||
if pos < 0 {
|
||||
pos = l - 1
|
||||
suffix = "-\n"
|
||||
}
|
||||
|
||||
if len(ret) != 0 {
|
||||
ret += "\n" + prefix
|
||||
}
|
||||
|
||||
ret += strings.TrimSpace(s[:pos]) + suffix
|
||||
s = strings.TrimSpace(s[pos:])
|
||||
}
|
||||
|
||||
if len(s) > 0 {
|
||||
if len(ret) != 0 {
|
||||
ret += "\n" + prefix
|
||||
}
|
||||
|
||||
return ret + s
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
11
vendor/github.com/jessevdk/go-flags/error.go
generated
vendored
11
vendor/github.com/jessevdk/go-flags/error.go
generated
vendored
@@ -51,6 +51,13 @@ const (
|
||||
|
||||
// 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 {
|
||||
@@ -81,6 +88,10 @@ func (e ErrorType) String() string {
|
||||
return "command required"
|
||||
case ErrUnknownCommand:
|
||||
return "unknown command"
|
||||
case ErrInvalidChoice:
|
||||
return "invalid choice"
|
||||
case ErrInvalidTag:
|
||||
return "invalid tag"
|
||||
}
|
||||
|
||||
return "unrecognized error type"
|
||||
|
||||
40
vendor/github.com/jessevdk/go-flags/flags.go
generated
vendored
40
vendor/github.com/jessevdk/go-flags/flags.go
generated
vendored
@@ -35,6 +35,8 @@ Additional features specific to Windows:
|
||||
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
|
||||
@@ -76,15 +78,17 @@ 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: whether an option is required to appear on the command
|
||||
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)
|
||||
no-flag: if non-empty, this field is ignored as an option (optional)
|
||||
|
||||
optional: whether an argument of the option is optional (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)
|
||||
@@ -102,8 +106,11 @@ The following is a list of tags for struct fields supported by go-flags:
|
||||
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,
|
||||
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)
|
||||
@@ -133,7 +140,16 @@ The following is a list of tags for struct fields supported by go-flags:
|
||||
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 (optional)
|
||||
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.
|
||||
@@ -179,12 +195,16 @@ 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. It is currently not valid
|
||||
to specify options from the parent level of the command after the command
|
||||
name has occurred. Thus, given a top-level option "-v" and a command "add":
|
||||
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:
|
||||
|
||||
Valid: ./app -v add
|
||||
Invalid: ./app add -v
|
||||
./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
|
||||
|
||||
315
vendor/github.com/jessevdk/go-flags/group.go
generated
vendored
315
vendor/github.com/jessevdk/go-flags/group.go
generated
vendored
@@ -6,7 +6,9 @@ package flags
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// ErrNotPointerToStruct indicates that a provided data container is not
|
||||
@@ -32,6 +34,9 @@ type Group struct {
|
||||
// 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{}
|
||||
|
||||
@@ -47,6 +52,8 @@ type Group struct {
|
||||
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.
|
||||
@@ -89,3 +96,311 @@ func (g *Group) Find(shortDescription string) *Group {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
254
vendor/github.com/jessevdk/go-flags/group_private.go
generated
vendored
254
vendor/github.com/jessevdk/go-flags/group_private.go
generated
vendored
@@ -1,254 +0,0 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type scanHandler func(reflect.Value, *reflect.StructField) (bool, error)
|
||||
|
||||
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
|
||||
|
||||
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 (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 != "" {
|
||||
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 {
|
||||
if fld.IsNil() {
|
||||
fld.Set(reflect.New(fld.Type().Elem()))
|
||||
}
|
||||
|
||||
if err := g.scanStruct(reflect.Indirect(fld), &field, handler); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
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 := (mtag.Get("optional") != "")
|
||||
required := (mtag.Get("required") != "")
|
||||
|
||||
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,
|
||||
|
||||
group: g,
|
||||
|
||||
field: field,
|
||||
value: realval.Field(i),
|
||||
tag: mtag,
|
||||
}
|
||||
|
||||
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 {
|
||||
ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr()))
|
||||
description := mtag.Get("description")
|
||||
|
||||
group, err := g.AddGroup(subgroup, description, ptrval.Interface())
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
group.Namespace = mtag.Get("namespace")
|
||||
|
||||
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)
|
||||
}
|
||||
151
vendor/github.com/jessevdk/go-flags/help.go
generated
vendored
151
vendor/github.com/jessevdk/go-flags/help.go
generated
vendored
@@ -9,7 +9,6 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
@@ -92,13 +91,75 @@ func (p *Parser) getAlignmentInfo() alignmentInfo {
|
||||
ret.hasValueName = true
|
||||
}
|
||||
|
||||
ret.updateLen(info.LongNameWithNamespace()+info.ValueName, c != p.Command)
|
||||
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{}
|
||||
|
||||
@@ -108,6 +169,10 @@ func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alig
|
||||
prefix += 4
|
||||
}
|
||||
|
||||
if option.Hidden {
|
||||
return
|
||||
}
|
||||
|
||||
line.WriteString(strings.Repeat(" ", prefix))
|
||||
|
||||
if option.ShortName != 0 {
|
||||
@@ -136,6 +201,10 @@ func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alig
|
||||
if len(option.ValueName) > 0 {
|
||||
line.WriteString(option.ValueName)
|
||||
}
|
||||
|
||||
if len(option.Choices) > 0 {
|
||||
line.WriteString("[" + strings.Join(option.Choices, "|") + "]")
|
||||
}
|
||||
}
|
||||
|
||||
written := line.Len()
|
||||
@@ -145,39 +214,14 @@ func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alig
|
||||
dw := descstart - written
|
||||
writer.WriteString(strings.Repeat(" ", dw))
|
||||
|
||||
def := ""
|
||||
defs := option.Default
|
||||
var def string
|
||||
|
||||
if len(option.DefaultMask) != 0 {
|
||||
if option.DefaultMask != "-" {
|
||||
def = option.DefaultMask
|
||||
}
|
||||
} else 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])
|
||||
} else {
|
||||
def = option.defaultLiteral
|
||||
}
|
||||
|
||||
var envDef string
|
||||
@@ -194,7 +238,7 @@ func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alig
|
||||
var desc string
|
||||
|
||||
if def != "" {
|
||||
desc = fmt.Sprintf("%s (%v)%s", option.Description, def, envDef)
|
||||
desc = fmt.Sprintf("%s (default: %v)%s", option.Description, def, envDef)
|
||||
} else {
|
||||
desc = option.Description + envDef
|
||||
}
|
||||
@@ -302,10 +346,12 @@ func (p *Parser) WriteHelp(writer io.Writer) {
|
||||
co, cc = "<", ">"
|
||||
}
|
||||
|
||||
if len(allcmd.commands) > 3 {
|
||||
visibleCommands := allcmd.visibleCommands()
|
||||
|
||||
if len(visibleCommands) > 3 {
|
||||
fmt.Fprintf(wr, " %scommand%s", co, cc)
|
||||
} else {
|
||||
subcommands := allcmd.sortedCommands()
|
||||
subcommands := allcmd.sortedVisibleCommands()
|
||||
names := make([]string, len(subcommands))
|
||||
|
||||
for i, subc := range subcommands {
|
||||
@@ -342,12 +388,12 @@ func (p *Parser) WriteHelp(writer io.Writer) {
|
||||
|
||||
// Skip built-in help group for all commands except the top-level
|
||||
// parser
|
||||
if grp.isBuiltinHelp && c != p.Command {
|
||||
if grp.Hidden || (grp.isBuiltinHelp && c != p.Command) {
|
||||
return
|
||||
}
|
||||
|
||||
for _, info := range grp.options {
|
||||
if !info.canCli() {
|
||||
if !info.canCli() || info.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -372,22 +418,41 @@ func (p *Parser) WriteHelp(writer io.Writer) {
|
||||
}
|
||||
})
|
||||
|
||||
if len(c.args) > 0 {
|
||||
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)
|
||||
}
|
||||
|
||||
maxlen := aligninfo.descriptionStart()
|
||||
descStart := aligninfo.descriptionStart() + paddingBeforeOption
|
||||
|
||||
for _, arg := range c.args {
|
||||
prefix := strings.Repeat(" ", paddingBeforeOption)
|
||||
fmt.Fprintf(wr, "%s%s", prefix, arg.Name)
|
||||
for _, arg := range args {
|
||||
argPrefix := strings.Repeat(" ", paddingBeforeOption)
|
||||
argPrefix += arg.Name
|
||||
|
||||
if len(arg.Description) > 0 {
|
||||
align := strings.Repeat(" ", maxlen-len(arg.Name)-1)
|
||||
fmt.Fprintf(wr, ":%s%s", align, arg.Description)
|
||||
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)
|
||||
@@ -397,7 +462,7 @@ func (p *Parser) WriteHelp(writer io.Writer) {
|
||||
c = c.Active
|
||||
}
|
||||
|
||||
scommands := cmd.sortedCommands()
|
||||
scommands := cmd.sortedVisibleCommands()
|
||||
|
||||
if len(scommands) > 0 {
|
||||
maxnamelen := maxCommandLength(scommands)
|
||||
|
||||
469
vendor/github.com/jessevdk/go-flags/ini.go
generated
vendored
469
vendor/github.com/jessevdk/go-flags/ini.go
generated
vendored
@@ -1,11 +1,17 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IniError contains location information on where an error occured.
|
||||
// IniError contains location information on where an error occurred.
|
||||
type IniError struct {
|
||||
// The error message.
|
||||
Message string
|
||||
@@ -52,9 +58,25 @@ const (
|
||||
// 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{
|
||||
@@ -76,8 +98,6 @@ func IniParse(filename string, data interface{}) error {
|
||||
// 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 {
|
||||
i.parser.clearIsSet()
|
||||
|
||||
ini, err := readIniFromFile(filename)
|
||||
|
||||
if err != nil {
|
||||
@@ -112,8 +132,6 @@ func (i *IniParser) ParseFile(filename string) error {
|
||||
//
|
||||
// The returned errors can be of the type flags.Error or flags.IniError.
|
||||
func (i *IniParser) Parse(reader io.Reader) error {
|
||||
i.parser.clearIsSet()
|
||||
|
||||
ini, err := readIni(reader, "")
|
||||
|
||||
if err != nil {
|
||||
@@ -123,7 +141,7 @@ func (i *IniParser) Parse(reader io.Reader) error {
|
||||
return i.parse(ini)
|
||||
}
|
||||
|
||||
// WriteFile writes the flags as ini format into a file. See WriteIni
|
||||
// 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 {
|
||||
@@ -138,3 +156,442 @@ func (i *IniParser) WriteFile(filename string, options IniOptions) error {
|
||||
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
|
||||
}
|
||||
|
||||
452
vendor/github.com/jessevdk/go-flags/ini_private.go
generated
vendored
452
vendor/github.com/jessevdk/go-flags/ini_private.go
generated
vendored
@@ -1,452 +0,0 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type iniValue struct {
|
||||
Name string
|
||||
Value string
|
||||
Quoted bool
|
||||
LineNumber uint
|
||||
}
|
||||
|
||||
type iniSection []iniValue
|
||||
type ini struct {
|
||||
File string
|
||||
Sections map[string]iniSection
|
||||
}
|
||||
|
||||
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() {
|
||||
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) {
|
||||
writeGroupIni(command, group, namespace, writer, options)
|
||||
})
|
||||
|
||||
for _, c := range command.commands {
|
||||
var nns string
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
79
vendor/github.com/jessevdk/go-flags/man.go
generated
vendored
79
vendor/github.com/jessevdk/go-flags/man.go
generated
vendored
@@ -3,38 +3,58 @@ 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", s)
|
||||
fmt.Fprintf(wr, "%s", manQuote(s))
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "%s", s[:idx])
|
||||
fmt.Fprintf(wr, "%s", manQuote(s[:idx]))
|
||||
|
||||
s = s[idx+1:]
|
||||
idx = strings.IndexRune(s, '\'')
|
||||
|
||||
if idx < 0 {
|
||||
fmt.Fprintf(wr, "%s", s)
|
||||
fmt.Fprintf(wr, "%s", manQuote(s))
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "\\fB%s\\fP", s[:idx])
|
||||
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() {
|
||||
if !opt.canCli() || opt.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -42,7 +62,7 @@ func writeManPageOptions(wr io.Writer, grp *Group) {
|
||||
fmt.Fprintf(wr, "\\fB")
|
||||
|
||||
if opt.ShortName != 0 {
|
||||
fmt.Fprintf(wr, "-%c", opt.ShortName)
|
||||
fmt.Fprintf(wr, "\\fB\\-%c\\fR", opt.ShortName)
|
||||
}
|
||||
|
||||
if len(opt.LongName) != 0 {
|
||||
@@ -50,10 +70,33 @@ func writeManPageOptions(wr io.Writer, grp *Group) {
|
||||
fmt.Fprintf(wr, ", ")
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "--%s", opt.LongNameWithNamespace())
|
||||
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, "")
|
||||
@@ -63,11 +106,15 @@ func writeManPageOptions(wr io.Writer, grp *Group) {
|
||||
}
|
||||
|
||||
func writeManPageSubcommands(wr io.Writer, name string, root *Command) {
|
||||
commands := root.sortedCommands()
|
||||
commands := root.sortedVisibleCommands()
|
||||
|
||||
for _, c := range commands {
|
||||
var nn string
|
||||
|
||||
if c.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(name) != 0 {
|
||||
nn = name + " " + c.Name
|
||||
} else {
|
||||
@@ -85,10 +132,10 @@ func writeManPageCommand(wr io.Writer, name string, root *Command, command *Comm
|
||||
if len(command.LongDescription) > 0 {
|
||||
fmt.Fprintln(wr, "")
|
||||
|
||||
cmdstart := fmt.Sprintf("The %s command", command.Name)
|
||||
cmdstart := fmt.Sprintf("The %s command", manQuote(command.Name))
|
||||
|
||||
if strings.HasPrefix(command.LongDescription, cmdstart) {
|
||||
fmt.Fprintf(wr, "The \\fI%s\\fP command", command.Name)
|
||||
fmt.Fprintf(wr, "The \\fI%s\\fP command", manQuote(command.Name))
|
||||
|
||||
formatForMan(wr, command.LongDescription[len(cmdstart):])
|
||||
fmt.Fprintln(wr, "")
|
||||
@@ -113,11 +160,11 @@ func writeManPageCommand(wr io.Writer, name string, root *Command, command *Comm
|
||||
}
|
||||
|
||||
if len(usage) > 0 {
|
||||
fmt.Fprintf(wr, "\n\\fBUsage\\fP: %s %s\n\n", pre, usage)
|
||||
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", strings.Join(command.Aliases, ", "))
|
||||
fmt.Fprintf(wr, "\n\\fBAliases\\fP: %s\n\n", manQuote(strings.Join(command.Aliases, ", ")))
|
||||
}
|
||||
|
||||
writeManPageOptions(wr, command.Group)
|
||||
@@ -129,9 +176,9 @@ func writeManPageCommand(wr io.Writer, name string, root *Command, command *Comm
|
||||
func (p *Parser) WriteManPage(wr io.Writer) {
|
||||
t := time.Now()
|
||||
|
||||
fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", p.Name, t.Format("2 January 2006"))
|
||||
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", p.Name, p.ShortDescription)
|
||||
fmt.Fprintf(wr, "%s \\- %s\n", manQuote(p.Name), manQuote(p.ShortDescription))
|
||||
fmt.Fprintln(wr, ".SH SYNOPSIS")
|
||||
|
||||
usage := p.Usage
|
||||
@@ -140,7 +187,7 @@ func (p *Parser) WriteManPage(wr io.Writer) {
|
||||
usage = "[OPTIONS]"
|
||||
}
|
||||
|
||||
fmt.Fprintf(wr, "\\fB%s\\fP %s\n", p.Name, usage)
|
||||
fmt.Fprintf(wr, "\\fB%s\\fP %s\n", manQuote(p.Name), manQuote(usage))
|
||||
fmt.Fprintln(wr, ".SH DESCRIPTION")
|
||||
|
||||
formatForMan(wr, p.LongDescription)
|
||||
@@ -150,7 +197,7 @@ func (p *Parser) WriteManPage(wr io.Writer) {
|
||||
|
||||
writeManPageOptions(wr, p.Command.Group)
|
||||
|
||||
if len(p.commands) > 0 {
|
||||
if len(p.visibleCommands()) > 0 {
|
||||
fmt.Fprintln(wr, ".SH COMMANDS")
|
||||
|
||||
writeManPageSubcommands(wr, "", p.Command)
|
||||
|
||||
308
vendor/github.com/jessevdk/go-flags/option.go
generated
vendored
308
vendor/github.com/jessevdk/go-flags/option.go
generated
vendored
@@ -1,8 +1,11 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
@@ -35,7 +38,7 @@ type Option struct {
|
||||
|
||||
// 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 Default will be set in the field this option represents.
|
||||
// value of OptionalValue will be set in the field this option represents.
|
||||
// This is only valid for non-boolean options.
|
||||
OptionalArgument bool
|
||||
|
||||
@@ -59,6 +62,12 @@ type Option struct {
|
||||
// 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
|
||||
|
||||
@@ -71,8 +80,12 @@ type Option struct {
|
||||
// Determines if the option will be always quoted in the INI output
|
||||
iniQuote bool
|
||||
|
||||
tag multiTag
|
||||
isSet bool
|
||||
tag multiTag
|
||||
isSet bool
|
||||
isSetDefault bool
|
||||
preventDefault bool
|
||||
|
||||
defaultLiteral string
|
||||
}
|
||||
|
||||
// LongNameWithNamespace returns the option's long name with the group namespaces
|
||||
@@ -155,3 +168,292 @@ func (option *Option) String() string {
|
||||
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()
|
||||
}
|
||||
|
||||
182
vendor/github.com/jessevdk/go-flags/option_private.go
generated
vendored
182
vendor/github.com/jessevdk/go-flags/option_private.go
generated
vendored
@@ -1,182 +0,0 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
option.isSet = true
|
||||
|
||||
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 != "" {
|
||||
// os.Getenv() makes no distinction between undefined and
|
||||
// empty values, so we use syscall.Getenv()
|
||||
if value, ok := syscall.Getenv(envKey); ok {
|
||||
if option.EnvDefaultDelim != "" {
|
||||
usedDefault = strings.Split(value,
|
||||
option.EnvDefaultDelim)
|
||||
} else {
|
||||
usedDefault = []string{value}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(usedDefault) > 0 {
|
||||
option.empty()
|
||||
|
||||
for _, d := range usedDefault {
|
||||
option.set(&d)
|
||||
}
|
||||
} 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.Bool:
|
||||
return true
|
||||
case reflect.Slice:
|
||||
return (tp.Elem().Kind() == reflect.Bool)
|
||||
case reflect.Func:
|
||||
return tp.NumIn() == 0
|
||||
case reflect.Ptr:
|
||||
tp = tp.Elem()
|
||||
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
|
||||
}
|
||||
2
vendor/github.com/jessevdk/go-flags/optstyle_other.go
generated
vendored
2
vendor/github.com/jessevdk/go-flags/optstyle_other.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build !windows
|
||||
// +build !windows forceposix
|
||||
|
||||
package flags
|
||||
|
||||
|
||||
2
vendor/github.com/jessevdk/go-flags/optstyle_windows.go
generated
vendored
2
vendor/github.com/jessevdk/go-flags/optstyle_windows.go
generated
vendored
@@ -1,3 +1,5 @@
|
||||
// +build !forceposix
|
||||
|
||||
package flags
|
||||
|
||||
import (
|
||||
|
||||
454
vendor/github.com/jessevdk/go-flags/parser.go
generated
vendored
454
vendor/github.com/jessevdk/go-flags/parser.go
generated
vendored
@@ -5,8 +5,13 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A Parser provides command line option parsing. It can contain several
|
||||
@@ -32,6 +37,21 @@ type Parser struct {
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -67,7 +87,7 @@ const (
|
||||
// -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.Stderr.
|
||||
// will also be automatically printed to os.Stdout.
|
||||
HelpFlag = 1 << iota
|
||||
|
||||
// PassDoubleDash passes all arguments after a double dash, --, as
|
||||
@@ -80,7 +100,8 @@ const (
|
||||
IgnoreUnknown
|
||||
|
||||
// PrintErrors prints any errors which occurred during parsing to
|
||||
// os.Stderr.
|
||||
// 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
|
||||
@@ -93,6 +114,17 @@ const (
|
||||
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
|
||||
@@ -162,14 +194,19 @@ func (p *Parser) Parse() ([]string, error) {
|
||||
//
|
||||
// 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. Furthermore, the special error type ErrHelp is returned.
|
||||
// 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.clearIsSet()
|
||||
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 {
|
||||
@@ -180,13 +217,15 @@ func (p *Parser) ParseArgs(args []string) ([]string, error) {
|
||||
|
||||
if len(compval) != 0 {
|
||||
comp := &completion{parser: p}
|
||||
items := comp.complete(args)
|
||||
|
||||
if compval == "verbose" {
|
||||
comp.ShowDescriptions = true
|
||||
if p.CompletionHandler != nil {
|
||||
p.CompletionHandler(items)
|
||||
} else {
|
||||
comp.print(items, compval == "verbose")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
comp.execute(args)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -253,17 +292,13 @@ func (p *Parser) ParseArgs(args []string) ([]string, error) {
|
||||
}
|
||||
|
||||
if s.err == nil {
|
||||
p.eachCommand(func(c *Command) {
|
||||
c.eachGroup(func(g *Group) {
|
||||
for _, option := range g.options {
|
||||
if option.isSet {
|
||||
continue
|
||||
}
|
||||
p.eachOption(func(c *Command, g *Group, option *Option) {
|
||||
if option.preventDefault {
|
||||
return
|
||||
}
|
||||
|
||||
option.clearDefault()
|
||||
}
|
||||
})
|
||||
}, true)
|
||||
option.clearDefault()
|
||||
})
|
||||
|
||||
s.checkRequired(p)
|
||||
}
|
||||
@@ -275,12 +310,391 @@ func (p *Parser) ParseArgs(args []string) ([]string, error) {
|
||||
} else if len(s.command.commands) != 0 && !s.command.SubcommandsOptional {
|
||||
reterr = s.estimateCommand()
|
||||
} else if cmd, ok := s.command.data.(Commander); ok {
|
||||
reterr = cmd.Execute(s.retargs)
|
||||
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 {
|
||||
return append([]string{s.arg}, s.args...), p.printError(reterr)
|
||||
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)
|
||||
}
|
||||
|
||||
340
vendor/github.com/jessevdk/go-flags/parser_private.go
generated
vendored
340
vendor/github.com/jessevdk/go-flags/parser_private.go
generated
vendored
@@ -1,340 +0,0 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type parseState struct {
|
||||
arg string
|
||||
args []string
|
||||
retargs []string
|
||||
positional []*Arg
|
||||
err error
|
||||
|
||||
command *Command
|
||||
lookup lookup
|
||||
}
|
||||
|
||||
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 && p.command.ArgsRequired {
|
||||
var reqnames []string
|
||||
|
||||
for _, arg := range p.positional {
|
||||
if arg.isRemaining() {
|
||||
break
|
||||
}
|
||||
|
||||
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.sortedCommands()
|
||||
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 {
|
||||
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 {
|
||||
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) {
|
||||
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 {
|
||||
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 cmd := s.lookup.commands[s.arg]; cmd != nil {
|
||||
s.command.Active = cmd
|
||||
cmd.fillParseState(s)
|
||||
} else 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 {
|
||||
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)
|
||||
}
|
||||
2
vendor/github.com/jessevdk/go-flags/termsize.go
generated
vendored
2
vendor/github.com/jessevdk/go-flags/termsize.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build !windows,!plan9,!solaris
|
||||
// +build !windows,!plan9,!solaris,!appengine
|
||||
|
||||
package flags
|
||||
|
||||
|
||||
2
vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go
generated
vendored
2
vendor/github.com/jessevdk/go-flags/termsize_nosysioctl.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
// +build windows plan9 solaris
|
||||
// +build windows plan9 solaris appengine
|
||||
|
||||
package flags
|
||||
|
||||
|
||||
Reference in New Issue
Block a user