github.com/theliebeskind/genfig@v0.1.5-alpha/plugins/substitutor.go (about) 1 package plugins 2 3 import ( 4 "io" 5 "strings" 6 "text/template" 7 8 "github.com/theliebeskind/genfig/models" 9 ) 10 11 type substitutorPlugin struct { 12 s models.SchemaMap 13 tpl *template.Template 14 } 15 16 var ( 17 substitutor = substitutorPlugin{ 18 s: models.SchemaMap{}, 19 tpl: template.Must(template. 20 New("substitutor"). 21 Funcs(template.FuncMap{ 22 // Convert an env var name to a substitution path 23 "makeSubstPath": func(s string) string { 24 return strings.ToLower(strings.Join(strings.Split(s, "_")[1:], ".")) 25 }, 26 // Convert an env var name to a Config path 27 "makePath": func(s string) string { 28 return strings.Join(strings.Split(s, "_")[1:], ".") 29 }, 30 }). 31 Parse(`import ( 32 "strings" 33 ) 34 35 var _ = strings.Contains 36 37 const ( 38 maxSubstitutionIteraions = 5 39 ) 40 41 var ( 42 raw Config 43 ) 44 45 // Substitute replaces all. 46 // The return value informs, whether all substitutions could be 47 // applied within {maxSubstitutionIteraions} or not 48 func (c *Config) Substitute() bool { 49 c.ResetSubstitution() 50 51 // backup the "raw" configuration 52 raw = *c 53 54 run := 0 55 for { 56 if run == maxSubstitutionIteraions { 57 return false 58 } 59 if c.substitute() == 0 { 60 return true 61 } 62 run += 1 63 } 64 } 65 66 // ResetSubstitution resets the configuration to the state, 67 // before the substitution was applied 68 func (c *Config) ResetSubstitution() { 69 c = &raw 70 } 71 72 // substitute tries to replace all substitutions in strings 73 func (c *Config) substitute() int { 74 cnt := 0 75 76 r := strings.NewReplacer({{range $_, $v := .}}{{if eq $v.Content "string"}} 77 "${{"{"}}{{makeSubstPath $v.Path}}{{"}"}}", c.{{makePath $v.Path}}, 78 {{end}}{{end}}) 79 80 {{range $_, $v := .}}{{if eq $v.Content "string"}} 81 if strings.Contains(c.{{makePath $v.Path}}, "${") { 82 cnt += 1 83 c.{{makePath $v.Path}} = r.Replace(c.{{makePath $v.Path}}) 84 if !strings.Contains(c.{{makePath $v.Path}}, "${") { 85 cnt -= 1 86 } 87 } 88 {{end}}{{end}} 89 90 return cnt 91 } 92 `))} 93 ) 94 95 func init() { 96 // "register" plugin 97 Plugins["substitutor"] = &substitutor 98 } 99 100 // GetInitCall returns the availibility and the string of the 101 // function to be called on init 102 func (p *substitutorPlugin) GetInitCall() (string, bool) { 103 return "Current.Substitute()", true 104 } 105 106 // SetSchemaMap sets the schema to be used when WriteTo is called 107 func (p *substitutorPlugin) SetSchemaMap(s models.SchemaMap) { 108 p.s = s 109 } 110 111 // WriteTo performs the acutal writing to a buffer (or io.Writer). 112 // For this plugin, the template is simply "rendered" into the writer. 113 func (p *substitutorPlugin) WriteTo(w io.Writer) (l int64, err error) { 114 err = p.tpl.Execute(w, p.s) 115 return 116 }