Treat envars as higher priority than resolvers.

This commit is contained in:
Alec Thomas
2018-09-21 12:06:24 +10:00
parent 026359efd8
commit 3a832f8343
5 changed files with 28 additions and 52 deletions
+3
View File
@@ -198,6 +198,9 @@ func (c *Context) FlagValue(flag *Flag) interface{} {
return v.Interface()
}
}
if flag.Target.IsValid() {
return flag.Target.Interface()
}
return flag.DefaultValue.Interface()
}
+12 -12
View File
@@ -63,13 +63,12 @@ type Kong struct {
// See the README (https://github.com/alecthomas/kong) for usage instructions.
func New(grammar interface{}, options ...Option) (*Kong, error) {
k := &Kong{
Exit: os.Exit,
Stdout: os.Stdout,
Stderr: os.Stderr,
registry: NewRegistry().RegisterDefaults(),
resolvers: []ResolverFunc{Envars()},
vars: Vars{},
bindings: bindings{},
Exit: os.Exit,
Stdout: os.Stdout,
Stderr: os.Stderr,
registry: NewRegistry().RegisterDefaults(),
vars: Vars{},
bindings: bindings{},
}
options = append(options, Bind(k))
@@ -169,11 +168,12 @@ func (k *Kong) extraFlags() []*Flag {
value := reflect.ValueOf(&helpTarget).Elem()
helpFlag := &Flag{
Value: &Value{
Name: "help",
Help: "Show context-sensitive help.",
Target: value,
Tag: &Tag{},
Mapper: k.registry.ForValue(value),
Name: "help",
Help: "Show context-sensitive help.",
Target: value,
Tag: &Tag{},
Mapper: k.registry.ForValue(value),
DefaultValue: reflect.ValueOf(false),
},
}
helpFlag.Flag = helpFlag
+13 -1
View File
@@ -2,6 +2,7 @@ package kong
import (
"fmt"
"os"
"reflect"
"strconv"
"strings"
@@ -282,11 +283,22 @@ func (v *Value) Apply(value reflect.Value) {
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.
func (v *Value) Reset() error {
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 != "" {
return v.Parse(Scan(v.Default), v.Target)
}
-14
View File
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"io"
"os"
"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)
}
// 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
}
}
-25
View File
@@ -61,31 +61,6 @@ func TestEnvarsFlagOverride(t *testing.T) {
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) {
var cli struct {
Slice []int `env:"KONG_NUMBERS"`