1package main 2 3import ( 4 "encoding/json" 5 "errors" 6 "io/ioutil" 7 "log" 8 "os" 9 "strconv" 10 "strings" 11 "text/template" 12) 13 14func toInt(v interface{}) int { 15 switch v := v.(type) { 16 case float64: 17 return int(v) 18 case int: 19 return v 20 default: 21 return 0 22 } 23} 24 25func toString(v interface{}) string { 26 switch v := v.(type) { 27 case string: 28 return v 29 case int: 30 return strconv.Itoa(v) 31 default: 32 return "" 33 } 34} 35 36func main() { 37 funcMap := template.FuncMap{ 38 "xrange": func(args ...interface{}) (interface{}, error) { 39 if len(args) < 2 { 40 return nil, errors.New("need min and max argument") 41 } 42 43 min := toInt(args[0]) 44 max := toInt(args[1]) 45 var v []int 46 for i := min; i <= max; i++ { 47 v = append(v, i) 48 } 49 50 return v, nil 51 }, 52 "replace": func(args ...interface{}) (interface{}, error) { 53 if len(args) < 3 { 54 return nil, errors.New("need tmpl, old and new argument") 55 } 56 57 s := toString(args[0]) 58 o := toString(args[1]) 59 n := toString(args[2]) 60 61 return strings.Replace(s, o, n, -1), nil 62 }, 63 } 64 65 data := map[string]interface{}{} 66 if len(os.Args) > 1 { 67 r, err := os.Open(os.Args[1]) 68 if err != nil { 69 log.Fatalf("%s: %s", os.Args[1], err) 70 } 71 defer r.Close() 72 _ = json.NewDecoder(r).Decode(&data) 73 } 74 75 templateBytes, err := ioutil.ReadAll(os.Stdin) 76 if err != nil { 77 panic(err) 78 } 79 templateStr := string(templateBytes) 80 81 tmpl, err := template.New("").Funcs(funcMap).Parse(templateStr) 82 if err != nil { 83 log.Fatalf("template.New: %s", err) 84 } 85 86 err = tmpl.Execute(os.Stdout, &data) 87 if err != nil { 88 log.Fatalf("tmpl.Execute: %s", err) 89 } 90} 91