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  }