From 34c566773a1364077e1397daece85b22948dc721 Mon Sep 17 00:00:00 2001 From: Artem Sidorenko Date: Mon, 3 Jul 2017 00:20:49 +0200 Subject: [PATCH] tpl/math: Add log function It might be very useful for building tag clouds. --- docs/content/templates/functions.md | 8 ++++++- tpl/math/init.go | 7 ++++++ tpl/math/math.go | 13 ++++++++++ tpl/math/math_test.go | 37 +++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/docs/content/templates/functions.md b/docs/content/templates/functions.md index 0c6968bd27f..99fb56d6834 100644 --- a/docs/content/templates/functions.md +++ b/docs/content/templates/functions.md @@ -432,6 +432,12 @@ favicon.ico: {{.Width}} x {{.Height}} {{div 6 3}} → 2 + +math.Log +Natural logarithm of one float. +{{math.Log 1.0}} → 0 + + mod Modulus of two integers. @@ -714,7 +720,7 @@ e.g. * `{{ "this is a text" | truncate 10 " ..." }}` → `this is a ...` * `{{ "Keep my HTML" | safeHTML | truncate 10 }}` → `Keep my …` -* `{{ "With [Markdown](#markdown) inside." | markdownify | truncate 10 }}` → `With Markdown …` +* `{{ "With [Markdown](#markdown) inside." | markdownify | truncate 10 }}` → `With Markdown …` ### split diff --git a/tpl/math/init.go b/tpl/math/init.go index 3faf0e3a680..4d740c537c9 100644 --- a/tpl/math/init.go +++ b/tpl/math/init.go @@ -43,6 +43,13 @@ func init() { }, ) + ns.AddMethodMapping(ctx.Log, + nil, + [][2]string{ + {"{{math.Log 1}}", "0"}, + }, + ) + ns.AddMethodMapping(ctx.Mod, []string{"mod"}, [][2]string{ diff --git a/tpl/math/math.go b/tpl/math/math.go index 57e7baf1246..303f029afad 100644 --- a/tpl/math/math.go +++ b/tpl/math/math.go @@ -15,7 +15,10 @@ package math import ( "errors" + "math" "reflect" + + "github.com/spf13/cast" ) // New returns a new instance of the math-namespaced template functions. @@ -34,6 +37,16 @@ func (ns *Namespace) Div(a, b interface{}) (interface{}, error) { return DoArithmetic(a, b, '/') } +func (ns *Namespace) Log(a interface{}) (float64, error) { + af, err := cast.ToFloat64E(a) + + if err != nil { + return 0, errors.New("Log operator can't be used with non integer or float value") + } + + return math.Log(af), nil +} + // Mod returns a % b. func (ns *Namespace) Mod(a, b interface{}) (int64, error) { av := reflect.ValueOf(a) diff --git a/tpl/math/math_test.go b/tpl/math/math_test.go index 40bed553982..49ac053fd65 100644 --- a/tpl/math/math_test.go +++ b/tpl/math/math_test.go @@ -15,6 +15,7 @@ package math import ( "fmt" + "math" "testing" "github.com/stretchr/testify/assert" @@ -142,6 +143,42 @@ func TestDoArithmetic(t *testing.T) { } } +func TestLog(t *testing.T) { + t.Parallel() + + ns := New() + + for i, test := range []struct { + a interface{} + expect interface{} + }{ + {1, float64(0)}, + {3, float64(1.0986)}, + {0, float64(math.Inf(-1))}, + {1.0, float64(0)}, + {3.1, float64(1.1314)}, + {"abc", false}, + } { + errMsg := fmt.Sprintf("[%d] %v", i, test) + + result, err := ns.Log(test.a) + + if b, ok := test.expect.(bool); ok && !b { + require.Error(t, err, errMsg) + continue + } + + // we compare only 4 digits behind point if its a real float + // otherwise we usually get different float values on the last positions + if result != math.Inf(-1) { + result = float64(int(result*10000)) / 10000 + } + + require.NoError(t, err, errMsg) + assert.Equal(t, test.expect, result, errMsg) + } +} + func TestMod(t *testing.T) { t.Parallel()