Slicestr fix for other int type param - hugo - [fork] hugo port for 9front
 (HTM) git clone git@git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 5b51b3b9fb19d8d20e99d3c249c0052793abe50a
 (DIR) parent d313bc78a478f9457ce8b496ede0b231e6b4d0f1
 (HTM) Author: Benny Wu <benzwu@gmail.com>
       Date:   Fri, 14 Aug 2015 15:36:56 +0700
       
       Slicestr fix for other int type param
       
       Fixes #1347
       
       Diffstat:
         M tpl/template_funcs.go               |      65 +++++++++++++++++++------------
         M tpl/template_funcs_test.go          |      53 ++++++++++++++++++++-----------
       
       2 files changed, 76 insertions(+), 42 deletions(-)
       ---
 (DIR) diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go
       @@ -128,32 +128,65 @@ func compareGetFloat(a interface{}, b interface{}) (float64, float64) {
                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 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
                }
        
                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)
        
 (DIR) diff --git a/tpl/template_funcs_test.go b/tpl/template_funcs_test.go
       @@ -348,29 +348,46 @@ func TestIn(t *testing.T) {
        }
        
        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 {