templatex.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package util
  2. import (
  3. "bytes"
  4. goformat "go/format"
  5. "os"
  6. "regexp"
  7. "text/template"
  8. "github.com/zeromicro/go-zero/tools/goctl/internal/errorx"
  9. "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
  10. )
  11. const regularPerm = 0o666
  12. // DefaultTemplate is a tool to provides the text/template operations
  13. type DefaultTemplate struct {
  14. name string
  15. text string
  16. goFmt bool
  17. }
  18. // With returns an instance of DefaultTemplate
  19. func With(name string) *DefaultTemplate {
  20. return &DefaultTemplate{
  21. name: name,
  22. }
  23. }
  24. // Parse accepts a source template and returns DefaultTemplate
  25. func (t *DefaultTemplate) Parse(text string) *DefaultTemplate {
  26. t.text = text
  27. return t
  28. }
  29. // GoFmt sets the value to goFmt and marks the generated codes will be formatted or not
  30. func (t *DefaultTemplate) GoFmt(format bool) *DefaultTemplate {
  31. t.goFmt = format
  32. return t
  33. }
  34. // SaveTo writes the codes to the target path
  35. func (t *DefaultTemplate) SaveTo(data any, path string, forceUpdate bool) error {
  36. if pathx.FileExists(path) && !forceUpdate {
  37. return nil
  38. }
  39. output, err := t.Execute(data)
  40. if err != nil {
  41. return err
  42. }
  43. return os.WriteFile(path, output.Bytes(), regularPerm)
  44. }
  45. // Execute returns the codes after the template executed
  46. func (t *DefaultTemplate) Execute(data any) (*bytes.Buffer, error) {
  47. tem, err := template.New(t.name).Parse(t.text)
  48. if err != nil {
  49. return nil, errorx.Wrap(err, "template parse error:", t.text)
  50. }
  51. buf := new(bytes.Buffer)
  52. if err = tem.Execute(buf, data); err != nil {
  53. return nil, errorx.Wrap(err, "template execute error:", t.text)
  54. }
  55. if !t.goFmt {
  56. return buf, nil
  57. }
  58. formatOutput, err := goformat.Source(buf.Bytes())
  59. if err != nil {
  60. return nil, errorx.Wrap(err, "go format error:", buf.String())
  61. }
  62. buf.Reset()
  63. buf.Write(formatOutput)
  64. return buf, nil
  65. }
  66. // IsTemplateVariable returns true if the text is a template variable.
  67. // The text must start with a dot and be a valid template.
  68. func IsTemplateVariable(text string) bool {
  69. match, _ := regexp.MatchString(`(?m)^{{(\.\w+)+}}$`, text)
  70. return match
  71. }
  72. // TemplateVariable returns the variable name of the template.
  73. func TemplateVariable(text string) string {
  74. if IsTemplateVariable(text) {
  75. return text[3 : len(text)-2]
  76. }
  77. return ""
  78. }