Created collections functions namespace for templates

This commit is contained in:
Maxim Lebedev 2023-11-10 09:11:12 +06:00
parent c4dd174c92
commit 79b9d5174d
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
3 changed files with 146 additions and 0 deletions

View File

@ -0,0 +1,96 @@
package collections
import (
"errors"
)
type (
Namespace struct{}
seq struct {
first int
increment int
last int
}
)
func New() *Namespace {
return &Namespace{}
}
var (
ErrSeqFew error = errors.New("seq must have at least one argument")
ErrSeqMany error = errors.New("seq must have no more than three arguments")
ErrSeqZero error = errors.New("seq increment must be not zero")
ErrSeqLess error = errors.New("seq increment must be less than zero")
ErrSeqMore error = errors.New("seq increment must be more than zero")
ErrIndexLess error = errors.New("index is less than zero")
ErrIndexMore error = errors.New("index is more than provided collection size")
)
func (ns *Namespace) Slice(items ...any) []any {
return items
}
func (ns *Namespace) Seq(args ...int) ([]int, error) {
if len(args) < 1 {
return nil, ErrSeqFew
}
if 3 < len(args) {
return nil, ErrSeqMany
}
opts := seq{
first: 1,
increment: 1,
last: args[len(args)-1],
}
switch len(args) {
case 3: // NOTE(toby3d): first, increment, last
opts.increment = args[1]
switch {
case opts.increment == 0:
return nil, ErrSeqZero
case opts.first < opts.last && opts.increment < 0:
return nil, ErrSeqMore
case opts.last < opts.first && 0 < opts.increment:
return nil, ErrSeqMore
}
fallthrough
case 2: // NOTE(toby3d): first, last
opts.first = args[0]
case 1: // NOTE(toby3d): last
if opts.last < 0 {
opts.first = opts.last
opts.last = -1
}
}
out := make([]int, 0)
if opts.first < opts.last {
for i := opts.first; i <= opts.last; i += opts.increment {
out = append(out, i)
}
} else {
for i := opts.first; opts.last <= i; i -= opts.increment {
out = append(out, i)
}
}
return out, nil
}
func (ns *Namespace) Index(collection []any, index int) (any, error) {
if index < 0 {
return nil, ErrIndexLess
} else if len(collection) < index {
return nil, ErrIndexMore
}
return collection[index], nil
}

View File

@ -0,0 +1,39 @@
package collections_test
import (
"testing"
"github.com/google/go-cmp/cmp"
"source.toby3d.me/toby3d/home/internal/templateutil/collections"
)
func TestNamespace_Seq(t *testing.T) {
t.Parallel()
for name, tc := range map[string]struct {
input []int
expect []int
}{
"incremental": {[]int{3}, []int{1, 2, 3}},
"decremental": {[]int{-3}, []int{-3, -2, -1}},
"stepped": {[]int{1, 2, 4}, []int{1, 3}},
"positive-region": {[]int{1, 4}, []int{1, 2, 3, 4}},
"negative-region": {[]int{1, -2}, []int{1, 0, -1, -2}},
} {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
t.Parallel()
actual, err := collections.New().Seq(tc.input...)
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(tc.expect, actual); diff != "" {
t.Error(diff)
}
})
}
}

View File

@ -6,6 +6,7 @@ import (
"io/fs"
"source.toby3d.me/toby3d/home/internal/site"
"source.toby3d.me/toby3d/home/internal/templateutil/collections"
"source.toby3d.me/toby3d/home/internal/templateutil/partials"
"source.toby3d.me/toby3d/home/internal/templateutil/safe"
"source.toby3d.me/toby3d/home/internal/templateutil/strings"
@ -69,6 +70,16 @@ func New(dir fs.FS, siter site.UseCase) (template.FuncMap, error) {
"markdownify": transformNamespace.Markdownify,
},
})
collectionsNamespace := collections.New()
funcs = append(funcs, Function{
Name: "collections",
Handler: func(v ...any) any { return collectionsNamespace },
Methods: template.FuncMap{
"slice": collectionsNamespace.Slice,
"seq": collectionsNamespace.Seq,
"index": collectionsNamespace.Index,
},
})
for _, f := range funcs {
funcMap[f.Name] = f.Handler