main.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "flag"
  6. "fmt"
  7. "go/format"
  8. "io"
  9. "log"
  10. "os"
  11. "strings"
  12. "text/template"
  13. "unicode"
  14. )
  15. // Command line options
  16. var (
  17. oPackage = flag.String("pkg", "icon", "Package name")
  18. )
  19. const (
  20. PROGNAME = "g3nicodes"
  21. VMAJOR = 0
  22. VMINOR = 1
  23. )
  24. type constInfo struct {
  25. Name string
  26. Value string
  27. }
  28. type templateData struct {
  29. Packname string
  30. Consts []constInfo
  31. }
  32. func main() {
  33. // Parse command line parameters
  34. flag.Usage = usage
  35. flag.Parse()
  36. // Opens input file
  37. if len(flag.Args()) == 0 {
  38. log.Fatal("Input file not supplied")
  39. return
  40. }
  41. finput, err := os.Open(flag.Args()[0])
  42. if err != nil {
  43. log.Fatal(err)
  44. return
  45. }
  46. // Creates optional output file
  47. fout := os.Stdout
  48. if len(flag.Args()) > 1 {
  49. fout, err = os.Create(flag.Args()[1])
  50. if err != nil {
  51. log.Fatal(err)
  52. return
  53. }
  54. defer fout.Close()
  55. }
  56. // Parse input file
  57. var td templateData
  58. td.Packname = *oPackage
  59. err = parse(finput, &td)
  60. if err != nil {
  61. log.Fatal(err)
  62. return
  63. }
  64. // Parses the template
  65. tmpl := template.New("templ")
  66. tmpl, err = tmpl.Parse(templText)
  67. if err != nil {
  68. log.Fatal(err)
  69. return
  70. }
  71. // Expands template to buffer
  72. var buf bytes.Buffer
  73. err = tmpl.Execute(&buf, &td)
  74. if err != nil {
  75. log.Fatal(err)
  76. return
  77. }
  78. // Formats buffer as Go source
  79. p, err := format.Source(buf.Bytes())
  80. if err != nil {
  81. log.Fatal(err)
  82. return
  83. }
  84. // Writes formatted source to output file
  85. fout.Write(p)
  86. }
  87. func parse(fin io.Reader, td *templateData) error {
  88. // Read words from input reader and builds words map
  89. scanner := bufio.NewScanner(fin)
  90. for scanner.Scan() {
  91. // Read next line
  92. line := scanner.Text()
  93. if err := scanner.Err(); err != nil {
  94. return err
  95. }
  96. // Remove line terminator, spaces and ignore empty lines
  97. line = strings.Trim(line, "\n ")
  98. if len(line) == 0 {
  99. continue
  100. }
  101. parts := strings.Split(line, " ")
  102. if len(parts) != 2 {
  103. continue
  104. }
  105. name := parts[0]
  106. code := parts[1]
  107. nameParts := strings.Split(name, "_")
  108. for i := 0; i < len(nameParts); i++ {
  109. nameParts[i] = strings.Title(nameParts[i])
  110. }
  111. finalName := strings.Join(nameParts, "")
  112. // If name starts with number adds prefix
  113. runes := []rune(finalName)
  114. if unicode.IsDigit(runes[0]) {
  115. finalName = "N" + finalName
  116. }
  117. td.Consts = append(td.Consts, constInfo{Name: finalName, Value: "0x" + code})
  118. }
  119. return nil
  120. }
  121. // Shows application usage
  122. func usage() {
  123. fmt.Fprintf(os.Stderr, "%s v%d.%d\n", PROGNAME, VMAJOR, VMINOR)
  124. fmt.Fprintf(os.Stderr, "usage: %s [options] <input file> <output file>\n", strings.ToLower(PROGNAME))
  125. flag.PrintDefaults()
  126. os.Exit(0)
  127. }
  128. const templText = `// File generated by g3nicodes. Do not edit.
  129. // This file is based on the original 'codepoints' file
  130. // from the material design icon fonts:
  131. // https://github.com/google/material-design-icons
  132. package {{.Packname}}
  133. const (
  134. {{range .Consts}}
  135. {{.Name}} = string({{.Value}})
  136. {{- end}}
  137. )
  138. // Codepoint returns the codepoint for the specified icon name.
  139. // Returns 0 if the name not found
  140. func Codepoint(name string) string {
  141. return name2Codepoint[name]
  142. }
  143. // Maps icon name to codepoint
  144. var name2Codepoint = map[string]string{
  145. {{range .Consts}}
  146. "{{.Name}}": string({{.Value}}),
  147. {{- end}}
  148. }
  149. `