Skip to content

Commit

Permalink
fine tune Expand behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
wxiaoguang committed Mar 31, 2022
1 parent d99b308 commit b9c1142
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 29 deletions.
15 changes: 10 additions & 5 deletions modules/templates/vars/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package vars
import (
"fmt"
"strings"
"unicode"
"unicode/utf8"
)

// ErrWrongSyntax represents a wrong syntax with a tempate
Expand Down Expand Up @@ -40,9 +42,11 @@ func IsErrNoMatchedVar(err error) bool {
return ok
}

// Expand replaces all variables like {var} to match, if error occurs, the error part doesn't change and is returned as it is.
// `#' is a reversed char, templates can use `{#{}` to do escape and output char '{'.
// Expand replaces all variables like {var} to match, if error occurs,
// the error part doesn't change and is returned as it is.
func Expand(template string, match map[string]string) (string, error) {
// in the future, if necessary, we can introduce some escape-char,
// for example: it will use `#' as a reversed char, templates will use `{#{}` to do escape and output char '{'.
var buf strings.Builder
var err error

Expand Down Expand Up @@ -84,9 +88,10 @@ func Expand(template string, match map[string]string) (string, error) {
} else {
// now we get a valid key "{...}"
key := part[1 : len(part)-1]
if key[0] == '#' {
// escaped char
buf.WriteString(key[1:])
keyFirst, _ := utf8.DecodeRuneInString(key)
if unicode.IsSpace(keyFirst) || unicode.IsPunct(keyFirst) || unicode.IsControl(keyFirst) {
// the if key doesn't start with a letter, then we do not treat it as a var now
buf.WriteString(part)
} else {
// look up in the map
if val, ok := match[key]; ok {
Expand Down
48 changes: 24 additions & 24 deletions modules/templates/vars/vars_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,61 +12,61 @@ import (

func TestExpandVars(t *testing.T) {
kases := []struct {
template string
maps map[string]string
expected string
fail bool
tmpl string
data map[string]string
out string
error bool
}{
{
template: "{a}",
maps: map[string]string{
tmpl: "{a}",
data: map[string]string{
"a": "1",
},
expected: "1",
out: "1",
},
{
template: "expand {a}, {b} and {c}, with escaped {#{}",
maps: map[string]string{
tmpl: "expand {a}, {b} and {c}, with non-var { } {#}",
data: map[string]string{
"a": "1",
"b": "2",
"c": "3",
},
expected: "expand 1, 2 and 3, with escaped {",
out: "expand 1, 2 and 3, with non-var { } {#}",
},
{
template: "中文内容 {一}, {二} 和 {三} 中文结尾",
maps: map[string]string{
tmpl: "中文内容 {一}, {二} 和 {三} 中文结尾",
data: map[string]string{
"一": "11",
"二": "22",
"三": "33",
},
expected: "中文内容 11, 22 和 33 中文结尾",
out: "中文内容 11, 22 和 33 中文结尾",
},
{
template: "expand {{a}, {b} and {c}",
maps: map[string]string{
tmpl: "expand {{a}, {b} and {c}",
data: map[string]string{
"a": "foo",
"b": "bar",
},
expected: "expand {{a}, bar and {c}",
fail: true,
out: "expand {{a}, bar and {c}",
error: true,
},
{
template: "expand } {} and {",
expected: "expand } {} and {",
fail: true,
tmpl: "expand } {} and {",
out: "expand } {} and {",
error: true,
},
}

for _, kase := range kases {
t.Run(kase.template, func(t *testing.T) {
res, err := Expand(kase.template, kase.maps)
if kase.fail {
t.Run(kase.tmpl, func(t *testing.T) {
res, err := Expand(kase.tmpl, kase.data)
if kase.error {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
assert.EqualValues(t, kase.expected, res)
assert.EqualValues(t, kase.out, res)
})
}
}

0 comments on commit b9c1142

Please sign in to comment.