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