package strings import ( "context" "regexp" "strconv" "strings" "github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/values" "github.com/pkg/errors" ) // Fmt formats the template using these arguments. // @params template (String) - template. // @params args (Any Values) - template arguments. // @returns (String) - string formed by template using arguments. func Fmt(_ context.Context, args ...core.Value) (core.Value, error) { err := core.ValidateArgs(args, 1, core.MaxArgs) if err != nil { return values.None, err } err = core.ValidateType(args[0], core.StringType) if err != nil { return values.None, err } formatted, err := format(args[0].String(), args[1:]) if err != nil { return values.None, err } return values.NewString(formatted), nil } func format(template string, args []core.Value) (string, error) { rgx, err := regexp.Compile("{[0-9]*}") if err != nil { return "", errors.Errorf("failed to build regexp: %v", err) } argsCount := len(args) emptyBracketsCount := strings.Count(template, "{}") if argsCount > emptyBracketsCount && emptyBracketsCount != 0 { return "", errors.Errorf("there are arguments that have never been used") } var betweenBrackets string var n int // index of the last value // inserted into the template var lastArgIdx int template = rgx.ReplaceAllStringFunc(template, func(s string) string { if err != nil { return "" } betweenBrackets = s[1 : len(s)-1] if betweenBrackets == "" { if argsCount <= lastArgIdx { err = errors.Errorf("not enought arguments") return "" } lastArgIdx++ return args[lastArgIdx-1].String() } n, err = strconv.Atoi(betweenBrackets) if err != nil { err = errors.Errorf("failed to parse int: %v", err) return "" } if n >= argsCount { err = errors.Errorf("invalid reference to argument `%d`", n) return "" } return args[n].String() }) return template, err }