github.com/MontFerret/ferret@v0.18.0/pkg/stdlib/strings/fmt.go (about) 1 package strings 2 3 import ( 4 "context" 5 "regexp" 6 "strconv" 7 "strings" 8 9 "github.com/pkg/errors" 10 11 "github.com/MontFerret/ferret/pkg/runtime/core" 12 "github.com/MontFerret/ferret/pkg/runtime/values" 13 "github.com/MontFerret/ferret/pkg/runtime/values/types" 14 ) 15 16 // FMT formats the template using these arguments. 17 // @param {String} template - template. 18 // @param {Any, repeated} args - template arguments. 19 // @return {String} - string formed by template using arguments. 20 func Fmt(_ context.Context, args ...core.Value) (core.Value, error) { 21 err := core.ValidateArgs(args, 1, core.MaxArgs) 22 if err != nil { 23 return values.None, err 24 } 25 26 err = core.ValidateType(args[0], types.String) 27 if err != nil { 28 return values.None, err 29 } 30 31 formatted, err := format(args[0].String(), args[1:]) 32 if err != nil { 33 return values.None, err 34 } 35 36 return values.NewString(formatted), nil 37 } 38 39 func format(template string, args []core.Value) (string, error) { 40 rgx := regexp.MustCompile("{[0-9]*}") 41 42 argsCount := len(args) 43 emptyBracketsCount := strings.Count(template, "{}") 44 45 if argsCount > emptyBracketsCount && emptyBracketsCount != 0 { 46 return "", errors.Errorf("there are arguments that have never been used") 47 } 48 49 var betweenBrackets string 50 var n int 51 // index of the last value 52 // inserted into the template 53 var lastArgIdx int 54 var err error 55 56 template = rgx.ReplaceAllStringFunc(template, func(s string) string { 57 if err != nil { 58 return "" 59 } 60 61 betweenBrackets = s[1 : len(s)-1] 62 63 if betweenBrackets == "" { 64 if argsCount <= lastArgIdx { 65 err = errors.Errorf("not enough arguments") 66 return "" 67 } 68 69 lastArgIdx++ 70 return args[lastArgIdx-1].String() 71 } 72 73 n, err = strconv.Atoi(betweenBrackets) 74 if err != nil { 75 err = errors.Errorf("failed to parse int: %v", err) 76 return "" 77 } 78 79 if n >= argsCount { 80 err = errors.Errorf("invalid reference to argument `%d`", n) 81 return "" 82 } 83 84 return args[n].String() 85 }) 86 87 return template, err 88 }