github.com/codyleyhan/gqlgen@v0.4.4/codegen/templates/templates.go (about) 1 //go:generate go run ./inliner/inliner.go 2 3 package templates 4 5 import ( 6 "bytes" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "sort" 12 "strconv" 13 "strings" 14 "text/template" 15 "unicode" 16 17 "log" 18 19 "github.com/pkg/errors" 20 "golang.org/x/tools/imports" 21 ) 22 23 func Run(name string, tpldata interface{}) (*bytes.Buffer, error) { 24 t := template.New("").Funcs(template.FuncMap{ 25 "ucFirst": ucFirst, 26 "lcFirst": lcFirst, 27 "quote": strconv.Quote, 28 "rawQuote": rawQuote, 29 "toCamel": ToCamel, 30 "dump": dump, 31 "prefixLines": prefixLines, 32 }) 33 34 for filename, data := range data { 35 _, err := t.New(filename).Parse(data) 36 if err != nil { 37 panic(err) 38 } 39 } 40 41 buf := &bytes.Buffer{} 42 err := t.Lookup(name).Execute(buf, tpldata) 43 if err != nil { 44 return nil, err 45 } 46 47 return buf, nil 48 } 49 50 func ucFirst(s string) string { 51 if s == "" { 52 return "" 53 } 54 r := []rune(s) 55 r[0] = unicode.ToUpper(r[0]) 56 return string(r) 57 } 58 59 func lcFirst(s string) string { 60 if s == "" { 61 return "" 62 } 63 64 r := []rune(s) 65 r[0] = unicode.ToLower(r[0]) 66 return string(r) 67 } 68 69 func isDelimiter(c rune) bool { 70 return c == '-' || c == '_' || unicode.IsSpace(c) 71 } 72 73 func ToCamel(s string) string { 74 buffer := make([]rune, 0, len(s)) 75 upper := true 76 lastWasUpper := false 77 78 for _, c := range s { 79 if isDelimiter(c) { 80 upper = true 81 continue 82 } 83 if !lastWasUpper && unicode.IsUpper(c) { 84 upper = true 85 } 86 87 if upper { 88 buffer = append(buffer, unicode.ToUpper(c)) 89 } else { 90 buffer = append(buffer, unicode.ToLower(c)) 91 } 92 upper = false 93 lastWasUpper = unicode.IsUpper(c) 94 } 95 96 return string(buffer) 97 } 98 99 func rawQuote(s string) string { 100 return "`" + strings.Replace(s, "`", "`+\"`\"+`", -1) + "`" 101 } 102 103 func dump(val interface{}) string { 104 switch val := val.(type) { 105 case int: 106 return strconv.Itoa(val) 107 case int64: 108 return fmt.Sprintf("%d", val) 109 case float64: 110 return fmt.Sprintf("%f", val) 111 case string: 112 return strconv.Quote(val) 113 case bool: 114 return strconv.FormatBool(val) 115 case nil: 116 return "nil" 117 case []interface{}: 118 var parts []string 119 for _, part := range val { 120 parts = append(parts, dump(part)) 121 } 122 return "[]interface{}{" + strings.Join(parts, ",") + "}" 123 case map[string]interface{}: 124 buf := bytes.Buffer{} 125 buf.WriteString("map[string]interface{}{") 126 var keys []string 127 for key := range val { 128 keys = append(keys, key) 129 } 130 sort.Strings(keys) 131 132 for _, key := range keys { 133 data := val[key] 134 135 buf.WriteString(strconv.Quote(key)) 136 buf.WriteString(":") 137 buf.WriteString(dump(data)) 138 buf.WriteString(",") 139 } 140 buf.WriteString("}") 141 return buf.String() 142 default: 143 panic(fmt.Errorf("unsupported type %T", val)) 144 } 145 } 146 147 func prefixLines(prefix, s string) string { 148 return prefix + strings.Replace(s, "\n", "\n"+prefix, -1) 149 } 150 151 func RenderToFile(tpl string, filename string, data interface{}) error { 152 var buf *bytes.Buffer 153 buf, err := Run(tpl, data) 154 if err != nil { 155 return errors.Wrap(err, filename+" generation failed") 156 } 157 158 if err := write(filename, buf.Bytes()); err != nil { 159 return err 160 } 161 162 log.Println(filename) 163 164 return nil 165 } 166 167 func gofmt(filename string, b []byte) ([]byte, error) { 168 out, err := imports.Process(filename, b, nil) 169 if err != nil { 170 return b, errors.Wrap(err, "unable to gofmt") 171 } 172 return out, nil 173 } 174 175 func write(filename string, b []byte) error { 176 err := os.MkdirAll(filepath.Dir(filename), 0755) 177 if err != nil { 178 return errors.Wrap(err, "failed to create directory") 179 } 180 181 formatted, err := gofmt(filename, b) 182 if err != nil { 183 fmt.Fprintf(os.Stderr, "gofmt failed: %s\n", err.Error()) 184 formatted = b 185 } 186 187 err = ioutil.WriteFile(filename, formatted, 0644) 188 if err != nil { 189 return errors.Wrapf(err, "failed to write %s", filename) 190 } 191 192 return nil 193 }