diff options
author | Rob Pike <r@golang.org> | 2009-04-27 21:04:46 -0700 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2009-04-27 21:04:46 -0700 |
commit | 4b69a278bf554e8bc1f49ccb47f789ad9f9dc084 (patch) | |
tree | 432c642c06d5c62d0397c43cac214978a32a937a | |
parent | 5ac70968962dc2240ff9f4f8dda4a68034137f4d (diff) | |
download | golang-4b69a278bf554e8bc1f49ccb47f789ad9f9dc084.tar.gz |
implement .alternates
R=rsc
OCL=27928
CL=27928
-rw-r--r-- | src/lib/template/template.go | 30 | ||||
-rw-r--r-- | src/lib/template/template_test.go | 14 |
2 files changed, 40 insertions, 4 deletions
diff --git a/src/lib/template/template.go b/src/lib/template/template.go index 1676a8fdd..c6957d4de 100644 --- a/src/lib/template/template.go +++ b/src/lib/template/template.go @@ -36,7 +36,6 @@ is executed for each element. If the array is nil or empty, YYY is executed instead. If the {.alternates with} marker is present, ZZZ is executed between iterations of XXX. - (TODO(r): .alternates is not yet implemented) {field} {field|formatter} @@ -132,9 +131,11 @@ type sectionElement struct { end int; // one beyond last element } -// A .repeated block, possibly with a .or. TODO(r): .alternates +// A .repeated block, possibly with a .or and a .alternates type repeatedElement struct { - sectionElement; // It has the same structure! + sectionElement; // It has the same structure... + altstart int; // ... except for alternates + altend int; } // Template is the type that represents a template definition. @@ -438,6 +439,8 @@ func (t *Template) parseRepeated(words []string) *repeatedElement { // Scan section, collecting true and false (.or) blocks. r.start = t.elems.Len(); r.or = -1; + r.altstart = -1; + r.altend = -1; Loop: for { item := t.nextItem(); @@ -455,17 +458,27 @@ Loop: if r.or >= 0 { t.parseError("extra .or in .repeated section"); } + r.altend = t.elems.Len(); r.or = t.elems.Len(); case tokSection: t.parseSection(w); case tokRepeated: t.parseRepeated(w); case tokAlternates: - t.parseError("internal error: .alternates not implemented"); + if r.altstart >= 0 { + t.parseError("extra .alternates in .repeated section"); + } + if r.or >= 0 { + t.parseError(".alternates inside .or block in .repeated section"); + } + r.altstart = t.elems.Len(); default: t.parseError("internal error: unknown repeated section item: %s", item); } } + if r.altend < 0 { + r.altend = t.elems.Len() + } r.end = t.elems.Len(); return r; } @@ -693,6 +706,9 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) { if end < 0 { end = r.end } + if r.altstart >= 0 { + end = r.altstart + } if field != nil { array := field.(reflect.ArrayValue); for j := 0; j < array.Len(); j++ { @@ -700,6 +716,12 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) { for i := start; i < end; { i = t.executeElement(i, newst) } + // If appropriate, do .alternates between elements + if j < array.Len() - 1 && r.altstart >= 0 { + for i := r.altstart; i < r.altend; i++ { + i = t.executeElement(i, newst) + } + } } } } diff --git a/src/lib/template/template_test.go b/src/lib/template/template_test.go index cacc4404f..fb931615e 100644 --- a/src/lib/template/template_test.go +++ b/src/lib/template/template_test.go @@ -183,6 +183,20 @@ var tests = []*Test { "this should appear: empty field\n" }, + &Test{ + "{.section pdata }\n" + "{.repeated section @ }\n" + "{item}={value}\n" + "{.alternates with}DIVIDER\n" + "{.or}\n" + "this should not appear\n" + "{.end}\n" + "{.end}\n", + + "ItemNumber1=ValueNumber1\n" + "DIVIDER\n" + "ItemNumber2=ValueNumber2\n" + }, // Formatters &Test{ |