mirror of https://github.com/restic/restic.git
Update spf13/pflag
This commit is contained in:
parent
5a7e463ef6
commit
faca9276e9
|
@ -70,7 +70,7 @@
|
||||||
{
|
{
|
||||||
"importpath": "github.com/spf13/pflag",
|
"importpath": "github.com/spf13/pflag",
|
||||||
"repository": "https://github.com/spf13/pflag",
|
"repository": "https://github.com/spf13/pflag",
|
||||||
"revision": "c7e63cf4530bcd3ba943729cee0efeff2ebea63f",
|
"revision": "2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51",
|
||||||
"branch": "master"
|
"branch": "master"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
|
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
@ -106,9 +108,9 @@ that give one-letter shorthands for flags. You can use these by appending
|
||||||
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
||||||
var flagvar bool
|
var flagvar bool
|
||||||
func init() {
|
func init() {
|
||||||
flag.BoolVarP("boolname", "b", true, "help message")
|
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
|
||||||
}
|
}
|
||||||
flag.VarP(&flagVar, "varname", "v", 1234, "help message")
|
flag.VarP(&flagVal, "varname", "v", "help message")
|
||||||
```
|
```
|
||||||
|
|
||||||
Shorthand letters can be used with single dashes on the command line.
|
Shorthand letters can be used with single dashes on the command line.
|
||||||
|
@ -268,8 +270,8 @@ func main() {
|
||||||
You can see the full reference documentation of the pflag package
|
You can see the full reference documentation of the pflag package
|
||||||
[at godoc.org][3], or through go's standard documentation system by
|
[at godoc.org][3], or through go's standard documentation system by
|
||||||
running `godoc -http=:6060` and browsing to
|
running `godoc -http=:6060` and browsing to
|
||||||
[http://localhost:6060/pkg/github.com/ogier/pflag][2] after
|
[http://localhost:6060/pkg/github.com/spf13/pflag][2] after
|
||||||
installation.
|
installation.
|
||||||
|
|
||||||
[2]: http://localhost:6060/pkg/github.com/ogier/pflag
|
[2]: http://localhost:6060/pkg/github.com/spf13/pflag
|
||||||
[3]: http://godoc.org/github.com/ogier/pflag
|
[3]: http://godoc.org/github.com/spf13/pflag
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- boolSlice Value
|
||||||
|
type boolSliceValue struct {
|
||||||
|
value *[]bool
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
|
||||||
|
bsv := new(boolSliceValue)
|
||||||
|
bsv.value = p
|
||||||
|
*bsv.value = val
|
||||||
|
return bsv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
|
||||||
|
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
|
||||||
|
func (s *boolSliceValue) Set(val string) error {
|
||||||
|
|
||||||
|
// remove all quote characters
|
||||||
|
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||||
|
|
||||||
|
// read flag arguments with CSV parser
|
||||||
|
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse boolean values into slice
|
||||||
|
out := make([]bool, 0, len(boolStrSlice))
|
||||||
|
for _, boolStr := range boolStrSlice {
|
||||||
|
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out = append(out, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.changed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns a string that uniquely represents this flag's type.
|
||||||
|
func (s *boolSliceValue) Type() string {
|
||||||
|
return "boolSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a "native" format for this boolean slice flag value.
|
||||||
|
func (s *boolSliceValue) String() string {
|
||||||
|
|
||||||
|
boolStrSlice := make([]string, len(*s.value))
|
||||||
|
for i, b := range *s.value {
|
||||||
|
boolStrSlice[i] = strconv.FormatBool(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, _ := writeAsCSV(boolStrSlice)
|
||||||
|
|
||||||
|
return "[" + out + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []bool{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]bool, len(ss))
|
||||||
|
for i, t := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.ParseBool(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBoolSlice returns the []bool value of a flag with the given name.
|
||||||
|
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
|
||||||
|
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []bool{}, err
|
||||||
|
}
|
||||||
|
return val.([]bool), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []bool variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
||||||
|
f.VarP(newBoolSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
||||||
|
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []bool variable in which to store the value of the flag.
|
||||||
|
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
|
||||||
|
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
|
||||||
|
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []bool variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
|
||||||
|
p := []bool{}
|
||||||
|
f.BoolSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
||||||
|
p := []bool{}
|
||||||
|
f.BoolSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []bool variable that stores the value of the flag.
|
||||||
|
func BoolSlice(name string, value []bool, usage string) *[]bool {
|
||||||
|
return CommandLine.BoolSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
|
||||||
|
return CommandLine.BoolSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
|
@ -0,0 +1,215 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setUpBSFlagSet(bsp *[]bool) *FlagSet {
|
||||||
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
|
f.BoolSliceVar(bsp, "bs", []bool{}, "Command separated list!")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUpBSFlagSetWithDefault(bsp *[]bool) *FlagSet {
|
||||||
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
|
f.BoolSliceVar(bsp, "bs", []bool{false, true}, "Command separated list!")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyBS(t *testing.T) {
|
||||||
|
var bs []bool
|
||||||
|
f := setUpBSFlagSet(&bs)
|
||||||
|
err := f.Parse([]string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
getBS, err := f.GetBoolSlice("bs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetBoolSlice():", err)
|
||||||
|
}
|
||||||
|
if len(getBS) != 0 {
|
||||||
|
t.Fatalf("got bs %v with len=%d but expected length=0", getBS, len(getBS))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBS(t *testing.T) {
|
||||||
|
var bs []bool
|
||||||
|
f := setUpBSFlagSet(&bs)
|
||||||
|
|
||||||
|
vals := []string{"1", "F", "TRUE", "0"}
|
||||||
|
arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
|
||||||
|
err := f.Parse([]string{arg})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range bs {
|
||||||
|
b, err := strconv.ParseBool(vals[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if b != v {
|
||||||
|
t.Fatalf("expected is[%d] to be %s but got: %t", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getBS, err := f.GetBoolSlice("bs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
for i, v := range getBS {
|
||||||
|
b, err := strconv.ParseBool(vals[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if b != v {
|
||||||
|
t.Fatalf("expected bs[%d] to be %s but got: %t from GetBoolSlice", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBSDefault(t *testing.T) {
|
||||||
|
var bs []bool
|
||||||
|
f := setUpBSFlagSetWithDefault(&bs)
|
||||||
|
|
||||||
|
vals := []string{"false", "T"}
|
||||||
|
|
||||||
|
err := f.Parse([]string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range bs {
|
||||||
|
b, err := strconv.ParseBool(vals[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if b != v {
|
||||||
|
t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getBS, err := f.GetBoolSlice("bs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetBoolSlice():", err)
|
||||||
|
}
|
||||||
|
for i, v := range getBS {
|
||||||
|
b, err := strconv.ParseBool(vals[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetBoolSlice():", err)
|
||||||
|
}
|
||||||
|
if b != v {
|
||||||
|
t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBSWithDefault(t *testing.T) {
|
||||||
|
var bs []bool
|
||||||
|
f := setUpBSFlagSetWithDefault(&bs)
|
||||||
|
|
||||||
|
vals := []string{"FALSE", "1"}
|
||||||
|
arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ","))
|
||||||
|
err := f.Parse([]string{arg})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range bs {
|
||||||
|
b, err := strconv.ParseBool(vals[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if b != v {
|
||||||
|
t.Fatalf("expected bs[%d] to be %t but got: %t", i, b, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getBS, err := f.GetBoolSlice("bs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetBoolSlice():", err)
|
||||||
|
}
|
||||||
|
for i, v := range getBS {
|
||||||
|
b, err := strconv.ParseBool(vals[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if b != v {
|
||||||
|
t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBSCalledTwice(t *testing.T) {
|
||||||
|
var bs []bool
|
||||||
|
f := setUpBSFlagSet(&bs)
|
||||||
|
|
||||||
|
in := []string{"T,F", "T"}
|
||||||
|
expected := []bool{true, false, true}
|
||||||
|
argfmt := "--bs=%s"
|
||||||
|
arg1 := fmt.Sprintf(argfmt, in[0])
|
||||||
|
arg2 := fmt.Sprintf(argfmt, in[1])
|
||||||
|
err := f.Parse([]string{arg1, arg2})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range bs {
|
||||||
|
if expected[i] != v {
|
||||||
|
t.Fatalf("expected bs[%d] to be %t but got %t", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBSBadQuoting(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Want []bool
|
||||||
|
FlagArg []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Want: []bool{true, false, true},
|
||||||
|
FlagArg: []string{"1", "0", "true"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []bool{true, false},
|
||||||
|
FlagArg: []string{"True", "F"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []bool{true, false},
|
||||||
|
FlagArg: []string{"T", "0"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []bool{true, false},
|
||||||
|
FlagArg: []string{"1", "0"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []bool{true, false, false},
|
||||||
|
FlagArg: []string{"true,false", "false"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []bool{true, false, false, true, false, true, false},
|
||||||
|
FlagArg: []string{`"true,false,false,1,0, T"`, " false "},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []bool{false, false, true, false, true, false, true},
|
||||||
|
FlagArg: []string{`"0, False, T,false , true,F"`, "true"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
|
||||||
|
var bs []bool
|
||||||
|
f := setUpBSFlagSet(&bs)
|
||||||
|
|
||||||
|
if err := f.Parse([]string{fmt.Sprintf("--bs=%s", strings.Join(test.FlagArg, ","))}); err != nil {
|
||||||
|
t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%#v",
|
||||||
|
err, test.FlagArg, test.Want[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, b := range bs {
|
||||||
|
if b != test.Want[j] {
|
||||||
|
t.Fatalf("bad value parsed for test %d on bool %d:\nwant:\t%t\ngot:\t%t", i, j, test.Want[j], b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ package pflag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -48,7 +47,7 @@ func (v *triStateValue) String() string {
|
||||||
if *v == triStateMaybe {
|
if *v == triStateMaybe {
|
||||||
return strTriStateMaybe
|
return strTriStateMaybe
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%v", bool(*v == triStateTrue))
|
return strconv.FormatBool(*v == triStateTrue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The type of the flag as required by the pflag.Value interface
|
// The type of the flag as required by the pflag.Value interface
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package pflag
|
package pflag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Printf
|
|
||||||
|
|
||||||
func setUpCount(c *int) *FlagSet {
|
func setUpCount(c *int) *FlagSet {
|
||||||
f := NewFlagSet("test", ContinueOnError)
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
f.CountVarP(c, "verbose", "v", "a counter")
|
f.CountVarP(c, "verbose", "v", "a counter")
|
||||||
|
|
|
@ -16,9 +16,9 @@ pflag is a drop-in replacement of Go's native flag package. If you import
|
||||||
pflag under the name "flag" then all code should continue to function
|
pflag under the name "flag" then all code should continue to function
|
||||||
with no changes.
|
with no changes.
|
||||||
|
|
||||||
import flag "github.com/ogier/pflag"
|
import flag "github.com/spf13/pflag"
|
||||||
|
|
||||||
There is one exception to this: if you directly instantiate the Flag struct
|
There is one exception to this: if you directly instantiate the Flag struct
|
||||||
there is one more field "Shorthand" that you will need to set.
|
there is one more field "Shorthand" that you will need to set.
|
||||||
Most code never instantiates this struct directly, and instead uses
|
Most code never instantiates this struct directly, and instead uses
|
||||||
functions such as String(), BoolVar(), and Var(), and is therefore
|
functions such as String(), BoolVar(), and Var(), and is therefore
|
||||||
|
@ -134,14 +134,21 @@ type FlagSet struct {
|
||||||
// a custom error handler.
|
// a custom error handler.
|
||||||
Usage func()
|
Usage func()
|
||||||
|
|
||||||
|
// SortFlags is used to indicate, if user wants to have sorted flags in
|
||||||
|
// help/usage messages.
|
||||||
|
SortFlags bool
|
||||||
|
|
||||||
name string
|
name string
|
||||||
parsed bool
|
parsed bool
|
||||||
actual map[NormalizedName]*Flag
|
actual map[NormalizedName]*Flag
|
||||||
|
orderedActual []*Flag
|
||||||
|
sortedActual []*Flag
|
||||||
formal map[NormalizedName]*Flag
|
formal map[NormalizedName]*Flag
|
||||||
|
orderedFormal []*Flag
|
||||||
|
sortedFormal []*Flag
|
||||||
shorthands map[byte]*Flag
|
shorthands map[byte]*Flag
|
||||||
args []string // arguments after flags
|
args []string // arguments after flags
|
||||||
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
|
||||||
exitOnError bool // does the program exit if there's an error?
|
|
||||||
errorHandling ErrorHandling
|
errorHandling ErrorHandling
|
||||||
output io.Writer // nil means stderr; use out() accessor
|
output io.Writer // nil means stderr; use out() accessor
|
||||||
interspersed bool // allow interspersed option/non-option args
|
interspersed bool // allow interspersed option/non-option args
|
||||||
|
@ -156,7 +163,7 @@ type Flag struct {
|
||||||
Value Value // value as set
|
Value Value // value as set
|
||||||
DefValue string // default value (as text); for usage message
|
DefValue string // default value (as text); for usage message
|
||||||
Changed bool // If the user set the value (or if left to default)
|
Changed bool // If the user set the value (or if left to default)
|
||||||
NoOptDefVal string //default value (as text); if the flag is on the command line without any options
|
NoOptDefVal string // default value (as text); if the flag is on the command line without any options
|
||||||
Deprecated string // If this flag is deprecated, this string is the new or now thing to use
|
Deprecated string // If this flag is deprecated, this string is the new or now thing to use
|
||||||
Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text
|
Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text
|
||||||
ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use
|
ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use
|
||||||
|
@ -194,11 +201,13 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
||||||
// "--getUrl" which may also be translated to "geturl" and everything will work.
|
// "--getUrl" which may also be translated to "geturl" and everything will work.
|
||||||
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
||||||
f.normalizeNameFunc = n
|
f.normalizeNameFunc = n
|
||||||
for k, v := range f.formal {
|
f.sortedFormal = f.sortedFormal[:0]
|
||||||
delete(f.formal, k)
|
for k, v := range f.orderedFormal {
|
||||||
nname := f.normalizeFlagName(string(k))
|
delete(f.formal, NormalizedName(v.Name))
|
||||||
f.formal[nname] = v
|
nname := f.normalizeFlagName(v.Name)
|
||||||
v.Name = string(nname)
|
v.Name = string(nname)
|
||||||
|
f.formal[nname] = v
|
||||||
|
f.orderedFormal[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,10 +238,25 @@ func (f *FlagSet) SetOutput(output io.Writer) {
|
||||||
f.output = output
|
f.output = output
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisitAll visits the flags in lexicographical order, calling fn for each.
|
// VisitAll visits the flags in lexicographical order or
|
||||||
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
// It visits all flags, even those not set.
|
// It visits all flags, even those not set.
|
||||||
func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
||||||
for _, flag := range sortFlags(f.formal) {
|
if len(f.formal) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags []*Flag
|
||||||
|
if f.SortFlags {
|
||||||
|
if len(f.formal) != len(f.sortedFormal) {
|
||||||
|
f.sortedFormal = sortFlags(f.formal)
|
||||||
|
}
|
||||||
|
flags = f.sortedFormal
|
||||||
|
} else {
|
||||||
|
flags = f.orderedFormal
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flag := range flags {
|
||||||
fn(flag)
|
fn(flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,22 +277,39 @@ func (f *FlagSet) HasAvailableFlags() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// VisitAll visits the command-line flags in lexicographical order, calling
|
// VisitAll visits the command-line flags in lexicographical order or
|
||||||
// fn for each. It visits all flags, even those not set.
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
|
// It visits all flags, even those not set.
|
||||||
func VisitAll(fn func(*Flag)) {
|
func VisitAll(fn func(*Flag)) {
|
||||||
CommandLine.VisitAll(fn)
|
CommandLine.VisitAll(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit visits the flags in lexicographical order, calling fn for each.
|
// Visit visits the flags in lexicographical order or
|
||||||
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
// It visits only those flags that have been set.
|
// It visits only those flags that have been set.
|
||||||
func (f *FlagSet) Visit(fn func(*Flag)) {
|
func (f *FlagSet) Visit(fn func(*Flag)) {
|
||||||
for _, flag := range sortFlags(f.actual) {
|
if len(f.actual) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var flags []*Flag
|
||||||
|
if f.SortFlags {
|
||||||
|
if len(f.actual) != len(f.sortedActual) {
|
||||||
|
f.sortedActual = sortFlags(f.actual)
|
||||||
|
}
|
||||||
|
flags = f.sortedActual
|
||||||
|
} else {
|
||||||
|
flags = f.orderedActual
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flag := range flags {
|
||||||
fn(flag)
|
fn(flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Visit visits the command-line flags in lexicographical order, calling fn
|
// Visit visits the command-line flags in lexicographical order or
|
||||||
// for each. It visits only those flags that have been set.
|
// in primordial order if f.SortFlags is false, calling fn for each.
|
||||||
|
// It visits only those flags that have been set.
|
||||||
func Visit(fn func(*Flag)) {
|
func Visit(fn func(*Flag)) {
|
||||||
CommandLine.Visit(fn)
|
CommandLine.Visit(fn)
|
||||||
}
|
}
|
||||||
|
@ -373,6 +414,7 @@ func (f *FlagSet) Set(name, value string) error {
|
||||||
f.actual = make(map[NormalizedName]*Flag)
|
f.actual = make(map[NormalizedName]*Flag)
|
||||||
}
|
}
|
||||||
f.actual[normalName] = flag
|
f.actual[normalName] = flag
|
||||||
|
f.orderedActual = append(f.orderedActual, flag)
|
||||||
flag.Changed = true
|
flag.Changed = true
|
||||||
if len(flag.Deprecated) > 0 {
|
if len(flag.Deprecated) > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
||||||
|
@ -416,7 +458,7 @@ func Set(name, value string) error {
|
||||||
// otherwise, the default values of all defined flags in the set.
|
// otherwise, the default values of all defined flags in the set.
|
||||||
func (f *FlagSet) PrintDefaults() {
|
func (f *FlagSet) PrintDefaults() {
|
||||||
usages := f.FlagUsages()
|
usages := f.FlagUsages()
|
||||||
fmt.Fprintf(f.out(), "%s", usages)
|
fmt.Fprint(f.out(), usages)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultIsZeroValue returns true if the default value for this flag represents
|
// defaultIsZeroValue returns true if the default value for this flag represents
|
||||||
|
@ -487,9 +529,76 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlagUsages Returns a string containing the usage information for all flags in
|
// Splits the string `s` on whitespace into an initial substring up to
|
||||||
// the FlagSet
|
// `i` runes in length and the remainder. Will go `slop` over `i` if
|
||||||
func (f *FlagSet) FlagUsages() string {
|
// that encompasses the entire string (which allows the caller to
|
||||||
|
// avoid short orphan words on the final line).
|
||||||
|
func wrapN(i, slop int, s string) (string, string) {
|
||||||
|
if i+slop > len(s) {
|
||||||
|
return s, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
w := strings.LastIndexAny(s[:i], " \t")
|
||||||
|
if w <= 0 {
|
||||||
|
return s, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return s[:w], s[w+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps the string `s` to a maximum width `w` with leading indent
|
||||||
|
// `i`. The first line is not indented (this is assumed to be done by
|
||||||
|
// caller). Pass `w` == 0 to do no wrapping
|
||||||
|
func wrap(i, w int, s string) string {
|
||||||
|
if w == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// space between indent i and end of line width w into which
|
||||||
|
// we should wrap the text.
|
||||||
|
wrap := w - i
|
||||||
|
|
||||||
|
var r, l string
|
||||||
|
|
||||||
|
// Not enough space for sensible wrapping. Wrap as a block on
|
||||||
|
// the next line instead.
|
||||||
|
if wrap < 24 {
|
||||||
|
i = 16
|
||||||
|
wrap = w - i
|
||||||
|
r += "\n" + strings.Repeat(" ", i)
|
||||||
|
}
|
||||||
|
// If still not enough space then don't even try to wrap.
|
||||||
|
if wrap < 24 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to avoid short orphan words on the final line, by
|
||||||
|
// allowing wrapN to go a bit over if that would fit in the
|
||||||
|
// remainder of the line.
|
||||||
|
slop := 5
|
||||||
|
wrap = wrap - slop
|
||||||
|
|
||||||
|
// Handle first line, which is indented by the caller (or the
|
||||||
|
// special case above)
|
||||||
|
l, s = wrapN(wrap, slop, s)
|
||||||
|
r = r + l
|
||||||
|
|
||||||
|
// Now wrap the rest
|
||||||
|
for s != "" {
|
||||||
|
var t string
|
||||||
|
|
||||||
|
t, s = wrapN(wrap, slop, s)
|
||||||
|
r = r + "\n" + strings.Repeat(" ", i) + t
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlagUsagesWrapped returns a string containing the usage information
|
||||||
|
// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no
|
||||||
|
// wrapping)
|
||||||
|
func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||||
x := new(bytes.Buffer)
|
x := new(bytes.Buffer)
|
||||||
|
|
||||||
lines := make([]string, 0, len(f.formal))
|
lines := make([]string, 0, len(f.formal))
|
||||||
|
@ -514,7 +623,7 @@ func (f *FlagSet) FlagUsages() string {
|
||||||
if len(flag.NoOptDefVal) > 0 {
|
if len(flag.NoOptDefVal) > 0 {
|
||||||
switch flag.Value.Type() {
|
switch flag.Value.Type() {
|
||||||
case "string":
|
case "string":
|
||||||
line += fmt.Sprintf("[=%q]", flag.NoOptDefVal)
|
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
|
||||||
case "bool":
|
case "bool":
|
||||||
if flag.NoOptDefVal != "true" {
|
if flag.NoOptDefVal != "true" {
|
||||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||||
|
@ -546,12 +655,19 @@ func (f *FlagSet) FlagUsages() string {
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
sidx := strings.Index(line, "\x00")
|
sidx := strings.Index(line, "\x00")
|
||||||
spacing := strings.Repeat(" ", maxlen-sidx)
|
spacing := strings.Repeat(" ", maxlen-sidx)
|
||||||
fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:])
|
// maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx
|
||||||
|
fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return x.String()
|
return x.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlagUsages returns a string containing the usage information for all flags in
|
||||||
|
// the FlagSet
|
||||||
|
func (f *FlagSet) FlagUsages() string {
|
||||||
|
return f.FlagUsagesWrapped(0)
|
||||||
|
}
|
||||||
|
|
||||||
// PrintDefaults prints to standard error the default values of all defined command-line flags.
|
// PrintDefaults prints to standard error the default values of all defined command-line flags.
|
||||||
func PrintDefaults() {
|
func PrintDefaults() {
|
||||||
CommandLine.PrintDefaults()
|
CommandLine.PrintDefaults()
|
||||||
|
@ -635,7 +751,7 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag {
|
||||||
|
|
||||||
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
|
// VarP is like Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
|
func (f *FlagSet) VarP(value Value, name, shorthand, usage string) {
|
||||||
_ = f.VarPF(value, name, shorthand, usage)
|
f.VarPF(value, name, shorthand, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFlag will add the flag to the FlagSet
|
// AddFlag will add the flag to the FlagSet
|
||||||
|
@ -655,6 +771,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
||||||
|
|
||||||
flag.Name = string(normalizedFlagName)
|
flag.Name = string(normalizedFlagName)
|
||||||
f.formal[normalizedFlagName] = flag
|
f.formal[normalizedFlagName] = flag
|
||||||
|
f.orderedFormal = append(f.orderedFormal, flag)
|
||||||
|
|
||||||
if len(flag.Shorthand) == 0 {
|
if len(flag.Shorthand) == 0 {
|
||||||
return
|
return
|
||||||
|
@ -733,6 +850,7 @@ func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error {
|
||||||
f.actual = make(map[NormalizedName]*Flag)
|
f.actual = make(map[NormalizedName]*Flag)
|
||||||
}
|
}
|
||||||
f.actual[f.normalizeFlagName(flag.Name)] = flag
|
f.actual[f.normalizeFlagName(flag.Name)] = flag
|
||||||
|
f.orderedActual = append(f.orderedActual, flag)
|
||||||
flag.Changed = true
|
flag.Changed = true
|
||||||
if len(flag.Deprecated) > 0 {
|
if len(flag.Deprecated) > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
fmt.Fprintf(os.Stderr, "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
||||||
|
@ -752,7 +870,7 @@ func containsShorthand(arg, shorthand string) bool {
|
||||||
return strings.Contains(arg, shorthand)
|
return strings.Contains(arg, shorthand)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) {
|
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
a = args
|
a = args
|
||||||
name := s[2:]
|
name := s[2:]
|
||||||
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
|
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
|
||||||
|
@ -786,11 +904,11 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error)
|
||||||
err = f.failf("flag needs an argument: %s", s)
|
err = f.failf("flag needs an argument: %s", s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = f.setFlag(flag, value, s)
|
err = fn(flag, value, s)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) {
|
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||||
if strings.HasPrefix(shorthands, "test.") {
|
if strings.HasPrefix(shorthands, "test.") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -825,16 +943,16 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShor
|
||||||
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
err = f.failf("flag needs an argument: %q in -%s", c, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = f.setFlag(flag, value, shorthands)
|
err = fn(flag, value, shorthands)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) {
|
func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||||
a = args
|
a = args
|
||||||
shorthands := s[1:]
|
shorthands := s[1:]
|
||||||
|
|
||||||
for len(shorthands) > 0 {
|
for len(shorthands) > 0 {
|
||||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args)
|
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -843,7 +961,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlagSet) parseArgs(args []string) (err error) {
|
func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
|
||||||
for len(args) > 0 {
|
for len(args) > 0 {
|
||||||
s := args[0]
|
s := args[0]
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
|
@ -863,9 +981,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
||||||
f.args = append(f.args, args...)
|
f.args = append(f.args, args...)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
args, err = f.parseLongArg(s, args)
|
args, err = f.parseLongArg(s, args, fn)
|
||||||
} else {
|
} else {
|
||||||
args, err = f.parseShortArg(s, args)
|
args, err = f.parseShortArg(s, args, fn)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -881,7 +999,41 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
||||||
func (f *FlagSet) Parse(arguments []string) error {
|
func (f *FlagSet) Parse(arguments []string) error {
|
||||||
f.parsed = true
|
f.parsed = true
|
||||||
f.args = make([]string, 0, len(arguments))
|
f.args = make([]string, 0, len(arguments))
|
||||||
err := f.parseArgs(arguments)
|
|
||||||
|
assign := func(flag *Flag, value, origArg string) error {
|
||||||
|
return f.setFlag(flag, value, origArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f.parseArgs(arguments, assign)
|
||||||
|
if err != nil {
|
||||||
|
switch f.errorHandling {
|
||||||
|
case ContinueOnError:
|
||||||
|
return err
|
||||||
|
case ExitOnError:
|
||||||
|
os.Exit(2)
|
||||||
|
case PanicOnError:
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type parseFunc func(flag *Flag, value, origArg string) error
|
||||||
|
|
||||||
|
// ParseAll parses flag definitions from the argument list, which should not
|
||||||
|
// include the command name. The arguments for fn are flag and value. Must be
|
||||||
|
// called after all flags in the FlagSet are defined and before flags are
|
||||||
|
// accessed by the program. The return value will be ErrHelp if -help was set
|
||||||
|
// but not defined.
|
||||||
|
func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error {
|
||||||
|
f.parsed = true
|
||||||
|
f.args = make([]string, 0, len(arguments))
|
||||||
|
|
||||||
|
assign := func(flag *Flag, value, origArg string) error {
|
||||||
|
return fn(flag, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f.parseArgs(arguments, assign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch f.errorHandling {
|
switch f.errorHandling {
|
||||||
case ContinueOnError:
|
case ContinueOnError:
|
||||||
|
@ -907,6 +1059,14 @@ func Parse() {
|
||||||
CommandLine.Parse(os.Args[1:])
|
CommandLine.Parse(os.Args[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseAll parses the command-line flags from os.Args[1:] and called fn for each.
|
||||||
|
// The arguments for fn are flag and value. Must be called after all flags are
|
||||||
|
// defined and before flags are accessed by the program.
|
||||||
|
func ParseAll(fn func(flag *Flag, value string) error) {
|
||||||
|
// Ignore errors; CommandLine is set for ExitOnError.
|
||||||
|
CommandLine.ParseAll(os.Args[1:], fn)
|
||||||
|
}
|
||||||
|
|
||||||
// SetInterspersed sets whether to support interspersed option/non-option arguments.
|
// SetInterspersed sets whether to support interspersed option/non-option arguments.
|
||||||
func SetInterspersed(interspersed bool) {
|
func SetInterspersed(interspersed bool) {
|
||||||
CommandLine.SetInterspersed(interspersed)
|
CommandLine.SetInterspersed(interspersed)
|
||||||
|
@ -920,14 +1080,15 @@ func Parsed() bool {
|
||||||
// CommandLine is the default set of command-line flags, parsed from os.Args.
|
// CommandLine is the default set of command-line flags, parsed from os.Args.
|
||||||
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
|
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
|
||||||
|
|
||||||
// NewFlagSet returns a new, empty flag set with the specified name and
|
// NewFlagSet returns a new, empty flag set with the specified name,
|
||||||
// error handling property.
|
// error handling property and SortFlags set to true.
|
||||||
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
||||||
f := &FlagSet{
|
f := &FlagSet{
|
||||||
name: name,
|
name: name,
|
||||||
errorHandling: errorHandling,
|
errorHandling: errorHandling,
|
||||||
argsLenAtDash: -1,
|
argsLenAtDash: -1,
|
||||||
interspersed: true,
|
interspersed: true,
|
||||||
|
SortFlags: true,
|
||||||
}
|
}
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,6 +333,59 @@ func testParse(f *FlagSet, t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testParseAll(f *FlagSet, t *testing.T) {
|
||||||
|
if f.Parsed() {
|
||||||
|
t.Error("f.Parse() = true before Parse")
|
||||||
|
}
|
||||||
|
f.BoolP("boola", "a", false, "bool value")
|
||||||
|
f.BoolP("boolb", "b", false, "bool2 value")
|
||||||
|
f.BoolP("boolc", "c", false, "bool3 value")
|
||||||
|
f.BoolP("boold", "d", false, "bool4 value")
|
||||||
|
f.StringP("stringa", "s", "0", "string value")
|
||||||
|
f.StringP("stringz", "z", "0", "string value")
|
||||||
|
f.StringP("stringx", "x", "0", "string value")
|
||||||
|
f.StringP("stringy", "y", "0", "string value")
|
||||||
|
f.Lookup("stringx").NoOptDefVal = "1"
|
||||||
|
args := []string{
|
||||||
|
"-ab",
|
||||||
|
"-cs=xx",
|
||||||
|
"--stringz=something",
|
||||||
|
"-d=true",
|
||||||
|
"-x",
|
||||||
|
"-y",
|
||||||
|
"ee",
|
||||||
|
}
|
||||||
|
want := []string{
|
||||||
|
"boola", "true",
|
||||||
|
"boolb", "true",
|
||||||
|
"boolc", "true",
|
||||||
|
"stringa", "xx",
|
||||||
|
"stringz", "something",
|
||||||
|
"boold", "true",
|
||||||
|
"stringx", "1",
|
||||||
|
"stringy", "ee",
|
||||||
|
}
|
||||||
|
got := []string{}
|
||||||
|
store := func(flag *Flag, value string) error {
|
||||||
|
got = append(got, flag.Name)
|
||||||
|
if len(value) > 0 {
|
||||||
|
got = append(got, value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := f.ParseAll(args, store); err != nil {
|
||||||
|
t.Errorf("expected no error, got %s", err)
|
||||||
|
}
|
||||||
|
if !f.Parsed() {
|
||||||
|
t.Errorf("f.Parse() = false after Parse")
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("f.ParseAll() fail to restore the args")
|
||||||
|
t.Errorf("Got: %v", got)
|
||||||
|
t.Errorf("Want: %v", want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestShorthand(t *testing.T) {
|
func TestShorthand(t *testing.T) {
|
||||||
f := NewFlagSet("shorthand", ContinueOnError)
|
f := NewFlagSet("shorthand", ContinueOnError)
|
||||||
if f.Parsed() {
|
if f.Parsed() {
|
||||||
|
@ -398,16 +451,21 @@ func TestParse(t *testing.T) {
|
||||||
testParse(GetCommandLine(), t)
|
testParse(GetCommandLine(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseAll(t *testing.T) {
|
||||||
|
ResetForTesting(func() { t.Error("bad parse") })
|
||||||
|
testParseAll(GetCommandLine(), t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestFlagSetParse(t *testing.T) {
|
func TestFlagSetParse(t *testing.T) {
|
||||||
testParse(NewFlagSet("test", ContinueOnError), t)
|
testParse(NewFlagSet("test", ContinueOnError), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChangedHelper(t *testing.T) {
|
func TestChangedHelper(t *testing.T) {
|
||||||
f := NewFlagSet("changedtest", ContinueOnError)
|
f := NewFlagSet("changedtest", ContinueOnError)
|
||||||
_ = f.Bool("changed", false, "changed bool")
|
f.Bool("changed", false, "changed bool")
|
||||||
_ = f.Bool("settrue", true, "true to true")
|
f.Bool("settrue", true, "true to true")
|
||||||
_ = f.Bool("setfalse", false, "false to false")
|
f.Bool("setfalse", false, "false to false")
|
||||||
_ = f.Bool("unchanged", false, "unchanged bool")
|
f.Bool("unchanged", false, "unchanged bool")
|
||||||
|
|
||||||
args := []string{"--changed", "--settrue", "--setfalse=false"}
|
args := []string{"--changed", "--settrue", "--setfalse=false"}
|
||||||
if err := f.Parse(args); err != nil {
|
if err := f.Parse(args); err != nil {
|
||||||
|
@ -946,3 +1004,43 @@ func TestPrintDefaults(t *testing.T) {
|
||||||
t.Errorf("got %q want %q\n", got, defaultOutput)
|
t.Errorf("got %q want %q\n", got, defaultOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVisitAllFlagOrder(t *testing.T) {
|
||||||
|
fs := NewFlagSet("TestVisitAllFlagOrder", ContinueOnError)
|
||||||
|
fs.SortFlags = false
|
||||||
|
// https://github.com/spf13/pflag/issues/120
|
||||||
|
fs.SetNormalizeFunc(func(f *FlagSet, name string) NormalizedName {
|
||||||
|
return NormalizedName(name)
|
||||||
|
})
|
||||||
|
|
||||||
|
names := []string{"C", "B", "A", "D"}
|
||||||
|
for _, name := range names {
|
||||||
|
fs.Bool(name, false, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
fs.VisitAll(func(f *Flag) {
|
||||||
|
if names[i] != f.Name {
|
||||||
|
t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVisitFlagOrder(t *testing.T) {
|
||||||
|
fs := NewFlagSet("TestVisitFlagOrder", ContinueOnError)
|
||||||
|
fs.SortFlags = false
|
||||||
|
names := []string{"C", "B", "A", "D"}
|
||||||
|
for _, name := range names {
|
||||||
|
fs.Bool(name, false, "")
|
||||||
|
fs.Set(name, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
fs.Visit(func(f *Flag) {
|
||||||
|
if names[i] != f.Name {
|
||||||
|
t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -6,13 +6,10 @@ package pflag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
goflag "flag"
|
goflag "flag"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
|
||||||
|
|
||||||
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
||||||
// difference here is the addition of the Type method that returns a string
|
// difference here is the addition of the Type method that returns a string
|
||||||
// name of the type. As this is generally unknown, we approximate that with
|
// name of the type. As this is generally unknown, we approximate that with
|
||||||
|
|
|
@ -6,8 +6,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = strings.TrimSpace
|
|
||||||
|
|
||||||
// -- net.IP value
|
// -- net.IP value
|
||||||
type ipValue net.IP
|
type ipValue net.IP
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- ipSlice Value
|
||||||
|
type ipSliceValue struct {
|
||||||
|
value *[]net.IP
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
|
||||||
|
ipsv := new(ipSliceValue)
|
||||||
|
ipsv.value = p
|
||||||
|
*ipsv.value = val
|
||||||
|
return ipsv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
|
||||||
|
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
|
||||||
|
func (s *ipSliceValue) Set(val string) error {
|
||||||
|
|
||||||
|
// remove all quote characters
|
||||||
|
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
|
||||||
|
|
||||||
|
// read flag arguments with CSV parser
|
||||||
|
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse ip values into slice
|
||||||
|
out := make([]net.IP, 0, len(ipStrSlice))
|
||||||
|
for _, ipStr := range ipStrSlice {
|
||||||
|
ip := net.ParseIP(strings.TrimSpace(ipStr))
|
||||||
|
if ip == nil {
|
||||||
|
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
|
||||||
|
}
|
||||||
|
out = append(out, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.changed = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type returns a string that uniquely represents this flag's type.
|
||||||
|
func (s *ipSliceValue) Type() string {
|
||||||
|
return "ipSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
// String defines a "native" format for this net.IP slice flag value.
|
||||||
|
func (s *ipSliceValue) String() string {
|
||||||
|
|
||||||
|
ipStrSlice := make([]string, len(*s.value))
|
||||||
|
for i, ip := range *s.value {
|
||||||
|
ipStrSlice[i] = ip.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
out, _ := writeAsCSV(ipStrSlice)
|
||||||
|
|
||||||
|
return "[" + out + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Emtpy string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []net.IP{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]net.IP, len(ss))
|
||||||
|
for i, sval := range ss {
|
||||||
|
ip := net.ParseIP(strings.TrimSpace(sval))
|
||||||
|
if ip == nil {
|
||||||
|
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
|
||||||
|
}
|
||||||
|
out[i] = ip
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIPSlice returns the []net.IP value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
|
||||||
|
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []net.IP{}, err
|
||||||
|
}
|
||||||
|
return val.([]net.IP), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
||||||
|
f.VarP(newIPSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
||||||
|
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []net.IP variable in which to store the value of the flag.
|
||||||
|
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
|
||||||
|
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
|
||||||
|
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []net.IP variable that stores the value of that flag.
|
||||||
|
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
p := []net.IP{}
|
||||||
|
f.IPSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
p := []net.IP{}
|
||||||
|
f.IPSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []net.IP variable that stores the value of the flag.
|
||||||
|
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
return CommandLine.IPSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
|
||||||
|
return CommandLine.IPSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
|
@ -0,0 +1,222 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setUpIPSFlagSet(ipsp *[]net.IP) *FlagSet {
|
||||||
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
|
f.IPSliceVar(ipsp, "ips", []net.IP{}, "Command separated list!")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUpIPSFlagSetWithDefault(ipsp *[]net.IP) *FlagSet {
|
||||||
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
|
f.IPSliceVar(ipsp, "ips",
|
||||||
|
[]net.IP{
|
||||||
|
net.ParseIP("192.168.1.1"),
|
||||||
|
net.ParseIP("0:0:0:0:0:0:0:1"),
|
||||||
|
},
|
||||||
|
"Command separated list!")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyIP(t *testing.T) {
|
||||||
|
var ips []net.IP
|
||||||
|
f := setUpIPSFlagSet(&ips)
|
||||||
|
err := f.Parse([]string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
getIPS, err := f.GetIPSlice("ips")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetIPSlice():", err)
|
||||||
|
}
|
||||||
|
if len(getIPS) != 0 {
|
||||||
|
t.Fatalf("got ips %v with len=%d but expected length=0", getIPS, len(getIPS))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPS(t *testing.T) {
|
||||||
|
var ips []net.IP
|
||||||
|
f := setUpIPSFlagSet(&ips)
|
||||||
|
|
||||||
|
vals := []string{"192.168.1.1", "10.0.0.1", "0:0:0:0:0:0:0:2"}
|
||||||
|
arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ","))
|
||||||
|
err := f.Parse([]string{arg})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range ips {
|
||||||
|
if ip := net.ParseIP(vals[i]); ip == nil {
|
||||||
|
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
||||||
|
} else if !ip.Equal(v) {
|
||||||
|
t.Fatalf("expected ips[%d] to be %s but got: %s from GetIPSlice", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPSDefault(t *testing.T) {
|
||||||
|
var ips []net.IP
|
||||||
|
f := setUpIPSFlagSetWithDefault(&ips)
|
||||||
|
|
||||||
|
vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"}
|
||||||
|
err := f.Parse([]string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range ips {
|
||||||
|
if ip := net.ParseIP(vals[i]); ip == nil {
|
||||||
|
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
||||||
|
} else if !ip.Equal(v) {
|
||||||
|
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIPS, err := f.GetIPSlice("ips")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetIPSlice")
|
||||||
|
}
|
||||||
|
for i, v := range getIPS {
|
||||||
|
if ip := net.ParseIP(vals[i]); ip == nil {
|
||||||
|
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
||||||
|
} else if !ip.Equal(v) {
|
||||||
|
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPSWithDefault(t *testing.T) {
|
||||||
|
var ips []net.IP
|
||||||
|
f := setUpIPSFlagSetWithDefault(&ips)
|
||||||
|
|
||||||
|
vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"}
|
||||||
|
arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ","))
|
||||||
|
err := f.Parse([]string{arg})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range ips {
|
||||||
|
if ip := net.ParseIP(vals[i]); ip == nil {
|
||||||
|
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
||||||
|
} else if !ip.Equal(v) {
|
||||||
|
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIPS, err := f.GetIPSlice("ips")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetIPSlice")
|
||||||
|
}
|
||||||
|
for i, v := range getIPS {
|
||||||
|
if ip := net.ParseIP(vals[i]); ip == nil {
|
||||||
|
t.Fatalf("invalid string being converted to IP address: %s", vals[i])
|
||||||
|
} else if !ip.Equal(v) {
|
||||||
|
t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPSCalledTwice(t *testing.T) {
|
||||||
|
var ips []net.IP
|
||||||
|
f := setUpIPSFlagSet(&ips)
|
||||||
|
|
||||||
|
in := []string{"192.168.1.2,0:0:0:0:0:0:0:1", "10.0.0.1"}
|
||||||
|
expected := []net.IP{net.ParseIP("192.168.1.2"), net.ParseIP("0:0:0:0:0:0:0:1"), net.ParseIP("10.0.0.1")}
|
||||||
|
argfmt := "ips=%s"
|
||||||
|
arg1 := fmt.Sprintf(argfmt, in[0])
|
||||||
|
arg2 := fmt.Sprintf(argfmt, in[1])
|
||||||
|
err := f.Parse([]string{arg1, arg2})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range ips {
|
||||||
|
if !expected[i].Equal(v) {
|
||||||
|
t.Fatalf("expected ips[%d] to be %s but got: %s", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPSBadQuoting(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Want []net.IP
|
||||||
|
FlagArg []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Want: []net.IP{
|
||||||
|
net.ParseIP("a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568"),
|
||||||
|
net.ParseIP("203.107.49.208"),
|
||||||
|
net.ParseIP("14.57.204.90"),
|
||||||
|
},
|
||||||
|
FlagArg: []string{
|
||||||
|
"a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568",
|
||||||
|
"203.107.49.208",
|
||||||
|
"14.57.204.90",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []net.IP{
|
||||||
|
net.ParseIP("204.228.73.195"),
|
||||||
|
net.ParseIP("86.141.15.94"),
|
||||||
|
},
|
||||||
|
FlagArg: []string{
|
||||||
|
"204.228.73.195",
|
||||||
|
"86.141.15.94",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []net.IP{
|
||||||
|
net.ParseIP("c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f"),
|
||||||
|
net.ParseIP("4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472"),
|
||||||
|
},
|
||||||
|
FlagArg: []string{
|
||||||
|
"c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f",
|
||||||
|
"4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []net.IP{
|
||||||
|
net.ParseIP("5170:f971:cfac:7be3:512a:af37:952c:bc33"),
|
||||||
|
net.ParseIP("93.21.145.140"),
|
||||||
|
net.ParseIP("2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca"),
|
||||||
|
},
|
||||||
|
FlagArg: []string{
|
||||||
|
" 5170:f971:cfac:7be3:512a:af37:952c:bc33 , 93.21.145.140 ",
|
||||||
|
"2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Want: []net.IP{
|
||||||
|
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
||||||
|
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
||||||
|
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
||||||
|
net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"),
|
||||||
|
},
|
||||||
|
FlagArg: []string{
|
||||||
|
`"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b, 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b "`,
|
||||||
|
" 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
|
||||||
|
var ips []net.IP
|
||||||
|
f := setUpIPSFlagSet(&ips)
|
||||||
|
|
||||||
|
if err := f.Parse([]string{fmt.Sprintf("--ips=%s", strings.Join(test.FlagArg, ","))}); err != nil {
|
||||||
|
t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%s",
|
||||||
|
err, test.FlagArg, test.Want[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, b := range ips {
|
||||||
|
if !b.Equal(test.Want[j]) {
|
||||||
|
t.Fatalf("bad value parsed for test %d on net.IP %d:\nwant:\t%s\ngot:\t%s", i, j, test.Want[j], b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,8 +27,6 @@ func (*ipNetValue) Type() string {
|
||||||
return "ipNet"
|
return "ipNet"
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = strings.TrimSpace
|
|
||||||
|
|
||||||
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
||||||
*p = val
|
*p = val
|
||||||
return (*ipNetValue)(p)
|
return (*ipNetValue)(p)
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
package pflag
|
package pflag
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = fmt.Fprint
|
|
||||||
|
|
||||||
// -- stringArray Value
|
// -- stringArray Value
|
||||||
type stringArrayValue struct {
|
type stringArrayValue struct {
|
||||||
value *[]string
|
value *[]string
|
||||||
|
@ -40,7 +33,7 @@ func (s *stringArrayValue) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringArrayConv(sval string) (interface{}, error) {
|
func stringArrayConv(sval string) (interface{}, error) {
|
||||||
sval = strings.Trim(sval, "[]")
|
sval = sval[1 : len(sval)-1]
|
||||||
// An empty string would cause a array with one (empty) string
|
// An empty string would cause a array with one (empty) string
|
||||||
if len(sval) == 0 {
|
if len(sval) == 0 {
|
||||||
return []string{}, nil
|
return []string{}, nil
|
||||||
|
|
|
@ -192,3 +192,42 @@ func TestSAWithSpecialChar(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSAWithSquareBrackets(t *testing.T) {
|
||||||
|
var sa []string
|
||||||
|
f := setUpSAFlagSet(&sa)
|
||||||
|
|
||||||
|
in := []string{"][]-[", "[a-z]", "[a-z]+"}
|
||||||
|
expected := []string{"][]-[", "[a-z]", "[a-z]+"}
|
||||||
|
argfmt := "--sa=%s"
|
||||||
|
arg1 := fmt.Sprintf(argfmt, in[0])
|
||||||
|
arg2 := fmt.Sprintf(argfmt, in[1])
|
||||||
|
arg3 := fmt.Sprintf(argfmt, in[2])
|
||||||
|
err := f.Parse([]string{arg1, arg2, arg3})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expected) != len(sa) {
|
||||||
|
t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa))
|
||||||
|
}
|
||||||
|
for i, v := range sa {
|
||||||
|
if expected[i] != v {
|
||||||
|
t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
values, err := f.GetStringArray("sa")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expected) != len(values) {
|
||||||
|
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
|
||||||
|
}
|
||||||
|
for i, v := range values {
|
||||||
|
if expected[i] != v {
|
||||||
|
t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,12 +3,9 @@ package pflag
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Fprint
|
|
||||||
|
|
||||||
// -- stringSlice Value
|
// -- stringSlice Value
|
||||||
type stringSliceValue struct {
|
type stringSliceValue struct {
|
||||||
value *[]string
|
value *[]string
|
||||||
|
@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
w.Flush()
|
w.Flush()
|
||||||
return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil
|
return strings.TrimSuffix(b.String(), "\n"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stringSliceValue) Set(val string) error {
|
func (s *stringSliceValue) Set(val string) error {
|
||||||
|
@ -66,7 +63,7 @@ func (s *stringSliceValue) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringSliceConv(sval string) (interface{}, error) {
|
func stringSliceConv(sval string) (interface{}, error) {
|
||||||
sval = strings.Trim(sval, "[]")
|
sval = sval[1 : len(sval)-1]
|
||||||
// An empty string would cause a slice with one (empty) string
|
// An empty string would cause a slice with one (empty) string
|
||||||
if len(sval) == 0 {
|
if len(sval) == 0 {
|
||||||
return []string{}, nil
|
return []string{}, nil
|
||||||
|
|
|
@ -213,3 +213,41 @@ func TestSSWithComma(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSSWithSquareBrackets(t *testing.T) {
|
||||||
|
var ss []string
|
||||||
|
f := setUpSSFlagSet(&ss)
|
||||||
|
|
||||||
|
in := []string{`"[a-z]"`, `"[a-z]+"`}
|
||||||
|
expected := []string{"[a-z]", "[a-z]+"}
|
||||||
|
argfmt := "--ss=%s"
|
||||||
|
arg1 := fmt.Sprintf(argfmt, in[0])
|
||||||
|
arg2 := fmt.Sprintf(argfmt, in[1])
|
||||||
|
err := f.Parse([]string{arg1, arg2})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expected) != len(ss) {
|
||||||
|
t.Fatalf("expected number of ss to be %d but got: %d", len(expected), len(ss))
|
||||||
|
}
|
||||||
|
for i, v := range ss {
|
||||||
|
if expected[i] != v {
|
||||||
|
t.Fatalf("expected ss[%d] to be %s but got: %s", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
values, err := f.GetStringSlice("ss")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(expected) != len(values) {
|
||||||
|
t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
|
||||||
|
}
|
||||||
|
for i, v := range values {
|
||||||
|
if expected[i] != v {
|
||||||
|
t.Fatalf("expected got ss[%d] to be %s but got: %s", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- uintSlice Value
|
||||||
|
type uintSliceValue struct {
|
||||||
|
value *[]uint
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
|
||||||
|
uisv := new(uintSliceValue)
|
||||||
|
uisv.value = p
|
||||||
|
*uisv.value = val
|
||||||
|
return uisv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]uint, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
u, err := strconv.ParseUint(d, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out[i] = uint(u)
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) Type() string {
|
||||||
|
return "uintSlice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%d", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func uintSliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []uint{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]uint, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
u, err := strconv.ParseUint(d, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[i] = uint(u)
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUintSlice returns the []uint value of a flag with the given name.
|
||||||
|
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
|
||||||
|
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []uint{}, err
|
||||||
|
}
|
||||||
|
return val.([]uint), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []uint variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
||||||
|
f.VarP(newUintSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
||||||
|
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a uint[] variable in which to store the value of the flag.
|
||||||
|
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
|
||||||
|
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
|
||||||
|
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []uint variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
|
||||||
|
p := []uint{}
|
||||||
|
f.UintSliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
||||||
|
p := []uint{}
|
||||||
|
f.UintSliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSlice defines a []uint flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []uint variable that stores the value of the flag.
|
||||||
|
func UintSlice(name string, value []uint, usage string) *[]uint {
|
||||||
|
return CommandLine.UintSliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
|
||||||
|
return CommandLine.UintSliceP(name, shorthand, value, usage)
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setUpUISFlagSet(uisp *[]uint) *FlagSet {
|
||||||
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
|
f.UintSliceVar(uisp, "uis", []uint{}, "Command separated list!")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUpUISFlagSetWithDefault(uisp *[]uint) *FlagSet {
|
||||||
|
f := NewFlagSet("test", ContinueOnError)
|
||||||
|
f.UintSliceVar(uisp, "uis", []uint{0, 1}, "Command separated list!")
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyUIS(t *testing.T) {
|
||||||
|
var uis []uint
|
||||||
|
f := setUpUISFlagSet(&uis)
|
||||||
|
err := f.Parse([]string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
getUIS, err := f.GetUintSlice("uis")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetUintSlice():", err)
|
||||||
|
}
|
||||||
|
if len(getUIS) != 0 {
|
||||||
|
t.Fatalf("got is %v with len=%d but expected length=0", getUIS, len(getUIS))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUIS(t *testing.T) {
|
||||||
|
var uis []uint
|
||||||
|
f := setUpUISFlagSet(&uis)
|
||||||
|
|
||||||
|
vals := []string{"1", "2", "4", "3"}
|
||||||
|
arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ","))
|
||||||
|
err := f.Parse([]string{arg})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range uis {
|
||||||
|
u, err := strconv.ParseUint(vals[i], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if uint(u) != v {
|
||||||
|
t.Fatalf("expected uis[%d] to be %s but got %d", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getUIS, err := f.GetUintSlice("uis")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
for i, v := range getUIS {
|
||||||
|
u, err := strconv.ParseUint(vals[i], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if uint(u) != v {
|
||||||
|
t.Fatalf("expected uis[%d] to be %s but got: %d from GetUintSlice", i, vals[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUISDefault(t *testing.T) {
|
||||||
|
var uis []uint
|
||||||
|
f := setUpUISFlagSetWithDefault(&uis)
|
||||||
|
|
||||||
|
vals := []string{"0", "1"}
|
||||||
|
|
||||||
|
err := f.Parse([]string{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range uis {
|
||||||
|
u, err := strconv.ParseUint(vals[i], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if uint(u) != v {
|
||||||
|
t.Fatalf("expect uis[%d] to be %d but got: %d", i, u, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getUIS, err := f.GetUintSlice("uis")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetUintSlice():", err)
|
||||||
|
}
|
||||||
|
for i, v := range getUIS {
|
||||||
|
u, err := strconv.ParseUint(vals[i], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetIntSlice():", err)
|
||||||
|
}
|
||||||
|
if uint(u) != v {
|
||||||
|
t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUISWithDefault(t *testing.T) {
|
||||||
|
var uis []uint
|
||||||
|
f := setUpUISFlagSetWithDefault(&uis)
|
||||||
|
|
||||||
|
vals := []string{"1", "2"}
|
||||||
|
arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ","))
|
||||||
|
err := f.Parse([]string{arg})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range uis {
|
||||||
|
u, err := strconv.ParseUint(vals[i], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if uint(u) != v {
|
||||||
|
t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getUIS, err := f.GetUintSlice("uis")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("got an error from GetUintSlice():", err)
|
||||||
|
}
|
||||||
|
for i, v := range getUIS {
|
||||||
|
u, err := strconv.ParseUint(vals[i], 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("got error: %v", err)
|
||||||
|
}
|
||||||
|
if uint(u) != v {
|
||||||
|
t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUISCalledTwice(t *testing.T) {
|
||||||
|
var uis []uint
|
||||||
|
f := setUpUISFlagSet(&uis)
|
||||||
|
|
||||||
|
in := []string{"1,2", "3"}
|
||||||
|
expected := []int{1, 2, 3}
|
||||||
|
argfmt := "--uis=%s"
|
||||||
|
arg1 := fmt.Sprintf(argfmt, in[0])
|
||||||
|
arg2 := fmt.Sprintf(argfmt, in[1])
|
||||||
|
err := f.Parse([]string{arg1, arg2})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected no error; got", err)
|
||||||
|
}
|
||||||
|
for i, v := range uis {
|
||||||
|
if uint(expected[i]) != v {
|
||||||
|
t.Fatalf("expected uis[%d] to be %d but got: %d", i, expected[i], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue