✨ Created collections functions namespace for templates
This commit is contained in:
parent
c4dd174c92
commit
79b9d5174d
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue