shithub: hugo

Download patch

ref: 5b51b3b9fb19d8d20e99d3c249c0052793abe50a
parent: d313bc78a478f9457ce8b496ede0b231e6b4d0f1
author: Benny Wu <[email protected]>
date: Fri Aug 14 11:36:56 EDT 2015

Slicestr fix for other int type param

Fixes #1347

--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -128,32 +128,65 @@
 	return left, right
 }
 
+// Taken out from Substr, to be used by Slicestr too.
+func toInt(v interface{}, message string) (int, error) {
+	switch i := v.(type) {
+	case int:
+		return i, nil
+	case int8:
+		return int(i), nil
+	case int16:
+		return int(i), nil
+	case int32:
+		return int(i), nil
+	case int64:
+		return int(i), nil
+	default:
+		return 0, errors.New(message)
+	}
+}
+
 // Slicing in Slicestr is done by specifying a half-open range with
 // two indices, start and end. 1 and 4 creates a slice including elements 1 through 3.
 // The end index can be omitted, it defaults to the string's length.
-func Slicestr(a interface{}, startEnd ...int) (string, error) {
+func Slicestr(a interface{}, startEnd ...interface{}) (string, error) {
 	aStr, err := cast.ToStringE(a)
 	if err != nil {
 		return "", err
 	}
 
-	if len(startEnd) > 2 {
+	var argStart, argEnd int
+
+	argNum := len(startEnd)
+
+	if argNum > 0 {
+		if argStart, err = toInt(startEnd[0], "start argument must be integer"); err != nil {
+			return "", err
+		}
+	}
+	if argNum > 1 {
+		if argEnd, err = toInt(startEnd[1], "end argument must be integer"); err != nil {
+			return "", err
+		}
+	}
+
+	if argNum > 2 {
 		return "", errors.New("too many arguments")
 	}
 
 	asRunes := []rune(aStr)
 
-	if len(startEnd) > 0 && (startEnd[0] < 0 || startEnd[0] >= len(asRunes)) {
+	if argNum > 0 && (argStart < 0 || argStart >= len(asRunes)) {
 		return "", errors.New("slice bounds out of range")
 	}
 
-	if len(startEnd) == 2 {
-		if startEnd[1] < 0 || startEnd[1] > len(asRunes) {
+	if argNum == 2 {
+		if argEnd < 0 || argEnd > len(asRunes) {
 			return "", errors.New("slice bounds out of range")
 		}
-		return string(asRunes[startEnd[0]:startEnd[1]]), nil
-	} else if len(startEnd) == 1 {
-		return string(asRunes[startEnd[0]:]), nil
+		return string(asRunes[argStart:argEnd]), nil
+	} else if argNum == 1 {
+		return string(asRunes[argStart:]), nil
 	} else {
 		return string(asRunes[:]), nil
 	}
@@ -179,22 +212,6 @@
 	}
 
 	var start, length int
-	toInt := func(v interface{}, message string) (int, error) {
-		switch i := v.(type) {
-		case int:
-			return i, nil
-		case int8:
-			return int(i), nil
-		case int16:
-			return int(i), nil
-		case int32:
-			return int(i), nil
-		case int64:
-			return int(i), nil
-		default:
-			return 0, errors.New(message)
-		}
-	}
 
 	asRunes := []rune(aStr)
 
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -348,29 +348,46 @@
 }
 
 func TestSlicestr(t *testing.T) {
+	var err error
 	for i, this := range []struct {
 		v1     interface{}
-		v2     []int
+		v2     interface{}
+		v3     interface{}
 		expect interface{}
 	}{
-		{"abc", []int{1, 2}, "b"},
-		{"abc", []int{1, 3}, "bc"},
-		{"abc", []int{0, 1}, "a"},
-		{"abcdef", []int{}, "abcdef"},
-		{"abcdef", []int{0, 6}, "abcdef"},
-		{"abcdef", []int{0, 2}, "ab"},
-		{"abcdef", []int{2}, "cdef"},
-		{123, []int{1, 3}, "23"},
-		{123, []int{1, 2, 3}, false},
-		{"abcdef", []int{6}, false},
-		{"abcdef", []int{4, 7}, false},
-		{"abcdef", []int{-1}, false},
-		{"abcdef", []int{-1, 7}, false},
-		{"abcdef", []int{1, -1}, false},
-		{tstNoStringer{}, []int{0, 1}, false},
-		{"ĀĀĀ", []int{0, 1}, "Ā"}, // issue #1333
+		{"abc", 1, 2, "b"},
+		{"abc", 1, 3, "bc"},
+		{"abcdef", 1, int8(3), "bc"},
+		{"abcdef", 1, int16(3), "bc"},
+		{"abcdef", 1, int32(3), "bc"},
+		{"abcdef", 1, int64(3), "bc"},
+		{"abc", 0, 1, "a"},
+		{"abcdef", nil, nil, "abcdef"},
+		{"abcdef", 0, 6, "abcdef"},
+		{"abcdef", 0, 2, "ab"},
+		{"abcdef", 2, nil, "cdef"},
+		{"abcdef", int8(2), nil, "cdef"},
+		{"abcdef", int16(2), nil, "cdef"},
+		{"abcdef", int32(2), nil, "cdef"},
+		{"abcdef", int64(2), nil, "cdef"},
+		{123, 1, 3, "23"},
+		{"abcdef", 6, nil, false},
+		{"abcdef", 4, 7, false},
+		{"abcdef", -1, nil, false},
+		{"abcdef", -1, 7, false},
+		{"abcdef", 1, -1, false},
+		{tstNoStringer{}, 0, 1, false},
+		{"ĀĀĀ", 0, 1, "Ā"}, // issue #1333
 	} {
-		result, err := Slicestr(this.v1, this.v2...)
+
+		var result string
+		if this.v2 == nil {
+			result, err = Slicestr(this.v1)
+		} else if this.v3 == nil {
+			result, err = Slicestr(this.v1, this.v2)
+		} else {
+			result, err = Slicestr(this.v1, this.v2, this.v3)
+		}
 
 		if b, ok := this.expect.(bool); ok && !b {
 			if err == nil {