ref: 0be2aade99a4e7d16a48cb4372d383a3d1748d10
parent: 358dcce7a6b4a8100964597f81cf371451f6c4d3
author: bep <bjorn.erik.pedersen@gmail.com>
date: Tue Feb 24 05:56:16 EST 2015
Add Seq template func Very similar to GNU's seq. Fixes #552 Conflicts: tpl/template.go
--- a/helpers/general.go
+++ b/helpers/general.go
@@ -19,6 +19,7 @@
"encoding/hex"
"errors"
"fmt"
+ "github.com/spf13/cast"
bp "github.com/spf13/hugo/bufferpool"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
@@ -157,6 +158,74 @@
h := md5.New()
h.Write([]byte(f))
return hex.EncodeToString(h.Sum([]byte{}))+}
+
+// Seq creates a sequence of integers.
+// It's named and used as GNU's seq.
+// Examples:
+// 3 => 1, 2, 3
+// 1 2 4 => 1, 3
+// -3 => -1, -2, -3
+// 1 4 => 1, 2, 3, 4
+// 1 -2 => 1, 0, -1, -2
+func Seq(args ...interface{}) ([]int, error) {+ if len(args) < 1 || len(args) > 3 {+ return nil, errors.New("Seq, invalid number of args: 'first' 'increment' (optional) 'last' (optional)")+ }
+
+ intArgs := cast.ToIntSlice(args)
+
+ var inc int = 1
+ var last int
+ var first = intArgs[0]
+
+ if len(intArgs) == 1 {+ last = first
+ if last == 0 {+ return []int{}, nil+ } else if last > 0 {+ first = 1
+ } else {+ first = -1
+ inc = -1
+ }
+ } else if len(intArgs) == 2 {+ last = intArgs[1]
+ if last < first {+ inc = -1
+ }
+ } else {+ inc = intArgs[1]
+ last = intArgs[2]
+ if inc == 0 {+ return nil, errors.New("'increment' must not be 0")+ }
+ if first < last && inc < 0 {+ return nil, errors.New("'increment' must be > 0")+ }
+ if first > last && inc > 0 {+ return nil, errors.New("'increment' must be < 0")+ }
+ }
+
+ size := int(((last - first) / inc) + 1)
+
+ // sanity check
+ if size > 2000 {+ return nil, errors.New("size of result exeeds limit")+ }
+
+ seq := make([]int, size)
+ val := first
+ for i := 0; ; i++ {+ seq[i] = val
+ val += inc
+ if (inc < 0 && val < last) || (inc > 0 && val > last) {+ break
+ }
+ }
+
+ return seq, nil
}
// DoArithmetic performs arithmetic operations (+,-,*,/) using reflection to
--- a/helpers/general_test.go
+++ b/helpers/general_test.go
@@ -133,6 +133,49 @@
}
}
+func TestSeq(t *testing.T) {+ for i, this := range []struct {+ in []interface{}+ expect interface{}+ }{+ {[]interface{}{-2, 5}, []int{-2, -1, 0, 1, 2, 3, 4, 5}},+ {[]interface{}{1, 2, 4}, []int{1, 3}},+ {[]interface{}{1}, []int{1}},+ {[]interface{}{3}, []int{1, 2, 3}},+ {[]interface{}{3.2}, []int{1, 2, 3}},+ {[]interface{}{0}, []int{}},+ {[]interface{}{-1}, []int{-1}},+ {[]interface{}{-3}, []int{-1, -2, -3}},+ {[]interface{}{3, -2}, []int{3, 2, 1, 0, -1, -2}},+ {[]interface{}{6, -2, 2}, []int{6, 4, 2}},+ {[]interface{}{1, 0, 2}, false},+ {[]interface{}{1, -1, 2}, false},+ {[]interface{}{2, 1, 1}, false},+ {[]interface{}{2, 1, 1, 1}, false},+ {[]interface{}{2001}, false},+ {[]interface{}{}, false},+ {[]interface{}{t}, []int{}},+ {nil, false},+ } {+
+ result, err := Seq(this.in...)
+
+ if b, ok := this.expect.(bool); ok && !b {+ if err == nil {+ t.Errorf("[%d] TestSeq didn't return an expected error %s", i)+ }
+ } else {+ if err != nil {+ t.Errorf("[%d] failed: %s", i, err)+ continue
+ }
+ if !reflect.DeepEqual(result, this.expect) {+ t.Errorf("[%d] TestSeq got %v but expected %v", i, result, this.expect)+ }
+ }
+ }
+}
+
func TestDoArithmetic(t *testing.T) { for i, this := range []struct { a interface{}--- a/tpl/template.go
+++ b/tpl/template.go
@@ -1340,6 +1340,7 @@
"getJson": GetJSON,
"getCSV": GetCSV,
"getCsv": GetCSV,
+ "seq": helpers.Seq,
}
}
--
⑨