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",
|
||||
"repository": "https://github.com/spf13/pflag",
|
||||
"revision": "c7e63cf4530bcd3ba943729cee0efeff2ebea63f",
|
||||
"revision": "2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51",
|
||||
"branch": "master"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
[![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
|
||||
|
||||
|
@ -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 flagvar bool
|
||||
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.
|
||||
|
@ -268,8 +270,8 @@ func main() {
|
|||
You can see the full reference documentation of the pflag package
|
||||
[at godoc.org][3], or through go's standard documentation system by
|
||||
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.
|
||||
|
||||
[2]: http://localhost:6060/pkg/github.com/ogier/pflag
|
||||
[3]: http://godoc.org/github.com/ogier/pflag
|
||||
[2]: http://localhost:6060/pkg/github.com/spf13/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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
@ -48,7 +47,7 @@ func (v *triStateValue) String() string {
|
|||
if *v == triStateMaybe {
|
||||
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
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var _ = fmt.Printf
|
||||
|
||||
func setUpCount(c *int) *FlagSet {
|
||||
f := NewFlagSet("test", ContinueOnError)
|
||||
f.CountVarP(c, "verbose", "v", "a counter")
|
||||
|
|
|
@ -16,7 +16,7 @@ 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
|
||||
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 more field "Shorthand" that you will need to set.
|
||||
|
@ -134,14 +134,21 @@ type FlagSet struct {
|
|||
// a custom error handler.
|
||||
Usage func()
|
||||
|
||||
// SortFlags is used to indicate, if user wants to have sorted flags in
|
||||
// help/usage messages.
|
||||
SortFlags bool
|
||||
|
||||
name string
|
||||
parsed bool
|
||||
actual map[NormalizedName]*Flag
|
||||
orderedActual []*Flag
|
||||
sortedActual []*Flag
|
||||
formal map[NormalizedName]*Flag
|
||||
orderedFormal []*Flag
|
||||
sortedFormal []*Flag
|
||||
shorthands map[byte]*Flag
|
||||
args []string // arguments after flags
|
||||
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
|
||||
output io.Writer // nil means stderr; use out() accessor
|
||||
interspersed bool // allow interspersed option/non-option args
|
||||
|
@ -194,11 +201,13 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
|||
// "--getUrl" which may also be translated to "geturl" and everything will work.
|
||||
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
||||
f.normalizeNameFunc = n
|
||||
for k, v := range f.formal {
|
||||
delete(f.formal, k)
|
||||
nname := f.normalizeFlagName(string(k))
|
||||
f.formal[nname] = v
|
||||
f.sortedFormal = f.sortedFormal[:0]
|
||||
for k, v := range f.orderedFormal {
|
||||
delete(f.formal, NormalizedName(v.Name))
|
||||
nname := f.normalizeFlagName(v.Name)
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -253,22 +277,39 @@ func (f *FlagSet) HasAvailableFlags() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// VisitAll visits the command-line flags in lexicographical order, calling
|
||||
// fn for each. It visits all flags, even those not set.
|
||||
// VisitAll visits the command-line 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.
|
||||
func VisitAll(fn func(*Flag)) {
|
||||
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.
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// Visit visits the command-line flags in lexicographical order, calling fn
|
||||
// for each. It visits only those flags that have been set.
|
||||
// Visit visits the command-line 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.
|
||||
func Visit(fn func(*Flag)) {
|
||||
CommandLine.Visit(fn)
|
||||
}
|
||||
|
@ -373,6 +414,7 @@ func (f *FlagSet) Set(name, value string) error {
|
|||
f.actual = make(map[NormalizedName]*Flag)
|
||||
}
|
||||
f.actual[normalName] = flag
|
||||
f.orderedActual = append(f.orderedActual, flag)
|
||||
flag.Changed = true
|
||||
if len(flag.Deprecated) > 0 {
|
||||
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.
|
||||
func (f *FlagSet) PrintDefaults() {
|
||||
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
|
||||
|
@ -487,9 +529,76 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
|
|||
return
|
||||
}
|
||||
|
||||
// FlagUsages Returns a string containing the usage information for all flags in
|
||||
// the FlagSet
|
||||
func (f *FlagSet) FlagUsages() string {
|
||||
// Splits the string `s` on whitespace into an initial substring up to
|
||||
// `i` runes in length and the remainder. Will go `slop` over `i` if
|
||||
// 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)
|
||||
|
||||
lines := make([]string, 0, len(f.formal))
|
||||
|
@ -514,7 +623,7 @@ func (f *FlagSet) FlagUsages() string {
|
|||
if len(flag.NoOptDefVal) > 0 {
|
||||
switch flag.Value.Type() {
|
||||
case "string":
|
||||
line += fmt.Sprintf("[=%q]", flag.NoOptDefVal)
|
||||
line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal)
|
||||
case "bool":
|
||||
if flag.NoOptDefVal != "true" {
|
||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||
|
@ -546,12 +655,19 @@ func (f *FlagSet) FlagUsages() string {
|
|||
for _, line := range lines {
|
||||
sidx := strings.Index(line, "\x00")
|
||||
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()
|
||||
}
|
||||
|
||||
// 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.
|
||||
func 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.
|
||||
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
|
||||
|
@ -655,6 +771,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
|
|||
|
||||
flag.Name = string(normalizedFlagName)
|
||||
f.formal[normalizedFlagName] = flag
|
||||
f.orderedFormal = append(f.orderedFormal, flag)
|
||||
|
||||
if len(flag.Shorthand) == 0 {
|
||||
return
|
||||
|
@ -733,6 +850,7 @@ func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error {
|
|||
f.actual = make(map[NormalizedName]*Flag)
|
||||
}
|
||||
f.actual[f.normalizeFlagName(flag.Name)] = flag
|
||||
f.orderedActual = append(f.orderedActual, flag)
|
||||
flag.Changed = true
|
||||
if len(flag.Deprecated) > 0 {
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
name := s[2:]
|
||||
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)
|
||||
return
|
||||
}
|
||||
err = f.setFlag(flag, value, s)
|
||||
err = fn(flag, value, s)
|
||||
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.") {
|
||||
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)
|
||||
return
|
||||
}
|
||||
err = f.setFlag(flag, value, shorthands)
|
||||
err = fn(flag, value, shorthands)
|
||||
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
|
||||
shorthands := s[1:]
|
||||
|
||||
for len(shorthands) > 0 {
|
||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args)
|
||||
shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -843,7 +961,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error)
|
|||
return
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseArgs(args []string) (err error) {
|
||||
func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
|
||||
for len(args) > 0 {
|
||||
s := args[0]
|
||||
args = args[1:]
|
||||
|
@ -863,9 +981,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
|||
f.args = append(f.args, args...)
|
||||
break
|
||||
}
|
||||
args, err = f.parseLongArg(s, args)
|
||||
args, err = f.parseLongArg(s, args, fn)
|
||||
} else {
|
||||
args, err = f.parseShortArg(s, args)
|
||||
args, err = f.parseShortArg(s, args, fn)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -881,7 +999,41 @@ func (f *FlagSet) parseArgs(args []string) (err error) {
|
|||
func (f *FlagSet) Parse(arguments []string) error {
|
||||
f.parsed = true
|
||||
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 {
|
||||
switch f.errorHandling {
|
||||
case ContinueOnError:
|
||||
|
@ -907,6 +1059,14 @@ func Parse() {
|
|||
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.
|
||||
func SetInterspersed(interspersed bool) {
|
||||
CommandLine.SetInterspersed(interspersed)
|
||||
|
@ -920,14 +1080,15 @@ func Parsed() bool {
|
|||
// CommandLine is the default set of command-line flags, parsed from os.Args.
|
||||
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
|
||||
|
||||
// NewFlagSet returns a new, empty flag set with the specified name and
|
||||
// error handling property.
|
||||
// NewFlagSet returns a new, empty flag set with the specified name,
|
||||
// error handling property and SortFlags set to true.
|
||||
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
||||
f := &FlagSet{
|
||||
name: name,
|
||||
errorHandling: errorHandling,
|
||||
argsLenAtDash: -1,
|
||||
interspersed: true,
|
||||
SortFlags: true,
|
||||
}
|
||||
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) {
|
||||
f := NewFlagSet("shorthand", ContinueOnError)
|
||||
if f.Parsed() {
|
||||
|
@ -398,16 +451,21 @@ func TestParse(t *testing.T) {
|
|||
testParse(GetCommandLine(), t)
|
||||
}
|
||||
|
||||
func TestParseAll(t *testing.T) {
|
||||
ResetForTesting(func() { t.Error("bad parse") })
|
||||
testParseAll(GetCommandLine(), t)
|
||||
}
|
||||
|
||||
func TestFlagSetParse(t *testing.T) {
|
||||
testParse(NewFlagSet("test", ContinueOnError), t)
|
||||
}
|
||||
|
||||
func TestChangedHelper(t *testing.T) {
|
||||
f := NewFlagSet("changedtest", ContinueOnError)
|
||||
_ = f.Bool("changed", false, "changed bool")
|
||||
_ = f.Bool("settrue", true, "true to true")
|
||||
_ = f.Bool("setfalse", false, "false to false")
|
||||
_ = f.Bool("unchanged", false, "unchanged bool")
|
||||
f.Bool("changed", false, "changed bool")
|
||||
f.Bool("settrue", true, "true to true")
|
||||
f.Bool("setfalse", false, "false to false")
|
||||
f.Bool("unchanged", false, "unchanged bool")
|
||||
|
||||
args := []string{"--changed", "--settrue", "--setfalse=false"}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
goflag "flag"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
// flagValueWrapper implements pflag.Value around a flag.Value. The main
|
||||
// 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
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
|
||||
// -- net.IP value
|
||||
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"
|
||||
}
|
||||
|
||||
var _ = strings.TrimSpace
|
||||
|
||||
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
|
||||
*p = val
|
||||
return (*ipNetValue)(p)
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = fmt.Fprint
|
||||
|
||||
// -- stringArray Value
|
||||
type stringArrayValue struct {
|
||||
value *[]string
|
||||
|
@ -40,7 +33,7 @@ func (s *stringArrayValue) String() string {
|
|||
}
|
||||
|
||||
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
|
||||
if len(sval) == 0 {
|
||||
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 (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = fmt.Fprint
|
||||
|
||||
// -- stringSlice Value
|
||||
type stringSliceValue struct {
|
||||
value *[]string
|
||||
|
@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
w.Flush()
|
||||
return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil
|
||||
return strings.TrimSuffix(b.String(), "\n"), nil
|
||||
}
|
||||
|
||||
func (s *stringSliceValue) Set(val string) error {
|
||||
|
@ -66,7 +63,7 @@ func (s *stringSliceValue) String() string {
|
|||
}
|
||||
|
||||
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
|
||||
if len(sval) == 0 {
|
||||
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