Repository: CloudyKit/jet (go)

Issue:
For-loop or range between some ints
Hi!

I wanted to range over a particular set of ints (for-loop like behavior) but I don't seem to see it supported in jet wiki.

Example: 
```
{{ startInt, endInt := getNavRange(context) }}
{{ range i := startInt...endInt }}
<a href="?page={{i}}">Page {{i}}</a>
{{ end }} 
```

I know there is the work around to create a slice of ints and range over it, but it's less efficient (variable allocations, unnecessary slice, ...). So I would like to know if it's supported but not documented.

Pull request description:
introduce ints() built-in function
Closes #81.

Patch:
diff --git a/default.go b/default.go
index 19d1ef0..939f60b 100644
--- a/default.go
+++ b/default.go
@@ -16,6 +16,7 @@ package jet
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"html"
 	"io"
@@ -135,6 +136,18 @@ func init() {
 
 			return result
 		})),
+		"ints": reflect.ValueOf(Func(func(a Arguments) (result reflect.Value) {
+			var from, to int
+			err := a.ParseInto(&from, &to)
+			if err != nil {
+				panic(err)
+			}
+			// check to > from
+			if to <= from {
+				panic(errors.New("invalid range for ints ranger: 'from' must be smaller than 'to'"))
+			}
+			return reflect.ValueOf(&intsRanger{from: from, to: to})
+		})),
 	}
 }
 
@@ -175,3 +188,18 @@ func newMap(values ...interface{}) (nmap map[string]interface{}) {
 	}
 	return
 }
+
+type intsRanger struct {
+	i, from, to int
+}
+
+// implements Ranger type
+var _ Ranger = &intsRanger{}
+
+func (ir *intsRanger) Range() (index, value reflect.Value, end bool) {
+	index = reflect.ValueOf(ir.i)
+	value = reflect.ValueOf(ir.from + ir.i)
+	end = ir.i == ir.to-ir.from
+	ir.i++
+	return
+}


Test patch:
diff --git a/eval_test.go b/eval_test.go
index d282a92..1939bf2 100644
--- a/eval_test.go
+++ b/eval_test.go
@@ -642,6 +642,10 @@ func TestTryCatch(t *testing.T) {
 	RunJetTestWithSet(t, set, nil, nil, "try_include", "", "before broken include ...\n\nafter broken include ...")
 }
 
+func TestIntsRanger(t *testing.T) {
+	RunJetTest(t, nil, nil, "ints_ranger", `{{ range i := ints(0, 10) }}{{ (i == 0 ? "" : ", ") + i }}{{ end }}`, "0, 1, 2, 3, 4, 5, 6, 7, 8, 9")
+}
+
 func BenchmarkSimpleAction(b *testing.B) {
 	t, _ := JetTestingSet.GetTemplate("actionNode_dummy")
 	for i := 0; i < b.N; i++ {