<th align=center>Method</th><th align=center>Calls</th>
{.repeated section meth}
<tr>
- <td align=left font=fixed>{name}({.section m}{argType}, {replyType}) os.Error</td>
- <td align=center>{numCalls}</td>{.end}
+ <td align=left font=fixed>{name}({m.argType}, {m.replyType}) os.Error</td>
+ <td align=center>{m.numCalls}</td>
</tr>
{.end}
</table>
// -- Execution
// If the data for this template is a struct, find the named variable.
+// Names of the form a.b.c are walked down the data tree.
// The special name "@" (the "cursor") denotes the current data.
func (st *state) findVar(s string) reflect.Value {
if s == "@" {
return st.data
}
data := reflect.Indirect(st.data);
- typ, ok := data.Type().(*reflect.StructType);
- if ok {
- if field, ok := typ.FieldByName(s); ok {
- return data.(*reflect.StructValue).Field(field.Index)
+ elems := strings.Split(s, ".", 0);
+ for i := 0; i < len(elems); i++ {
+ // Look up field; data must be a struct.
+ typ, ok := data.Type().(*reflect.StructType);
+ if !ok {
+ return nil
}
+ field, ok := typ.FieldByName(elems[i]);
+ if !ok {
+ return nil
+ }
+ data = reflect.Indirect(data.(*reflect.StructValue).Field(field.Index));
}
- return nil
+ return data
}
// Is there no data to look at?
header string;
integer int;
raw string;
+ innerT T;
data []T;
pdata []*T;
empty []*T;
"ItemNumber2=ValueNumber2\n"
},
+ // Nested names
+ &Test{
+ "{.section @ }\n"
+ "{innerT.item}={innerT.value}\n"
+ "{.end}",
+
+ "ItemNumber1=ValueNumber1\n"
+ },
+
// Formatters
&Test{
"{.section pdata }\n"
s.header = "Header";
s.integer = 77;
s.raw = "&<>!@ #$%^";
+ s.innerT = t1;
s.data = []T{ t1, t2 };
s.pdata = []*T{ &t1, &t2 };
s.empty = []*T{ };