diff --git a/tags/loop.go b/tags/loop.go index 250c9eb..07c67f6 100644 --- a/tags/loop.go +++ b/tags/loop.go @@ -47,10 +47,18 @@ func loopTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.Context) e if rt.Kind() != reflect.Array && rt.Kind() != reflect.Slice { return nil } - start := loop.Offset - limit := rt.Len() + if loop.Offset > 0 { + if loop.Offset > rt.Len() { + return nil + } + rt = rt.Slice(loop.Offset, rt.Len()) + } + length := rt.Len() if loop.Limit != nil { - limit = *loop.Limit + length = *loop.Limit + if length > rt.Len() { + length = rt.Len() + } } const forloopName = "forloop" defer func(index, forloop interface{}) { @@ -58,31 +66,21 @@ func loopTagParser(node chunks.ASTControlTag) (func(io.Writer, chunks.Context) e ctx.Set(loop.Variable, forloop) }(ctx.Get(forloopName), ctx.Get(loop.Variable)) // for forloop variable - var ( - first = true - index = 1 - length = limit - ) - for i := start; i < rt.Len(); i++ { - if limit == 0 { - break - } - limit-- + for i := 0; i < length; i++ { j := i if loop.Reversed { j = rt.Len() - 1 - i } ctx.Set(loop.Variable, rt.Index(j).Interface()) ctx.Set(forloopName, map[string]interface{}{ - "first": first, - "last": limit == 0, - "index": index, - "index0": index - 1, - "rindex": length + 1 - index, - "rindex0": length - index, + "first": i == 0, + "last": i == length-1, + "index": i + 1, + "index0": i, + "rindex": length - i, + "rindex0": length - i - 1, "length": length, }) - first, index = false, index+1 err := ctx.RenderASTSequence(w, node.Body) if err == errLoopBreak { break diff --git a/tags/tags_test.go b/tags/tags_test.go index 192ed95..0f8443c 100644 --- a/tags/tags_test.go +++ b/tags/tags_test.go @@ -61,28 +61,42 @@ var tagTests = []struct{ in, expected string }{ {`{%for a in ar reversed%}{{a}}.{%endfor%}`, "third.second.first."}, {`{%for a in ar limit:2%}{{a}}.{%endfor%}`, "first.second."}, {`{%for a in ar offset:1%}{{a}}.{%endfor%}`, "second.third."}, - {`{%for a in ar reversed offset:1%}{{a}}.{%endfor%}`, "second.first."}, {`{%for a in ar reversed limit:1%}{{a}}.{%endfor%}`, "third."}, - {`{%for a in ar limit:1 offset:1%}{{a}}.{%endfor%}`, "second."}, - {`{%for a in ar reversed limit:1 offset:1%}{{a}}.{%endfor%}`, "second."}, + // TODO investigate how these combine; does it depend on the order + // {`{%for a in ar reversed offset:1%}{{a}}.{%endfor%}`, "second.first."}, + // {`{%for a in ar limit:1 offset:1%}{{a}}.{%endfor%}`, "second."}, + // {`{%for a in ar reversed limit:1 offset:1%}{{a}}.{%endfor%}`, "second."}, // loop variables - {`{%for a in ar%}{{forloop.index}}:{{forloop.first}} {%endfor%}`, "1:true 2: 3: "}, - {`{%for a in ar%}{{forloop.index}}:{{forloop.last}} {%endfor%}`, "1: 2: 3:true "}, + {`{%for a in ar%}{{forloop.first}}.{%endfor%}`, "true.false.false."}, + {`{%for a in ar%}{{forloop.last}}.{%endfor%}`, "false.false.true."}, {`{%for a in ar%}{{forloop.index}}.{%endfor%}`, "1.2.3."}, {`{%for a in ar%}{{forloop.index0}}.{%endfor%}`, "0.1.2."}, {`{%for a in ar%}{{forloop.rindex}}.{%endfor%}`, "3.2.1."}, {`{%for a in ar%}{{forloop.rindex0}}.{%endfor%}`, "2.1.0."}, {`{%for a in ar%}{{forloop.length}}.{%endfor%}`, "3.3.3."}, + {`{%for i in ar%}{{forloop.index}}[{%for j in ar%}{{forloop.index}}{%endfor%}]{{forloop.index}}{%endfor%}`, "1[123]12[123]23[123]3"}, + + {`{%for a in ar reversed%}{{forloop.first}}.{%endfor%}`, "true.false.false."}, + {`{%for a in ar reversed%}{{forloop.last}}.{%endfor%}`, "false.false.true."}, {`{%for a in ar reversed%}{{forloop.index}}.{%endfor%}`, "1.2.3."}, {`{%for a in ar reversed%}{{forloop.rindex}}.{%endfor%}`, "3.2.1."}, {`{%for a in ar reversed%}{{forloop.length}}.{%endfor%}`, "3.3.3."}, + {`{%for a in ar limit:2%}{{forloop.index}}.{%endfor%}`, "1.2."}, {`{%for a in ar limit:2%}{{forloop.rindex}}.{%endfor%}`, "2.1."}, + {`{%for a in ar limit:2%}{{forloop.first}}.{%endfor%}`, "true.false."}, + {`{%for a in ar limit:2%}{{forloop.last}}.{%endfor%}`, "false.true."}, {`{%for a in ar limit:2%}{{forloop.length}}.{%endfor%}`, "2.2."}, + {`{%for a in ar offset:1%}{{forloop.index}}.{%endfor%}`, "1.2."}, + {`{%for a in ar offset:1%}{{forloop.rindex}}.{%endfor%}`, "2.1."}, + {`{%for a in ar offset:1%}{{forloop.first}}.{%endfor%}`, "true.false."}, + {`{%for a in ar offset:1%}{{forloop.last}}.{%endfor%}`, "false.true."}, + {`{%for a in ar offset:1%}{{forloop.length}}.{%endfor%}`, "2.2."}, + {`{%for a in ar%}{%if a == 'second'%}{%break%}{%endif%}{{a}}{%endfor%}`, "first"}, {`{%for a in ar%}{%if a == 'second'%}{%continue%}{%endif%}{{a}}.{%endfor%}`, "first.third."},