Treat envars as higher priority than resolvers.
This commit is contained in:
@@ -198,6 +198,9 @@ func (c *Context) FlagValue(flag *Flag) interface{} {
|
|||||||
return v.Interface()
|
return v.Interface()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if flag.Target.IsValid() {
|
||||||
|
return flag.Target.Interface()
|
||||||
|
}
|
||||||
return flag.DefaultValue.Interface()
|
return flag.DefaultValue.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,13 +63,12 @@ type Kong struct {
|
|||||||
// See the README (https://github.com/alecthomas/kong) for usage instructions.
|
// See the README (https://github.com/alecthomas/kong) for usage instructions.
|
||||||
func New(grammar interface{}, options ...Option) (*Kong, error) {
|
func New(grammar interface{}, options ...Option) (*Kong, error) {
|
||||||
k := &Kong{
|
k := &Kong{
|
||||||
Exit: os.Exit,
|
Exit: os.Exit,
|
||||||
Stdout: os.Stdout,
|
Stdout: os.Stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: os.Stderr,
|
||||||
registry: NewRegistry().RegisterDefaults(),
|
registry: NewRegistry().RegisterDefaults(),
|
||||||
resolvers: []ResolverFunc{Envars()},
|
vars: Vars{},
|
||||||
vars: Vars{},
|
bindings: bindings{},
|
||||||
bindings: bindings{},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options = append(options, Bind(k))
|
options = append(options, Bind(k))
|
||||||
@@ -169,11 +168,12 @@ func (k *Kong) extraFlags() []*Flag {
|
|||||||
value := reflect.ValueOf(&helpTarget).Elem()
|
value := reflect.ValueOf(&helpTarget).Elem()
|
||||||
helpFlag := &Flag{
|
helpFlag := &Flag{
|
||||||
Value: &Value{
|
Value: &Value{
|
||||||
Name: "help",
|
Name: "help",
|
||||||
Help: "Show context-sensitive help.",
|
Help: "Show context-sensitive help.",
|
||||||
Target: value,
|
Target: value,
|
||||||
Tag: &Tag{},
|
Tag: &Tag{},
|
||||||
Mapper: k.registry.ForValue(value),
|
Mapper: k.registry.ForValue(value),
|
||||||
|
DefaultValue: reflect.ValueOf(false),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
helpFlag.Flag = helpFlag
|
helpFlag.Flag = helpFlag
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package kong
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -282,11 +283,22 @@ func (v *Value) Apply(value reflect.Value) {
|
|||||||
v.Set = true
|
v.Set = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset this value to its default, either the zero value or the parsed result of its "default" tag.
|
// Reset this value to its default, either the zero value or the parsed result of its envar,
|
||||||
|
// or its "default" tag.
|
||||||
//
|
//
|
||||||
// Does not include resolvers.
|
// Does not include resolvers.
|
||||||
func (v *Value) Reset() error {
|
func (v *Value) Reset() error {
|
||||||
v.Target.Set(reflect.Zero(v.Target.Type()))
|
v.Target.Set(reflect.Zero(v.Target.Type()))
|
||||||
|
if v.Tag.Env != "" {
|
||||||
|
envar := os.Getenv(v.Tag.Env)
|
||||||
|
if envar != "" {
|
||||||
|
err := v.Parse(Scan(envar), v.Target)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s (from envar %s=%q)", err, v.Tag.Env, envar)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
if v.Default != "" {
|
if v.Default != "" {
|
||||||
return v.Parse(Scan(v.Default), v.Target)
|
return v.Parse(Scan(v.Default), v.Target)
|
||||||
}
|
}
|
||||||
|
|||||||
-14
@@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,16 +60,3 @@ func jsonDecodeValue(sep rune, value interface{}) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", fmt.Errorf("unsupported JSON value %v (of type %T)", value, value)
|
return "", fmt.Errorf("unsupported JSON value %v (of type %T)", value, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Envars resolves flag values using the `env:"<name>"` tag. It ignores flags without this tag.
|
|
||||||
//
|
|
||||||
// This resolver is installed by default.
|
|
||||||
func Envars() ResolverFunc {
|
|
||||||
return func(context *Context, parent *Path, flag *Flag) (string, error) {
|
|
||||||
if flag.Tag.Env == "" {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
v, _ := os.LookupEnv(flag.Tag.Env)
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -61,31 +61,6 @@ func TestEnvarsFlagOverride(t *testing.T) {
|
|||||||
require.Equal(t, "hello", cli.Flag)
|
require.Equal(t, "hello", cli.Flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvarsOnlyPopulateUsedBranches(t *testing.T) {
|
|
||||||
// nolint
|
|
||||||
var cli struct {
|
|
||||||
UnvisitedArg struct {
|
|
||||||
UnvisitedArg string `arg`
|
|
||||||
Int int `env:"KONG_INT"`
|
|
||||||
} `arg`
|
|
||||||
UnvisitedCmd struct {
|
|
||||||
Int int `env:"KONG_INT"`
|
|
||||||
} `cmd`
|
|
||||||
Visited struct {
|
|
||||||
Int int `env:"KONG_INT"`
|
|
||||||
} `cmd`
|
|
||||||
}
|
|
||||||
parser, restoreEnv := newEnvParser(t, &cli, envMap{"KONG_INT": "512"})
|
|
||||||
defer restoreEnv()
|
|
||||||
|
|
||||||
_, err := parser.Parse([]string{"visited"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Equal(t, 512, cli.Visited.Int)
|
|
||||||
require.Equal(t, 0, cli.UnvisitedArg.Int)
|
|
||||||
require.Equal(t, 0, cli.UnvisitedCmd.Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnvarsTag(t *testing.T) {
|
func TestEnvarsTag(t *testing.T) {
|
||||||
var cli struct {
|
var cli struct {
|
||||||
Slice []int `env:"KONG_NUMBERS"`
|
Slice []int `env:"KONG_NUMBERS"`
|
||||||
|
|||||||
Reference in New Issue
Block a user