feat(kit/cli): add support for int32 and int64 CLI flags
parent
affb64c888
commit
a952dff92d
|
@ -150,6 +150,58 @@ func BindOptions(v *viper.Viper, cmd *cobra.Command, opts []Opt) {
|
|||
}
|
||||
mustBindPFlag(v, o.Flag, flagset)
|
||||
*destP = v.GetInt(envVar)
|
||||
case *int32:
|
||||
var d int32
|
||||
if o.Default != nil {
|
||||
// N.B. since our CLI kit types default values as interface{} and
|
||||
// literal numbers get typed as int by default, it's very easy to
|
||||
// create an int32 CLI flag with an int default value.
|
||||
//
|
||||
// The compiler doesn't know to complain in that case, so you end up
|
||||
// with a runtime panic when trying to bind the CLI options.
|
||||
//
|
||||
// To avoid that headache, we support both int32 and int defaults
|
||||
// for int32 fields. This introduces a new runtime bomb if somebody
|
||||
// specifies an int default > math.MaxInt32, but that's hopefully
|
||||
// less likely.
|
||||
var ok bool
|
||||
d, ok = o.Default.(int32)
|
||||
if !ok {
|
||||
d = int32(o.Default.(int))
|
||||
}
|
||||
}
|
||||
if hasShort {
|
||||
flagset.Int32VarP(destP, o.Flag, string(o.Short), d, o.Desc)
|
||||
} else {
|
||||
flagset.Int32Var(destP, o.Flag, d, o.Desc)
|
||||
}
|
||||
mustBindPFlag(v, o.Flag, flagset)
|
||||
*destP = v.GetInt32(envVar)
|
||||
case *int64:
|
||||
var d int64
|
||||
if o.Default != nil {
|
||||
// N.B. since our CLI kit types default values as interface{} and
|
||||
// literal numbers get typed as int by default, it's very easy to
|
||||
// create an int64 CLI flag with an int default value.
|
||||
//
|
||||
// The compiler doesn't know to complain in that case, so you end up
|
||||
// with a runtime panic when trying to bind the CLI options.
|
||||
//
|
||||
// To avoid that headache, we support both int64 and int defaults
|
||||
// for int64 fields.
|
||||
var ok bool
|
||||
d, ok = o.Default.(int64)
|
||||
if !ok {
|
||||
d = int64(o.Default.(int))
|
||||
}
|
||||
}
|
||||
if hasShort {
|
||||
flagset.Int64VarP(destP, o.Flag, string(o.Short), d, o.Desc)
|
||||
} else {
|
||||
flagset.Int64Var(destP, o.Flag, d, o.Desc)
|
||||
}
|
||||
mustBindPFlag(v, o.Flag, flagset)
|
||||
*destP = v.GetInt64(envVar)
|
||||
case *bool:
|
||||
var d bool
|
||||
if o.Default != nil {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
@ -40,6 +41,8 @@ func (c *customFlag) Type() string {
|
|||
func ExampleNewCommand() {
|
||||
var monitorHost string
|
||||
var number int
|
||||
var smallerNumber int32
|
||||
var longerNumber int64
|
||||
var sleep bool
|
||||
var duration time.Duration
|
||||
var stringSlice []string
|
||||
|
@ -50,6 +53,7 @@ func ExampleNewCommand() {
|
|||
for i := 0; i < number; i++ {
|
||||
fmt.Printf("%d\n", i)
|
||||
}
|
||||
fmt.Println(longerNumber - int64(smallerNumber))
|
||||
fmt.Println(sleep)
|
||||
fmt.Println(duration)
|
||||
fmt.Println(stringSlice)
|
||||
|
@ -70,6 +74,18 @@ func ExampleNewCommand() {
|
|||
Default: 2,
|
||||
Desc: "number of times to loop",
|
||||
},
|
||||
{
|
||||
DestP: &smallerNumber,
|
||||
Flag: "smaller-number",
|
||||
Default: math.MaxInt32,
|
||||
Desc: "limited size number",
|
||||
},
|
||||
{
|
||||
DestP: &longerNumber,
|
||||
Flag: "longer-number",
|
||||
Default: math.MaxInt64,
|
||||
Desc: "explicitly expanded-size number",
|
||||
},
|
||||
{
|
||||
DestP: &sleep,
|
||||
Flag: "sleep",
|
||||
|
@ -104,6 +120,7 @@ func ExampleNewCommand() {
|
|||
// http://localhost:8086
|
||||
// 0
|
||||
// 1
|
||||
// 9223372034707292160
|
||||
// true
|
||||
// 1m0s
|
||||
// [foo bar]
|
||||
|
@ -113,8 +130,10 @@ func ExampleNewCommand() {
|
|||
func Test_NewProgram(t *testing.T) {
|
||||
testFilePath, cleanup := newConfigFile(t, map[string]string{
|
||||
// config values should be same as flags
|
||||
"foo": "bar",
|
||||
"shoe-fly": "yadon",
|
||||
"foo": "bar",
|
||||
"shoe-fly": "yadon",
|
||||
"number": "2147483647",
|
||||
"long-number": "9223372036854775807",
|
||||
})
|
||||
defer cleanup()
|
||||
defer setEnvVar("TEST_CONFIG_PATH", testFilePath)()
|
||||
|
@ -155,6 +174,8 @@ func Test_NewProgram(t *testing.T) {
|
|||
|
||||
var testVar string
|
||||
var testFly string
|
||||
var testNumber int32
|
||||
var testLongNumber int64
|
||||
program := &Program{
|
||||
Name: "test",
|
||||
Opts: []Opt{
|
||||
|
@ -167,6 +188,14 @@ func Test_NewProgram(t *testing.T) {
|
|||
DestP: &testFly,
|
||||
Flag: "shoe-fly",
|
||||
},
|
||||
{
|
||||
DestP: &testNumber,
|
||||
Flag: "number",
|
||||
},
|
||||
{
|
||||
DestP: &testLongNumber,
|
||||
Flag: "long-number",
|
||||
},
|
||||
},
|
||||
Run: func() error { return nil },
|
||||
}
|
||||
|
@ -177,6 +206,8 @@ func Test_NewProgram(t *testing.T) {
|
|||
|
||||
require.Equal(t, tt.expected, testVar)
|
||||
assert.Equal(t, "yadon", testFly)
|
||||
assert.Equal(t, int32(math.MaxInt32), testNumber)
|
||||
assert.Equal(t, int64(math.MaxInt64), testLongNumber)
|
||||
}
|
||||
|
||||
t.Run(tt.name, fn)
|
||||
|
|
Loading…
Reference in New Issue