mirror of
https://github.com/golang/go
synced 2024-11-22 21:50:03 -07:00
template:
* do full lookup for {.section}, so that it is always allowed to replace {Foo} with {.section Foo}{@}{.end} * treat False as empty so that .section can be used to test bools R=r DELTA=29 (21 added, 0 deleted, 8 changed) OCL=34215 CL=34219
This commit is contained in:
parent
f56e6fd786
commit
59db1f7bb1
@ -595,6 +595,8 @@ func empty(v reflect.Value) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
|
case *reflect.BoolValue:
|
||||||
|
return v.Get() == false;
|
||||||
case *reflect.StringValue:
|
case *reflect.StringValue:
|
||||||
return v.Get() == "";
|
return v.Get() == "";
|
||||||
case *reflect.StructValue:
|
case *reflect.StructValue:
|
||||||
@ -608,13 +610,13 @@ func empty(v reflect.Value) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look up a variable, up through the parent if necessary.
|
// Look up a variable, up through the parent if necessary.
|
||||||
func (t *Template) varValue(v *variableElement, st *state) reflect.Value {
|
func (t *Template) varValue(name string, st *state) reflect.Value {
|
||||||
field := st.findVar(v.name);
|
field := st.findVar(name);
|
||||||
if field == nil {
|
if field == nil {
|
||||||
if st.parent == nil {
|
if st.parent == nil {
|
||||||
t.execError(st, t.linenum, "name not found: %s", v.name)
|
t.execError(st, t.linenum, "name not found: %s", name)
|
||||||
}
|
}
|
||||||
return t.varValue(v, st.parent);
|
return t.varValue(name, st.parent);
|
||||||
}
|
}
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
@ -623,7 +625,7 @@ func (t *Template) varValue(v *variableElement, st *state) reflect.Value {
|
|||||||
// If it has a formatter attached ({var|formatter}) run that too.
|
// If it has a formatter attached ({var|formatter}) run that too.
|
||||||
func (t *Template) writeVariable(v *variableElement, st *state) {
|
func (t *Template) writeVariable(v *variableElement, st *state) {
|
||||||
formatter := v.formatter;
|
formatter := v.formatter;
|
||||||
val := t.varValue(v, st).Interface();
|
val := t.varValue(v.name, st).Interface();
|
||||||
// is it in user-supplied map?
|
// is it in user-supplied map?
|
||||||
if t.fmap != nil {
|
if t.fmap != nil {
|
||||||
if fn, ok := t.fmap[v.formatter]; ok {
|
if fn, ok := t.fmap[v.formatter]; ok {
|
||||||
@ -673,7 +675,7 @@ func (t *Template) execute(start, end int, st *state) {
|
|||||||
// Execute a .section
|
// Execute a .section
|
||||||
func (t *Template) executeSection(s *sectionElement, st *state) {
|
func (t *Template) executeSection(s *sectionElement, st *state) {
|
||||||
// Find driver data for this section. It must be in the current struct.
|
// Find driver data for this section. It must be in the current struct.
|
||||||
field := st.findVar(s.field);
|
field := t.varValue(s.field, st);
|
||||||
if field == nil {
|
if field == nil {
|
||||||
t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, reflect.Indirect(st.data).Type());
|
t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, reflect.Indirect(st.data).Type());
|
||||||
}
|
}
|
||||||
@ -718,7 +720,7 @@ func iter(v reflect.Value) *reflect.ChanValue {
|
|||||||
// Execute a .repeated section
|
// Execute a .repeated section
|
||||||
func (t *Template) executeRepeated(r *repeatedElement, st *state) {
|
func (t *Template) executeRepeated(r *repeatedElement, st *state) {
|
||||||
// Find driver data for this section. It must be in the current struct.
|
// Find driver data for this section. It must be in the current struct.
|
||||||
field := st.findVar(r.field);
|
field := t.varValue(r.field, st);
|
||||||
if field == nil {
|
if field == nil {
|
||||||
t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, reflect.Indirect(st.data).Type());
|
t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, reflect.Indirect(st.data).Type());
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ type S struct {
|
|||||||
emptystring string;
|
emptystring string;
|
||||||
null []*T;
|
null []*T;
|
||||||
vec *vector.Vector;
|
vec *vector.Vector;
|
||||||
|
true bool;
|
||||||
|
false bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
var t1 = T{ "ItemNumber1", "ValueNumber1" }
|
var t1 = T{ "ItemNumber1", "ValueNumber1" }
|
||||||
@ -234,6 +236,14 @@ var tests = []*Test {
|
|||||||
|
|
||||||
out: "ItemNumber1=ValueNumber1\n"
|
out: "ItemNumber1=ValueNumber1\n"
|
||||||
},
|
},
|
||||||
|
&Test{
|
||||||
|
in: "{.section @ }\n"
|
||||||
|
"{innerT.item}={.section innerT}{.section value}{@}{.end}{.end}\n"
|
||||||
|
"{.end}",
|
||||||
|
|
||||||
|
out: "ItemNumber1=ValueNumber1\n"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// Formatters
|
// Formatters
|
||||||
&Test{
|
&Test{
|
||||||
@ -260,6 +270,13 @@ var tests = []*Test {
|
|||||||
|
|
||||||
out: "\nheader\n"
|
out: "\nheader\n"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
&Test {
|
||||||
|
in: "{.section true}1{.or}2{.end}\n"
|
||||||
|
"{.section false}3{.or}4{.end}\n",
|
||||||
|
|
||||||
|
out: "1\n4\n"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAll(t *testing.T) {
|
func TestAll(t *testing.T) {
|
||||||
@ -276,6 +293,8 @@ func TestAll(t *testing.T) {
|
|||||||
s.vec = vector.New(0);
|
s.vec = vector.New(0);
|
||||||
s.vec.Push("elt1");
|
s.vec.Push("elt1");
|
||||||
s.vec.Push("elt2");
|
s.vec.Push("elt2");
|
||||||
|
s.true = true;
|
||||||
|
s.false = false;
|
||||||
|
|
||||||
var buf bytes.Buffer;
|
var buf bytes.Buffer;
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
Loading…
Reference in New Issue
Block a user