diff --git a/README.md b/README.md index ccbbf7d..e8294c4 100644 --- a/README.md +++ b/README.md @@ -416,10 +416,11 @@ default values. Variables are in the form: ${} + ${=} Variables are set with the `Vars{"key": "value", ...}` option. Undefined -variable references in the grammar will result in an error at construction -time. +variable references in the grammar without a default will result in an error at +construction time. Variables can also be set via the `set:"K=V"` tag. In this case, those variables will be available for that node and all children. This is useful for composition by allowing the same struct to be reused. diff --git a/interpolate.go b/interpolate.go index 296f9a4..9de1ff7 100644 --- a/interpolate.go +++ b/interpolate.go @@ -5,18 +5,21 @@ import ( "regexp" ) -var interpolationRegex = regexp.MustCompile(`(\${[[:alpha:]_][[:word:]]*})|(\$)|([^$]+)`) +var interpolationRegex = regexp.MustCompile(`((?:\${([[:alpha:]_][[:word:]]*))(?:=([^}]+))?})|(\$)|([^$]+)`) -// Interpolate variables from vars into s for substrings in the form ${var}. +// 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 := "" matches := interpolationRegex.FindAllStringSubmatch(s, -1) for _, match := range matches { - if match[1] != "" { - name := match[1][2 : len(match[1])-1] + if name := match[2]; name != "" { value, ok := vars[name] if !ok { - return "", fmt.Errorf("undefined variable ${%s}", name) + // No default value. + if match[3] == "" { + return "", fmt.Errorf("undefined variable ${%s}", name) + } + value = match[3] } out += value } else { diff --git a/interpolate_test.go b/interpolate_test.go index f049e38..a2c9df1 100644 --- a/interpolate_test.go +++ b/interpolate_test.go @@ -8,10 +8,9 @@ import ( func TestInterpolate(t *testing.T) { vars := map[string]string{ - "name": "Bobby Brown", - "age": "35", + "age": "35", } - actual, err := interpolate("${name} is ${age} years old", vars) + actual, err := interpolate("${name=Bobby Brown} is ${age} years old", vars) require.NoError(t, err) require.Equal(t, `Bobby Brown is 35 years old`, actual) }