From 2fb40ece5df38c3d6565cfd69ae194dbe0126f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 17 Jan 2023 09:35:16 +0100 Subject: tpl/strings: Add findRESubmatch Fixes #10594 --- tpl/internal/templatefuncsRegistry.go | 5 +++++ tpl/strings/init.go | 12 +++++++++++- tpl/strings/regexp.go | 25 +++++++++++++++++++++++++ tpl/strings/regexp_test.go | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) (limited to 'tpl') diff --git a/tpl/internal/templatefuncsRegistry.go b/tpl/internal/templatefuncsRegistry.go index da9aa5d29..84e0e25fa 100644 --- a/tpl/internal/templatefuncsRegistry.go +++ b/tpl/internal/templatefuncsRegistry.go @@ -66,6 +66,11 @@ func (t *TemplateFuncsNamespace) AddMethodMapping(m any, aliases []string, examp name := methodToName(m) + // Rewrite §§ to ` in example commands. + for i, e := range examples { + examples[i][0] = strings.ReplaceAll(e[0], "§§", "`") + } + // sanity check for _, e := range examples { if e[0] == "" { diff --git a/tpl/strings/init.go b/tpl/strings/init.go index 0a4d87762..503ec6a25 100644 --- a/tpl/strings/init.go +++ b/tpl/strings/init.go @@ -78,12 +78,22 @@ func init() { []string{"findRE"}, [][2]string{ { - `{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`, + `{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." 1 }}`, `[go]`, }, }, ) + ns.AddMethodMapping(ctx.FindRESubmatch, + []string{"findRESubmatch"}, + [][2]string{ + { + `{{ findRESubmatch §§(.+?)§§ §§
  • Foo
  • Bar
  • §§ | print | safeHTML }}`, + "[[Foo #foo Foo] [Bar #bar Bar]]", + }, + }, + ) + ns.AddMethodMapping(ctx.HasPrefix, []string{"hasPrefix"}, [][2]string{ diff --git a/tpl/strings/regexp.go b/tpl/strings/regexp.go index 5b6a812d4..84b015ffb 100644 --- a/tpl/strings/regexp.go +++ b/tpl/strings/regexp.go @@ -45,6 +45,31 @@ func (ns *Namespace) FindRE(expr string, content any, limit ...any) ([]string, e return re.FindAllString(conv, lim), nil } +// FindRESubmatch returns returns a slice of strings holding the text of the leftmost match of the regular expression in s and the matches, if any, of its subexpressions. +// +// By default all matches will be included. The number of matches can be limited with the optional limit parameter. A return value of nil indicates no match. +func (ns *Namespace) FindRESubmatch(expr string, content any, limit ...any) ([][]string, error) { + re, err := reCache.Get(expr) + if err != nil { + return nil, err + } + + conv, err := cast.ToStringE(content) + if err != nil { + return nil, err + } + n := -1 + if len(limit) > 0 { + n, err = cast.ToIntE(limit[0]) + if err != nil { + return nil, err + } + } + + return re.FindAllStringSubmatch(conv, n), nil + +} + // ReplaceRE returns a copy of s, replacing all matches of the regular // expression pattern with the replacement text repl. The number of replacements // can be limited with an optional fourth parameter. diff --git a/tpl/strings/regexp_test.go b/tpl/strings/regexp_test.go index 9ac098c17..b6ec5cb9e 100644 --- a/tpl/strings/regexp_test.go +++ b/tpl/strings/regexp_test.go @@ -50,6 +50,39 @@ func TestFindRE(t *testing.T) { } } +func TestFindRESubmatch(t *testing.T) { + t.Parallel() + c := qt.New(t) + + for _, test := range []struct { + expr string + content any + limit any + expect any + }{ + {`(.+?)`, `
  • Foo
  • Bar
  • `, -1, [][]string{ + {"Foo", "#foo", "Foo"}, + {"Bar", "#bar", "Bar"}, + }}, + // Some simple cases. + {"([G|g]o)", "Hugo is a static site generator written in Go.", -1, [][]string{{"go", "go"}, {"Go", "Go"}}}, + {"([G|g]o)", "Hugo is a static site generator written in Go.", 1, [][]string{{"go", "go"}}}, + + // errors + {"([G|go", "Hugo is a static site generator written in Go.", nil, false}, + {"([G|g]o)", t, nil, false}, + } { + result, err := ns.FindRESubmatch(test.expr, test.content, test.limit) + + if b, ok := test.expect.(bool); ok && !b { + c.Assert(err, qt.Not(qt.IsNil)) + continue + } + + c.Assert(err, qt.IsNil) + c.Check(result, qt.DeepEquals, test.expect) + } +} func TestReplaceRE(t *testing.T) { t.Parallel() c := qt.New(t) -- cgit v1.2.3