summaryrefslogtreecommitdiffstats
path: root/tpl
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-08-01 10:19:19 +0200
committerGitHub <noreply@github.com>2019-08-01 10:19:19 +0200
commit53077b0da54906feee64a03612e5186043e17341 (patch)
treec99b1456485cfc2ed41f3a1b732e44c4acbc3061 /tpl
parenta4f96a9d8c2d2da40796757f7e9a3023157abd2f (diff)
Merge pull request #6149 from bep/sort-caseinsensitive
Implement lexicographically string sorting
Diffstat (limited to 'tpl')
-rw-r--r--tpl/collections/sort.go8
-rw-r--r--tpl/collections/sort_test.go1
-rw-r--r--tpl/compare/compare.go28
-rw-r--r--tpl/compare/compare_test.go14
-rw-r--r--tpl/compare/init.go2
-rw-r--r--tpl/compare/truth_test.go2
6 files changed, 40 insertions, 15 deletions
diff --git a/tpl/collections/sort.go b/tpl/collections/sort.go
index 1ab4409b6..9639fe1d0 100644
--- a/tpl/collections/sort.go
+++ b/tpl/collections/sort.go
@@ -23,7 +23,7 @@ import (
"github.com/spf13/cast"
)
-var comp = compare.New()
+var sortComp = compare.New(true)
// Sort returns a sorted sequence.
func (ns *Namespace) Sort(seq interface{}, args ...interface{}) (interface{}, error) {
@@ -133,15 +133,15 @@ func (p pairList) Less(i, j int) bool {
if iv.IsValid() {
if jv.IsValid() {
// can only call Interface() on valid reflect Values
- return comp.Lt(iv.Interface(), jv.Interface())
+ return sortComp.Lt(iv.Interface(), jv.Interface())
}
// if j is invalid, test i against i's zero value
- return comp.Lt(iv.Interface(), reflect.Zero(iv.Type()))
+ return sortComp.Lt(iv.Interface(), reflect.Zero(iv.Type()))
}
if jv.IsValid() {
// if i is invalid, test j against j's zero value
- return comp.Lt(reflect.Zero(jv.Type()), jv.Interface())
+ return sortComp.Lt(reflect.Zero(jv.Type()), jv.Interface())
}
return false
diff --git a/tpl/collections/sort_test.go b/tpl/collections/sort_test.go
index f5f291f0b..612a928cb 100644
--- a/tpl/collections/sort_test.go
+++ b/tpl/collections/sort_test.go
@@ -45,6 +45,7 @@ func TestSort(t *testing.T) {
}{
{[]string{"class1", "class2", "class3"}, nil, "asc", []string{"class1", "class2", "class3"}},
{[]string{"class3", "class1", "class2"}, nil, "asc", []string{"class1", "class2", "class3"}},
+ {[]string{"CLASS3", "class1", "class2"}, nil, "asc", []string{"class1", "class2", "CLASS3"}},
// Issue 6023
{stringsSlice{"class3", "class1", "class2"}, nil, "asc", stringsSlice{"class1", "class2", "class3"}},
diff --git a/tpl/compare/compare.go b/tpl/compare/compare.go
index 251b3d13b..ec228822c 100644
--- a/tpl/compare/compare.go
+++ b/tpl/compare/compare.go
@@ -20,18 +20,20 @@ import (
"strconv"
"time"
- "github.com/gohugoio/hugo/common/types"
-
"github.com/gohugoio/hugo/compare"
+
+ "github.com/gohugoio/hugo/common/types"
)
// New returns a new instance of the compare-namespaced template functions.
-func New() *Namespace {
- return &Namespace{}
+func New(caseInsensitive bool) *Namespace {
+ return &Namespace{caseInsensitive: caseInsensitive}
}
// Namespace provides template functions for the "compare" namespace.
type Namespace struct {
+ // Enable to do case insensitive string compares.
+ caseInsensitive bool
}
// Default checks whether a given value is set and returns a default value if it
@@ -89,7 +91,10 @@ func (*Namespace) Default(dflt interface{}, given ...interface{}) (interface{},
}
// Eq returns the boolean truth of arg1 == arg2.
-func (*Namespace) Eq(x, y interface{}) bool {
+func (ns *Namespace) Eq(x, y interface{}) bool {
+ if ns.caseInsensitive {
+ panic("caseInsensitive not implemented for Eq")
+ }
if e, ok := x.(compare.Eqer); ok {
return e.Eq(y)
}
@@ -157,7 +162,7 @@ func (n *Namespace) Conditional(condition bool, a, b interface{}) interface{} {
return b
}
-func (*Namespace) compareGet(a interface{}, b interface{}) (float64, float64) {
+func (ns *Namespace) compareGet(a interface{}, b interface{}) (float64, float64) {
if ac, ok := a.(compare.Comparer); ok {
c := ac.Compare(b)
if c < 0 {
@@ -228,6 +233,17 @@ func (*Namespace) compareGet(a interface{}, b interface{}) (float64, float64) {
}
}
+ if ns.caseInsensitive && leftStr != nil && rightStr != nil {
+ c := compare.Strings(*leftStr, *rightStr)
+ if c < 0 {
+ return 0, 1
+ } else if c > 0 {
+ return 1, 0
+ } else {
+ return 0, 0
+ }
+ }
+
switch {
case leftStr == nil || rightStr == nil:
case *leftStr < *rightStr:
diff --git a/tpl/compare/compare_test.go b/tpl/compare/compare_test.go
index 6c4be7e50..a7b1e54a6 100644
--- a/tpl/compare/compare_test.go
+++ b/tpl/compare/compare_test.go
@@ -83,7 +83,7 @@ func TestDefaultFunc(t *testing.T) {
then := time.Now()
now := time.Now()
- ns := New()
+ ns := New(false)
for i, test := range []struct {
dflt interface{}
@@ -139,7 +139,7 @@ func TestDefaultFunc(t *testing.T) {
func TestCompare(t *testing.T) {
t.Parallel()
- n := New()
+ n := New(false)
for _, test := range []struct {
tstCompareType
@@ -233,6 +233,14 @@ func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b inte
}
}
+func TestCase(t *testing.T) {
+ assert := require.New(t)
+ n := New(true)
+
+ assert.True(n.Lt("az", "Za"))
+ assert.True(n.Gt("ab", "Ab"))
+}
+
func TestTimeUnix(t *testing.T) {
t.Parallel()
var sec int64 = 1234567890
@@ -258,7 +266,7 @@ func TestTimeUnix(t *testing.T) {
func TestConditional(t *testing.T) {
assert := require.New(t)
- n := New()
+ n := New(false)
a, b := "a", "b"
assert.Equal(a, n.Conditional(true, a, b))
diff --git a/tpl/compare/init.go b/tpl/compare/init.go
index 619293203..2e536ff04 100644
--- a/tpl/compare/init.go
+++ b/tpl/compare/init.go
@@ -22,7 +22,7 @@ const name = "compare"
func init() {
f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
- ctx := New()
+ ctx := New(false)
ns := &internal.TemplateFuncsNamespace{
Name: name,
diff --git a/tpl/compare/truth_test.go b/tpl/compare/truth_test.go
index 04d897212..7a9d03442 100644
--- a/tpl/compare/truth_test.go
+++ b/tpl/compare/truth_test.go
@@ -23,7 +23,7 @@ import (
)
func TestTruth(t *testing.T) {
- n := New()
+ n := New(false)
truthv, falsev := reflect.ValueOf(time.Now()), reflect.ValueOf(false)