Add UintFlag, Uint64Flag types and supporting code

main
Dan Buch 8 years ago
parent b7750a08e7
commit a0e694ed72
No known key found for this signature in database
GPG Key ID: FAEF12936DD3E3EC

@ -7,7 +7,7 @@
- `./runtests` test runner with coverage tracking by default
- testing on OS X
- testing on Windows
- `Int64Flag` type and supporting code
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
### Changed
- Use spaces for alignment in help/usage output instead of tabs, making the

@ -211,7 +211,7 @@ COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS
--version Shows version information
--version Shows version information
```
### Arguments
@ -984,7 +984,7 @@ func main() {
demonstration purposes. Use of one's imagination is encouraged.
<!-- {
"output": "made it!\nPhew!"
"output": "made it!\nPhew!"
} -->
``` go
package main
@ -1036,6 +1036,19 @@ func (w *hexWriter) Write(p []byte) (int, error) {
return len(p), nil
}
type genericType struct{
s string
}
func (g *genericType) Set(value string) error {
g.s = value
return nil
}
func (g *genericType) String() string {
return g.s
}
func main() {
app := cli.NewApp()
app.Name = "kənˈtrīv"
@ -1105,7 +1118,17 @@ func main() {
app.Flags = []cli.Flag{
cli.BoolFlag{Name: "fancy"},
cli.BoolTFlag{Name: "fancier"},
cli.DurationFlag{Name: "howlong, H", Value: time.Second * 3},
cli.Float64Flag{Name: "howmuch"},
cli.GenericFlag{Name: "wat", Value: &genericType{}},
cli.Int64Flag{Name: "longdistance"},
cli.Int64SliceFlag{Name: "intervals"},
cli.IntFlag{Name: "distance"},
cli.IntSliceFlag{Name: "times"},
cli.StringFlag{Name: "dance-move, d"},
cli.StringSliceFlag{Name: "names, N"},
cli.UintFlag{Name: "age"},
cli.Uint64Flag{Name: "bigage"},
}
app.EnableBashCompletion = true
app.HideHelp = false
@ -1182,10 +1205,14 @@ func main() {
fmt.Printf("%#v\n", nc.Duration("howlong"))
fmt.Printf("%#v\n", nc.Float64("hay"))
fmt.Printf("%#v\n", nc.Generic("bloop"))
fmt.Printf("%#v\n", nc.Int64("bonk"))
fmt.Printf("%#v\n", nc.Int64Slice("burnks"))
fmt.Printf("%#v\n", nc.Int("bips"))
fmt.Printf("%#v\n", nc.IntSlice("blups"))
fmt.Printf("%#v\n", nc.String("snurt"))
fmt.Printf("%#v\n", nc.StringSlice("snurkles"))
fmt.Printf("%#v\n", nc.Uint("flub"))
fmt.Printf("%#v\n", nc.Uint64("florb"))
fmt.Printf("%#v\n", nc.GlobalBool("global-nope"))
fmt.Printf("%#v\n", nc.GlobalBoolT("global-nerp"))
fmt.Printf("%#v\n", nc.GlobalDuration("global-howlong"))

@ -36,6 +36,16 @@ func (c *Context) Int64(name string) int64 {
return lookupInt64(name, c.flagSet)
}
// Uint looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Uint(name string) uint {
return lookupUint(name, c.flagSet)
}
// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Uint64(name string) uint64 {
return lookupUint64(name, c.flagSet)
}
// Duration looks up the value of a local time.Duration flag, returns 0 if no
// time.Duration flag exists
func (c *Context) Duration(name string) time.Duration {
@ -103,6 +113,22 @@ func (c *Context) GlobalInt64(name string) int64 {
return 0
}
// GlobalUint looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalUint(name string) uint {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint(name, fs)
}
return 0
}
// GlobalUint64 looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalUint64(name string) uint64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint64(name, fs)
}
return 0
}
// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0)
// if no float64 flag exists
func (c *Context) GlobalFloat64(name string) float64 {
@ -334,11 +360,11 @@ func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
func lookupInt(name string, set *flag.FlagSet) int {
f := set.Lookup(name)
if f != nil {
val, err := strconv.Atoi(f.Value.String())
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return val
return int(val)
}
return 0
@ -347,7 +373,33 @@ func lookupInt(name string, set *flag.FlagSet) int {
func lookupInt64(name string, set *flag.FlagSet) int64 {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseInt(f.Value.String(), 10, 64)
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return val
}
return 0
}
func lookupUint(name string, set *flag.FlagSet) uint {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return uint(val)
}
return 0
}
func lookupUint64(name string, set *flag.FlagSet) uint64 {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}

@ -9,11 +9,15 @@ import (
func TestNewContext(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
set.Int("myflagInt64", 12, "doc")
set.Int64("myflagInt64", int64(12), "doc")
set.Uint("myflagUint", uint(93), "doc")
set.Uint64("myflagUint64", uint64(93), "doc")
set.Float64("myflag64", float64(17), "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Int("myflag", 42, "doc")
globalSet.Int64("myflagInt64", int64(42), "doc")
globalSet.Uint("myflagUint", uint(33), "doc")
globalSet.Uint64("myflagUint64", uint64(33), "doc")
globalSet.Float64("myflag64", float64(47), "doc")
globalCtx := NewContext(nil, globalSet, nil)
command := Command{Name: "mycommand"}
@ -21,9 +25,13 @@ func TestNewContext(t *testing.T) {
c.Command = command
expect(t, c.Int("myflag"), 12)
expect(t, c.Int64("myflagInt64"), int64(12))
expect(t, c.Uint("myflagUint"), uint(93))
expect(t, c.Uint64("myflagUint64"), uint64(93))
expect(t, c.Float64("myflag64"), float64(17))
expect(t, c.GlobalInt("myflag"), 42)
expect(t, c.GlobalInt64("myflagInt64"), int64(42))
expect(t, c.GlobalUint("myflagUint"), uint(33))
expect(t, c.GlobalUint64("myflagUint64"), uint64(33))
expect(t, c.GlobalFloat64("myflag64"), float64(47))
expect(t, c.Command.Name, "mycommand")
}
@ -42,6 +50,20 @@ func TestContext_Int64(t *testing.T) {
expect(t, c.Int64("myflagInt64"), int64(12))
}
func TestContext_Uint(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Uint("myflagUint", uint(13), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Uint("myflagUint"), uint(13))
}
func TestContext_Uint64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Uint64("myflagUint64", uint64(9), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Uint64("myflagUint64"), uint64(9))
}
func TestContext_GlobalInt(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")

@ -534,6 +534,94 @@ func (f Int64Flag) GetName() string {
return f.Name
}
// UintFlag is a flag that takes an unsigned integer
type UintFlag struct {
Name string
Value uint
Usage string
EnvVar string
Destination *uint
Hidden bool
}
// String returns the usage
func (f UintFlag) String() string {
return FlagStringer(f)
}
// Apply populates the flag given the flag set and environment
func (f UintFlag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err == nil {
f.Value = uint(envValInt)
break
}
}
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.UintVar(f.Destination, name, f.Value, f.Usage)
return
}
set.Uint(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f UintFlag) GetName() string {
return f.Name
}
// Uint64Flag is a flag that takes an unsigned 64-bit integer
type Uint64Flag struct {
Name string
Value uint64
Usage string
EnvVar string
Destination *uint64
Hidden bool
}
// String returns the usage
func (f Uint64Flag) String() string {
return FlagStringer(f)
}
// Apply populates the flag given the flag set and environment
func (f Uint64Flag) Apply(set *flag.FlagSet) {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal := os.Getenv(envVar); envVal != "" {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err == nil {
f.Value = uint64(envValInt)
break
}
}
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
return
}
set.Uint64(name, f.Value, f.Usage)
})
}
// GetName returns the name of the flag.
func (f Uint64Flag) GetName() string {
return f.Name
}
// DurationFlag is a flag that takes a duration specified in Go's duration
// format: https://golang.org/pkg/time/#ParseDuration
type DurationFlag struct {

@ -198,6 +198,78 @@ func TestInt64FlagWithEnvVarHelpOutput(t *testing.T) {
}
}
var uintFlagTests = []struct {
name string
expected string
}{
{"nerfs", "--nerfs value\t(default: 41)"},
{"N", "-N value\t(default: 41)"},
}
func TestUintFlagHelpOutput(t *testing.T) {
for _, test := range uintFlagTests {
flag := UintFlag{Name: test.name, Value: 41}
output := flag.String()
if output != test.expected {
t.Errorf("%s does not match %s", output, test.expected)
}
}
}
func TestUintFlagWithEnvVarHelpOutput(t *testing.T) {
os.Clearenv()
os.Setenv("APP_BAR", "2")
for _, test := range uintFlagTests {
flag := UintFlag{Name: test.name, EnvVar: "APP_BAR"}
output := flag.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
}
}
var uint64FlagTests = []struct {
name string
expected string
}{
{"gerfs", "--gerfs value\t(default: 8589934582)"},
{"G", "-G value\t(default: 8589934582)"},
}
func TestUint64FlagHelpOutput(t *testing.T) {
for _, test := range uint64FlagTests {
flag := Uint64Flag{Name: test.name, Value: 8589934582}
output := flag.String()
if output != test.expected {
t.Errorf("%s does not match %s", output, test.expected)
}
}
}
func TestUint64FlagWithEnvVarHelpOutput(t *testing.T) {
os.Clearenv()
os.Setenv("APP_BAR", "2")
for _, test := range uint64FlagTests {
flag := UintFlag{Name: test.name, EnvVar: "APP_BAR"}
output := flag.String()
expectedSuffix := " [$APP_BAR]"
if runtime.GOOS == "windows" {
expectedSuffix = " [%APP_BAR%]"
}
if !strings.HasSuffix(output, expectedSuffix) {
t.Errorf("%s does not end with"+expectedSuffix, output)
}
}
}
var durationFlagTests = []struct {
name string
expected string

Loading…
Cancel
Save