main.go 3.2 KB

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