From 73ecfde9b28305995191db7d69e1c1990c7844e9 Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Wed, 19 Feb 2020 15:49:59 +1100 Subject: [PATCH] Automatically add envar to help. See #57. --- README.md | 5 +++++ interpolate.go | 11 +++++++++++ kong.go | 13 +++++++++++++ kong_test.go | 11 +++++++++++ 4 files changed, 40 insertions(+) diff --git a/README.md b/README.md index f0f519b..a96c059 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,10 @@ eg. -f, --force Force removal. -r, --recursive Recursively remove files. +For flags with associated environment variables, the variable `${env}` can be +interpolated into the help string. In the absence of this variable in the help, + + ## Command handling @@ -459,6 +463,7 @@ are defined from the value itself: ${default} ${enum} + ${env} eg. diff --git a/interpolate.go b/interpolate.go index 9de1ff7..bbfff54 100644 --- a/interpolate.go +++ b/interpolate.go @@ -7,6 +7,17 @@ import ( var interpolationRegex = regexp.MustCompile(`((?:\${([[:alpha:]_][[:word:]]*))(?:=([^}]+))?})|(\$)|([^$]+)`) +// Returns true if the variable "v" is interpolated in "s". +func interpolationHasVar(s string, v string) bool { + matches := interpolationRegex.FindAllStringSubmatch(s, -1) + for _, match := range matches { + if name := match[2]; name == v { + return true + } + } + return false +} + // Interpolate variables from vars into s for substrings in the form ${var} or ${var=default}. func interpolate(s string, vars map[string]string) (string, error) { out := "" diff --git a/kong.go b/kong.go index 64cd407..5296ef2 100644 --- a/kong.go +++ b/kong.go @@ -155,6 +155,19 @@ func (k *Kong) interpolateValue(value *Value, vars Vars) (err error) { }) if value.Tag.Env != "" { vars["env"] = value.Tag.Env + if !interpolationHasVar(value.Help, "env") { + suffix := "($" + value.Tag.Env + ")" + switch { + case strings.HasSuffix(value.Help, "."): + value.Help = value.Help[:len(value.Help)-1] + " " + suffix + "." + + case value.Help == "": + value.Help += suffix + + default: + value.Help += " " + suffix + } + } } if value.Help, err = interpolate(value.Help, vars); err != nil { return fmt.Errorf("help for %s: %s", value.Summary(), err) diff --git a/kong_test.go b/kong_test.go index b55093a..087252a 100644 --- a/kong_test.go +++ b/kong_test.go @@ -750,6 +750,17 @@ func TestEnvarEnumValidated(t *testing.T) { require.EqualError(t, err, "--flag must be one of \"valid\" but got \"invalid\"") } +func TestEnvarAutoHelp(t *testing.T) { + var cli struct { + Flag string `env:"FLAG" help:"A flag."` + } + w := &strings.Builder{} + p := mustNew(t, &cli, kong.Writers(w, w), kong.Exit(func(int) {})) + _, err := p.Parse([]string{"--help"}) + require.NoError(t, err) + require.Contains(t, w.String(), "A flag ($FLAG).") +} + func TestXor(t *testing.T) { var cli struct { Hello bool `xor:"another"`