mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 22:51:32 -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 {
|
type Template interface {
|
||||||
ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
||||||
Lookup(name string) *template.Template
|
Lookup(name string) *template.Template
|
||||||
|
@ -496,9 +530,9 @@ func NewTemplate() Template {
|
||||||
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
||||||
"sub": 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, '/') },
|
"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, '*') },
|
"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) },
|
"lower": func(a string) string { return strings.ToLower(a) },
|
||||||
"upper": func(a string) string { return strings.ToUpper(a) },
|
"upper": func(a string) string { return strings.ToUpper(a) },
|
||||||
"title": func(a string) string { return strings.Title(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) {
|
func TestFirst(t *testing.T) {
|
||||||
for i, this := range []struct {
|
for i, this := range []struct {
|
||||||
count interface{}
|
count interface{}
|
||||||
|
|
Loading…
Reference in a new issue