mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Extend template's mod and modBool functions to accept any int types
Fixes #575
This commit is contained in:
parent
d4ed59198a
commit
af47e5a2cf
2 changed files with 111 additions and 2 deletions
|
@ -446,6 +446,40 @@ func doArithmetic(a, b interface{}, op rune) (interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func Mod(a, b interface{}) (int64, error) {
|
||||
av := reflect.ValueOf(a)
|
||||
bv := reflect.ValueOf(b)
|
||||
var ai, bi int64
|
||||
|
||||
switch av.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
ai = av.Int()
|
||||
default:
|
||||
return 0, errors.New("Modulo operator can't be used with non integer value")
|
||||
}
|
||||
|
||||
switch bv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
bi = bv.Int()
|
||||
default:
|
||||
return 0, errors.New("Modulo operator can't be used with non integer value")
|
||||
}
|
||||
|
||||
if bi == 0 {
|
||||
return 0, errors.New("The number can't be divided by zero at modulo operation")
|
||||
}
|
||||
|
||||
return ai % bi, nil
|
||||
}
|
||||
|
||||
func ModBool(a, b interface{}) (bool, error) {
|
||||
res, err := Mod(a, b)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return res == int64(0), nil
|
||||
}
|
||||
|
||||
type Template interface {
|
||||
ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
||||
Lookup(name string) *template.Template
|
||||
|
@ -496,9 +530,9 @@ func NewTemplate() Template {
|
|||
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
||||
"sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
|
||||
"div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
|
||||
"mod": func(a, b int) int { return a % b },
|
||||
"mod": Mod,
|
||||
"mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
|
||||
"modBool": func(a, b int) bool { return a%b == 0 },
|
||||
"modBool": ModBool,
|
||||
"lower": func(a string) string { return strings.ToLower(a) },
|
||||
"upper": func(a string) string { return strings.ToUpper(a) },
|
||||
"title": func(a string) string { return strings.Title(a) },
|
||||
|
|
|
@ -123,6 +123,81 @@ func TestDoArithmetic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestMod(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
a interface{}
|
||||
b interface{}
|
||||
expect interface{}
|
||||
}{
|
||||
{3, 2, int64(1)},
|
||||
{3, 1, int64(0)},
|
||||
{3, 0, false},
|
||||
{0, 3, int64(0)},
|
||||
{3.1, 2, false},
|
||||
{3, 2.1, false},
|
||||
{3.1, 2.1, false},
|
||||
{int8(3), int8(2), int64(1)},
|
||||
{int16(3), int16(2), int64(1)},
|
||||
{int32(3), int32(2), int64(1)},
|
||||
{int64(3), int64(2), int64(1)},
|
||||
} {
|
||||
result, err := Mod(this.a, this.b)
|
||||
if b, ok := this.expect.(bool); ok && !b {
|
||||
if err == nil {
|
||||
t.Errorf("[%d] modulo didn't return an expected error")
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("[%d] failed: %s", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(result, this.expect) {
|
||||
t.Errorf("[%d] modulo got %v but expected %v", i, result, this.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestModBool(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
a interface{}
|
||||
b interface{}
|
||||
expect interface{}
|
||||
}{
|
||||
{3, 3, true},
|
||||
{3, 2, false},
|
||||
{3, 1, true},
|
||||
{3, 0, nil},
|
||||
{0, 3, true},
|
||||
{3.1, 2, nil},
|
||||
{3, 2.1, nil},
|
||||
{3.1, 2.1, nil},
|
||||
{int8(3), int8(3), true},
|
||||
{int8(3), int8(2), false},
|
||||
{int16(3), int16(3), true},
|
||||
{int16(3), int16(2), false},
|
||||
{int32(3), int32(3), true},
|
||||
{int32(3), int32(2), false},
|
||||
{int64(3), int64(3), true},
|
||||
{int64(3), int64(2), false},
|
||||
} {
|
||||
result, err := ModBool(this.a, this.b)
|
||||
if this.expect == nil {
|
||||
if err == nil {
|
||||
t.Errorf("[%d] modulo didn't return an expected error")
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("[%d] failed: %s", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(result, this.expect) {
|
||||
t.Errorf("[%d] modulo got %v but expected %v", i, result, this.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirst(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
count interface{}
|
||||
|
|
Loading…
Reference in a new issue