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  }