diff --git a/args.go b/args.go index 9484e997d2..280297bfb4 100644 --- a/args.go +++ b/args.go @@ -152,9 +152,17 @@ func (a *ArgumentBase[T, C, VC]) Parse(s []string) ([]string, error) { type ( FloatArg = ArgumentBase[float64, NoConfig, floatValue] - IntArg = ArgumentBase[int64, IntegerConfig, intValue] + IntArg = ArgumentBase[int, IntegerConfig, intValue[int]] + Int8Arg = ArgumentBase[int8, IntegerConfig, intValue[int8]] + Int16Arg = ArgumentBase[int16, IntegerConfig, intValue[int16]] + Int32Arg = ArgumentBase[int32, IntegerConfig, intValue[int32]] + Int64Arg = ArgumentBase[int64, IntegerConfig, intValue[int64]] StringArg = ArgumentBase[string, StringConfig, stringValue] StringMapArg = ArgumentBase[map[string]string, StringConfig, StringMap] TimestampArg = ArgumentBase[time.Time, TimestampConfig, timestampValue] - UintArg = ArgumentBase[uint64, IntegerConfig, uintValue] + UintArg = ArgumentBase[uint, IntegerConfig, uintValue[uint]] + Uint8Arg = ArgumentBase[uint8, IntegerConfig, uintValue[uint8]] + Uint16Arg = ArgumentBase[uint16, IntegerConfig, uintValue[uint16]] + Uint32Arg = ArgumentBase[uint32, IntegerConfig, uintValue[uint32]] + Uint64Arg = ArgumentBase[uint64, IntegerConfig, uintValue[uint64]] ) diff --git a/args_test.go b/args_test.go index cd9fc79346..b5267e2852 100644 --- a/args_test.go +++ b/args_test.go @@ -15,7 +15,7 @@ func TestArgumentsRootCommand(t *testing.T) { var fval float64 var fvals []float64 cmd.Arguments = []Argument{ - &IntArg{ + &Int64Arg{ Name: "ia", Min: 1, Max: 1, @@ -49,7 +49,7 @@ func TestArgumentsRootCommand(t *testing.T) { &StringArg{ Name: "sa", }, - &UintArg{ + &Uint64Arg{ Name: "ua", Min: 2, Max: 1, // max is less than min @@ -68,7 +68,7 @@ func TestArgumentsSubcommand(t *testing.T) { { Name: "subcmd", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "foo", Value: 10, Destination: &ifval, @@ -114,7 +114,7 @@ func TestArgumentsSubcommand(t *testing.T) { } func TestArgsUsage(t *testing.T) { - arg := &IntArg{ + arg := &Int64Arg{ Name: "ia", Min: 0, Max: 1, diff --git a/command_test.go b/command_test.go index de1b06aa5c..c0715ad9ea 100644 --- a/command_test.go +++ b/command_test.go @@ -355,7 +355,7 @@ func TestCommand_OnUsageError_hasCommandContext(t *testing.T) { cmd := &Command{ Name: "bar", Flags: []Flag{ - &IntFlag{Name: "flag"}, + &Int64Flag{Name: "flag"}, }, OnUsageError: func(_ context.Context, cmd *Command, err error, _ bool) error { return fmt.Errorf("intercepted in %s: %s", cmd.Name, err.Error()) @@ -370,7 +370,7 @@ func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) { cmd := &Command{ Name: "bar", Flags: []Flag{ - &IntFlag{Name: "flag"}, + &Int64Flag{Name: "flag"}, }, OnUsageError: func(_ context.Context, _ *Command, err error, _ bool) error { assert.ErrorContains(t, err, "strconv.ParseInt: parsing \"wrong\"") @@ -391,7 +391,7 @@ func TestCommand_OnUsageError_WithSubcommand(t *testing.T) { }, }, Flags: []Flag{ - &IntFlag{Name: "flag"}, + &Int64Flag{Name: "flag"}, }, OnUsageError: func(_ context.Context, _ *Command, err error, _ bool) error { assert.ErrorContains(t, err, "parsing \"wrong\": invalid syntax") @@ -478,7 +478,7 @@ func TestCommand_Run_CustomShellCompleteAcceptsMalformedFlags(t *testing.T) { Name: "bar", Usage: "this is for testing", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "number", Usage: "A number to parse", }, @@ -558,7 +558,7 @@ func TestCommand_VisibleFlagCategories(t *testing.T) { Name: "strd1", // no category set and also hidden Hidden: true, }, - &IntFlag{ + &Int64Flag{ Name: "intd", Aliases: []string{"altd1", "altd2"}, Category: "cat1", @@ -1253,11 +1253,11 @@ func TestCommand_ParseSliceFlags(t *testing.T) { { Name: "cmd", Flags: []Flag{ - &IntSliceFlag{Name: "p", Value: []int64{}, Usage: "set one or more ip addr"}, + &Int64SliceFlag{Name: "p", Value: []int64{}, Usage: "set one or more ip addr"}, &StringSliceFlag{Name: "ip", Value: []string{}, Usage: "set one or more ports to open"}, }, Action: func(_ context.Context, cmd *Command) error { - parsedIntSlice = cmd.IntSlice("p") + parsedIntSlice = cmd.Int64Slice("p") parsedStringSlice = cmd.StringSlice("ip") return nil }, @@ -1281,11 +1281,11 @@ func TestCommand_ParseSliceFlagsWithMissingValue(t *testing.T) { { Name: "cmd", Flags: []Flag{ - &IntSliceFlag{Name: "a", Usage: "set numbers"}, + &Int64SliceFlag{Name: "a", Usage: "set numbers"}, &StringSliceFlag{Name: "str", Usage: "set strings"}, }, Action: func(_ context.Context, cmd *Command) error { - parsedIntSlice = cmd.IntSlice("a") + parsedIntSlice = cmd.Int64Slice("a") parsedStringSlice = cmd.StringSlice("str") return nil }, @@ -2301,7 +2301,7 @@ func TestCommand_Run_SubcommandDoesNotOverwriteErrorFromBefore(t *testing.T) { func TestCommand_OnUsageError_WithWrongFlagValue_ForSubcommand(t *testing.T) { cmd := &Command{ Flags: []Flag{ - &IntFlag{Name: "flag"}, + &Int64Flag{Name: "flag"}, }, OnUsageError: func(_ context.Context, _ *Command, err error, isSubcommand bool) error { assert.False(t, isSubcommand, "Expect subcommand") @@ -2455,7 +2455,7 @@ func TestHandleExitCoder_Custom(t *testing.T) { func TestShellCompletionForIncompleteFlags(t *testing.T) { cmd := &Command{ Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "test-completion", }, }, @@ -2808,7 +2808,7 @@ func TestFlagAction(t *testing.T) { return err }, }, - &IntFlag{ + &Int64Flag{ Name: "f_int", Local: true, Action: func(_ context.Context, cmd *Command, v int64) error { @@ -2819,7 +2819,7 @@ func TestFlagAction(t *testing.T) { return err }, }, - &IntSliceFlag{ + &Int64SliceFlag{ Name: "f_int_slice", Local: true, Action: func(_ context.Context, cmd *Command, v []int64) error { @@ -2846,7 +2846,7 @@ func TestFlagAction(t *testing.T) { return err }, }, - &UintFlag{ + &Uint64Flag{ Name: "f_uint", Local: true, Action: func(_ context.Context, cmd *Command, v uint64) error { @@ -2906,7 +2906,7 @@ func TestPersistentFlag(t *testing.T) { return nil }, }, - &IntSliceFlag{ + &Int64SliceFlag{ Name: "persistentCommandSliceFlag", Destination: &persistentCommandSliceInt, }, @@ -2914,7 +2914,7 @@ func TestPersistentFlag(t *testing.T) { Name: "persistentCommandFloatSliceFlag", Value: []float64{11.3, 12.5}, }, - &IntFlag{ + &Int64Flag{ Name: "persistentCommandOverrideFlag", Destination: &appOverrideInt, }, @@ -2928,16 +2928,16 @@ func TestPersistentFlag(t *testing.T) { { Name: "cmd", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "cmdFlag", Destination: &topInt, Local: true, }, - &IntFlag{ + &Int64Flag{ Name: "cmdPersistentFlag", Destination: &topPersistentInt, }, - &IntFlag{ + &Int64Flag{ Name: "paof", Aliases: []string{"persistentCommandOverrideFlag"}, Destination: &appOverrideCmdInt, @@ -2948,7 +2948,7 @@ func TestPersistentFlag(t *testing.T) { { Name: "subcmd", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "cmdFlag", Destination: &subCommandInt, Local: true, @@ -3080,7 +3080,7 @@ func TestRequiredFlagDelayed(t *testing.T) { { Name: "sub", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "if", Required: true, }, @@ -3169,7 +3169,7 @@ func TestFlagDuplicates(t *testing.T) { Name: "sflag", OnlyOnce: true, }, - &IntSliceFlag{ + &Int64SliceFlag{ Name: "isflag", }, &FloatSliceFlag{ @@ -3180,7 +3180,7 @@ func TestFlagDuplicates(t *testing.T) { Name: "bifflag", OnlyOnce: true, }, - &IntFlag{ + &Int64Flag{ Name: "iflag", }, }, @@ -3261,7 +3261,7 @@ func TestShorthandCommand(t *testing.T) { func TestCommand_Int(t *testing.T) { pCmd := &Command{ Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "myflag", Value: 12, }, @@ -3269,7 +3269,7 @@ func TestCommand_Int(t *testing.T) { } cmd := &Command{ Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "top-flag", Value: 13, }, @@ -3277,14 +3277,14 @@ func TestCommand_Int(t *testing.T) { parent: pCmd, } - require.Equal(t, int64(12), cmd.Int("myflag")) - require.Equal(t, int64(13), cmd.Int("top-flag")) + require.Equal(t, int64(12), cmd.Int64("myflag")) + require.Equal(t, int64(13), cmd.Int64("top-flag")) } func TestCommand_Uint(t *testing.T) { pCmd := &Command{ Flags: []Flag{ - &UintFlag{ + &Uint64Flag{ Name: "myflagUint", Value: 13, }, @@ -3292,7 +3292,7 @@ func TestCommand_Uint(t *testing.T) { } cmd := &Command{ Flags: []Flag{ - &UintFlag{ + &Uint64Flag{ Name: "top-flag", Value: 14, }, @@ -3300,8 +3300,8 @@ func TestCommand_Uint(t *testing.T) { parent: pCmd, } - require.Equal(t, uint64(13), cmd.Uint("myflagUint")) - require.Equal(t, uint64(14), cmd.Uint("top-flag")) + require.Equal(t, uint64(13), cmd.Uint64("myflagUint")) + require.Equal(t, uint64(14), cmd.Uint64("top-flag")) } func TestCommand_Float64(t *testing.T) { @@ -3442,7 +3442,7 @@ func TestCommand_Value(t *testing.T) { subCmd := &Command{ Name: "test", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "myflag", Usage: "doc", Aliases: []string{"m", "mf"}, @@ -3455,7 +3455,7 @@ func TestCommand_Value(t *testing.T) { cmd := &Command{ Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "top-flag", Usage: "doc", Aliases: []string{"t", "tf"}, @@ -3675,7 +3675,7 @@ func TestCommand_NumFlags(t *testing.T) { func TestCommand_Set(t *testing.T) { cmd := &Command{ Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "int", Value: 5, }, @@ -3685,7 +3685,7 @@ func TestCommand_Set(t *testing.T) { r.False(cmd.IsSet("int")) r.NoError(cmd.Set("int", "1")) - r.Equal(int64(1), cmd.Int("int")) + r.Equal(int64(1), cmd.Int64("int")) r.True(cmd.IsSet("int")) } @@ -4151,7 +4151,7 @@ func TestCommandReadArgsFromStdIn(t *testing.T) { cmd.Reader, err = os.Open(fp.Name()) r.NoError(err) cmd.Flags = []Flag{ - &IntFlag{ + &Int64Flag{ Name: "if", }, &FloatFlag{ @@ -4164,7 +4164,7 @@ func TestCommandReadArgsFromStdIn(t *testing.T) { actionCalled := false cmd.Action = func(ctx context.Context, c *Command) error { - r.Equal(tst.expectedInt, c.Int("if")) + r.Equal(tst.expectedInt, c.Int64("if")) r.Equal(tst.expectedFloat, c.Float("ff")) r.Equal(tst.expectedSlice, c.StringSlice("ssf")) actionCalled = true @@ -4189,15 +4189,15 @@ func TestZeroValueCommand(t *testing.T) { func TestCommandInvalidName(t *testing.T) { var cmd Command - assert.Equal(t, int64(0), cmd.Int("foo")) - assert.Equal(t, uint64(0), cmd.Uint("foo")) + assert.Equal(t, int64(0), cmd.Int64("foo")) + assert.Equal(t, uint64(0), cmd.Uint64("foo")) assert.Equal(t, float64(0), cmd.Float("foo")) assert.Equal(t, "", cmd.String("foo")) assert.Equal(t, time.Time{}, cmd.Timestamp("foo")) assert.Equal(t, time.Duration(0), cmd.Duration("foo")) - assert.Equal(t, []int64(nil), cmd.IntSlice("foo")) - assert.Equal(t, []uint64(nil), cmd.UintSlice("foo")) + assert.Equal(t, []int64(nil), cmd.Int64Slice("foo")) + assert.Equal(t, []uint64(nil), cmd.Uint64Slice("foo")) assert.Equal(t, []float64(nil), cmd.FloatSlice("foo")) assert.Equal(t, []string(nil), cmd.StringSlice("foo")) } @@ -4501,7 +4501,7 @@ func TestSliceStringFlagParsing(t *testing.T) { func TestJSONExportCommand(t *testing.T) { cmd := buildExtendedTestCommand() cmd.Arguments = []Argument{ - &IntArg{ + &Int64Arg{ Name: "fooi", }, } diff --git a/examples_test.go b/examples_test.go index 7a0cc3b92d..c86b89657f 100644 --- a/examples_test.go +++ b/examples_test.go @@ -246,7 +246,7 @@ func ExampleCommand_Run_shellComplete_bash_withShortFlag() { Name: "greet", EnableShellCompletion: true, Flags: []cli.Flag{ - &cli.IntFlag{ + &cli.Int64Flag{ Name: "other", Aliases: []string{"o"}, }, @@ -273,7 +273,7 @@ func ExampleCommand_Run_shellComplete_bash_withLongFlag() { Name: "greet", EnableShellCompletion: true, Flags: []cli.Flag{ - &cli.IntFlag{ + &cli.Int64Flag{ Name: "other", Aliases: []string{"o"}, }, @@ -305,7 +305,7 @@ func ExampleCommand_Run_shellComplete_bash_withMultipleLongFlag() { Name: "greet", EnableShellCompletion: true, Flags: []cli.Flag{ - &cli.IntFlag{ + &cli.Int64Flag{ Name: "int-flag", Aliases: []string{"i"}, }, @@ -415,7 +415,7 @@ func ExampleCommand_Run_sliceValues() { Flags: []cli.Flag{ &cli.StringSliceFlag{Name: "stringSlice"}, &cli.FloatSliceFlag{Name: "float64Slice"}, - &cli.IntSliceFlag{Name: "intSlice"}, + &cli.Int64SliceFlag{Name: "intSlice"}, }, HideHelp: true, Action: func(ctx context.Context, cmd *cli.Command) error { diff --git a/flag_ext.go b/flag_ext.go index 4d4760a77b..9972af7c56 100644 --- a/flag_ext.go +++ b/flag_ext.go @@ -7,6 +7,10 @@ type extFlag struct { } func (e *extFlag) PreParse() error { + if e.f.DefValue != "" { + return e.Set("", e.f.DefValue) + } + return nil } diff --git a/flag_int.go b/flag_int.go index f8e3640b1a..0e082221e4 100644 --- a/flag_int.go +++ b/flag_int.go @@ -2,55 +2,103 @@ package cli import ( "strconv" + "unsafe" ) -type IntFlag = FlagBase[int64, IntegerConfig, intValue] +type ( + IntFlag = FlagBase[int, IntegerConfig, intValue[int]] + Int8Flag = FlagBase[int8, IntegerConfig, intValue[int8]] + Int16Flag = FlagBase[int16, IntegerConfig, intValue[int16]] + Int32Flag = FlagBase[int32, IntegerConfig, intValue[int32]] + Int64Flag = FlagBase[int64, IntegerConfig, intValue[int64]] +) // IntegerConfig is the configuration for all integer type flags type IntegerConfig struct { Base int } -// -- int64 Value -type intValue struct { - val *int64 +// -- int Value +type intValue[T int | int8 | int16 | int32 | int64] struct { + val *T base int } // Below functions are to satisfy the ValueCreator interface -func (i intValue) Create(val int64, p *int64, c IntegerConfig) Value { +func (i intValue[T]) Create(val T, p *T, c IntegerConfig) Value { *p = val - return &intValue{ + + return &intValue[T]{ val: p, base: c.Base, } } -func (i intValue) ToString(b int64) string { - return strconv.FormatInt(b, 10) +func (i intValue[T]) ToString(b T) string { + if i.base == 0 { + i.base = 10 + } + + return strconv.FormatInt(int64(b), i.base) } // Below functions are to satisfy the flag.Value interface -func (i *intValue) Set(s string) error { - v, err := strconv.ParseInt(s, i.base, 64) +func (i *intValue[T]) Set(s string) error { + v, err := strconv.ParseInt(s, i.base, int(unsafe.Sizeof(T(0))*8)) if err != nil { return err } - *i.val = v + *i.val = T(v) return err } -func (i *intValue) Get() any { return int64(*i.val) } +func (i *intValue[T]) Get() any { return *i.val } -func (i *intValue) String() string { return strconv.FormatInt(int64(*i.val), 10) } +func (i *intValue[T]) String() string { + base := i.base + if base == 0 { + base = 10 + } + + return strconv.FormatInt(int64(*i.val), base) +} // Int looks up the value of a local Int64Flag, returns // 0 if not found -func (cmd *Command) Int(name string) int64 { - if v, ok := cmd.Value(name).(int64); ok { +func (cmd *Command) Int(name string) int { + return getInt[int](cmd, name) +} + +// Int8 looks up the value of a local Int8Flag, returns +// 0 if not found +func (cmd *Command) Int8(name string) int8 { + return getInt[int8](cmd, name) +} + +// Int16 looks up the value of a local Int16Flag, returns +// 0 if not found +func (cmd *Command) Int16(name string) int16 { + return getInt[int16](cmd, name) +} + +// Int32 looks up the value of a local Int32Flag, returns +// 0 if not found +func (cmd *Command) Int32(name string) int32 { + return getInt[int32](cmd, name) +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (cmd *Command) Int64(name string) int64 { + return getInt[int64](cmd, name) +} + +func getInt[T int | int8 | int16 | int32 | int64](cmd *Command, name string) T { + if v, ok := cmd.Value(name).(T); ok { tracef("int available for flag name %[1]q with value=%[2]v (cmd=%[3]q)", name, v, cmd.Name) + return v } diff --git a/flag_int_slice.go b/flag_int_slice.go index 94a9b78d2e..24d53a46fc 100644 --- a/flag_int_slice.go +++ b/flag_int_slice.go @@ -1,17 +1,60 @@ package cli type ( - IntSlice = SliceBase[int64, IntegerConfig, intValue] - IntSliceFlag = FlagBase[[]int64, IntegerConfig, IntSlice] + IntSlice = SliceBase[int, IntegerConfig, intValue[int]] + Int8Slice = SliceBase[int8, IntegerConfig, intValue[int8]] + Int16Slice = SliceBase[int16, IntegerConfig, intValue[int16]] + Int32Slice = SliceBase[int32, IntegerConfig, intValue[int32]] + Int64Slice = SliceBase[int64, IntegerConfig, intValue[int64]] + IntSliceFlag = FlagBase[[]int, IntegerConfig, IntSlice] + Int8SliceFlag = FlagBase[[]int8, IntegerConfig, Int8Slice] + Int16SliceFlag = FlagBase[[]int16, IntegerConfig, Int16Slice] + Int32SliceFlag = FlagBase[[]int32, IntegerConfig, Int32Slice] + Int64SliceFlag = FlagBase[[]int64, IntegerConfig, Int64Slice] ) -var NewIntSlice = NewSliceBase[int64, IntegerConfig, intValue] +var ( + NewIntSlice = NewSliceBase[int, IntegerConfig, intValue[int]] + NewInt8Slice = NewSliceBase[int8, IntegerConfig, intValue[int8]] + NewInt16Slice = NewSliceBase[int16, IntegerConfig, intValue[int16]] + NewInt32Slice = NewSliceBase[int32, IntegerConfig, intValue[int32]] + NewInt64Slice = NewSliceBase[int64, IntegerConfig, intValue[int64]] +) // IntSlice looks up the value of a local IntSliceFlag, returns // nil if not found -func (cmd *Command) IntSlice(name string) []int64 { - if v, ok := cmd.Value(name).([]int64); ok { +func (cmd *Command) IntSlice(name string) []int { + return getIntSlice[int](cmd, name) +} + +// Int8Slice looks up the value of a local Int8SliceFlag, returns +// nil if not found +func (cmd *Command) Int8Slice(name string) []int8 { + return getIntSlice[int8](cmd, name) +} + +// Int16Slice looks up the value of a local Int16SliceFlag, returns +// nil if not found +func (cmd *Command) Int16Slice(name string) []int16 { + return getIntSlice[int16](cmd, name) +} + +// Int32Slice looks up the value of a local Int32SliceFlag, returns +// nil if not found +func (cmd *Command) Int32Slice(name string) []int32 { + return getIntSlice[int32](cmd, name) +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// nil if not found +func (cmd *Command) Int64Slice(name string) []int64 { + return getIntSlice[int64](cmd, name) +} + +func getIntSlice[T int | int8 | int16 | int32 | int64](cmd *Command, name string) []T { + if v, ok := cmd.Value(name).([]T); ok { tracef("int slice available for flag name %[1]q with value=%[2]v (cmd=%[3]q)", name, v, cmd.Name) + return v } diff --git a/flag_int_slice_test.go b/flag_int_slice_test.go new file mode 100644 index 0000000000..7c85e2ece9 --- /dev/null +++ b/flag_int_slice_test.go @@ -0,0 +1,254 @@ +package cli + +import ( + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCommand_IntSlice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []int + expectErr bool + }{ + { + flag: &IntSliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []int{1, 2, 3, 4}, + }, + { + flag: &IntSliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []int{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.IntSlice(name), "IntSlice(%v)", name) + } + }) + } +} + +func TestCommand_Int8Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []int8 + expectErr bool + }{ + { + flag: &Int8SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []int8{1, 2, 3, 4}, + }, + { + flag: &Int8SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []int8{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Int8Slice(name), "Int8Slice(%v)", name) + } + }) + } +} + +func TestCommand_Int16Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []int16 + expectErr bool + }{ + { + flag: &Int16SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []int16{1, 2, 3, 4}, + }, + { + flag: &Int16SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []int16{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Int16Slice(name), "Int16Slice(%v)", name) + } + }) + } +} + +func TestCommand_Int32Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []int32 + expectErr bool + }{ + { + flag: &Int32SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []int32{1, 2, 3, 4}, + }, + { + flag: &Int32SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []int32{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Int32Slice(name), "Int32Slice(%v)", name) + } + }) + } +} + +func TestCommand_Int64Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []int64 + expectErr bool + }{ + { + flag: &Int64SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []int64{1, 2, 3, 4}, + }, + { + flag: &Int64SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []int64{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Int64Slice(name), "Int64Slice(%v)", name) + } + }) + } +} diff --git a/flag_int_test.go b/flag_int_test.go new file mode 100644 index 0000000000..47b8f69052 --- /dev/null +++ b/flag_int_test.go @@ -0,0 +1,387 @@ +package cli + +import ( + "flag" + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIntFlag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue int + expectErr bool + }{ + { + name: "valid", + flag: &IntFlag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "-234567"}, + expectedValue: -234567, + }, + { + name: "invalid", + flag: &IntFlag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Int(name)) + } + }) + } +} + +func TestInt8Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue int8 + expectErr bool + }{ + { + name: "valid", + flag: &Int8Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "127"}, + expectedValue: 127, + }, + { + name: "invalid", + flag: &Int8Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Int8(name)) + } + }) + } +} + +func TestInt16Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue int16 + expectErr bool + }{ + { + name: "valid", + flag: &Int16Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "32767"}, + expectedValue: 32767, + }, + { + name: "invalid", + flag: &Int16Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + { + name: "out of range", + flag: &Int16Flag{ + Name: "number", + }, + arguments: []string{"--number", "32768"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Int16(name)) + } + }) + } +} + +func TestInt32Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue int32 + expectErr bool + }{ + { + name: "valid", + flag: &Int32Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "2147483647"}, + expectedValue: 2147483647, + }, + { + name: "invalid", + flag: &Int32Flag{ + Name: "number", + }, + + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + { + name: "out of range", + flag: &Int32Flag{ + Name: "number", + }, + arguments: []string{"--number", "2147483648"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Int32(name)) + } + }) + } +} + +func TestInt64Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue int64 + expectErr bool + }{ + { + name: "valid", + flag: &Int64Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "-2147483648"}, + expectedValue: -2147483648, + }, + { + name: "invalid", + flag: &Int64Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Int64(name)) + } + }) + } +} + +func TestIntFlagExt(t *testing.T) { + tests := []struct { + name string + flag *flag.Flag + config IntegerConfig + arguments []string + flagName string + expectedValue string + expectErr bool + }{ + { + name: "valid", + flag: &flag.Flag{ + Name: "number", + }, + config: IntegerConfig{}, + arguments: []string{"--number", "234567"}, + flagName: "number", + expectedValue: "234567", + }, + { + name: "valid", + flag: &flag.Flag{ + Name: "number", + }, + config: IntegerConfig{Base: 10}, + arguments: []string{"--number", "234567"}, + flagName: "number", + expectedValue: "234567", + }, + { + name: "valid hex", + flag: &flag.Flag{ + Name: "number", + DefValue: "FFFF", + }, + config: IntegerConfig{Base: 16}, + arguments: []string{"--number", "39447"}, + flagName: "number", + expectedValue: "39447", + }, + { + name: "valid hex default", + flag: &flag.Flag{ + Name: "number", + DefValue: "FFFF", + }, + config: IntegerConfig{Base: 16}, + expectedValue: "ffff", + }, + { + name: "invalid", + flag: &flag.Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var uValue intValue[int] + var u int + + f := &extFlag{f: tt.flag} + + tt.flag.Value = uValue.Create(u, &u, tt.config) + + if tt.config.Base != 0 && tt.config.Base != 10 { + t.Skipf("skipping %q with base %d, only base 10 is supported", tt.name, tt.config.Base) + } + + cmd := &Command{ + Name: "mock", + Flags: []Flag{f}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + assert.Equal(t, tt.expectedValue, f.GetValue()) + }) + } +} diff --git a/flag_mutex_test.go b/flag_mutex_test.go index d8fb035900..69ceec2328 100644 --- a/flag_mutex_test.go +++ b/flag_mutex_test.go @@ -13,7 +13,7 @@ func newCommand() *Command { { Flags: [][]Flag{ { - &IntFlag{ + &Int64Flag{ Name: "i", }, &StringFlag{ @@ -25,7 +25,7 @@ func newCommand() *Command { }, }, { - &IntFlag{ + &Int64Flag{ Name: "t", Aliases: []string{"ai"}, Sources: EnvVars("T_VAR"), diff --git a/flag_test.go b/flag_test.go index 6fcdca2183..202c56aa3e 100644 --- a/flag_test.go +++ b/flag_test.go @@ -223,38 +223,38 @@ func TestFlagsFromEnv(t *testing.T) { }, { - name: "IntFlag valid", + name: "Int64Flag valid", input: "1", output: int64(1), - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, }, { - name: "IntFlag invalid from float", + name: "Int64Flag invalid from float", input: "1.2", output: 0, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "1.2" as int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "IntFlag invalid", + name: "Int64Flag invalid", input: "foobar", output: 0, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "foobar" as int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "IntFlag valid from hex", + name: "Int64Flag valid from hex", input: "deadBEEF", output: int64(3735928559), - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 16}}, + fl: &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 16}}, }, { - name: "IntFlag invalid from octal", + name: "Int64Flag invalid from octal", input: "08", output: 0, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 0}}, + fl: &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 8}}, errContains: `could not parse "08" as int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, @@ -280,47 +280,47 @@ func TestFlagsFromEnv(t *testing.T) { fl: &GenericFlag{Name: "names", Value: &Parser{}, Sources: EnvVars("NAMES")}, }, { - name: "IntSliceFlag valid", + name: "Int64SliceFlag valid", input: "1,2", output: []int64{1, 2}, - fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Int64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, }, { - name: "IntSliceFlag invalid from float", + name: "Int64SliceFlag invalid from float", input: "1.2,2", output: []int64{}, - fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Int64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "1.2,2" as []int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "IntSliceFlag invalid", + name: "Int64SliceFlag invalid", input: "foobar", output: []int64{}, - fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Int64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "foobar" as []int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "UintSliceFlag valid", + name: "Uint64SliceFlag valid", input: "1,2", output: []uint64{1, 2}, - fl: &UintSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Uint64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, }, { - name: "UintSliceFlag invalid with float", + name: "Uint64SliceFlag invalid with float", input: "1.2,2", output: []uint64{}, - fl: &UintSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Uint64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "1.2,2" as []uint64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "UintSliceFlag invalid", + name: "Uint64SliceFlag invalid", input: "foobar", output: []uint64{}, - fl: &UintSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Uint64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "foobar" as []uint64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, @@ -365,50 +365,50 @@ func TestFlagsFromEnv(t *testing.T) { }, { - name: "UintFlag valid", + name: "Uint64Flag valid", input: "1", output: uint64(1), - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, }, { - name: "UintFlag valid leading zero", + name: "Uint64Flag valid leading zero", input: "08", output: uint64(8), - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 10}}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 10}}, }, { - name: "UintFlag valid from octal", + name: "Uint64Flag valid from octal", input: "755", output: uint64(493), - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 8}}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 8}}, }, { - name: "UintFlag valid from hex", + name: "Uint64Flag valid from hex", input: "deadBEEF", output: uint64(3735928559), - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 16}}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 16}}, }, { - name: "UintFlag invalid octal", + name: "Uint64Flag invalid octal", input: "08", output: 0, - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 0}}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 8}}, errContains: `could not parse "08" as uint64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "UintFlag invalid float", + name: "Uint64Flag invalid float", input: "1.2", output: 0, - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "1.2" as uint64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { - name: "UintFlag invalid", + name: "Uint64Flag invalid", input: "foobar", output: 0, - fl: &UintFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, + fl: &Uint64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, errContains: `could not parse "foobar" as uint64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, @@ -518,52 +518,52 @@ func TestFlagStringifying(t *testing.T) { }, { name: "int-flag", - fl: &IntFlag{Name: "grubs"}, + fl: &Int64Flag{Name: "grubs"}, expected: "--grubs int\t(default: 0)", }, { name: "int-flag-with-default-text", - fl: &IntFlag{Name: "poisons", DefaultText: "11ty"}, + fl: &Int64Flag{Name: "poisons", DefaultText: "11ty"}, expected: "--poisons int\t(default: 11ty)", }, { name: "int-slice-flag", - fl: &IntSliceFlag{Name: "pencils"}, + fl: &Int64SliceFlag{Name: "pencils"}, expected: "--pencils int [ --pencils int ]\t", }, { name: "int-slice-flag-with-default-text", - fl: &IntFlag{Name: "pens", DefaultText: "-19"}, + fl: &Int64Flag{Name: "pens", DefaultText: "-19"}, expected: "--pens int\t(default: -19)", }, { name: "uint-slice-flag", - fl: &UintSliceFlag{Name: "pencils"}, + fl: &Uint64SliceFlag{Name: "pencils"}, expected: "--pencils uint [ --pencils uint ]\t", }, { name: "uint-slice-flag-with-default-text", - fl: &UintFlag{Name: "pens", DefaultText: "29"}, + fl: &Uint64Flag{Name: "pens", DefaultText: "29"}, expected: "--pens uint\t(default: 29)", }, { name: "int64-flag", - fl: &IntFlag{Name: "flume"}, + fl: &Int64Flag{Name: "flume"}, expected: "--flume int\t(default: 0)", }, { name: "int64-flag-with-default-text", - fl: &IntFlag{Name: "shattering", DefaultText: "22"}, + fl: &Int64Flag{Name: "shattering", DefaultText: "22"}, expected: "--shattering int\t(default: 22)", }, { name: "uint64-slice-flag", - fl: &UintSliceFlag{Name: "drawers"}, + fl: &Uint64SliceFlag{Name: "drawers"}, expected: "--drawers uint [ --drawers uint ]\t", }, { name: "uint64-slice-flag-with-default-text", - fl: &UintSliceFlag{Name: "handles", DefaultText: "-2"}, + fl: &Uint64SliceFlag{Name: "handles", DefaultText: "-2"}, expected: "--handles uint [ --handles uint ]\t(default: -2)", }, { @@ -598,22 +598,22 @@ func TestFlagStringifying(t *testing.T) { }, { name: "uint-flag", - fl: &UintFlag{Name: "jars"}, + fl: &Uint64Flag{Name: "jars"}, expected: "--jars uint\t(default: 0)", }, { name: "uint-flag-with-default-text", - fl: &UintFlag{Name: "bottles", DefaultText: "99"}, + fl: &Uint64Flag{Name: "bottles", DefaultText: "99"}, expected: "--bottles uint\t(default: 99)", }, { name: "uint64-flag", - fl: &UintFlag{Name: "cans"}, + fl: &Uint64Flag{Name: "cans"}, expected: "--cans uint\t(default: 0)", }, { name: "uint64-flag-with-default-text", - fl: &UintFlag{Name: "tubes", DefaultText: "13"}, + fl: &Uint64Flag{Name: "tubes", DefaultText: "13"}, expected: "--tubes uint\t(default: 13)", }, { @@ -872,7 +872,7 @@ var intFlagTests = []struct { func TestIntFlagHelpOutput(t *testing.T) { for _, test := range intFlagTests { - fl := &IntFlag{Name: test.name, Value: 9} + fl := &Int64Flag{Name: test.name, Value: 9} assert.Equal(t, test.expected, fl.String()) } } @@ -881,7 +881,7 @@ func TestIntFlagWithEnvVarHelpOutput(t *testing.T) { t.Setenv("APP_BAR", "2") for _, test := range intFlagTests { - fl := &IntFlag{Name: test.name, Sources: EnvVars("APP_BAR")} + fl := &Int64Flag{Name: test.name, Sources: EnvVars("APP_BAR")} output := fl.String() expectedSuffix := withEnvHint([]string{"APP_BAR"}, "") @@ -895,7 +895,7 @@ func TestIntFlagApply_SetsAllNames(t *testing.T) { v := int64(3) cmd := &Command{ Flags: []Flag{ - &IntFlag{Name: "banana", Aliases: []string{"B", "banannanana"}, Destination: &v}, + &Int64Flag{Name: "banana", Aliases: []string{"B", "banannanana"}, Destination: &v}, }, } r := require.New(t) @@ -904,14 +904,14 @@ func TestIntFlagApply_SetsAllNames(t *testing.T) { } func TestIntFlagValueFromCommand(t *testing.T) { - fl := &IntFlag{Name: "myflag"} + fl := &Int64Flag{Name: "myflag"} cmd := &Command{ Flags: []Flag{ fl, }, } require.NoError(t, cmd.Set("myflag", "42")) - require.Equal(t, int64(42), cmd.Int(fl.Name)) + require.Equal(t, int64(42), cmd.Int64(fl.Name)) } var uintFlagTests = []struct { @@ -924,7 +924,7 @@ var uintFlagTests = []struct { func TestUintFlagHelpOutput(t *testing.T) { for _, test := range uintFlagTests { - fl := &UintFlag{Name: test.name, Value: 41} + fl := &Uint64Flag{Name: test.name, Value: 41} assert.Equal(t, test.expected, fl.String()) } } @@ -933,7 +933,7 @@ func TestUintFlagWithEnvVarHelpOutput(t *testing.T) { t.Setenv("APP_BAR", "2") for _, test := range uintFlagTests { - fl := &UintFlag{Name: test.name, Sources: EnvVars("APP_BAR")} + fl := &Uint64Flag{Name: test.name, Sources: EnvVars("APP_BAR")} output := fl.String() expectedSuffix := withEnvHint([]string{"APP_BAR"}, "") @@ -944,14 +944,14 @@ func TestUintFlagWithEnvVarHelpOutput(t *testing.T) { } func TestUintFlagValueFromCommand(t *testing.T) { - fl := &UintFlag{Name: "myflag"} + fl := &Uint64Flag{Name: "myflag"} cmd := &Command{ Flags: []Flag{ fl, }, } require.NoError(t, cmd.Set("myflag", "42")) - require.Equal(t, uint64(42), cmd.Uint(fl.Name)) + require.Equal(t, uint64(42), cmd.Uint64(fl.Name)) } var uint64FlagTests = []struct { @@ -964,7 +964,7 @@ var uint64FlagTests = []struct { func TestUint64FlagHelpOutput(t *testing.T) { for _, test := range uint64FlagTests { - fl := UintFlag{Name: test.name, Value: 8589934582} + fl := Uint64Flag{Name: test.name, Value: 8589934582} assert.Equal(t, test.expected, fl.String()) } } @@ -973,7 +973,7 @@ func TestUint64FlagWithEnvVarHelpOutput(t *testing.T) { t.Setenv("APP_BAR", "2") for _, test := range uint64FlagTests { - fl := &UintFlag{Name: test.name, Sources: EnvVars("APP_BAR")} + fl := &Uint64Flag{Name: test.name, Sources: EnvVars("APP_BAR")} output := fl.String() expectedSuffix := withEnvHint([]string{"APP_BAR"}, "") @@ -984,14 +984,14 @@ func TestUint64FlagWithEnvVarHelpOutput(t *testing.T) { } func TestUint64FlagValueFromCommand(t *testing.T) { - f := &UintFlag{Name: "myflag"} + f := &Uint64Flag{Name: "myflag"} cmd := &Command{ Flags: []Flag{ f, }, } require.NoError(t, cmd.Set("myflag", "42")) - require.Equal(t, uint64(42), cmd.Uint(f.Name)) + require.Equal(t, uint64(42), cmd.Uint64(f.Name)) } var durationFlagTests = []struct { @@ -1059,7 +1059,7 @@ var intSliceFlagTests = []struct { func TestIntSliceFlagHelpOutput(t *testing.T) { for _, test := range intSliceFlagTests { - fl := &IntSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} + fl := &Int64SliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} assert.Equal(t, test.expected, fl.String()) } } @@ -1068,7 +1068,7 @@ func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) { t.Setenv("APP_SMURF", "42,3") for _, test := range intSliceFlagTests { - fl := &IntSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value, Sources: EnvVars("APP_SMURF")} + fl := &Int64SliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value, Sources: EnvVars("APP_SMURF")} output := fl.String() expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "") @@ -1079,7 +1079,7 @@ func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) { } func TestIntSliceFlagApply_SetsAllNames(t *testing.T) { - fl := &IntSliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} + fl := &Int64SliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} cmd := &Command{ Flags: []Flag{ fl, @@ -1092,7 +1092,7 @@ func TestIntSliceFlagApply_SetsAllNames(t *testing.T) { func TestIntSliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { t.Setenv("MY_GOAT", "1 , 2") - fl := &IntSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} + fl := &Int64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} cmd := &Command{ Flags: []Flag{ fl, @@ -1107,7 +1107,7 @@ func TestIntSliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { func TestIntSliceFlagApply_UsesEnvValues_withDefault(t *testing.T) { t.Setenv("MY_GOAT", "1 , 2") val := []int64{3, 4} - fl := &IntSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val} + fl := &Int64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val} cmd := &Command{ Flags: []Flag{ fl, @@ -1123,7 +1123,7 @@ func TestIntSliceFlagApply_DefaultValueWithDestination(t *testing.T) { defValue := []int64{1, 2} dest := []int64{3} - fl := &IntSliceFlag{Name: "country", Value: defValue, Destination: &dest} + fl := &Int64SliceFlag{Name: "country", Value: defValue, Destination: &dest} cmd := &Command{ Flags: []Flag{ fl, @@ -1137,13 +1137,13 @@ func TestIntSliceFlagApply_DefaultValueWithDestination(t *testing.T) { func TestIntSliceFlagApply_ParentContext(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3}}, + &Int64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3}}, }, Commands: []*Command{ { Name: "child", Action: func(_ context.Context, cmd *Command) error { - require.Equalf(t, []int64{1, 2, 3}, cmd.IntSlice("numbers"), "child context unable to view parent flag") + require.Equalf(t, []int64{1, 2, 3}, cmd.Int64Slice("numbers"), "child context unable to view parent flag") return nil }, @@ -1153,7 +1153,7 @@ func TestIntSliceFlagApply_ParentContext(t *testing.T) { } func TestIntSliceFlag_SetFromParentCommand(t *testing.T) { - fl := &IntSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3, 4}} + fl := &Int64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3, 4}} cmd := &Command{ parent: &Command{ @@ -1163,11 +1163,11 @@ func TestIntSliceFlag_SetFromParentCommand(t *testing.T) { }, } - require.Equalf(t, []int64{1, 2, 3, 4}, cmd.IntSlice("numbers"), "child context unable to view parent flag") + require.Equalf(t, []int64{1, 2, 3, 4}, cmd.Int64Slice("numbers"), "child context unable to view parent flag") } func TestIntSliceFlagValueFromCommand(t *testing.T) { - f := &IntSliceFlag{Name: "myflag"} + f := &Int64SliceFlag{Name: "myflag"} cmd := &Command{ Flags: []Flag{ f, @@ -1176,7 +1176,7 @@ func TestIntSliceFlagValueFromCommand(t *testing.T) { require.NoError(t, cmd.Set("myflag", "1")) require.NoError(t, cmd.Set("myflag", "2")) require.NoError(t, cmd.Set("myflag", "3")) - require.Equal(t, []int64{1, 2, 3}, cmd.IntSlice(f.Name)) + require.Equal(t, []int64{1, 2, 3}, cmd.Int64Slice(f.Name)) } var uintSliceFlagTests = []struct { @@ -1198,7 +1198,7 @@ var uintSliceFlagTests = []struct { func TestUintSliceFlagHelpOutput(t *testing.T) { for _, test := range uintSliceFlagTests { t.Run(test.name, func(t *testing.T) { - fl := &UintSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} + fl := &Uint64SliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} require.Equal(t, test.expected, fl.String()) }) } @@ -1208,7 +1208,7 @@ func TestUintSliceFlagWithEnvVarHelpOutput(t *testing.T) { t.Setenv("APP_SMURF", "42,17179869184") for _, test := range uintSliceFlagTests { - fl := &UintSliceFlag{Name: test.name, Value: test.value, Sources: EnvVars("APP_SMURF")} + fl := &Uint64SliceFlag{Name: test.name, Value: test.value, Sources: EnvVars("APP_SMURF")} output := fl.String() expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "") @@ -1219,7 +1219,7 @@ func TestUintSliceFlagWithEnvVarHelpOutput(t *testing.T) { } func TestUintSliceFlagApply_SetsAllNames(t *testing.T) { - fl := &UintSliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} + fl := &Uint64SliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} cmd := &Command{ Flags: []Flag{ fl, @@ -1232,7 +1232,7 @@ func TestUintSliceFlagApply_SetsAllNames(t *testing.T) { func TestUintSliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { t.Setenv("MY_GOAT", "1 , 2") - fl := &UintSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} + fl := &Uint64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} cmd := &Command{ Flags: []Flag{ fl, @@ -1245,8 +1245,8 @@ func TestUintSliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { func TestUintSliceFlagApply_UsesEnvValues_withDefault(t *testing.T) { t.Setenv("MY_GOAT", "1 , 2") - val := NewUintSlice(3, 4) - fl := &UintSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val.Value()} + val := NewUint64Slice(3, 4) + fl := &Uint64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val.Value()} cmd := &Command{ Flags: []Flag{ fl, @@ -1262,7 +1262,7 @@ func TestUintSliceFlagApply_DefaultValueWithDestination(t *testing.T) { defValue := []uint64{1, 2} var dest []uint64 - fl := &UintSliceFlag{Name: "country", Value: defValue, Destination: &dest} + fl := &Uint64SliceFlag{Name: "country", Value: defValue, Destination: &dest} cmd := &Command{ Flags: []Flag{ fl, @@ -1273,17 +1273,17 @@ func TestUintSliceFlagApply_DefaultValueWithDestination(t *testing.T) { assert.Equal(t, defValue, dest) } -func TestUintSliceFlagApply_ParentContext(t *testing.T) { +func TestUint64SliceFlagApply_ParentContext(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &UintSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3}}, + &Uint64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3}}, }, Commands: []*Command{ { Name: "child", Action: func(_ context.Context, cmd *Command) error { require.Equalf( - t, []uint64{1, 2, 3}, cmd.UintSlice("numbers"), + t, []uint64{1, 2, 3}, cmd.Uint64Slice("numbers"), "child context unable to view parent flag", ) return nil @@ -1294,7 +1294,7 @@ func TestUintSliceFlagApply_ParentContext(t *testing.T) { } func TestUintSliceFlag_SetFromParentCommand(t *testing.T) { - fl := &UintSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3, 4}} + fl := &UintSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint{1, 2, 3, 4}} cmd := &Command{ parent: &Command{ Flags: []Flag{ @@ -1305,14 +1305,14 @@ func TestUintSliceFlag_SetFromParentCommand(t *testing.T) { r := require.New(t) r.Equalf( - []uint64{1, 2, 3, 4}, + []uint{1, 2, 3, 4}, cmd.UintSlice("numbers"), "child context unable to view parent flag", ) } func TestUintSliceFlag_ReturnNil(t *testing.T) { - fl := &UintSliceFlag{} + fl := &Uint64SliceFlag{} r := require.New(t) cmd := &Command{ @@ -1324,7 +1324,7 @@ func TestUintSliceFlag_ReturnNil(t *testing.T) { } r.Equalf( []uint64(nil), - cmd.UintSlice("numbers"), + cmd.Uint64Slice("numbers"), "child context unable to view parent flag", ) } @@ -1347,7 +1347,7 @@ var uint64SliceFlagTests = []struct { func TestUint64SliceFlagHelpOutput(t *testing.T) { for _, test := range uint64SliceFlagTests { - fl := UintSliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} + fl := Uint64SliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} assert.Equal(t, test.expected, fl.String()) } } @@ -1356,7 +1356,7 @@ func TestUint64SliceFlagWithEnvVarHelpOutput(t *testing.T) { t.Setenv("APP_SMURF", "42,17179869184") for _, test := range uint64SliceFlagTests { - fl := UintSliceFlag{Name: test.name, Value: test.value, Sources: EnvVars("APP_SMURF")} + fl := Uint64SliceFlag{Name: test.name, Value: test.value, Sources: EnvVars("APP_SMURF")} output := fl.String() expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "") @@ -1367,7 +1367,7 @@ func TestUint64SliceFlagWithEnvVarHelpOutput(t *testing.T) { } func TestUint64SliceFlagApply_SetsAllNames(t *testing.T) { - fl := UintSliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} + fl := Uint64SliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} cmd := &Command{ Flags: []Flag{ &fl, @@ -1379,7 +1379,7 @@ func TestUint64SliceFlagApply_SetsAllNames(t *testing.T) { func TestUint64SliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { t.Setenv("MY_GOAT", "1 , 2") - fl := UintSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} + fl := Uint64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} cmd := &Command{ Flags: []Flag{ &fl, @@ -1392,7 +1392,7 @@ func TestUint64SliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { func TestUint64SliceFlagApply_UsesEnvValues_withDefault(t *testing.T) { t.Setenv("MY_GOAT", "1 , 2") val := []uint64{3, 4} - fl := UintSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val} + fl := Uint64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val} cmd := &Command{ Flags: []Flag{ &fl, @@ -1406,7 +1406,7 @@ func TestUint64SliceFlagApply_DefaultValueWithDestination(t *testing.T) { defValue := []uint64{1, 2} dest := []uint64{3} - fl := UintSliceFlag{Name: "country", Value: defValue, Destination: &dest} + fl := Uint64SliceFlag{Name: "country", Value: defValue, Destination: &dest} cmd := &Command{ Flags: []Flag{ &fl, @@ -1422,14 +1422,14 @@ func TestUint64SliceFlagApply_DefaultValueWithDestination(t *testing.T) { func TestUint64SliceFlagApply_ParentCommand(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &UintSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3}}, + &Uint64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3}}, }, Commands: []*Command{ { Name: "child", Action: func(_ context.Context, cmd *Command) error { require.Equalf( - t, []uint64{1, 2, 3}, cmd.UintSlice("numbers"), + t, []uint64{1, 2, 3}, cmd.Uint64Slice("numbers"), "child context unable to view parent flag", ) return nil @@ -1440,7 +1440,7 @@ func TestUint64SliceFlagApply_ParentCommand(t *testing.T) { } func TestUint64SliceFlag_SetFromParentCommand(t *testing.T) { - fl := &UintSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3, 4}} + fl := &Uint64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []uint64{1, 2, 3, 4}} cmd := &Command{ parent: &Command{ Flags: []Flag{ @@ -1450,13 +1450,13 @@ func TestUint64SliceFlag_SetFromParentCommand(t *testing.T) { } r := require.New(t) r.Equalf( - []uint64{1, 2, 3, 4}, cmd.UintSlice("numbers"), + []uint64{1, 2, 3, 4}, cmd.Uint64Slice("numbers"), "child context unable to view parent flag", ) } func TestUint64SliceFlag_ReturnNil(t *testing.T) { - fl := &UintSliceFlag{} + fl := &Uint64SliceFlag{} cmd := &Command{ parent: &Command{ Flags: []Flag{ @@ -1466,7 +1466,7 @@ func TestUint64SliceFlag_ReturnNil(t *testing.T) { } r := require.New(t) r.Equalf( - []uint64(nil), cmd.UintSlice("numbers"), + []uint64(nil), cmd.Uint64Slice("numbers"), "child context unable to view parent flag", ) } @@ -1861,7 +1861,7 @@ func TestParseMultiIntSliceWithDestinationAndEnv(t *testing.T) { dest := []int64{} _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Destination: &dest, Sources: EnvVars("APP_INTERVALS")}, + &Int64SliceFlag{Name: "serve", Aliases: []string{"s"}, Destination: &dest, Sources: EnvVars("APP_INTERVALS")}, }, Action: func(context.Context, *Command) error { require.Equalf(t, []int64{10, 20}, dest, "main name not set") @@ -1967,11 +1967,11 @@ func TestParseMultiStringSliceFromEnvWithDestination(t *testing.T) { func TestParseMultiInt(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntFlag{Name: "serve", Aliases: []string{"s"}}, + &Int64Flag{Name: "serve", Aliases: []string{"s"}}, }, Action: func(_ context.Context, cmd *Command) error { - assert.Equal(t, int64(10), cmd.Int("serve"), "main name not set") - assert.Equal(t, int64(10), cmd.Int("s"), "short name not set") + assert.Equal(t, int64(10), cmd.Int64("serve"), "main name not set") + assert.Equal(t, int64(10), cmd.Int64("s"), "short name not set") return nil }, }).Run(buildTestContext(t), []string{"run", "-s", "10"}) @@ -1981,13 +1981,13 @@ func TestParseDestinationInt(t *testing.T) { var dest int64 _ = (&Command{ Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "dest", Destination: &dest, }, }, Action: func(context.Context, *Command) error { - assert.Equal(t, int64(10), dest, "expected destination Int 10") + assert.Equal(t, int64(10), dest, "expected destination Int64 10") return nil }, }).Run(buildTestContext(t), []string{"run", "--dest", "10"}) @@ -1997,11 +1997,11 @@ func TestParseMultiIntFromEnv(t *testing.T) { t.Setenv("APP_TIMEOUT_SECONDS", "10") _ = (&Command{ Flags: []Flag{ - &IntFlag{Name: "timeout", Aliases: []string{"t"}, Sources: EnvVars("APP_TIMEOUT_SECONDS")}, + &Int64Flag{Name: "timeout", Aliases: []string{"t"}, Sources: EnvVars("APP_TIMEOUT_SECONDS")}, }, Action: func(_ context.Context, cmd *Command) error { - assert.Equal(t, int64(10), cmd.Int("timeout"), "main name not set") - assert.Equal(t, int64(10), cmd.Int("t"), "short name not set") + assert.Equal(t, int64(10), cmd.Int64("timeout"), "main name not set") + assert.Equal(t, int64(10), cmd.Int64("t"), "short name not set") return nil }, }).Run(buildTestContext(t), []string{"run"}) @@ -2011,11 +2011,11 @@ func TestParseMultiIntFromEnvCascade(t *testing.T) { t.Setenv("APP_TIMEOUT_SECONDS", "10") _ = (&Command{ Flags: []Flag{ - &IntFlag{Name: "timeout", Aliases: []string{"t"}, Sources: EnvVars("COMPAT_TIMEOUT_SECONDS", "APP_TIMEOUT_SECONDS")}, + &Int64Flag{Name: "timeout", Aliases: []string{"t"}, Sources: EnvVars("COMPAT_TIMEOUT_SECONDS", "APP_TIMEOUT_SECONDS")}, }, Action: func(_ context.Context, cmd *Command) error { - assert.Equal(t, int64(10), cmd.Int("timeout"), "main name not set") - assert.Equal(t, int64(10), cmd.Int("t"), "short name not set") + assert.Equal(t, int64(10), cmd.Int64("timeout"), "main name not set") + assert.Equal(t, int64(10), cmd.Int64("t"), "short name not set") return nil }, }).Run(buildTestContext(t), []string{"run"}) @@ -2024,13 +2024,13 @@ func TestParseMultiIntFromEnvCascade(t *testing.T) { func TestParseMultiIntSlice(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{}}, + &Int64SliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{}}, }, Action: func(_ context.Context, cmd *Command) error { r := require.New(t) - r.Equalf([]int64{10, 20}, cmd.IntSlice("serve"), "main name not set") - r.Equalf([]int64{10, 20}, cmd.IntSlice("s"), "short name not set") + r.Equalf([]int64{10, 20}, cmd.Int64Slice("serve"), "main name not set") + r.Equalf([]int64{10, 20}, cmd.Int64Slice("s"), "short name not set") return nil }, @@ -2040,13 +2040,13 @@ func TestParseMultiIntSlice(t *testing.T) { func TestParseMultiIntSliceWithDefaults(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{9, 2}}, + &Int64SliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{9, 2}}, }, Action: func(_ context.Context, cmd *Command) error { r := require.New(t) - r.Equalf([]int64{10, 20}, cmd.IntSlice("serve"), "main name not set") - r.Equalf([]int64{10, 20}, cmd.IntSlice("s"), "short name not set") + r.Equalf([]int64{10, 20}, cmd.Int64Slice("serve"), "main name not set") + r.Equalf([]int64{10, 20}, cmd.Int64Slice("s"), "short name not set") return nil }, @@ -2056,12 +2056,12 @@ func TestParseMultiIntSliceWithDefaults(t *testing.T) { func TestParseMultiIntSliceWithDefaultsUnset(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{9, 2}}, + &Int64SliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{9, 2}}, }, Action: func(_ context.Context, cmd *Command) error { expected := []int64{9, 2} - assert.Equal(t, expected, cmd.IntSlice("serve"), "main name not set") - assert.Equal(t, expected, cmd.IntSlice("s"), "short name not set") + assert.Equal(t, expected, cmd.Int64Slice("serve"), "main name not set") + assert.Equal(t, expected, cmd.Int64Slice("s"), "short name not set") return nil }, }).Run(buildTestContext(t), []string{"run"}) @@ -2072,13 +2072,13 @@ func TestParseMultiIntSliceFromEnv(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{}, Sources: EnvVars("APP_INTERVALS")}, + &Int64SliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{}, Sources: EnvVars("APP_INTERVALS")}, }, Action: func(_ context.Context, cmd *Command) error { r := require.New(t) - r.Equalf([]int64{20, 30, 40}, cmd.IntSlice("intervals"), "main name not set from env") - r.Equalf([]int64{20, 30, 40}, cmd.IntSlice("i"), "short name not set from env") + r.Equalf([]int64{20, 30, 40}, cmd.Int64Slice("intervals"), "main name not set from env") + r.Equalf([]int64{20, 30, 40}, cmd.Int64Slice("i"), "short name not set from env") return nil }, @@ -2090,13 +2090,13 @@ func TestParseMultiIntSliceFromEnvWithDefaults(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{1, 2, 5}, Sources: EnvVars("APP_INTERVALS")}, + &Int64SliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{1, 2, 5}, Sources: EnvVars("APP_INTERVALS")}, }, Action: func(_ context.Context, cmd *Command) error { r := require.New(t) - r.Equalf([]int64{20, 30, 40}, cmd.IntSlice("intervals"), "main name not set from env") - r.Equalf([]int64{20, 30, 40}, cmd.IntSlice("i"), "short name not set from env") + r.Equalf([]int64{20, 30, 40}, cmd.Int64Slice("intervals"), "main name not set from env") + r.Equalf([]int64{20, 30, 40}, cmd.Int64Slice("i"), "short name not set from env") return nil }, }).Run(buildTestContext(t), []string{"run"}) @@ -2107,13 +2107,13 @@ func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{}, Sources: EnvVars("COMPAT_INTERVALS", "APP_INTERVALS")}, + &Int64SliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{}, Sources: EnvVars("COMPAT_INTERVALS", "APP_INTERVALS")}, }, Action: func(_ context.Context, cmd *Command) error { r := require.New(t) - r.Equalf([]int64{20, 30, 40}, cmd.IntSlice("intervals"), "main name not set from env") - r.Equalf([]int64{20, 30, 40}, cmd.IntSlice("i"), "short name not set from env") + r.Equalf([]int64{20, 30, 40}, cmd.Int64Slice("intervals"), "main name not set from env") + r.Equalf([]int64{20, 30, 40}, cmd.Int64Slice("i"), "short name not set from env") return nil }, @@ -2337,36 +2337,36 @@ func TestStringSlice_Serialized_Set(t *testing.T) { } func TestIntSlice_Serialized_Set(t *testing.T) { - sl0 := NewIntSlice(1, 2) + sl0 := NewInt64Slice(1, 2) ser0 := sl0.Serialize() require.GreaterOrEqual(t, len(ser0), len(slPfx), "serialized shorter than expected") - sl1 := NewIntSlice(3, 4) + sl1 := NewInt64Slice(3, 4) _ = sl1.Set(ser0) require.Equal(t, sl0.String(), sl1.String(), "pre and post serialization do not match") } func TestUintSlice_Serialized_Set(t *testing.T) { - sl0 := NewUintSlice(1, 2) + sl0 := NewUint64Slice(1, 2) ser0 := sl0.Serialize() require.GreaterOrEqual(t, len(ser0), len(slPfx), "serialized shorter than expected") - sl1 := NewUintSlice(3, 4) + sl1 := NewUint64Slice(3, 4) _ = sl1.Set(ser0) require.Equal(t, sl0.String(), sl1.String(), "pre and post serialization do not match") } func TestUint64Slice_Serialized_Set(t *testing.T) { - sl0 := NewUintSlice(1, 2) + sl0 := NewUint64Slice(1, 2) ser0 := sl0.Serialize() require.GreaterOrEqual(t, len(ser0), len(slPfx), "serialized shorter than expected") - sl1 := NewUintSlice(3, 4) + sl1 := NewUint64Slice(3, 4) _ = sl1.Set(ser0) require.Equal(t, sl0.String(), sl1.String(), "pre and post serialization do not match") @@ -2733,13 +2733,13 @@ func TestFlagDefaultValue(t *testing.T) { }, { name: "intSlice", - flag: &IntSliceFlag{Name: "flag", Value: []int64{1, 2}}, + flag: &Int64SliceFlag{Name: "flag", Value: []int64{1, 2}}, toParse: []string{"--flag", "13"}, expect: `--flag int [ --flag int ] (default: 1, 2)`, }, { name: "uintSlice", - flag: &UintSliceFlag{Name: "flag", Value: []uint64{1, 2}}, + flag: &Uint64SliceFlag{Name: "flag", Value: []uint64{1, 2}}, toParse: []string{"--flag", "13"}, expect: `--flag uint [ --flag uint ] (default: 1, 2)`, }, @@ -2756,11 +2756,17 @@ func TestFlagDefaultValue(t *testing.T) { expect: `--flag (default: true)`, }, { - name: "uint64", + name: "uint", flag: &UintFlag{Name: "flag", Value: 1}, toParse: []string{"--flag", "13"}, expect: `--flag uint (default: 1)`, }, + { + name: "uint64", + flag: &Uint64Flag{Name: "flag", Value: 1}, + toParse: []string{"--flag", "13"}, + expect: `--flag uint (default: 1)`, + }, { name: "stringMap", flag: &StringMapFlag{Name: "flag", Value: map[string]string{"default1": "default2"}}, @@ -2813,7 +2819,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "intSlice", - flag: &IntSliceFlag{Name: "flag", Value: []int64{1, 2}, Sources: EnvVars("isflag")}, + flag: &Int64SliceFlag{Name: "flag", Value: []int64{1, 2}, Sources: EnvVars("isflag")}, toParse: []string{"--flag", "13"}, expect: `--flag int [ --flag int ] (default: 1, 2)` + withEnvHint([]string{"isflag"}, ""), environ: map[string]string{ @@ -2822,7 +2828,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "uintSlice", - flag: &UintSliceFlag{Name: "flag", Value: []uint64{1, 2}, Sources: EnvVars("uisflag")}, + flag: &Uint64SliceFlag{Name: "flag", Value: []uint64{1, 2}, Sources: EnvVars("uisflag")}, toParse: []string{"--flag", "13"}, expect: `--flag uint [ --flag uint ] (default: 1, 2)` + withEnvHint([]string{"uisflag"}, ""), environ: map[string]string{ @@ -2857,7 +2863,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "uint64", - flag: &UintFlag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, + flag: &Uint64Flag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, toParse: []string{"--flag", "13"}, expect: `--flag uint (default: 1)` + withEnvHint([]string{"uflag"}, ""), environ: map[string]string{ @@ -2866,7 +2872,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "uint", - flag: &UintFlag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, + flag: &Uint64Flag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, toParse: []string{"--flag", "13"}, expect: `--flag uint (default: 1)` + withEnvHint([]string{"uflag"}, ""), environ: map[string]string{ @@ -2875,7 +2881,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "int64", - flag: &IntFlag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, + flag: &Int64Flag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, toParse: []string{"--flag", "13"}, expect: `--flag int (default: 1)` + withEnvHint([]string{"uflag"}, ""), environ: map[string]string{ @@ -2884,7 +2890,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "int", - flag: &IntFlag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, + flag: &Int64Flag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, toParse: []string{"--flag", "13"}, expect: `--flag int (default: 1)` + withEnvHint([]string{"uflag"}, ""), environ: map[string]string{ @@ -2969,13 +2975,13 @@ func TestFlagValue(t *testing.T) { }, { name: "intSlice", - flag: &IntSliceFlag{Name: "flag", Value: []int64{1, 2}}, + flag: &Int64SliceFlag{Name: "flag", Value: []int64{1, 2}}, toParse: []string{"--flag", "13,14", "--flag", "15,16"}, expect: `[]int64{13, 14, 15, 16}`, }, { name: "uintSlice", - flag: &UintSliceFlag{Name: "flag", Value: []uint64{1, 2}}, + flag: &Uint64SliceFlag{Name: "flag", Value: []uint64{1, 2}}, toParse: []string{"--flag", "13,14", "--flag", "15,16"}, expect: `[]uint64{13, 14, 15, 16}`, }, @@ -2985,6 +2991,18 @@ func TestFlagValue(t *testing.T) { toParse: []string{"--flag", "parsed=parsed2", "--flag", "parsed3=parsed4"}, expect: `map[parsed:parsed2 parsed3:parsed4]`, }, + { + name: "int", + flag: &IntFlag{Name: "flag", Value: 1}, + toParse: []string{"--flag", "42"}, + expect: `int(42)`, + }, + { + name: "uint", + flag: &UintFlag{Name: "flag", Value: 1}, + toParse: []string{"--flag", "42"}, + expect: `uint(42)`, + }, } for _, v := range cases { t.Run(v.name, func(t *testing.T) { @@ -3199,7 +3217,7 @@ func TestZeroValueMutexFlag(t *testing.T) { } func TestExtFlag(t *testing.T) { - var iv intValue + var iv intValue[int64] var ipv int64 f := &flag.Flag{ @@ -3225,13 +3243,13 @@ func TestExtFlag(t *testing.T) { func TestSliceValuesNil(t *testing.T) { assert.Equal(t, []float64(nil), NewFloatSlice().Value()) - assert.Equal(t, []int64(nil), NewIntSlice().Value()) - assert.Equal(t, []uint64(nil), NewUintSlice().Value()) + assert.Equal(t, []int64(nil), NewInt64Slice().Value()) + assert.Equal(t, []uint64(nil), NewUint64Slice().Value()) assert.Equal(t, []string(nil), NewStringSlice().Value()) assert.Equal(t, []float64(nil), (&FloatSlice{}).Value()) - assert.Equal(t, []int64(nil), (&IntSlice{}).Value()) - assert.Equal(t, []uint64(nil), (&UintSlice{}).Value()) + assert.Equal(t, []int64(nil), (&Int64Slice{}).Value()) + assert.Equal(t, []uint64(nil), (&Uint64Slice{}).Value()) assert.Equal(t, []string(nil), (&StringSlice{}).Value()) } @@ -3247,7 +3265,7 @@ func TestFlagsByName(t *testing.T) { &StringFlag{ Name: "b2", }, - &IntFlag{ + &Int64Flag{ Name: "a0", }, &FloatFlag{ diff --git a/flag_uint.go b/flag_uint.go index 1f3c82da6d..64ee231926 100644 --- a/flag_uint.go +++ b/flag_uint.go @@ -2,50 +2,99 @@ package cli import ( "strconv" + "unsafe" ) -type UintFlag = FlagBase[uint64, IntegerConfig, uintValue] +type ( + UintFlag = FlagBase[uint, IntegerConfig, uintValue[uint]] + Uint8Flag = FlagBase[uint8, IntegerConfig, uintValue[uint8]] + Uint16Flag = FlagBase[uint16, IntegerConfig, uintValue[uint16]] + Uint32Flag = FlagBase[uint32, IntegerConfig, uintValue[uint32]] + Uint64Flag = FlagBase[uint64, IntegerConfig, uintValue[uint64]] +) -// -- uint64 Value -type uintValue struct { - val *uint64 +// -- uint Value +type uintValue[T uint | uint8 | uint16 | uint32 | uint64] struct { + val *T base int } // Below functions are to satisfy the ValueCreator interface -func (i uintValue) Create(val uint64, p *uint64, c IntegerConfig) Value { +func (i uintValue[T]) Create(val T, p *T, c IntegerConfig) Value { *p = val - return &uintValue{ + + return &uintValue[T]{ val: p, base: c.Base, } } -func (i uintValue) ToString(b uint64) string { - return strconv.FormatUint(b, 10) +func (i uintValue[T]) ToString(b T) string { + base := i.base + if base == 0 { + base = 10 + } + + return strconv.FormatUint(uint64(b), base) } // Below functions are to satisfy the flag.Value interface -func (i *uintValue) Set(s string) error { - v, err := strconv.ParseUint(s, i.base, 64) +func (i *uintValue[T]) Set(s string) error { + v, err := strconv.ParseUint(s, i.base, int(unsafe.Sizeof(T(0))*8)) if err != nil { return err } - *i.val = v + *i.val = T(v) return err } -func (i *uintValue) Get() any { return uint64(*i.val) } +func (i *uintValue[T]) Get() any { return *i.val } -func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i.val), 10) } +func (i *uintValue[T]) String() string { + base := i.base + if base == 0 { + base = 10 + } + + return strconv.FormatUint(uint64(*i.val), base) +} // Uint looks up the value of a local Uint64Flag, returns // 0 if not found -func (cmd *Command) Uint(name string) uint64 { - if v, ok := cmd.Value(name).(uint64); ok { +func (cmd *Command) Uint(name string) uint { + return getUint[uint](cmd, name) +} + +// Uint8 looks up the value of a local Uint8Flag, returns +// 0 if not found +func (cmd *Command) Uint8(name string) uint8 { + return getUint[uint8](cmd, name) +} + +// Uint16 looks up the value of a local Uint16Flag, returns +// 0 if not found +func (cmd *Command) Uint16(name string) uint16 { + return getUint[uint16](cmd, name) +} + +// Uint32 looks up the value of a local Uint32Flag, returns +// 0 if not found +func (cmd *Command) Uint32(name string) uint32 { + return getUint[uint32](cmd, name) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (cmd *Command) Uint64(name string) uint64 { + return getUint[uint64](cmd, name) +} + +func getUint[T uint | uint8 | uint16 | uint32 | uint64](cmd *Command, name string) T { + if v, ok := cmd.Value(name).(T); ok { tracef("uint available for flag name %[1]q with value=%[2]v (cmd=%[3]q)", name, v, cmd.Name) + return v } diff --git a/flag_uint_slice.go b/flag_uint_slice.go index ef7d4db467..18c5b4d232 100644 --- a/flag_uint_slice.go +++ b/flag_uint_slice.go @@ -1,17 +1,60 @@ package cli type ( - UintSlice = SliceBase[uint64, IntegerConfig, uintValue] - UintSliceFlag = FlagBase[[]uint64, IntegerConfig, UintSlice] + UintSlice = SliceBase[uint, IntegerConfig, uintValue[uint]] + Uint8Slice = SliceBase[uint8, IntegerConfig, uintValue[uint8]] + Uint16Slice = SliceBase[uint16, IntegerConfig, uintValue[uint16]] + Uint32Slice = SliceBase[uint32, IntegerConfig, uintValue[uint32]] + Uint64Slice = SliceBase[uint64, IntegerConfig, uintValue[uint64]] + UintSliceFlag = FlagBase[[]uint, IntegerConfig, UintSlice] + Uint8SliceFlag = FlagBase[[]uint8, IntegerConfig, Uint8Slice] + Uint16SliceFlag = FlagBase[[]uint16, IntegerConfig, Uint16Slice] + Uint32SliceFlag = FlagBase[[]uint32, IntegerConfig, Uint32Slice] + Uint64SliceFlag = FlagBase[[]uint64, IntegerConfig, Uint64Slice] ) -var NewUintSlice = NewSliceBase[uint64, IntegerConfig, uintValue] +var ( + NewUintSlice = NewSliceBase[uint, IntegerConfig, uintValue[uint]] + NewUint8Slice = NewSliceBase[uint8, IntegerConfig, uintValue[uint8]] + NewUint16Slice = NewSliceBase[uint16, IntegerConfig, uintValue[uint16]] + NewUint32Slice = NewSliceBase[uint32, IntegerConfig, uintValue[uint32]] + NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uintValue[uint64]] +) // UintSlice looks up the value of a local UintSliceFlag, returns // nil if not found -func (cmd *Command) UintSlice(name string) []uint64 { - if v, ok := cmd.Value(name).([]uint64); ok { +func (cmd *Command) UintSlice(name string) []uint { + return getUintSlice[uint](cmd, name) +} + +// Uint8Slice looks up the value of a local Uint8SliceFlag, returns +// nil if not found +func (cmd *Command) Uint8Slice(name string) []uint8 { + return getUintSlice[uint8](cmd, name) +} + +// Uint16Slice looks up the value of a local Uint16SliceFlag, returns +// nil if not found +func (cmd *Command) Uint16Slice(name string) []uint16 { + return getUintSlice[uint16](cmd, name) +} + +// Uint32Slice looks up the value of a local Uint32SliceFlag, returns +// nil if not found +func (cmd *Command) Uint32Slice(name string) []uint32 { + return getUintSlice[uint32](cmd, name) +} + +// Uint64Slice looks up the value of a local Uint64SliceFlag, returns +// nil if not found +func (cmd *Command) Uint64Slice(name string) []uint64 { + return getUintSlice[uint64](cmd, name) +} + +func getUintSlice[T uint | uint8 | uint16 | uint32 | uint64](cmd *Command, name string) []T { + if v, ok := cmd.Value(name).([]T); ok { tracef("uint slice available for flag name %[1]q with value=%[2]v (cmd=%[3]q)", name, v, cmd.Name) + return v } diff --git a/flag_uint_slice_test.go b/flag_uint_slice_test.go new file mode 100644 index 0000000000..023de5c2da --- /dev/null +++ b/flag_uint_slice_test.go @@ -0,0 +1,254 @@ +package cli + +import ( + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCommand_UintSlice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []uint + expectErr bool + }{ + { + flag: &UintSliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []uint{1, 2, 3, 4}, + }, + { + flag: &UintSliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []uint{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.UintSlice(name), "UintSlice(%v)", name) + } + }) + } +} + +func TestCommand_Uint8Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []uint8 + expectErr bool + }{ + { + flag: &Uint8SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []uint8{1, 2, 3, 4}, + }, + { + flag: &Uint8SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []uint8{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Uint8Slice(name), "Uint8Slice(%v)", name) + } + }) + } +} + +func TestCommand_Uint16Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []uint16 + expectErr bool + }{ + { + flag: &Uint16SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []uint16{1, 2, 3, 4}, + }, + { + flag: &Uint16SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []uint16{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Uint16Slice(name), "Uint16Slice(%v)", name) + } + }) + } +} + +func TestCommand_Uint32Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []uint32 + expectErr bool + }{ + { + flag: &Uint32SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []uint32{1, 2, 3, 4}, + }, + { + flag: &Uint32SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []uint32{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Uint32Slice(name), "Uint32Slice(%v)", name) + } + }) + } +} + +func TestCommand_Uint64Slice(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expect []uint64 + expectErr bool + }{ + { + flag: &Uint64SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2,3,4"}, + expect: []uint64{1, 2, 3, 4}, + }, + { + flag: &Uint64SliceFlag{ + Name: "numbers", + }, + arguments: []string{"--numbers", "1,2", "--numbers", "3,4"}, + expect: []uint64{1, 2, 3, 4}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equalf(t, tt.expect, cmd.Uint64Slice(name), "Uint64Slice(%v)", name) + } + }) + } +} diff --git a/flag_uint_test.go b/flag_uint_test.go new file mode 100644 index 0000000000..99557fd6e5 --- /dev/null +++ b/flag_uint_test.go @@ -0,0 +1,377 @@ +package cli + +import ( + "flag" + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUintFlag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue uint + expectErr bool + }{ + { + name: "valid", + flag: &UintFlag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "234567"}, + expectedValue: 234567, + }, + { + name: "invalid", + flag: &UintFlag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Uint(name)) + } + }) + } +} + +func TestUint8Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue uint8 + expectErr bool + }{ + { + name: "valid", + flag: &Uint8Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "255"}, + expectedValue: 255, + }, + { + name: "invalid", + flag: &Uint8Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Uint8(name)) + } + }) + } +} + +func TestUint16Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue uint16 + expectErr bool + }{ + { + name: "valid", + flag: &Uint16Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "65535"}, + expectedValue: 65535, + }, + { + name: "invalid", + flag: &Uint16Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + { + name: "out of range", + flag: &Uint16Flag{ + Name: "number", + }, + arguments: []string{"--number", "65536"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Uint16(name)) + } + }) + } +} + +func TestUint32Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue uint32 + expectErr bool + }{ + { + name: "valid", + flag: &Uint32Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "2147483648"}, + expectedValue: 2147483648, + }, + { + name: "invalid", + flag: &Uint32Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + { + name: "out of range", + flag: &Uint32Flag{ + Name: "number", + }, + arguments: []string{"--number", "4294967297"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Uint32(name)) + } + }) + } +} + +func TestUint64Flag(t *testing.T) { + tests := []struct { + name string + flag Flag + arguments []string + expectedValue uint64 + expectErr bool + }{ + { + name: "valid", + flag: &Uint64Flag{ + Name: "number", + Aliases: []string{"n"}, + }, + arguments: []string{"--number", "21474836480"}, + expectedValue: 21474836480, + }, + { + name: "invalid", + flag: &Uint64Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := &Command{ + Name: "mock", + Flags: []Flag{tt.flag}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + for _, name := range tt.flag.Names() { + assert.Equal(t, tt.expectedValue, cmd.Uint64(name)) + } + }) + } +} + +func TestUintFlagExt(t *testing.T) { + tests := []struct { + name string + flag *flag.Flag + config IntegerConfig + arguments []string + expectedValue string + expectErr bool + }{ + { + name: "valid", + flag: &flag.Flag{ + Name: "number", + }, + config: IntegerConfig{}, + arguments: []string{"--number", "234567"}, + expectedValue: "234567", + }, + { + name: "valid", + flag: &flag.Flag{ + Name: "number", + }, + config: IntegerConfig{Base: 10}, + arguments: []string{"--number", "234567"}, + expectedValue: "234567", + }, + { + name: "valid hex", + flag: &flag.Flag{ + Name: "number", + }, + config: IntegerConfig{Base: 16}, + arguments: []string{"--number", "39447"}, + expectedValue: "39447", + }, + { + name: "valid hex default", + flag: &flag.Flag{ + Name: "number", + DefValue: "FFFF", + }, + config: IntegerConfig{Base: 16}, + expectedValue: "ffff", + }, + { + name: "invalid", + flag: &flag.Flag{ + Name: "number", + }, + arguments: []string{"--number", "gopher"}, + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var uValue uintValue[uint] + var u uint + + f := &extFlag{f: tt.flag} + + tt.flag.Value = uValue.Create(u, &u, tt.config) + + cmd := &Command{ + Name: "mock", + Flags: []Flag{f}, + Writer: io.Discard, + ErrWriter: io.Discard, + } + + err := cmd.Run(buildTestContext(t), append([]string{"mock"}, tt.arguments...)) + + if tt.expectErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + + assert.Equal(t, tt.expectedValue, f.GetValue()) + }) + } +} diff --git a/flag_validation_test.go b/flag_validation_test.go index b476d89130..27fd4ae3a5 100644 --- a/flag_validation_test.go +++ b/flag_validation_test.go @@ -11,7 +11,7 @@ func TestFlagDefaultValidation(t *testing.T) { cmd := &Command{ Name: "foo", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "if", Value: 2, // this value should fail validation Validator: func(i int64) error { @@ -119,7 +119,7 @@ func TestFlagValidation(t *testing.T) { cmd := &Command{ Name: "foo", Flags: []Flag{ - &IntFlag{ + &Int64Flag{ Name: "it", Value: 5, // note that this value should pass validation Validator: func(i int64) error { diff --git a/godoc-current.txt b/godoc-current.txt index d9448f3cbc..e62ba79f5b 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -26,6 +26,20 @@ application: VARIABLES +var ( + NewIntSlice = NewSliceBase[int, IntegerConfig, intValue[int]] + NewInt8Slice = NewSliceBase[int8, IntegerConfig, intValue[int8]] + NewInt16Slice = NewSliceBase[int16, IntegerConfig, intValue[int16]] + NewInt32Slice = NewSliceBase[int32, IntegerConfig, intValue[int32]] + NewInt64Slice = NewSliceBase[int64, IntegerConfig, intValue[int64]] +) +var ( + NewUintSlice = NewSliceBase[uint, IntegerConfig, uintValue[uint]] + NewUint8Slice = NewSliceBase[uint8, IntegerConfig, uintValue[uint8]] + NewUint16Slice = NewSliceBase[uint16, IntegerConfig, uintValue[uint16]] + NewUint32Slice = NewSliceBase[uint32, IntegerConfig, uintValue[uint32]] + NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uintValue[uint64]] +) var ( SuggestFlag SuggestFlagFunc = suggestFlag SuggestCommand SuggestCommandFunc = suggestCommand @@ -79,10 +93,8 @@ end {{ range $v := .Completions }}{{ $v }} {{ end }}` var NewFloatSlice = NewSliceBase[float64, NoConfig, floatValue] -var NewIntSlice = NewSliceBase[int64, IntegerConfig, intValue] var NewStringMap = NewMapBase[string, StringConfig, stringValue] var NewStringSlice = NewSliceBase[string, StringConfig, stringValue] -var NewUintSlice = NewSliceBase[uint64, IntegerConfig, uintValue] var OsExiter = os.Exit OsExiter is the function used when the app exits. If not set defaults to os.Exit. @@ -496,10 +508,38 @@ func (cmd *Command) Generic(name string) Value func (cmd *Command) HasName(name string) bool HasName returns true if Command.Name matches given name -func (cmd *Command) Int(name string) int64 +func (cmd *Command) Int(name string) int Int looks up the value of a local Int64Flag, returns 0 if not found -func (cmd *Command) IntSlice(name string) []int64 +func (cmd *Command) Int16(name string) int16 + Int16 looks up the value of a local Int16Flag, returns 0 if not found + +func (cmd *Command) Int16Slice(name string) []int16 + Int16Slice looks up the value of a local Int16SliceFlag, returns nil if not + found + +func (cmd *Command) Int32(name string) int32 + Int32 looks up the value of a local Int32Flag, returns 0 if not found + +func (cmd *Command) Int32Slice(name string) []int32 + Int32Slice looks up the value of a local Int32SliceFlag, returns nil if not + found + +func (cmd *Command) Int64(name string) int64 + Int64 looks up the value of a local Int64Flag, returns 0 if not found + +func (cmd *Command) Int64Slice(name string) []int64 + Int64Slice looks up the value of a local Int64SliceFlag, returns nil if not + found + +func (cmd *Command) Int8(name string) int8 + Int8 looks up the value of a local Int8Flag, returns 0 if not found + +func (cmd *Command) Int8Slice(name string) []int8 + Int8Slice looks up the value of a local Int8SliceFlag, returns nil if not + found + +func (cmd *Command) IntSlice(name string) []int IntSlice looks up the value of a local IntSliceFlag, returns nil if not found @@ -550,10 +590,38 @@ func (cmd *Command) ToFishCompletion() (string, error) ToFishCompletion creates a fish completion string for the `*App` The function errors if either parsing or writing of the string fails. -func (cmd *Command) Uint(name string) uint64 +func (cmd *Command) Uint(name string) uint Uint looks up the value of a local Uint64Flag, returns 0 if not found -func (cmd *Command) UintSlice(name string) []uint64 +func (cmd *Command) Uint16(name string) uint16 + Uint16 looks up the value of a local Uint16Flag, returns 0 if not found + +func (cmd *Command) Uint16Slice(name string) []uint16 + Uint16Slice looks up the value of a local Uint16SliceFlag, returns nil if + not found + +func (cmd *Command) Uint32(name string) uint32 + Uint32 looks up the value of a local Uint32Flag, returns 0 if not found + +func (cmd *Command) Uint32Slice(name string) []uint32 + Uint32Slice looks up the value of a local Uint32SliceFlag, returns nil if + not found + +func (cmd *Command) Uint64(name string) uint64 + Uint64 looks up the value of a local Uint64Flag, returns 0 if not found + +func (cmd *Command) Uint64Slice(name string) []uint64 + Uint64Slice looks up the value of a local Uint64SliceFlag, returns nil if + not found + +func (cmd *Command) Uint8(name string) uint8 + Uint8 looks up the value of a local Uint8Flag, returns 0 if not found + +func (cmd *Command) Uint8Slice(name string) []uint8 + Uint8Slice looks up the value of a local Uint8SliceFlag, returns nil if not + found + +func (cmd *Command) UintSlice(name string) []uint UintSlice looks up the value of a local UintSliceFlag, returns nil if not found @@ -879,13 +947,45 @@ type FloatSliceFlag = FlagBase[[]float64, NoConfig, FloatSlice] type GenericFlag = FlagBase[Value, NoConfig, genericValue] -type IntArg = ArgumentBase[int64, IntegerConfig, intValue] +type Int16Arg = ArgumentBase[int16, IntegerConfig, intValue[int16]] + +type Int16Flag = FlagBase[int16, IntegerConfig, intValue[int16]] + +type Int16Slice = SliceBase[int16, IntegerConfig, intValue[int16]] -type IntFlag = FlagBase[int64, IntegerConfig, intValue] +type Int16SliceFlag = FlagBase[[]int16, IntegerConfig, Int16Slice] -type IntSlice = SliceBase[int64, IntegerConfig, intValue] +type Int32Arg = ArgumentBase[int32, IntegerConfig, intValue[int32]] -type IntSliceFlag = FlagBase[[]int64, IntegerConfig, IntSlice] +type Int32Flag = FlagBase[int32, IntegerConfig, intValue[int32]] + +type Int32Slice = SliceBase[int32, IntegerConfig, intValue[int32]] + +type Int32SliceFlag = FlagBase[[]int32, IntegerConfig, Int32Slice] + +type Int64Arg = ArgumentBase[int64, IntegerConfig, intValue[int64]] + +type Int64Flag = FlagBase[int64, IntegerConfig, intValue[int64]] + +type Int64Slice = SliceBase[int64, IntegerConfig, intValue[int64]] + +type Int64SliceFlag = FlagBase[[]int64, IntegerConfig, Int64Slice] + +type Int8Arg = ArgumentBase[int8, IntegerConfig, intValue[int8]] + +type Int8Flag = FlagBase[int8, IntegerConfig, intValue[int8]] + +type Int8Slice = SliceBase[int8, IntegerConfig, intValue[int8]] + +type Int8SliceFlag = FlagBase[[]int8, IntegerConfig, Int8Slice] + +type IntArg = ArgumentBase[int, IntegerConfig, intValue[int]] + +type IntFlag = FlagBase[int, IntegerConfig, intValue[int]] + +type IntSlice = SliceBase[int, IntegerConfig, intValue[int]] + +type IntSliceFlag = FlagBase[[]int, IntegerConfig, IntSlice] type IntegerConfig struct { Base int @@ -1055,13 +1155,45 @@ type TimestampConfig struct { type TimestampFlag = FlagBase[time.Time, TimestampConfig, timestampValue] -type UintArg = ArgumentBase[uint64, IntegerConfig, uintValue] +type Uint16Arg = ArgumentBase[uint16, IntegerConfig, uintValue[uint16]] + +type Uint16Flag = FlagBase[uint16, IntegerConfig, uintValue[uint16]] + +type Uint16Slice = SliceBase[uint16, IntegerConfig, uintValue[uint16]] + +type Uint16SliceFlag = FlagBase[[]uint16, IntegerConfig, Uint16Slice] + +type Uint32Arg = ArgumentBase[uint32, IntegerConfig, uintValue[uint32]] + +type Uint32Flag = FlagBase[uint32, IntegerConfig, uintValue[uint32]] + +type Uint32Slice = SliceBase[uint32, IntegerConfig, uintValue[uint32]] + +type Uint32SliceFlag = FlagBase[[]uint32, IntegerConfig, Uint32Slice] + +type Uint64Arg = ArgumentBase[uint64, IntegerConfig, uintValue[uint64]] + +type Uint64Flag = FlagBase[uint64, IntegerConfig, uintValue[uint64]] + +type Uint64Slice = SliceBase[uint64, IntegerConfig, uintValue[uint64]] + +type Uint64SliceFlag = FlagBase[[]uint64, IntegerConfig, Uint64Slice] + +type Uint8Arg = ArgumentBase[uint8, IntegerConfig, uintValue[uint8]] + +type Uint8Flag = FlagBase[uint8, IntegerConfig, uintValue[uint8]] + +type Uint8Slice = SliceBase[uint8, IntegerConfig, uintValue[uint8]] + +type Uint8SliceFlag = FlagBase[[]uint8, IntegerConfig, Uint8Slice] + +type UintArg = ArgumentBase[uint, IntegerConfig, uintValue[uint]] -type UintFlag = FlagBase[uint64, IntegerConfig, uintValue] +type UintFlag = FlagBase[uint, IntegerConfig, uintValue[uint]] -type UintSlice = SliceBase[uint64, IntegerConfig, uintValue] +type UintSlice = SliceBase[uint, IntegerConfig, uintValue[uint]] -type UintSliceFlag = FlagBase[[]uint64, IntegerConfig, UintSlice] +type UintSliceFlag = FlagBase[[]uint, IntegerConfig, UintSlice] type Value interface { flag.Value diff --git a/help_test.go b/help_test.go index 75c37696d6..096fee7b8b 100644 --- a/help_test.go +++ b/help_test.go @@ -70,7 +70,7 @@ func Test_Help_RequiredFlagsNoDefault(t *testing.T) { cmd := &Command{ Flags: []Flag{ - &IntFlag{Name: "foo", Aliases: []string{"f"}, Required: true}, + &Int64Flag{Name: "foo", Aliases: []string{"f"}, Required: true}, }, Arguments: AnyArguments, Writer: output, @@ -1174,7 +1174,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, Commands: []*Command{ {Name: "putz"}, @@ -1196,7 +1196,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, Commands: []*Command{ {Name: "putz"}, @@ -1218,7 +1218,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, Commands: []*Command{ {Name: "putz"}, @@ -1244,7 +1244,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, }, }, @@ -1267,7 +1267,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, }, }, @@ -1287,7 +1287,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, }, }, @@ -1307,7 +1307,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &IntFlag{Name: "everybody-jump-on"}, + &Int64Flag{Name: "everybody-jump-on"}, }, }, }, @@ -1670,7 +1670,7 @@ func TestCategorizedHelp(t *testing.T) { &StringFlag{ Name: "strd", // no category set }, - &IntFlag{ + &Int64Flag{ Name: "intd", Aliases: []string{"altd1", "altd2"}, Category: "cat1", diff --git a/testdata/godoc-v3.x.txt b/testdata/godoc-v3.x.txt index d9448f3cbc..e62ba79f5b 100644 --- a/testdata/godoc-v3.x.txt +++ b/testdata/godoc-v3.x.txt @@ -26,6 +26,20 @@ application: VARIABLES +var ( + NewIntSlice = NewSliceBase[int, IntegerConfig, intValue[int]] + NewInt8Slice = NewSliceBase[int8, IntegerConfig, intValue[int8]] + NewInt16Slice = NewSliceBase[int16, IntegerConfig, intValue[int16]] + NewInt32Slice = NewSliceBase[int32, IntegerConfig, intValue[int32]] + NewInt64Slice = NewSliceBase[int64, IntegerConfig, intValue[int64]] +) +var ( + NewUintSlice = NewSliceBase[uint, IntegerConfig, uintValue[uint]] + NewUint8Slice = NewSliceBase[uint8, IntegerConfig, uintValue[uint8]] + NewUint16Slice = NewSliceBase[uint16, IntegerConfig, uintValue[uint16]] + NewUint32Slice = NewSliceBase[uint32, IntegerConfig, uintValue[uint32]] + NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uintValue[uint64]] +) var ( SuggestFlag SuggestFlagFunc = suggestFlag SuggestCommand SuggestCommandFunc = suggestCommand @@ -79,10 +93,8 @@ end {{ range $v := .Completions }}{{ $v }} {{ end }}` var NewFloatSlice = NewSliceBase[float64, NoConfig, floatValue] -var NewIntSlice = NewSliceBase[int64, IntegerConfig, intValue] var NewStringMap = NewMapBase[string, StringConfig, stringValue] var NewStringSlice = NewSliceBase[string, StringConfig, stringValue] -var NewUintSlice = NewSliceBase[uint64, IntegerConfig, uintValue] var OsExiter = os.Exit OsExiter is the function used when the app exits. If not set defaults to os.Exit. @@ -496,10 +508,38 @@ func (cmd *Command) Generic(name string) Value func (cmd *Command) HasName(name string) bool HasName returns true if Command.Name matches given name -func (cmd *Command) Int(name string) int64 +func (cmd *Command) Int(name string) int Int looks up the value of a local Int64Flag, returns 0 if not found -func (cmd *Command) IntSlice(name string) []int64 +func (cmd *Command) Int16(name string) int16 + Int16 looks up the value of a local Int16Flag, returns 0 if not found + +func (cmd *Command) Int16Slice(name string) []int16 + Int16Slice looks up the value of a local Int16SliceFlag, returns nil if not + found + +func (cmd *Command) Int32(name string) int32 + Int32 looks up the value of a local Int32Flag, returns 0 if not found + +func (cmd *Command) Int32Slice(name string) []int32 + Int32Slice looks up the value of a local Int32SliceFlag, returns nil if not + found + +func (cmd *Command) Int64(name string) int64 + Int64 looks up the value of a local Int64Flag, returns 0 if not found + +func (cmd *Command) Int64Slice(name string) []int64 + Int64Slice looks up the value of a local Int64SliceFlag, returns nil if not + found + +func (cmd *Command) Int8(name string) int8 + Int8 looks up the value of a local Int8Flag, returns 0 if not found + +func (cmd *Command) Int8Slice(name string) []int8 + Int8Slice looks up the value of a local Int8SliceFlag, returns nil if not + found + +func (cmd *Command) IntSlice(name string) []int IntSlice looks up the value of a local IntSliceFlag, returns nil if not found @@ -550,10 +590,38 @@ func (cmd *Command) ToFishCompletion() (string, error) ToFishCompletion creates a fish completion string for the `*App` The function errors if either parsing or writing of the string fails. -func (cmd *Command) Uint(name string) uint64 +func (cmd *Command) Uint(name string) uint Uint looks up the value of a local Uint64Flag, returns 0 if not found -func (cmd *Command) UintSlice(name string) []uint64 +func (cmd *Command) Uint16(name string) uint16 + Uint16 looks up the value of a local Uint16Flag, returns 0 if not found + +func (cmd *Command) Uint16Slice(name string) []uint16 + Uint16Slice looks up the value of a local Uint16SliceFlag, returns nil if + not found + +func (cmd *Command) Uint32(name string) uint32 + Uint32 looks up the value of a local Uint32Flag, returns 0 if not found + +func (cmd *Command) Uint32Slice(name string) []uint32 + Uint32Slice looks up the value of a local Uint32SliceFlag, returns nil if + not found + +func (cmd *Command) Uint64(name string) uint64 + Uint64 looks up the value of a local Uint64Flag, returns 0 if not found + +func (cmd *Command) Uint64Slice(name string) []uint64 + Uint64Slice looks up the value of a local Uint64SliceFlag, returns nil if + not found + +func (cmd *Command) Uint8(name string) uint8 + Uint8 looks up the value of a local Uint8Flag, returns 0 if not found + +func (cmd *Command) Uint8Slice(name string) []uint8 + Uint8Slice looks up the value of a local Uint8SliceFlag, returns nil if not + found + +func (cmd *Command) UintSlice(name string) []uint UintSlice looks up the value of a local UintSliceFlag, returns nil if not found @@ -879,13 +947,45 @@ type FloatSliceFlag = FlagBase[[]float64, NoConfig, FloatSlice] type GenericFlag = FlagBase[Value, NoConfig, genericValue] -type IntArg = ArgumentBase[int64, IntegerConfig, intValue] +type Int16Arg = ArgumentBase[int16, IntegerConfig, intValue[int16]] + +type Int16Flag = FlagBase[int16, IntegerConfig, intValue[int16]] + +type Int16Slice = SliceBase[int16, IntegerConfig, intValue[int16]] -type IntFlag = FlagBase[int64, IntegerConfig, intValue] +type Int16SliceFlag = FlagBase[[]int16, IntegerConfig, Int16Slice] -type IntSlice = SliceBase[int64, IntegerConfig, intValue] +type Int32Arg = ArgumentBase[int32, IntegerConfig, intValue[int32]] -type IntSliceFlag = FlagBase[[]int64, IntegerConfig, IntSlice] +type Int32Flag = FlagBase[int32, IntegerConfig, intValue[int32]] + +type Int32Slice = SliceBase[int32, IntegerConfig, intValue[int32]] + +type Int32SliceFlag = FlagBase[[]int32, IntegerConfig, Int32Slice] + +type Int64Arg = ArgumentBase[int64, IntegerConfig, intValue[int64]] + +type Int64Flag = FlagBase[int64, IntegerConfig, intValue[int64]] + +type Int64Slice = SliceBase[int64, IntegerConfig, intValue[int64]] + +type Int64SliceFlag = FlagBase[[]int64, IntegerConfig, Int64Slice] + +type Int8Arg = ArgumentBase[int8, IntegerConfig, intValue[int8]] + +type Int8Flag = FlagBase[int8, IntegerConfig, intValue[int8]] + +type Int8Slice = SliceBase[int8, IntegerConfig, intValue[int8]] + +type Int8SliceFlag = FlagBase[[]int8, IntegerConfig, Int8Slice] + +type IntArg = ArgumentBase[int, IntegerConfig, intValue[int]] + +type IntFlag = FlagBase[int, IntegerConfig, intValue[int]] + +type IntSlice = SliceBase[int, IntegerConfig, intValue[int]] + +type IntSliceFlag = FlagBase[[]int, IntegerConfig, IntSlice] type IntegerConfig struct { Base int @@ -1055,13 +1155,45 @@ type TimestampConfig struct { type TimestampFlag = FlagBase[time.Time, TimestampConfig, timestampValue] -type UintArg = ArgumentBase[uint64, IntegerConfig, uintValue] +type Uint16Arg = ArgumentBase[uint16, IntegerConfig, uintValue[uint16]] + +type Uint16Flag = FlagBase[uint16, IntegerConfig, uintValue[uint16]] + +type Uint16Slice = SliceBase[uint16, IntegerConfig, uintValue[uint16]] + +type Uint16SliceFlag = FlagBase[[]uint16, IntegerConfig, Uint16Slice] + +type Uint32Arg = ArgumentBase[uint32, IntegerConfig, uintValue[uint32]] + +type Uint32Flag = FlagBase[uint32, IntegerConfig, uintValue[uint32]] + +type Uint32Slice = SliceBase[uint32, IntegerConfig, uintValue[uint32]] + +type Uint32SliceFlag = FlagBase[[]uint32, IntegerConfig, Uint32Slice] + +type Uint64Arg = ArgumentBase[uint64, IntegerConfig, uintValue[uint64]] + +type Uint64Flag = FlagBase[uint64, IntegerConfig, uintValue[uint64]] + +type Uint64Slice = SliceBase[uint64, IntegerConfig, uintValue[uint64]] + +type Uint64SliceFlag = FlagBase[[]uint64, IntegerConfig, Uint64Slice] + +type Uint8Arg = ArgumentBase[uint8, IntegerConfig, uintValue[uint8]] + +type Uint8Flag = FlagBase[uint8, IntegerConfig, uintValue[uint8]] + +type Uint8Slice = SliceBase[uint8, IntegerConfig, uintValue[uint8]] + +type Uint8SliceFlag = FlagBase[[]uint8, IntegerConfig, Uint8Slice] + +type UintArg = ArgumentBase[uint, IntegerConfig, uintValue[uint]] -type UintFlag = FlagBase[uint64, IntegerConfig, uintValue] +type UintFlag = FlagBase[uint, IntegerConfig, uintValue[uint]] -type UintSlice = SliceBase[uint64, IntegerConfig, uintValue] +type UintSlice = SliceBase[uint, IntegerConfig, uintValue[uint]] -type UintSliceFlag = FlagBase[[]uint64, IntegerConfig, UintSlice] +type UintSliceFlag = FlagBase[[]uint, IntegerConfig, UintSlice] type Value interface { flag.Value