fix(template): support all numbers for trunc

resolves #4184
This commit is contained in:
Jan De Dobbeleer 2023-08-25 11:36:09 +02:00 committed by Jan De Dobbeleer
parent 3b1bf903d9
commit a1841d21e2
4 changed files with 73 additions and 5 deletions

View file

@ -18,6 +18,7 @@ func funcMap() template.FuncMap {
"lt": lt, "lt": lt,
"reason": GetReasonFromStatus, "reason": GetReasonFromStatus,
"hresult": hresult, "hresult": hresult,
"trunc": trunc,
} }
for key, fun := range sprig.TxtFuncMap() { for key, fun := range sprig.TxtFuncMap() {
if _, ok := funcMap[key]; !ok { if _, ok := funcMap[key]; !ok {

View file

@ -6,23 +6,25 @@ import (
"strings" "strings"
) )
func parseSeconds(seconds interface{}) (int, error) { func toInt(integer any) (int, error) {
switch seconds := seconds.(type) { switch seconds := integer.(type) {
default: default:
return 0, errors.New("invalid seconds type") return 0, errors.New("invalid integer type")
case string: case string:
return strconv.Atoi(seconds) return strconv.Atoi(seconds)
case int: case int:
return seconds, nil return seconds, nil
case int64: case int64:
return int(seconds), nil return int(seconds), nil
case uint64:
return int(seconds), nil
case float64: case float64:
return int(seconds), nil return int(seconds), nil
} }
} }
func secondsRound(seconds interface{}) string { func secondsRound(seconds any) string {
s, err := parseSeconds(seconds) s, err := toInt(seconds)
if err != nil { if err != nil {
return err.Error() return err.Error()
} }

18
src/template/strings.go Normal file
View file

@ -0,0 +1,18 @@
package template
func trunc(length any, s string) string {
c, err := toInt(length)
if err != nil {
panic(err)
}
if c < 0 && len(s)+c > 0 {
return s[len(s)+c:]
}
if c >= 0 && len(s) > c {
return s[:c]
}
return s
}

View file

@ -0,0 +1,47 @@
package template
import (
"testing"
"github.com/jandedobbeleer/oh-my-posh/src/mock"
"github.com/jandedobbeleer/oh-my-posh/src/platform"
"github.com/stretchr/testify/assert"
mock2 "github.com/stretchr/testify/mock"
)
func TestTrunc(t *testing.T) {
cases := []struct {
Case string
Expected string
Template string
ShouldError bool
}{
{Case: "5 length integer", Expected: "Hello", Template: `{{ trunc 5 "Hello World" }}`},
{Case: "5 length stringteger", Expected: "Hello", Template: `{{ trunc "5" "Hello World" }}`},
{Case: "5 length float", Expected: "Hello", Template: `{{ trunc 5.0 "Hello World" }}`},
{Case: "invalid", ShouldError: true, Template: `{{ trunc "foo" "Hello World" }}`},
{Case: "smaller than length", Expected: "Hello World", Template: `{{ trunc 20 "Hello World" }}`},
{Case: "negative", Expected: "ld", Template: `{{ trunc -2 "Hello World" }}`},
}
env := &mock.MockedEnvironment{}
env.On("TemplateCache").Return(&platform.TemplateCache{
Env: make(map[string]string),
})
env.On("Error", mock2.Anything)
env.On("Debug", mock2.Anything)
for _, tc := range cases {
tmpl := &Text{
Template: tc.Template,
Context: nil,
Env: env,
}
text, err := tmpl.Render()
if tc.ShouldError {
assert.Error(t, err)
continue
}
assert.Equal(t, tc.Expected, text, tc.Case)
}
}