utils.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package generator
  2. import (
  3. bytes "bytes"
  4. "fmt"
  5. "os/exec"
  6. "reflect"
  7. "strings"
  8. "git.eugeniocarvalho.dev/eugeniucarvalho/utils"
  9. )
  10. var (
  11. LitTemplates = map[string]string{
  12. "string": " '%s' ",
  13. "int": " %d ",
  14. "int8": " %d ",
  15. "int16": " %d ",
  16. "int32": " %d ",
  17. "int64": " %d ",
  18. "float32": " %.2f ",
  19. "float64": " %.2f ",
  20. "bool": " %.2f ",
  21. }
  22. )
  23. type File struct {
  24. Group
  25. Name string
  26. }
  27. func NewFile(file string) *File {
  28. return &File{Name: file}
  29. }
  30. // Entidade representa menor unidade de Statement.
  31. type Stmt struct {
  32. Group
  33. Value interface{}
  34. Template string
  35. Separete string
  36. }
  37. // Root node group of Statement.
  38. type Group struct {
  39. Stmts []CodeInterface
  40. }
  41. // Metodo realiza a renderização de um grupo e todos os seus statements.
  42. func (g *Group) Render(buffer *bytes.Buffer) (err error) {
  43. for _, s := range g.Stmts {
  44. err = s.Render(buffer)
  45. }
  46. return
  47. }
  48. // Metodo Gera a string do arquivo.
  49. func (g *Group) GoString() string {
  50. buf := bytes.Buffer{}
  51. if err := g.Render(&buf); err != nil {
  52. panic(err)
  53. }
  54. return buf.String()
  55. }
  56. func NewGroup() *Group {
  57. return &Group{}
  58. }
  59. func (f *File) Save() (err error) {
  60. fmt.Println("Save in :", f.Name)
  61. if err = utils.FilePutContents(f.Name, f.GoString(), 777); err != nil {
  62. return
  63. }
  64. // Formate code with https://www.npmjs.com/package/typescript-formatter
  65. var out bytes.Buffer
  66. cmd := exec.Command("tsfmt", "-r", f.Name)
  67. cmd.Stdin = strings.NewReader("")
  68. cmd.Stdout = &out
  69. if err = cmd.Run(); err != nil {
  70. panic(err)
  71. }
  72. fmt.Printf("in all caps: %q\n", out.String())
  73. return
  74. }
  75. func (s *Stmt) Render(buffer *bytes.Buffer) (err error) {
  76. // fmt.Println("Render stmt")
  77. // spew.Dump(s)
  78. var (
  79. Value interface{}
  80. bufLocal *bytes.Buffer
  81. bufLocalMaster = &bytes.Buffer{}
  82. wbv string
  83. )
  84. if len(s.Stmts) > 0 {
  85. for _, stmt := range s.Stmts {
  86. bufLocal = &bytes.Buffer{}
  87. stmt.Render(bufLocal)
  88. bufLocalMaster.WriteString(bufLocal.String())
  89. }
  90. Value = bufLocalMaster.String()
  91. } else {
  92. Value = s.Value
  93. }
  94. if strings.Contains(s.Template, "%") {
  95. // switch Value.(type) {
  96. // case string:
  97. // wbv = fmt.Sprintf(s.Template, Value.(string))
  98. // case :
  99. // }
  100. wbv = fmt.Sprintf(s.Template, Value)
  101. } else {
  102. wbv = s.Template
  103. }
  104. buffer.WriteString(wbv)
  105. return
  106. }
  107. func (g *Group) Lit(stmt interface{}) *Group {
  108. var (
  109. Template string
  110. typ = reflect.TypeOf(stmt).Name()
  111. )
  112. if t, ok := LitTemplates[typ]; ok {
  113. Template = t
  114. } else {
  115. Template = " %v "
  116. }
  117. s := &Stmt{
  118. Template: Template,
  119. Value: stmt,
  120. }
  121. g.Stmts = append(g.Stmts, s)
  122. return g
  123. }
  124. func Lit(stmt interface{}) *Group {
  125. return NewGroup().Lit(stmt)
  126. }
  127. func (g *Group) Comment(stmt string) *Group {
  128. var (
  129. Template string
  130. )
  131. if strings.Contains(stmt, "\n") {
  132. Template = " \n/*\n%s\n*/\n "
  133. } else {
  134. Template = " \n//%s\n "
  135. }
  136. s := &Stmt{
  137. Template: Template,
  138. Value: stmt,
  139. }
  140. g.Stmts = append(g.Stmts, s)
  141. return g
  142. }
  143. func Comment(stmt string) *Group {
  144. return NewGroup().Comment(stmt)
  145. }
  146. func (g *Group) Params(params ...CodeInterface) *Group {
  147. s := &Stmt{Template: " (%s) ", Group: Group{Stmts: params}, Value: "params"}
  148. g.Stmts = append(g.Stmts, s)
  149. return g
  150. }
  151. func Params(params ...CodeInterface) *Group {
  152. return NewGroup().Params(params...)
  153. }
  154. func (g *Group) Op(op string) *Group {
  155. s := &Stmt{Template: " %s ", Value: op}
  156. g.Stmts = append(g.Stmts, s)
  157. return g
  158. }
  159. func Op(op string) *Group {
  160. return NewGroup().Op(op)
  161. }
  162. func (g *Group) Block(stmts ...CodeInterface) *Group {
  163. s := &Stmt{Template: " {%s}\n ", Group: Group{Stmts: stmts}, Value: "block"}
  164. g.Stmts = append(g.Stmts, s)
  165. return g
  166. }
  167. func Block(stmts ...CodeInterface) *Group {
  168. return NewGroup().Block(stmts...)
  169. }
  170. func (g *Group) Call(params CodeInterface) *Group {
  171. s := &Stmt{Template: " (%s) ", Group: Group{Stmts: []CodeInterface{params}}, Value: "call"}
  172. g.Stmts = append(g.Stmts, s)
  173. return g
  174. }
  175. func Call(params CodeInterface) *Group {
  176. return NewGroup().Call(params)
  177. }
  178. func (g *Group) Id(stmt string) *Group {
  179. s := &Stmt{Template: " %s ", Value: stmt}
  180. g.Stmts = append(g.Stmts, s)
  181. return g
  182. }
  183. func Id(stmt string) *Group {
  184. return NewGroup().Id(stmt)
  185. }
  186. func (g *Group) Index(index CodeInterface) *Group {
  187. s := &Stmt{Template: " [%s] ", Group: Group{Stmts: []CodeInterface{index}}, Value: "index"}
  188. g.Stmts = append(g.Stmts, s)
  189. return g
  190. }
  191. func Index(index CodeInterface) *Group {
  192. return NewGroup().Index(index)
  193. }
  194. func (g *Group) Produce(f func(g *Group)) *Group {
  195. s := &Stmt{
  196. Template: " %s ",
  197. Value: f,
  198. }
  199. g.Stmts = append(g.Stmts, s)
  200. return g
  201. }
  202. func Produce(f func(g *Group)) *Group {
  203. return NewGroup().Produce(f)
  204. }
  205. type CodeInterface interface {
  206. Render(buffer *bytes.Buffer) error
  207. GoString() string
  208. Block(stmts ...CodeInterface) *Group
  209. Call(params CodeInterface) *Group
  210. Comment(stmt string) *Group
  211. Id(stmt string) *Group
  212. Index(index CodeInterface) *Group
  213. Lit(stmt interface{}) *Group
  214. Op(op string) *Group
  215. Params(params ...CodeInterface) *Group
  216. Produce(f func(g *Group)) *Group
  217. }