shithub: hugo

Download patch

ref: dd732e84f43570d87dba49a1e42061f8bd4f6afa
parent: 033a13e10e5ef42424db72ae45e01380b0d1e07c
author: Tatsushi Demachi <[email protected]>
date: Sat Jun 27 22:15:42 EDT 2015

Add nil comparison to where tpl function

`where` template function's internal condition check function always
returns `false` when a target value doesn't exist or it's nil value but
this behavior makes it difficult to filter values which doesn't have a
particular parameter.

To solve it, this adds nil value comparison to the function.
`where Values ".Param.key" nil` like clause can be used for the case
above.

Only "=", "==", "eq", "!=", "<>", "ne" operators are allowed to be used
with `nil`. If an other operator is passed with `nil`, the condition
check function returns `false` like before.

Fix #1232

--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -536,17 +536,21 @@
 }
 
 func checkCondition(v, mv reflect.Value, op string) (bool, error) {
-	if !v.IsValid() || !mv.IsValid() {
-		return false, nil
+	v, vIsNil := indirect(v)
+	if !v.IsValid() {
+		vIsNil = true
 	}
-
-	var isNil bool
-	v, isNil = indirect(v)
-	if isNil {
-		return false, nil
+	mv, mvIsNil := indirect(mv)
+	if !mv.IsValid() {
+		mvIsNil = true
 	}
-	mv, isNil = indirect(mv)
-	if isNil {
+	if vIsNil || mvIsNil {
+		switch op {
+		case "", "=", "==", "eq":
+			return vIsNil == mvIsNil, nil
+		case "!=", "<>", "ne":
+			return vIsNil != mvIsNil, nil
+		}
 		return false, nil
 	}
 
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -673,6 +673,7 @@
 			"",
 			expect{true, false},
 		},
+		{reflect.ValueOf(nil), reflect.ValueOf(nil), "", expect{true, false}},
 		{reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
 		{reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
 		{
@@ -681,6 +682,7 @@
 			"!=",
 			expect{true, false},
 		},
+		{reflect.ValueOf(123), reflect.ValueOf(nil), "!=", expect{true, false}},
 		{reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
 		{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
 		{
@@ -942,6 +944,31 @@
 			expect: []TstX{
 				{A: "a", B: "b"}, {A: "e", B: "f"},
 			},
+		},
+		{
+			sequence: []map[string]int{
+				{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
+			},
+			key: "b", op: "", match: nil,
+			expect: []map[string]int{
+				{"a": 3},
+			},
+		},
+		{
+			sequence: []map[string]int{
+				{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
+			},
+			key: "b", op: "!=", match: nil,
+			expect: []map[string]int{
+				{"a": 1, "b": 2}, {"a": 5, "b": 6},
+			},
+		},
+		{
+			sequence: []map[string]int{
+				{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
+			},
+			key: "b", op: ">", match: nil,
+			expect: []map[string]int{},
 		},
 		{sequence: (*[]TstX)(nil), key: "A", match: "a", expect: false},
 		{sequence: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},