diff --git a/README.md b/README.md index a3d8511..5595a41 100644 --- a/README.md +++ b/README.md @@ -648,7 +648,7 @@ normal validation. ## Modifying Kong's behaviour -Each Kong parser can be configured via functional options passed to `New(cli interface{}, options...Option)`. +Each Kong parser can be configured via functional options passed to `New(cli any, options...Option)`. The full set of options can be found [here](https://godoc.org/github.com/alecthomas/kong#Option). @@ -706,7 +706,7 @@ All builtin Go types (as well as a bunch of useful stdlib types like `time.Time` 1. `NamedMapper(string, Mapper)` and using the tag key `type:""`. 2. `KindMapper(reflect.Kind, Mapper)`. 3. `TypeMapper(reflect.Type, Mapper)`. -4. `ValueMapper(interface{}, Mapper)`, passing in a pointer to a field of the grammar. +4. `ValueMapper(any, Mapper)`, passing in a pointer to a field of the grammar. ### `ConfigureHelp(HelpOptions)` and `Help(HelpFunc)` - customising help diff --git a/build.go b/build.go index 42d30f0..166935b 100644 --- a/build.go +++ b/build.go @@ -9,9 +9,9 @@ import ( // Plugins are dynamically embedded command-line structures. // // Each element in the Plugins list *must* be a pointer to a structure. -type Plugins []interface{} +type Plugins []any -func build(k *Kong, ast interface{}) (app *Application, err error) { +func build(k *Kong, ast any) (app *Application, err error) { v := reflect.ValueOf(ast) iv := reflect.Indirect(v) if v.Kind() != reflect.Ptr || iv.Kind() != reflect.Struct { diff --git a/callbacks.go b/callbacks.go index 9733e91..c1fac81 100644 --- a/callbacks.go +++ b/callbacks.go @@ -19,7 +19,7 @@ func (b bindings) String() string { return "bindings{" + strings.Join(out, ", ") + "}" } -func (b bindings) add(values ...interface{}) bindings { +func (b bindings) add(values ...any) bindings { for _, v := range values { v := v b[reflect.TypeOf(v)] = func() (any, error) { return v, nil } @@ -27,11 +27,11 @@ func (b bindings) add(values ...interface{}) bindings { return b } -func (b bindings) addTo(impl, iface interface{}) { +func (b bindings) addTo(impl, iface any) { b[reflect.TypeOf(iface).Elem()] = func() (any, error) { return impl, nil } } -func (b bindings) addProvider(provider interface{}) error { +func (b bindings) addProvider(provider any) error { pv := reflect.ValueOf(provider) t := pv.Type() if t.Kind() != reflect.Func || t.NumOut() != 2 || t.Out(1) != reflect.TypeOf((*error)(nil)).Elem() { diff --git a/config_test.go b/config_test.go index 15d6eec..570f142 100644 --- a/config_test.go +++ b/config_test.go @@ -42,7 +42,7 @@ func TestConfigValidation(t *testing.T) { assert.Error(t, err) } -func makeConfig(t *testing.T, config interface{}) (path string, cleanup func()) { +func makeConfig(t *testing.T, config any) (path string, cleanup func()) { t.Helper() w, err := os.CreateTemp("", "") assert.NoError(t, err) diff --git a/context.go b/context.go index b840c68..4fd2302 100644 --- a/context.go +++ b/context.go @@ -102,7 +102,7 @@ func Trace(k *Kong, args []string) (*Context, error) { } // Bind adds bindings to the Context. -func (c *Context) Bind(args ...interface{}) { +func (c *Context) Bind(args ...any) { c.bindings.add(args...) } @@ -111,7 +111,7 @@ func (c *Context) Bind(args ...interface{}) { // This will typically have to be called like so: // // BindTo(impl, (*MyInterface)(nil)) -func (c *Context) BindTo(impl, iface interface{}) { +func (c *Context) BindTo(impl, iface any) { c.bindings.addTo(impl, iface) } @@ -119,7 +119,7 @@ func (c *Context) BindTo(impl, iface interface{}) { // // This is useful when the Run() function of different commands require different values that may // not all be initialisable from the main() function. -func (c *Context) BindToProvider(provider interface{}) error { +func (c *Context) BindToProvider(provider any) error { return c.bindings.addProvider(provider) } @@ -306,7 +306,7 @@ func (c *Context) AddResolver(resolver Resolver) { } // FlagValue returns the set value of a flag if it was encountered and exists, or its default value. -func (c *Context) FlagValue(flag *Flag) interface{} { +func (c *Context) FlagValue(flag *Flag) any { for _, trace := range c.Path { if trace.Flag == flag { v, ok := c.values[trace.Flag.Value] @@ -572,7 +572,7 @@ func (c *Context) Resolve() error { } // Pick the last resolved value. - var selected interface{} + var selected any for _, resolver := range resolvers { s, err := resolver.Resolve(c, path, flag) if err != nil { @@ -757,7 +757,7 @@ func (e *unknownFlagError) Unwrap() error { return e.Cause } func (e *unknownFlagError) Error() string { return e.Cause.Error() } // Call an arbitrary function filling arguments with bound values. -func (c *Context) Call(fn any, binds ...interface{}) (out []interface{}, err error) { +func (c *Context) Call(fn any, binds ...any) (out []any, err error) { fv := reflect.ValueOf(fn) bindings := c.Kong.bindings.clone().add(binds...).add(c).merge(c.bindings) return callAnyFunction(fv, bindings) @@ -769,7 +769,7 @@ func (c *Context) Call(fn any, binds ...interface{}) (out []interface{}, err err // // Any passed values will be bindable to arguments of the target Run() method. Additionally, // all parent nodes in the command structure will be bound. -func (c *Context) RunNode(node *Node, binds ...interface{}) (err error) { +func (c *Context) RunNode(node *Node, binds ...any) (err error) { type targetMethod struct { node *Node method reflect.Value @@ -815,7 +815,7 @@ func (c *Context) RunNode(node *Node, binds ...interface{}) (err error) { // // Any passed values will be bindable to arguments of the target Run() method. Additionally, // all parent nodes in the command structure will be bound. -func (c *Context) Run(binds ...interface{}) (err error) { +func (c *Context) Run(binds ...any) (err error) { node := c.Selected() if node == nil { if len(c.Path) == 0 { @@ -1087,7 +1087,7 @@ func checkAndMissing(paths []*Path) error { return nil } -func findPotentialCandidates(needle string, haystack []string, format string, args ...interface{}) error { +func findPotentialCandidates(needle string, haystack []string, format string, args ...any) error { if len(haystack) == 0 { return fmt.Errorf(format, args...) } diff --git a/defaults.go b/defaults.go index f6728d7..9489fb3 100644 --- a/defaults.go +++ b/defaults.go @@ -1,7 +1,7 @@ package kong // ApplyDefaults if they are not already set. -func ApplyDefaults(target interface{}, options ...Option) error { +func ApplyDefaults(target any, options ...Option) error { app, err := New(target, options...) if err != nil { return err diff --git a/global.go b/global.go index d4b3cb5..babe1e1 100644 --- a/global.go +++ b/global.go @@ -5,7 +5,7 @@ import ( ) // Parse constructs a new parser and parses the default command-line. -func Parse(cli interface{}, options ...Option) *Context { +func Parse(cli any, options ...Option) *Context { parser, err := New(cli, options...) if err != nil { panic(err) diff --git a/help.go b/help.go index 26f355d..6363ea2 100644 --- a/help.go +++ b/help.go @@ -386,7 +386,7 @@ func newHelpWriter(ctx *Context, options HelpOptions) *helpWriter { return w } -func (h *helpWriter) Printf(format string, args ...interface{}) { +func (h *helpWriter) Printf(format string, args ...any) { h.Print(fmt.Sprintf(format, args...)) } diff --git a/kong.go b/kong.go index 4f3bea2..b85e145 100644 --- a/kong.go +++ b/kong.go @@ -15,7 +15,7 @@ var ( callbackReturnSignature = reflect.TypeOf((*error)(nil)).Elem() ) -func failField(parent reflect.Value, field reflect.StructField, format string, args ...interface{}) error { +func failField(parent reflect.Value, field reflect.StructField, format string, args ...any) error { name := parent.Type().Name() if name == "" { name = "" @@ -24,7 +24,7 @@ func failField(parent reflect.Value, field reflect.StructField, format string, a } // Must creates a new Parser or panics if there is an error. -func Must(ast interface{}, options ...Option) *Kong { +func Must(ast any, options ...Option) *Kong { k, err := New(ast, options...) if err != nil { panic(err) @@ -76,7 +76,7 @@ type Kong struct { // New creates a new Kong parser on grammar. // // See the README (https://github.com/alecthomas/kong) for usage instructions. -func New(grammar interface{}, options ...Option) (*Kong, error) { +func New(grammar any, options ...Option) (*Kong, error) { k := &Kong{ Exit: os.Exit, Stdout: os.Stdout, @@ -401,7 +401,7 @@ func (k *Kong) applyHookToDefaultFlags(ctx *Context, node *Node, name string) er }) } -func formatMultilineMessage(w io.Writer, leaders []string, format string, args ...interface{}) { +func formatMultilineMessage(w io.Writer, leaders []string, format string, args ...any) { lines := strings.Split(strings.TrimRight(fmt.Sprintf(format, args...), "\n"), "\n") leader := "" for _, l := range leaders { @@ -417,25 +417,25 @@ func formatMultilineMessage(w io.Writer, leaders []string, format string, args . } // Printf writes a message to Kong.Stdout with the application name prefixed. -func (k *Kong) Printf(format string, args ...interface{}) *Kong { +func (k *Kong) Printf(format string, args ...any) *Kong { formatMultilineMessage(k.Stdout, []string{k.Model.Name}, format, args...) return k } // Errorf writes a message to Kong.Stderr with the application name prefixed. -func (k *Kong) Errorf(format string, args ...interface{}) *Kong { +func (k *Kong) Errorf(format string, args ...any) *Kong { formatMultilineMessage(k.Stderr, []string{k.Model.Name, "error"}, format, args...) return k } // Fatalf writes a message to Kong.Stderr with the application name prefixed then exits with a non-zero status. -func (k *Kong) Fatalf(format string, args ...interface{}) { +func (k *Kong) Fatalf(format string, args ...any) { k.Errorf(format, args...) k.Exit(1) } // FatalIfErrorf terminates with an error message if err != nil. -func (k *Kong) FatalIfErrorf(err error, args ...interface{}) { +func (k *Kong) FatalIfErrorf(err error, args ...any) { if err == nil { return } diff --git a/kong_test.go b/kong_test.go index 36d4e96..fce739a 100644 --- a/kong_test.go +++ b/kong_test.go @@ -14,7 +14,7 @@ import ( "github.com/alecthomas/kong" ) -func mustNew(t *testing.T, cli interface{}, options ...kong.Option) *kong.Kong { +func mustNew(t *testing.T, cli any, options ...kong.Option) *kong.Kong { t.Helper() options = append([]kong.Option{ kong.Name("test"), @@ -1680,7 +1680,7 @@ func TestOptionReturnsErr(t *testing.T) { func TestEnumValidation(t *testing.T) { tests := []struct { name string - cli interface{} + cli any fail bool }{ { @@ -1954,7 +1954,7 @@ func TestVersionFlagShouldStillWork(t *testing.T) { func TestSliceDecoderHelpfulErrorMsg(t *testing.T) { tests := []struct { name string - cli interface{} + cli any args []string err string }{ @@ -2004,7 +2004,7 @@ func TestSliceDecoderHelpfulErrorMsg(t *testing.T) { func TestMapDecoderHelpfulErrorMsg(t *testing.T) { tests := []struct { name string - cli interface{} + cli any args []string expected string }{ diff --git a/mapper.go b/mapper.go index 584bb00..db3f24e 100644 --- a/mapper.go +++ b/mapper.go @@ -251,7 +251,7 @@ func (r *Registry) RegisterType(typ reflect.Type, mapper Mapper) *Registry { } // RegisterValue registers a Mapper by pointer to the field value. -func (r *Registry) RegisterValue(ptr interface{}, mapper Mapper) *Registry { +func (r *Registry) RegisterValue(ptr any, mapper Mapper) *Registry { key := reflect.ValueOf(ptr) if key.Kind() != reflect.Ptr { panic("expected a pointer") @@ -473,7 +473,7 @@ func mapDecoder(r *Registry) MapperFunc { case string: childScanner = ScanAsType(t.Type, SplitEscaped(v, mapsep)...) - case []map[string]interface{}: + case []map[string]any: for _, m := range v { err := jsonTranscode(m, target.Addr().Interface()) if err != nil { @@ -482,7 +482,7 @@ func mapDecoder(r *Registry) MapperFunc { } return nil - case map[string]interface{}: + case map[string]any: return jsonTranscode(v, target.Addr().Interface()) default: @@ -548,11 +548,11 @@ func sliceDecoder(r *Registry) MapperFunc { case string: childScanner = ScanAsType(t.Type, SplitEscaped(v, sep)...) - case []interface{}: + case []any: return jsonTranscode(v, target.Addr().Interface()) default: - v = []interface{}{v} + v = []any{v} return jsonTranscode(v, target.Addr().Interface()) } } else { @@ -922,7 +922,7 @@ func (f *FileContentFlag) Decode(ctx *DecodeContext) error { //nolint: revive return nil } -func jsonTranscode(in, out interface{}) error { +func jsonTranscode(in, out any) error { data, err := json.Marshal(in) if err != nil { return err diff --git a/model.go b/model.go index 25ffe96..f15e6fb 100644 --- a/model.go +++ b/model.go @@ -69,7 +69,7 @@ func (n *Node) Leaf() bool { // Find a command/argument/flag by pointer to its field. // // Returns nil if not found. Panics if ptr is not a pointer. -func (n *Node) Find(ptr interface{}) *Node { +func (n *Node) Find(ptr any) *Node { key := reflect.ValueOf(ptr) if key.Kind() != reflect.Ptr { panic("expected a pointer") diff --git a/options.go b/options.go index 3bc991b..6263202 100644 --- a/options.go +++ b/options.go @@ -79,7 +79,7 @@ type dynamicCommand struct { help string group string tags []string - cmd interface{} + cmd any } // DynamicCommand registers a dynamically constructed command with the root of the CLI. @@ -87,7 +87,7 @@ type dynamicCommand struct { // This is useful for command-line structures that are extensible via user-provided plugins. // // "tags" is a list of extra tag strings to parse, in the form :"". -func DynamicCommand(name, help, group string, cmd interface{}, tags ...string) Option { +func DynamicCommand(name, help, group string, cmd any, tags ...string) Option { return OptionFunc(func(k *Kong) error { if run := getMethod(reflect.Indirect(reflect.ValueOf(cmd)), "Run"); !run.IsValid() { return fmt.Errorf("kong: DynamicCommand %q must be a type with a 'Run' method; got %T", name, cmd) @@ -156,7 +156,7 @@ func KindMapper(kind reflect.Kind, mapper Mapper) Option { } // ValueMapper registers a mapper to a field value. -func ValueMapper(ptr interface{}, mapper Mapper) Option { +func ValueMapper(ptr any, mapper Mapper) Option { return OptionFunc(func(k *Kong) error { k.registry.RegisterValue(ptr, mapper) return nil @@ -191,7 +191,7 @@ func Writers(stdout, stderr io.Writer) Option { // AfterApply(...) error // // Called before validation/assignment, and immediately after validation/assignment, respectively. -func Bind(args ...interface{}) Option { +func Bind(args ...any) Option { return OptionFunc(func(k *Kong) error { k.bindings.add(args...) return nil @@ -201,7 +201,7 @@ func Bind(args ...interface{}) Option { // BindTo allows binding of implementations to interfaces. // // BindTo(impl, (*iface)(nil)) -func BindTo(impl, iface interface{}) Option { +func BindTo(impl, iface any) Option { return OptionFunc(func(k *Kong) error { k.bindings.addTo(impl, iface) return nil @@ -212,11 +212,11 @@ func BindTo(impl, iface interface{}) Option { // // The provider function must have the signature: // -// func() (interface{}, error) +// func() (any, error) // // This is useful when the Run() function of different commands require different values that may // not all be initialisable from the main() function. -func BindToProvider(provider interface{}) Option { +func BindToProvider(provider any) Option { return OptionFunc(func(k *Kong) error { return k.bindings.addProvider(provider) }) diff --git a/resolver.go b/resolver.go index dca4309..29be1b9 100644 --- a/resolver.go +++ b/resolver.go @@ -14,15 +14,15 @@ type Resolver interface { Validate(app *Application) error // Resolve the value for a Flag. - Resolve(context *Context, parent *Path, flag *Flag) (interface{}, error) + Resolve(context *Context, parent *Path, flag *Flag) (any, error) } // ResolverFunc is a convenience type for non-validating Resolvers. -type ResolverFunc func(context *Context, parent *Path, flag *Flag) (interface{}, error) +type ResolverFunc func(context *Context, parent *Path, flag *Flag) (any, error) var _ Resolver = ResolverFunc(nil) -func (r ResolverFunc) Resolve(context *Context, parent *Path, flag *Flag) (interface{}, error) { //nolint: revive +func (r ResolverFunc) Resolve(context *Context, parent *Path, flag *Flag) (any, error) { //nolint: revive return r(context, parent, flag) } func (r ResolverFunc) Validate(app *Application) error { return nil } //nolint: revive @@ -31,12 +31,12 @@ func (r ResolverFunc) Validate(app *Application) error { return nil } //nolint: // // Flag names are used as JSON keys indirectly, by tring snake_case and camelCase variants. func JSON(r io.Reader) (Resolver, error) { - values := map[string]interface{}{} + values := map[string]any{} err := json.NewDecoder(r).Decode(&values) if err != nil { return nil, err } - var f ResolverFunc = func(context *Context, parent *Path, flag *Flag) (interface{}, error) { + var f ResolverFunc = func(context *Context, parent *Path, flag *Flag) (any, error) { name := strings.ReplaceAll(flag.Name, "-", "_") snakeCaseName := snakeCase(flag.Name) raw, ok := values[name] @@ -47,7 +47,7 @@ func JSON(r io.Reader) (Resolver, error) { } raw = values for _, part := range strings.Split(name, ".") { - if values, ok := raw.(map[string]interface{}); ok { + if values, ok := raw.(map[string]any); ok { raw, ok = values[part] if !ok { return nil, nil diff --git a/resolver_test.go b/resolver_test.go index 5c9eeda..7ce7ec1 100644 --- a/resolver_test.go +++ b/resolver_test.go @@ -12,7 +12,7 @@ import ( type envMap map[string]string -func newEnvParser(t *testing.T, cli interface{}, env envMap, options ...kong.Option) *kong.Kong { +func newEnvParser(t *testing.T, cli any, env envMap, options ...kong.Option) *kong.Kong { t.Helper() for name, value := range env { t.Setenv(name, value) @@ -275,7 +275,7 @@ func TestResolverWithBool(t *testing.T) { Bool bool } - var resolver kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (interface{}, error) { + var resolver kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (any, error) { if flag.Name == "bool" { return true, nil } @@ -294,14 +294,14 @@ func TestLastResolverWins(t *testing.T) { Int []int } - var first kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (interface{}, error) { + var first kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (any, error) { if flag.Name == "int" { return 1, nil } return nil, nil } - var second kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (interface{}, error) { + var second kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (any, error) { if flag.Name == "int" { return 2, nil } @@ -318,7 +318,7 @@ func TestResolverSatisfiesRequired(t *testing.T) { var cli struct { Int int `required` } - var resolver kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (interface{}, error) { + var resolver kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (any, error) { if flag.Name == "int" { return 1, nil } @@ -336,7 +336,7 @@ func TestResolverTriggersHooks(t *testing.T) { Flag hookValue } - var first kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (interface{}, error) { + var first kong.ResolverFunc = func(context *kong.Context, parent *kong.Path, flag *kong.Flag) (any, error) { if flag.Name == "flag" { return "one", nil } @@ -355,7 +355,7 @@ type validatingResolver struct { } func (v *validatingResolver) Validate(app *kong.Application) error { return v.err } -func (v *validatingResolver) Resolve(context *kong.Context, parent *kong.Path, flag *kong.Flag) (interface{}, error) { +func (v *validatingResolver) Resolve(context *kong.Context, parent *kong.Path, flag *kong.Flag) (any, error) { return nil, nil } diff --git a/scanner.go b/scanner.go index c8a8bd6..262d16f 100644 --- a/scanner.go +++ b/scanner.go @@ -41,7 +41,7 @@ func (t TokenType) String() string { // Token created by Scanner. type Token struct { - Value interface{} + Value any Type TokenType } @@ -171,7 +171,7 @@ func (s *Scanner) PopValue(context string) (Token, error) { // PopValueInto pops a value token into target or returns an error. // // "context" is used to assist the user if the value can not be popped, eg. "expected value but got " -func (s *Scanner) PopValueInto(context string, target interface{}) error { +func (s *Scanner) PopValueInto(context string, target any) error { t, err := s.PopValue(context) if err != nil { return err @@ -204,13 +204,13 @@ func (s *Scanner) Peek() Token { } // Push an untyped Token onto the front of the Scanner. -func (s *Scanner) Push(arg interface{}) *Scanner { +func (s *Scanner) Push(arg any) *Scanner { s.PushToken(Token{Value: arg}) return s } // PushTyped pushes a typed token onto the front of the Scanner. -func (s *Scanner) PushTyped(arg interface{}, typ TokenType) *Scanner { +func (s *Scanner) PushTyped(arg any, typ TokenType) *Scanner { s.PushToken(Token{Value: arg, Type: typ}) return s }