Skip to content

Commit b975919

Browse files
authored
Merge pull request #93 from codykrieger/cjk/for-else
implement support for else clauses in for loops. fixes #46
2 parents fc47b0b + a9b2aa0 commit b975919

File tree

3 files changed

+33
-17
lines changed

3 files changed

+33
-17
lines changed

tags/iteration_tags.go

+29-16
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,42 @@ func loopTagCompiler(node render.BlockNode) (func(io.Writer, render.Context) err
6767
if err != nil {
6868
return nil, err
6969
}
70-
return loopRenderer{stmt.Loop, node.Name}.render, nil
70+
71+
return func(w io.Writer, ctx render.Context) error {
72+
// loop modifiers
73+
val, err := ctx.Evaluate(stmt.Loop.Expr)
74+
if err != nil {
75+
return err
76+
}
77+
78+
iter := makeIterator(val)
79+
if iter == nil {
80+
return nil
81+
}
82+
83+
iter, err = applyLoopModifiers(stmt.Loop, ctx, iter)
84+
if err != nil {
85+
return err
86+
}
87+
88+
if len(node.Clauses) > 1 {
89+
return fmt.Errorf("for loops accept at most one else clause")
90+
}
91+
92+
if iter.Len() == 0 && len(node.Clauses) == 1 && node.Clauses[0].Name == "else" {
93+
return ctx.RenderBlock(w, node.Clauses[0])
94+
}
95+
96+
return loopRenderer{stmt.Loop, node.Name}.render(iter, w, ctx)
97+
}, nil
7198
}
7299

73100
type loopRenderer struct {
74101
expressions.Loop
75102
tagName string
76103
}
77104

78-
func (loop loopRenderer) render(w io.Writer, ctx render.Context) error {
79-
// loop modifiers
80-
val, err := ctx.Evaluate(loop.Expr)
81-
if err != nil {
82-
return err
83-
}
84-
iter := makeIterator(val)
85-
if iter == nil {
86-
return nil
87-
}
88-
iter, err = applyLoopModifiers(loop.Loop, ctx, iter)
89-
if err != nil {
90-
return err
91-
}
92-
105+
func (loop loopRenderer) render(iter iterable, w io.Writer, ctx render.Context) error {
93106
// loop decorator
94107
decorator, err := makeLoopDecorator(loop, ctx)
95108
if err != nil {

tags/iteration_tags_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717

1818
var iterationTests = []struct{ in, expected string }{
1919
{`{% for a in array %}{{ a }} {% endfor %}`, "first second third "},
20+
{`{% for a in array %}{{ a }} {% else %}else{% endfor %}`, "first second third "},
2021
{`{% for a in nil %}{{ a }}.{% endfor %}`, ""},
2122
{`{% for a in false %}{{ a }}.{% endfor %}`, ""},
2223
{`{% for a in 2 %}{{ a }}.{% endfor %}`, ""},
@@ -37,6 +38,7 @@ var iterationTests = []struct{ in, expected string }{
3738
{`{% for a in array offset: loopmods["offset"] %}{{ a }}.{% endfor %}`, "second.third."},
3839
{`{% for a in array reversed limit: 1 %}{{ a }}.{% endfor %}`, "third."},
3940
{`{% for a in array limit: 0 %}{{ a }}.{% endfor %}`, ""},
41+
{`{% for a in array limit: 0 %}{{ a }}.{% else %}ELSE{% endfor %}`, "ELSE"},
4042
{`{% for a in array offset: 3 %}{{ a }}.{% endfor %}`, ""},
4143
{`{% for a in array offset: 10 %}{{ a }}.{% endfor %}`, ""},
4244
// TODO investigate how these combine; does it depend on the order?
@@ -126,6 +128,7 @@ var iterationErrorTests = []struct{ in, expected string }{
126128
{`{% cycle 'a', 'b' %}`, "cycle must be within a forloop"},
127129
{`{% for a in array | undefined_filter %}{% endfor %}`, "undefined filter"},
128130
{`{% for a in array %}{{ a | undefined_filter }}{% endfor %}`, "undefined filter"},
131+
{`{% for a in array %}{% else %}{% else %}{% endfor %}`, "for loops accept at most one else clause"},
129132
}
130133

131134
var iterationTestBindings = map[string]interface{}{

tags/standard_tags.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func AddStandardTags(c render.Config) {
2222
c.AddBlock("capture").Compiler(captureTagCompiler)
2323
c.AddBlock("case").Clause("when").Clause("else").Compiler(caseTagCompiler)
2424
c.AddBlock("comment")
25-
c.AddBlock("for").Compiler(loopTagCompiler)
25+
c.AddBlock("for").Clause("else").Compiler(loopTagCompiler)
2626
c.AddBlock("if").Clause("else").Clause("elsif").Compiler(ifTagCompiler(true))
2727
c.AddBlock("raw")
2828
c.AddBlock("tablerow").Compiler(loopTagCompiler)

0 commit comments

Comments
 (0)