Allow defaults for template parameter
This commit is contained in:
parent
1a9ef8b7c9
commit
ee2a188be8
2 changed files with 71 additions and 16 deletions
|
|
@ -9,12 +9,13 @@ import (
|
||||||
type Replacer interface {
|
type Replacer interface {
|
||||||
// RegisterTemplate registers a template for a specific placeholder. Template
|
// RegisterTemplate registers a template for a specific placeholder. Template
|
||||||
// may contain placeholders as well of the form {name}. They will be replaced
|
// may contain placeholders as well of the form {name}. They will be replaced
|
||||||
// by the parameters of the placeholder (see Replace).
|
// by the parameters of the placeholder (see Replace). If a parameter is not of
|
||||||
RegisterTemplate(placeholder, template string)
|
// a template is not present, default values can be provided.
|
||||||
|
RegisterTemplate(placeholder, template string, defaults map[string]string)
|
||||||
|
|
||||||
// RegisterTemplateFunc does the same as RegisterTemplate, but the template
|
// RegisterTemplateFunc does the same as RegisterTemplate, but the template
|
||||||
// is returned by the template function.
|
// is returned by the template function.
|
||||||
RegisterTemplateFunc(placeholder string, template func() string)
|
RegisterTemplateFunc(placeholder string, template func() string, defaults map[string]string)
|
||||||
|
|
||||||
// Replace replaces all occurences of placeholder in str with value. The placeholder is of the
|
// Replace replaces all occurences of placeholder in str with value. The placeholder is of the
|
||||||
// form {placeholder}. It is possible to escape a characters in value with \\ by appending a ^
|
// form {placeholder}. It is possible to escape a characters in value with \\ by appending a ^
|
||||||
|
|
@ -28,8 +29,13 @@ type Replacer interface {
|
||||||
Replace(str, placeholder, value string) string
|
Replace(str, placeholder, value string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type template struct {
|
||||||
|
fn func() string
|
||||||
|
defaults map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
type replacer struct {
|
type replacer struct {
|
||||||
templates map[string]func() string
|
templates map[string]template
|
||||||
|
|
||||||
re *regexp.Regexp
|
re *regexp.Regexp
|
||||||
templateRe *regexp.Regexp
|
templateRe *regexp.Regexp
|
||||||
|
|
@ -38,7 +44,7 @@ type replacer struct {
|
||||||
// New returns a Replacer
|
// New returns a Replacer
|
||||||
func New() Replacer {
|
func New() Replacer {
|
||||||
r := &replacer{
|
r := &replacer{
|
||||||
templates: make(map[string]func() string),
|
templates: make(map[string]template),
|
||||||
re: regexp.MustCompile(`{([a-z]+)(?:\^(.))?(?:,(.*?))?}`),
|
re: regexp.MustCompile(`{([a-z]+)(?:\^(.))?(?:,(.*?))?}`),
|
||||||
templateRe: regexp.MustCompile(`{([a-z]+)}`),
|
templateRe: regexp.MustCompile(`{([a-z]+)}`),
|
||||||
}
|
}
|
||||||
|
|
@ -46,12 +52,18 @@ func New() Replacer {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *replacer) RegisterTemplate(placeholder, template string) {
|
func (r *replacer) RegisterTemplate(placeholder, tmpl string, defaults map[string]string) {
|
||||||
r.templates[placeholder] = func() string { return template }
|
r.templates[placeholder] = template{
|
||||||
|
fn: func() string { return tmpl },
|
||||||
|
defaults: defaults,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *replacer) RegisterTemplateFunc(placeholder string, template func() string) {
|
func (r *replacer) RegisterTemplateFunc(placeholder string, tmplFn func() string, defaults map[string]string) {
|
||||||
r.templates[placeholder] = template
|
r.templates[placeholder] = template{
|
||||||
|
fn: tmplFn,
|
||||||
|
defaults: defaults,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *replacer) Replace(str, placeholder, value string) string {
|
func (r *replacer) Replace(str, placeholder, value string) string {
|
||||||
|
|
@ -63,16 +75,20 @@ func (r *replacer) Replace(str, placeholder, value string) string {
|
||||||
|
|
||||||
// We need a copy from the value
|
// We need a copy from the value
|
||||||
v := value
|
v := value
|
||||||
|
var tmpl template = template{
|
||||||
|
fn: func() string { return v },
|
||||||
|
}
|
||||||
|
|
||||||
// Check for a registered template
|
// Check for a registered template
|
||||||
if len(v) == 0 {
|
if len(v) == 0 {
|
||||||
tmplFunc, ok := r.templates[placeholder]
|
t, ok := r.templates[placeholder]
|
||||||
if ok {
|
if ok {
|
||||||
v = tmplFunc()
|
tmpl = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v = r.compileTemplate(v, matches[3])
|
v = tmpl.fn()
|
||||||
|
v = r.compileTemplate(v, matches[3], tmpl.defaults)
|
||||||
|
|
||||||
if len(matches[2]) != 0 {
|
if len(matches[2]) != 0 {
|
||||||
// If there's a character to escape, we also have to escape the
|
// If there's a character to escape, we also have to escape the
|
||||||
|
|
@ -97,13 +113,18 @@ func (r *replacer) Replace(str, placeholder, value string) string {
|
||||||
// placeholder name and will be replaced with the value. The resulting string is "Hello World!".
|
// placeholder name and will be replaced with the value. The resulting string is "Hello World!".
|
||||||
// If a placeholder name is not present in the params string, it will not be replaced. The key
|
// If a placeholder name is not present in the params string, it will not be replaced. The key
|
||||||
// and values can be escaped as in net/url.QueryEscape.
|
// and values can be escaped as in net/url.QueryEscape.
|
||||||
func (r *replacer) compileTemplate(str, params string) string {
|
func (r *replacer) compileTemplate(str, params string, defaults map[string]string) string {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 && len(defaults) == 0 {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
p := make(map[string]string)
|
p := make(map[string]string)
|
||||||
|
|
||||||
|
// Copy the defaults
|
||||||
|
for key, value := range defaults {
|
||||||
|
p[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
// taken from net/url.ParseQuery
|
// taken from net/url.ParseQuery
|
||||||
for params != "" {
|
for params != "" {
|
||||||
var key string
|
var key string
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func TestReplace(t *testing.T) {
|
||||||
|
|
||||||
func TestReplaceTemplate(t *testing.T) {
|
func TestReplaceTemplate(t *testing.T) {
|
||||||
r := New()
|
r := New()
|
||||||
r.RegisterTemplate("foobar", "Hello {who}! {what}?")
|
r.RegisterTemplate("foobar", "Hello {who}! {what}?", nil)
|
||||||
|
|
||||||
replaced := r.Replace("{foobar,who=World}", "foobar", "")
|
replaced := r.Replace("{foobar,who=World}", "foobar", "")
|
||||||
require.Equal(t, "Hello World! {what}?", replaced)
|
require.Equal(t, "Hello World! {what}?", replaced)
|
||||||
|
|
@ -46,6 +46,20 @@ func TestReplaceTemplate(t *testing.T) {
|
||||||
require.Equal(t, "Hello World! E=mc\\\\:2?", replaced)
|
require.Equal(t, "Hello World! E=mc\\\\:2?", replaced)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReplaceTemplateDefaults(t *testing.T) {
|
||||||
|
r := New()
|
||||||
|
r.RegisterTemplate("foobar", "Hello {who}! {what}?", map[string]string{
|
||||||
|
"who": "someone",
|
||||||
|
"what": "something",
|
||||||
|
})
|
||||||
|
|
||||||
|
replaced := r.Replace("{foobar}", "foobar", "")
|
||||||
|
require.Equal(t, "Hello someone! something?", replaced)
|
||||||
|
|
||||||
|
replaced = r.Replace("{foobar,who=World}", "foobar", "")
|
||||||
|
require.Equal(t, "Hello World! something?", replaced)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReplaceCompileTemplate(t *testing.T) {
|
func TestReplaceCompileTemplate(t *testing.T) {
|
||||||
samples := [][3]string{
|
samples := [][3]string{
|
||||||
{"Hello {who}!", "who=World", "Hello World!"},
|
{"Hello {who}!", "who=World", "Hello World!"},
|
||||||
|
|
@ -58,7 +72,27 @@ func TestReplaceCompileTemplate(t *testing.T) {
|
||||||
r := New().(*replacer)
|
r := New().(*replacer)
|
||||||
|
|
||||||
for _, e := range samples {
|
for _, e := range samples {
|
||||||
replaced := r.compileTemplate(e[0], e[1])
|
replaced := r.compileTemplate(e[0], e[1], nil)
|
||||||
|
require.Equal(t, e[2], replaced, e[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReplaceCompileTemplateDefaults(t *testing.T) {
|
||||||
|
samples := [][3]string{
|
||||||
|
{"Hello {who}!", "", "Hello someone!"},
|
||||||
|
{"Hello {who}!", "who=World", "Hello World!"},
|
||||||
|
{"Hello {who}! {what}?", "who=World", "Hello World! something?"},
|
||||||
|
{"Hello {who}! {what}?", "who=World,what=Yeah", "Hello World! Yeah?"},
|
||||||
|
{"Hello {who}! {what}?", "who=World,what=", "Hello World! ?"},
|
||||||
|
}
|
||||||
|
|
||||||
|
r := New().(*replacer)
|
||||||
|
|
||||||
|
for _, e := range samples {
|
||||||
|
replaced := r.compileTemplate(e[0], e[1], map[string]string{
|
||||||
|
"who": "someone",
|
||||||
|
"what": "something",
|
||||||
|
})
|
||||||
require.Equal(t, e[2], replaced, e[0])
|
require.Equal(t, e[2], replaced, e[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue