diff --git a/README.md b/README.md index aa8f2cb..a2fd41d 100644 --- a/README.md +++ b/README.md @@ -588,13 +588,13 @@ func main() { } ``` -#### Values from Files +#### Values from files You can also have the default value set from file via `FilePath`. e.g. ``` go package main @@ -620,6 +620,9 @@ func main() { } ``` +Note that default values set from file (e.g. `FilePath`) take precedence over +default values set from the enviornment (e.g. `EnvVar`). + #### Values from alternate input sources (YAML, TOML, and others) There is a separate package altsrc that adds support for getting flag values diff --git a/flag.go b/flag.go index 4042093..68942ae 100644 --- a/flag.go +++ b/flag.go @@ -46,6 +46,10 @@ var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames // details. This is used by the default FlagStringer. var FlagEnvHinter FlagEnvHintFunc = withEnvHint +// FlagFileHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagFileHinter FlagFileHintFunc = withFileHint + // FlagsByName is a slice of Flag. type FlagsByName []Flag @@ -625,6 +629,14 @@ func withEnvHint(envVar, str string) string { return str + envText } +func withFileHint(filePath, str string) string { + fileText := "" + if filePath != "" { + fileText = fmt.Sprintf(" [%s]", filePath) + } + return str + fileText +} + func flagValue(f Flag) reflect.Value { fv := reflect.ValueOf(f) for fv.Kind() == reflect.Ptr { @@ -638,14 +650,33 @@ func stringifyFlag(f Flag) string { switch f.(type) { case IntSliceFlag: - return FlagEnvHinter(fv.FieldByName("EnvVar").String(), - stringifyIntSliceFlag(f.(IntSliceFlag))) + return FlagFileHinter( + fv.FieldByName("FilePath").String(), + FlagEnvHinter( + fv.FieldByName("EnvVar").String(), + stringifyIntSliceFlag(f.(IntSliceFlag)), + ), + ) case Int64SliceFlag: - return FlagEnvHinter(fv.FieldByName("EnvVar").String(), - stringifyInt64SliceFlag(f.(Int64SliceFlag))) + // return FlagEnvHinter(fv.FieldByName("EnvVar").String(), + // stringifyInt64SliceFlag(f.(Int64SliceFlag))) + return FlagFileHinter( + fv.FieldByName("FilePath").String(), + FlagEnvHinter( + fv.FieldByName("EnvVar").String(), + stringifyInt64SliceFlag(f.(Int64SliceFlag)), + ), + ) case StringSliceFlag: - return FlagEnvHinter(fv.FieldByName("EnvVar").String(), - stringifyStringSliceFlag(f.(StringSliceFlag))) + // return FlagEnvHinter(fv.FieldByName("EnvVar").String(), + // stringifyStringSliceFlag(f.(StringSliceFlag))) + return FlagFileHinter( + fv.FieldByName("FilePath").String(), + FlagEnvHinter( + fv.FieldByName("EnvVar").String(), + stringifyStringSliceFlag(f.(StringSliceFlag)), + ), + ) } placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) @@ -672,8 +703,13 @@ func stringifyFlag(f Flag) string { usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString)) - return FlagEnvHinter(fv.FieldByName("EnvVar").String(), - fmt.Sprintf("%s\t%s", FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder), usageWithDefault)) + return FlagFileHinter( + fv.FieldByName("FilePath").String(), + FlagEnvHinter( + fv.FieldByName("EnvVar").String(), + fmt.Sprintf("%s\t%s", FlagNamePrefixer(fv.FieldByName("Name").String(), placeholder), usageWithDefault), + ), + ) } func stringifyIntSliceFlag(f IntSliceFlag) string { @@ -727,16 +763,16 @@ func stringifySliceFlag(usage, name string, defaultVals []string) string { } func flagFromFileEnv(filePath, envName string) (val string, ok bool) { + if filePath != "" { + if data, err := ioutil.ReadFile(filePath); err == nil { + return string(data), true + } + } for _, envVar := range strings.Split(envName, ",") { envVar = strings.TrimSpace(envVar) if envVal, ok := syscall.Getenv(envVar); ok { return envVal, true } } - if filePath != "" { - if data, err := ioutil.ReadFile(filePath); err == nil { - return string(data), true - } - } return } diff --git a/flag_test.go b/flag_test.go index 98c2fb9..fb9163b 100644 --- a/flag_test.go +++ b/flag_test.go @@ -1316,7 +1316,7 @@ func TestFlagFromFile(t *testing.T) { {"file-does-not-exist", "APP_BAR", ""}, {"file-does-not-exist", "APP_FOO", "123"}, {"file-does-not-exist", "APP_FOO,APP_BAR", "123"}, - {temp.Name(), "APP_FOO", "123"}, + {temp.Name(), "APP_FOO", "abc"}, {temp.Name(), "APP_BAR", "abc"}, } diff --git a/funcs.go b/funcs.go index b335dbf..0036b11 100644 --- a/funcs.go +++ b/funcs.go @@ -39,3 +39,6 @@ type FlagNamePrefixFunc func(fullName, placeholder string) string // with the environment variable details. type FlagEnvHintFunc func(envVar, str string) string +// FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help +// with the file path details. +type FlagFileHintFunc func(filePath, str string) string