github.com/theliebeskind/genfig@v0.1.5-alpha/writers/config.go (about)

     1  package writers
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  
     9  	"github.com/imdario/mergo"
    10  
    11  	"github.com/theliebeskind/genfig/models"
    12  
    13  	"github.com/theliebeskind/genfig/util"
    14  	u "github.com/theliebeskind/genfig/util"
    15  )
    16  
    17  //WriteConfig writes
    18  func WriteConfig(w io.Writer, s models.SchemaMap, config map[string]interface{}, def map[string]interface{}, env string) (err error) {
    19  	defer func() {
    20  		if r := recover(); r != nil {
    21  			err = u.RecoverError(r)
    22  			return
    23  		}
    24  	}()
    25  
    26  	// first write into buffer, so that no gobbledygook is written
    27  	// into some files, when someting panics
    28  	buf := bytes.NewBuffer([]byte{})
    29  
    30  	// assigns this config to the according child of the global 'Envs' var
    31  	// via an init function
    32  	buf.Write(u.B("func init() {" + nl + indent + "Envs." + strings.Title(env) + " = "))
    33  
    34  	// write actual config
    35  	WriteConfigValue(buf, defaultSchemaRootName, def, config, s, 1)
    36  
    37  	merged := def
    38  	if err := mergo.Merge(&merged, config, mergo.WithOverride); err != nil {
    39  		panic(err)
    40  	}
    41  	buf.Write(u.B(nl + indent + "Envs." + strings.Title(env) + "._map = " + fmt.Sprintf("%#v", merged)))
    42  
    43  	// closing bracket of init func
    44  	buf.Write(u.B(nl + "}" + nl))
    45  
    46  	// now write buffer to writer
    47  	w.Write(buf.Bytes())
    48  
    49  	return
    50  }
    51  
    52  //WriteConfigLine writes
    53  func WriteConfigLine(w io.Writer, p string, k string, v interface{}, o interface{}, s models.SchemaMap, l int) {
    54  	if l > maxLevel {
    55  		panic(fmt.Errorf("Maximum of %d levels exceeded", maxLevel))
    56  	}
    57  
    58  	n := strings.Title(k)
    59  
    60  	if _, ex := s[p+n]; !ex {
    61  		panic(fmt.Errorf("Config property '%s' is not defined in the default config", p+n))
    62  	}
    63  
    64  	w.Write(u.B(indents[:l*len(indent)]))
    65  	w.Write(u.B(n + ": "))
    66  
    67  	WriteConfigValue(w, p+n, v, o, s, l)
    68  
    69  	w.Write(u.B("," + nl))
    70  }
    71  
    72  //WriteConfigValue writes
    73  func WriteConfigValue(w io.Writer, p string, v interface{}, o interface{}, s models.SchemaMap, l int) {
    74  	switch v.(type) {
    75  	case map[string]interface{}:
    76  		w.Write(u.B(p + "{" + nl))
    77  		for _k, _v := range v.(map[string]interface{}) {
    78  			_o := getOverwriteEntry(o, _k)
    79  			WriteConfigLine(w, p, _k, _v, _o, s, l+1)
    80  		}
    81  		w.Write(u.B(indents[:l*len(indent)]))
    82  		w.Write(u.B("}"))
    83  	case map[interface{}]interface{}:
    84  		w.Write(u.B(p + "{" + nl))
    85  		for _k, _v := range v.(map[interface{}]interface{}) {
    86  			_o := getOverwriteEntry(o, _k)
    87  			WriteConfigLine(w, p, fmt.Sprintf("%v", _k), _v, _o, s, l+1)
    88  		}
    89  		w.Write(u.B(indents[:l*len(indent)]))
    90  		w.Write(u.B("}"))
    91  	case []interface{}:
    92  		t := &v
    93  		if o != nil {
    94  			t = &o
    95  		}
    96  		typ := util.DetectSliceTypeString((*t).([]interface{}))
    97  		w.Write(u.B(strings.Replace(fmt.Sprintf("%#v", *t), "[]interface {}", typ, 1)))
    98  	default:
    99  		t := &v
   100  		if o != nil {
   101  			t = &o
   102  		}
   103  		fmt.Fprintf(w, `%#v`, *t)
   104  	}
   105  }
   106  
   107  func getOverwriteEntry(o interface{}, k interface{}) (r interface{}) {
   108  	if o == nil {
   109  		return
   110  	}
   111  	switch o.(type) {
   112  	case map[string]interface{}:
   113  		r = o.(map[string]interface{})[fmt.Sprintf("%v", k)]
   114  	case map[interface{}]interface{}:
   115  		r = o.(map[interface{}]interface{})[k]
   116  	}
   117  	return
   118  }