diff --git a/kong.go b/kong.go index 14f5c2d..d8be43a 100644 --- a/kong.go +++ b/kong.go @@ -183,6 +183,9 @@ func (k *Kong) interpolateValue(value *Value, vars Vars) (err error) { if len(value.Tag.Vars) > 0 { vars = vars.CloneWith(value.Tag.Vars) } + if varsContributor, ok := value.Mapper.(VarsContributor); ok { + vars = vars.CloneWith(varsContributor.Vars(value)) + } if value.Default, err = interpolate(value.Default, vars, nil); err != nil { return fmt.Errorf("default value for %s: %s", value.Summary(), err) } diff --git a/mapper.go b/mapper.go index 657b8ee..88fe1a5 100644 --- a/mapper.go +++ b/mapper.go @@ -115,6 +115,11 @@ type Mapper interface { Decode(ctx *DecodeContext, target reflect.Value) error } +// VarsContributor can be implemented by a Mapper to contribute Vars during interpolation. +type VarsContributor interface { + Vars(ctx *Value) Vars +} + // A BoolMapper is a Mapper to a value that is a boolean. // // This is used solely for formatting help. diff --git a/mapper_test.go b/mapper_test.go index 3f9b87a..8263b0d 100644 --- a/mapper_test.go +++ b/mapper_test.go @@ -464,3 +464,34 @@ func (t testMapperWithPlaceHolder) Decode(ctx *kong.DecodeContext, target reflec func (t testMapperWithPlaceHolder) PlaceHolder(flag *kong.Flag) string { return "/a/b/c" } + +func TestMapperVarsContributor(t *testing.T) { + var cli struct { + Flag string `help:"Some help with ${avar}"` + } + b := bytes.NewBuffer(nil) + k := mustNew( + t, + &cli, + kong.Writers(b, b), + kong.ValueMapper(&cli.Flag, testMapperVarsContributor{}), + kong.Exit(func(int) { panic("exit") }), + ) + // Ensure that --help + require.Panics(t, func() { + _, err := k.Parse([]string{"--help"}) + require.NoError(t, err) + }) + require.Regexp(t, "--flag=STRING\\s+Some help with a var", b.String()) +} + +type testMapperVarsContributor struct{} + +func (t testMapperVarsContributor) Vars(value *kong.Value) kong.Vars { + return kong.Vars{"avar": "a var"} +} + +func (t testMapperVarsContributor) Decode(ctx *kong.DecodeContext, target reflect.Value) error { + target.SetString("hi") + return nil +}