fmt.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package stdlib
  2. import (
  3. "fmt"
  4. "github.com/d5/tengo/v2"
  5. )
  6. var fmtModule = map[string]tengo.Object{
  7. "print": &tengo.UserFunction{Name: "print", Value: fmtPrint},
  8. "printf": &tengo.UserFunction{Name: "printf", Value: fmtPrintf},
  9. "println": &tengo.UserFunction{Name: "println", Value: fmtPrintln},
  10. "sprintf": &tengo.UserFunction{Name: "sprintf", Value: fmtSprintf},
  11. }
  12. func fmtPrint(args ...tengo.Object) (ret tengo.Object, err error) {
  13. printArgs, err := getPrintArgs(args...)
  14. if err != nil {
  15. return nil, err
  16. }
  17. _, _ = fmt.Print(printArgs...)
  18. return nil, nil
  19. }
  20. func fmtPrintf(args ...tengo.Object) (ret tengo.Object, err error) {
  21. numArgs := len(args)
  22. if numArgs == 0 {
  23. return nil, tengo.ErrWrongNumArguments
  24. }
  25. format, ok := args[0].(*tengo.String)
  26. if !ok {
  27. return nil, tengo.ErrInvalidArgumentType{
  28. Name: "format",
  29. Expected: "string",
  30. Found: args[0].TypeName(),
  31. }
  32. }
  33. if numArgs == 1 {
  34. fmt.Print(format)
  35. return nil, nil
  36. }
  37. s, err := tengo.Format(format.Value, args[1:]...)
  38. if err != nil {
  39. return nil, err
  40. }
  41. fmt.Print(s)
  42. return nil, nil
  43. }
  44. func fmtPrintln(args ...tengo.Object) (ret tengo.Object, err error) {
  45. printArgs, err := getPrintArgs(args...)
  46. if err != nil {
  47. return nil, err
  48. }
  49. printArgs = append(printArgs, "\n")
  50. _, _ = fmt.Print(printArgs...)
  51. return nil, nil
  52. }
  53. func fmtSprintf(args ...tengo.Object) (ret tengo.Object, err error) {
  54. numArgs := len(args)
  55. if numArgs == 0 {
  56. return nil, tengo.ErrWrongNumArguments
  57. }
  58. format, ok := args[0].(*tengo.String)
  59. if !ok {
  60. return nil, tengo.ErrInvalidArgumentType{
  61. Name: "format",
  62. Expected: "string",
  63. Found: args[0].TypeName(),
  64. }
  65. }
  66. if numArgs == 1 {
  67. // okay to return 'format' directly as String is immutable
  68. return format, nil
  69. }
  70. s, err := tengo.Format(format.Value, args[1:]...)
  71. if err != nil {
  72. return nil, err
  73. }
  74. return &tengo.String{Value: s}, nil
  75. }
  76. func getPrintArgs(args ...tengo.Object) ([]interface{}, error) {
  77. var printArgs []interface{}
  78. l := 0
  79. for _, arg := range args {
  80. s, _ := tengo.ToString(arg)
  81. slen := len(s)
  82. // make sure length does not exceed the limit
  83. if l+slen > tengo.MaxStringLen {
  84. return nil, tengo.ErrStringLimit
  85. }
  86. l += slen
  87. printArgs = append(printArgs, s)
  88. }
  89. return printArgs, nil
  90. }