Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make lookup support Ptr type #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions lookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,14 @@ func lookup(name string, context ...interface{}) (interface{}, bool) {
// struct that matches the name. In the near future I'd like to add
// support for matching struct names to tags so we can use lower_case
// names in our templates which makes it more mustache like.
case reflect.Ptr:
reflectValue = reflectValue.Elem()
fallthrough
case reflect.Struct:
field := reflectValue.FieldByName(name)
if field.IsValid() {
return field.Interface(), truth(field)
result, isTrue := lookupStructByName(reflectValue, name)
if result != nil {
return result, isTrue
}
method := reflectValue.MethodByName(name)
if method.IsValid() && method.Type().NumIn() == 1 {
out := method.Call(nil)[0]
return out.Interface(), truth(out)
}

}
// If by this point no value was matched, we'll move up a step in the
// chain and try to match a value there.
Expand All @@ -63,6 +60,21 @@ func lookup(name string, context ...interface{}) (interface{}, bool) {
return nil, false
}

// lookupStructByName will return the field or the method result with the given name.
// Returns nil, false if no such field or method.
func lookupStructByName(reflectValue reflect.Value, name string) (interface{}, bool) {
field := reflectValue.FieldByName(name)
if field.IsValid() {
return field.Interface(), truth(field)
}
method := reflectValue.MethodByName(name)
if method.IsValid() && method.Type().NumIn() == 1 {
out := method.Call(nil)[0]
return out.Interface(), truth(out)
}
return nil, false
}

// The truth function will tell us if r is a truthy value or not. This is
// important for sections as they will render their content based on the output
// of this function.
Expand Down
8 changes: 8 additions & 0 deletions lookup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ func TestSimpleLookup(t *testing.T) {
"map": map[string]interface{}{
"in": "I'm nested!",
},
"ptr": &struct {
Foo *struct{ Bar string }
}{
Foo: &struct{ Bar string }{
Bar: "bar",
},
},
},
assertions: []struct {
name string
Expand All @@ -34,6 +41,7 @@ func TestSimpleLookup(t *testing.T) {
{"string", "abc", true},
{"boolean", true, true},
{"map.in", "I'm nested!", true},
{"ptr.Foo.Bar", "bar", true},
},
},
{
Expand Down