diff --git a/CHANGELOG.md b/CHANGELOG.md index 096c696..6c0c5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ Templar ChangeLog ================= +v0.2.0 +------ + +Added `Debug` attribute +Added TOML and YAML support +Temporarily switched to `github.com/runeimp/gotenv` from `github.com/subosito/gotenv` + + v0.1.1 ------ diff --git a/Justfile b/Justfile index b4230c7..978d46c 100644 --- a/Justfile +++ b/Justfile @@ -4,6 +4,8 @@ # alias ver := version +# set load-dotenv := false # Not supported yet +# load-dotenv := false # Like in make the first recipe is used by default. # I like listing all the recipes by default. @@ -44,11 +46,14 @@ _dir-list: # Distribution Helper @dist sub="release": just dist-{{sub}} + # Distribution Releaser dist-release: #!/bin/sh just _term-wipe just _clean + git checkout master + git push --all && git push --tags goreleaser # goreleaser release --skip-publish ver="$(git tag | tail -1)" @@ -61,6 +66,7 @@ dist-release: cd dist mv *.{deb,gz,md,rpm,txt,yaml,zip} ../distro/templar_${ver}/ fi + git checkout develop # Distribution Tester dist-test: @@ -72,6 +78,8 @@ dist-test: # Run the command line app run +args="": + just _term-wipe + # NOTE: Just itself ALWAYS loads a .env file if present go run cmd/templar/main.go {{args}} # Run a test @@ -79,6 +87,13 @@ run +args="": just _term-wipe just test-{{cmd}} "{{data}}" +# Run Go Unit Tests +@test-coverage +data='': + just _term-wipe + echo "You need to run:" + echo "go test -coverprofile=c.out" + echo "go tool cover -func=c.out" + # Test with debug enabled test-debug +data="example.env": @# CLI_ENV_VAR="Sound and fury" go run cmd/templar/main.go example.tmpl --data-file example.env CLI_VAR="As you like it" --debug diff --git a/README.md b/README.md index 95165e5..64cff3b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Templar ======= Templar Command Line Tool v2.0.0 -Templar Library v0.1.1 +Templar Library v0.2.0 Command line templating system written in Go. Though the initial idea was written in BASH. And that was cool; but that version had serious limitations as well. Go to the rescue! @@ -19,8 +19,8 @@ Features * [x] Option to exclude automatic loading of a local `.env` file * [x] INI file data * [x] JSON file data - * [ ] YAML file data - * [ ] TOML file data + * [x] YAML file data + * [x] TOML file data * [ ] XML file data? * [ ] CSV file data? * [ ] SQLite database query? @@ -69,7 +69,17 @@ Test Suite Test uses Go's normal unit testing tools at this time. -Test Coverage: 83.9% +Test Coverage: 78.1% + +It was 83.9% but I added more stuff to test. :angel: + + +ToDo +---- + +* [ ] Add MVVM features so that the data input can processed into a ViewModel to limit or manipulate the input in simple ways for the View (template) +* [ ] Complete the data input options +* [ ] Optimize the data processing. Make it more memory friendly on constrained systems and allow for say referencing (for instance) a terabyte sized CSV file for data input. diff --git a/cmd/templar/main.go b/cmd/templar/main.go index 69efd09..13ee852 100644 --- a/cmd/templar/main.go +++ b/cmd/templar/main.go @@ -1,6 +1,4 @@ -/* - * PACKAGE - */ +// PACKAGE package main /* @@ -17,21 +15,26 @@ import ( ) /* - * CONSTANTS + * APP CONSTANTS */ const ( - AppDesc = "Command line templating system based on Mustache template engine and data supplied by environment variables, ENV, INI, and JSON files. And soon YAML, and TOML files as well." + AppDesc = "Command line templating system based on Mustache template engine and data supplied by environment variables, ENV, INI, JSON, YAML, and TOML files. And soon CSV, XML, and SQLite files as well." AppName = "Templar" - AppVersion = "2.0.0" + AppVersion = "2.1.0" CLIName = "templar" ) +/* + * CONSTANTS + */ const ( ErrorENVParsing = iota + 50 ErrorINIParsing ErrorJSONParsing ErrorTemplateMissing ErrorTemplateRendering + ErrorTOMLParsing + ErrorYAMLParsing ) /* @@ -59,7 +62,9 @@ var cli struct { DataFile []string `short:"f" help:"Use the specified DATA_FILE to populate the template environment. File type determined by the extension on the file name." placeholder:"DATA_FILE" type:"existingfile"` DataINI []string `short:"i" help:"Use the specified INI_FILE (regardless of it's file extension) to populate the template environment." placeholder:"INI_FILE" type:"existingfile"` DataJSON []string `short:"j" help:"Use the specified JSON_FILE (regardless of it's file extension) to populate the template environment." placeholder:"JSON_FILE" type:"existingfile"` - Debug bool `help:"Show debug info on stderr." hidden` + DataTOML []string `short:"t" help:"Use the specified TOML_FILE (regardless of it's file extension) to populate the template environment." placeholder:"TOML_FILE" type:"existingfile"` + DataYAML []string `short:"y" help:"Use the specified YAML_FILE (regardless of it's file extension) to populate the template environment." placeholder:"YAML_FILE" type:"existingfile"` + Debug int `help:"Show debug info on stderr." default:"0" hidden` NoDotenv bool `short:"n" help:"Do not load a local .env file if present."` OutputFile string `short:"o" help:"Output to the specified file." placeholder:"FILE" sep:' ' type:"file"` Template string `arg optional help:"Specify the template file to render." type:"existingfile"` @@ -76,6 +81,8 @@ var ( envFiles []string iniFiles []string jsonFiles []string + tomlFiles []string + yamlFiles []string ) /* @@ -95,7 +102,7 @@ func init() { * MAIN ENTRYPOINT */ func main() { - if cli.Debug { + if cli.Debug > templar.DebugOff { fmt.Println(AppLabel) } @@ -109,6 +116,8 @@ func main() { os.Exit(ErrorTemplateMissing) } + templar.Debug = cli.Debug + // fmt.Printf("templar.main() | cli.DataFile = %q\n", cli.DataFile) for _, file := range cli.DataFile { ext := path.Ext(file) @@ -119,8 +128,12 @@ func main() { iniFiles = append(iniFiles, file) case ".JSON": jsonFiles = append(jsonFiles, file) + case ".TOML": + tomlFiles = append(tomlFiles, file) + case ".YAML": + yamlFiles = append(yamlFiles, file) default: - fmt.Errorf("Unknown data file type: %q\n", ext) + fmt.Errorf("Unknown data file type: %q", ext) } } // fmt.Printf("templar.main() | templar.Data = %#v\n", templar.Data) @@ -134,18 +147,26 @@ func main() { for _, file := range cli.DataJSON { jsonFiles = append(jsonFiles, file) } + for _, file := range cli.DataTOML { + tomlFiles = append(tomlFiles, file) + } + for _, file := range cli.DataYAML { + yamlFiles = append(yamlFiles, file) + } // templar.Data.Template = cli.Template checkDotEnv := !cli.NoDotenv // fmt.Printf("templar.main() | cli.Template = %q\n", cli.Template) // fmt.Printf("templar.main() | templar.Data = %#v\n", templar.Data) - if cli.Debug { - fmt.Printf("templar.main() | envFiles = %#v\n", envFiles) - fmt.Printf("templar.main() | iniFiles = %#v\n", iniFiles) - fmt.Printf("templar.main() | jsonFiles = %#v\n", jsonFiles) - fmt.Printf("templar.main() | template = %q\n", cli.Template) - fmt.Printf("templar.main() | checkDotEnv = %t\n", checkDotEnv) + if cli.Debug > templar.DebugOff { + fmt.Fprintf(os.Stderr, "templar.main() | envFiles = %#v\n", envFiles) + fmt.Fprintf(os.Stderr, "templar.main() | iniFiles = %#v\n", iniFiles) + fmt.Fprintf(os.Stderr, "templar.main() | jsonFiles = %#v\n", jsonFiles) + fmt.Fprintf(os.Stderr, "templar.main() | tomlFiles = %#v\n", tomlFiles) + fmt.Fprintf(os.Stderr, "templar.main() | yamlFiles = %#v\n", yamlFiles) + fmt.Fprintf(os.Stderr, "templar.main() | template = %q\n", cli.Template) + fmt.Fprintf(os.Stderr, "templar.main() | checkDotEnv = %t\n", checkDotEnv) } err := templar.InitData(checkDotEnv, envFiles...) @@ -166,6 +187,18 @@ func main() { os.Exit(ErrorJSONParsing) } + err = templar.InitData(checkDotEnv, tomlFiles...) + if err != nil { + fmt.Fprintf(os.Stderr, "TOML File Parsing Error: %s\n", err.Error()) + os.Exit(ErrorTOMLParsing) + } + + err = templar.InitData(checkDotEnv, yamlFiles...) + if err != nil { + fmt.Fprintf(os.Stderr, "YAML File Parsing Error: %s\n", err.Error()) + os.Exit(ErrorYAMLParsing) + } + if len(cli.OutputFile) > 0 { _, err := templar.RenderToFile(cli.OutputFile, cli.Template) if err != nil { diff --git a/example.toml b/example.toml new file mode 100644 index 0000000..5259457 --- /dev/null +++ b/example.toml @@ -0,0 +1,11 @@ +all = ["your", "base", "are", "belong", "to", "us"] +boolean = false +# void = + +[one] + two-point-one = 2.1 + + [one.two] + five = "six" + four = true + three = 4 diff --git a/example.yaml b/example.yaml new file mode 100644 index 0000000..d30e4f5 --- /dev/null +++ b/example.yaml @@ -0,0 +1,9 @@ +all: ["your", "base", "are", "belong", "to", "us"] +one: + two: + three: 4 + four: true + five: six + two-point-one: 2.1 +boolean: false +void: null diff --git a/go.mod b/go.mod index 565f06c..efec21e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,10 @@ go 1.13 require ( github.com/alecthomas/kong v0.2.1 github.com/cbroglie/mustache v1.0.1 + github.com/pelletier/go-toml v1.8.0 + github.com/runeimp/gotenv v1.3.0 github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect - github.com/subosito/gotenv v1.2.0 + github.com/subosito/gotenv v1.2.0 // indirect gopkg.in/ini.v1 v1.51.0 + gopkg.in/yaml.v2 v2.3.0 ) diff --git a/go.sum b/go.sum index 02daa28..a6ce0d8 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,10 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/alecthomas/kong v0.2.1 h1:V1tLBhyQBC4rsbXbcOvm3GBaytJSwRNX69fp1WJxbqQ= github.com/alecthomas/kong v0.2.1/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= github.com/cbroglie/mustache v1.0.1 h1:ivMg8MguXq/rrz2eu3tw6g3b16+PQhoTn6EZAhst2mw= github.com/cbroglie/mustache v1.0.1/go.mod h1:R/RUa+SobQ14qkP4jtx5Vke5sDytONDQXNLPY/PO69g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= @@ -9,16 +12,23 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= +github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/runeimp/gotenv v1.3.0 h1:G8nyaB/v0l/8RLWr4JgYDjcFkB0MC3zw2BAm1iXP1eg= +github.com/runeimp/gotenv v1.3.0/go.mod h1:FO1U4BwxNeuduJ9KJf16W+MIZcVBoFwdGIVt+rVfYdk= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -26,5 +36,11 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/templar.go b/templar.go index 788d4a0..54b29dd 100644 --- a/templar.go +++ b/templar.go @@ -9,32 +9,50 @@ import ( "strings" "github.com/cbroglie/mustache" - "github.com/subosito/gotenv" + // "github.com/subosito/gotenv" + toml "github.com/pelletier/go-toml" + "github.com/runeimp/gotenv" ini "gopkg.in/ini.v1" + yaml "gopkg.in/yaml.v2" ) /* - * CONSTANTS + * LIB CONSTANTS */ const ( // Name denotes the library name Name = "Templar" // Version denotes the library version - Version = "0.1.1" + Version = "0.2.0" +) + +/* + * CONSTANTS + */ +const ( + DebugOff = 0 + DebugError = 1 + DebugWarn = 2 + DebugInfo = 3 + DebugLog = 4 ) /* * VARIABLES */ var ( + // envBackupData map[string]string dataProvider map[string]interface{} + Debug = DebugWarn initialized = false ) /* * TYPES */ + +// Data is a collection for all external data var Data struct { INIFile []string JSONFile []string @@ -44,11 +62,24 @@ var Data struct { /* * METHODS */ + +func debugDataPrint(l string, m map[string]interface{}) { + fmt.Fprintf(os.Stderr, l) + jsonBytes, _ := json.MarshalIndent(m, "", " ") + fmt.Println(string(jsonBytes)) + fmt.Printf("\n\n") +} + func init() { dataProvider = make(map[string]interface{}) } +// InitData initializes the template environment with external data func InitData(checkDotEnv bool, files ...string) (err error) { + if Debug >= DebugInfo { + fmt.Fprintf(os.Stderr, "templar.InitData() | checkDotEnv = %t | initialized = %t\n", checkDotEnv, initialized) + } + if initialized == false { if checkDotEnv { gotenv.OverLoad() @@ -64,7 +95,18 @@ func InitData(checkDotEnv bool, files ...string) (err error) { return err } +func mapMerge(a map[string]interface{}, b map[string]interface{}) map[string]interface{} { + for k, v := range b { + a[k] = v + } + + return a +} + func parseEnvironment() { + if Debug >= DebugInfo { + fmt.Fprintf(os.Stderr, "templar.parseEnvironment() | initialized = %t\n", initialized) + } for _, base := range os.Environ() { pair := strings.SplitN(base, "=", 2) k := pair[0] @@ -74,12 +116,17 @@ func parseEnvironment() { } func parseFileData(file string) (err error) { + if Debug >= DebugInfo { + fmt.Fprintf(os.Stderr, "templar.parseFileData() | file = %q\n", file) + } if len(file) > 0 { ext := path.Ext(file) switch strings.ToUpper(ext) { case ".ENV": - err = gotenv.OverLoad(file) - parseEnvironment() + err = ParseENV(file) + if err != nil { + return err + } case ".INI": err = ParseINI(file) if err != nil { @@ -90,14 +137,36 @@ func parseFileData(file string) (err error) { if err != nil { return err } + case ".TOML": + err = ParseTOML(file) + if err != nil { + return err + } + case ".YAML": + err = ParseYAML(file) + if err != nil { + return err + } default: - fmt.Errorf("Unknown data file type: %q\n", ext) + fmt.Errorf("Unknown data file type: %q", ext) } } return err } +// ParseENV loads ENV file data into the dataProvider +func ParseENV(file string) (err error) { + if Debug >= DebugInfo { + fmt.Fprintf(os.Stderr, "templar.parseFileData() | .ENV | gotenv.OverLoad(%q)\n", file) + } + err = gotenv.OverLoad(file) + parseEnvironment() + + return err +} + +// ParseINI loads INI file data into the dataProvider func ParseINI(file string) (err error) { var iniData *ini.File iniData, err = ini.Load(file) @@ -122,30 +191,87 @@ func ParseINI(file string) (err error) { return err } +// ParseJSON loads JSON file data into the dataProvider func ParseJSON(file string) (err error) { - var jsonData []byte + var ( + jsonBytes []byte + jsonProvider map[string]interface{} + ) + + if len(file) > 0 { + jsonBytes, err = ioutil.ReadFile(file) + if err != nil { + return err + } + err = json.Unmarshal(jsonBytes, &jsonProvider) + if err == nil { + dataProvider = mapMerge(dataProvider, jsonProvider) + } + } + + return err +} + +// ParseTOML loads TOML file data into the dataProvider +func ParseTOML(file string) (err error) { + var ( + tomlBytes []byte + tomlProvider map[string]interface{} + ) + + if len(file) > 0 { + tomlBytes, err = ioutil.ReadFile(file) + if err != nil { + return err + } + err = toml.Unmarshal(tomlBytes, &tomlProvider) + if err == nil { + dataProvider = mapMerge(dataProvider, tomlProvider) + } + } + + return err +} + +// ParseYAML loads YAML file data into the dataProvider +func ParseYAML(file string) (err error) { + var ( + yamlBytes []byte + yamlProvider map[string]interface{} + ) if len(file) > 0 { - jsonData, err = ioutil.ReadFile(file) + yamlBytes, err = ioutil.ReadFile(file) if err != nil { return err } - err = json.Unmarshal(jsonData, &dataProvider) + err = yaml.Unmarshal(yamlBytes, &yamlProvider) + if err == nil { + dataProvider = mapMerge(dataProvider, yamlProvider) + } } return err } -func Reinitialize() { +// Reinitialize resets the dataProvider +func Reinitialize(debug int) { + Debug = debug + if Debug >= DebugInfo { + fmt.Fprintf(os.Stderr, "templar.Reinitialize() | debug = %d | initialized = %t\n", debug, initialized) + } dataProvider = make(map[string]interface{}) + gotenv.Reset() initialized = false } +// Render handles template rendering func Render(template string) (output string, err error) { output, err = mustache.RenderFile(template, dataProvider) return output, err } +// RenderToFile handles rendering templates to file func RenderToFile(filename, template string) (output string, err error) { output, err = mustache.RenderFile(template, dataProvider) if err != nil { diff --git a/templar_test.go b/templar_test.go index 5f8456e..bf6ad11 100644 --- a/templar_test.go +++ b/templar_test.go @@ -1,12 +1,13 @@ package templar import ( - "os" - "testing" + "fmt" + "os" + "testing" ) -var noDotEnvExpectation = `Hello Oedipus! -How do you like it in "/Users/runeimp/dev/apps/templar"? +var exampleDotEnvExpectation = `Hello Oedipus! +How do you like it in "/Users/runeimp/Dropbox/Profile/Home/dev/apps/templar"? ENV_FILE_COMMENT == '' ENV_FILE_VAR == 'The Bard' @@ -23,7 +24,7 @@ DEFAULT.global_ini == ` var dotEnvExpectation = `Hello Horatio! -How do you like it in "/Users/runeimp/dev/apps/templar"? +How do you like it in "/Users/runeimp/Dropbox/Profile/Home/dev/apps/templar"? ENV_FILE_COMMENT == '' ENV_FILE_VAR == '.env Ninja!' @@ -40,7 +41,7 @@ DEFAULT.global_ini == ` var dotEnvAndINIExpectation = `Hello Hamlet! -How do you like it in "/Users/runeimp/dev/apps/templar"? +How do you like it in "/Users/runeimp/Dropbox/Profile/Home/dev/apps/templar"? ENV_FILE_COMMENT == '' ENV_FILE_VAR == '.env Ninja!' @@ -56,8 +57,25 @@ DEFAULT.global_ini == true ` +var dotEnvINIAndTOMLExpectation = `Hello Hamlet! +How do you like it in "/Users/runeimp/Dropbox/Profile/Home/dev/apps/templar"? + + ENV_FILE_COMMENT == '' + ENV_FILE_VAR == '.env Ninja!' + CLI_ENV_VAR == 'Sound and fury' + CLI_VAR == 'As you like it' + boolean == false + one.two.three == 4 + numbers.two == 2.1 + all == your base are belong to us + words.all == your base are belong to us + POSIX == Awesome! +DEFAULT.global_ini == true + +` + var dotEnvAndJSONExpectation = `Hello Horatio! -How do you like it in "/Users/runeimp/dev/apps/templar"? +How do you like it in "/Users/runeimp/Dropbox/Profile/Home/dev/apps/templar"? ENV_FILE_COMMENT == '' ENV_FILE_VAR == '.env Ninja!' @@ -73,86 +91,56 @@ DEFAULT.global_ini == ` +var noDotEnvExpectation = `Hello runeimp! +How do you like it in "/Users/runeimp/Dropbox/Profile/Home/dev/apps/templar"? + + ENV_FILE_COMMENT == '' + ENV_FILE_VAR == '' + CLI_ENV_VAR == 'Sound and fury' + CLI_VAR == 'As you like it' + boolean == + one.two.three == + numbers.two == + all == + words.all == + POSIX == +DEFAULT.global_ini == + +` + func TestTemplar(t *testing.T) { - tests := []struct { - name string - checkDotEnv bool - data []string - template string - want string - }{ - {name: ".env", template: "example.tmpl", checkDotEnv: true, want: dotEnvExpectation}, - {name: ".env and example.ini", template: "example.tmpl", checkDotEnv: true, data: []string{"example.ini"}, want: dotEnvAndINIExpectation}, - {name: ".env and example.json", template: "example.tmpl", checkDotEnv: true, data: []string{"example.json"}, want: dotEnvAndJSONExpectation}, - {name: "example.env", template: "example.tmpl", checkDotEnv: false, data: []string{"example.env"}, want: noDotEnvExpectation}, - } - - for _, tc := range tests { - Reinitialize() - os.Setenv("CLI_ENV_VAR", "Sound and fury") - os.Setenv("CLI_VAR", "As you like it") - if len(tc.data) == 0 { - InitData(tc.checkDotEnv) - } else { - for _, file := range tc.data { - InitData(tc.checkDotEnv, file) - } - } - got, _ := Render(tc.template) - if tc.want != got { - t.Fatalf(`"%s": expected: %v, got: %v`, tc.name, tc.want, got) - } - } + tests := []struct { + name string + checkDotEnv bool + data []string + template string + want string + }{ + {name: ".env", template: "example.tmpl", checkDotEnv: true, want: dotEnvExpectation}, + {name: ".env and example.ini", template: "example.tmpl", checkDotEnv: true, data: []string{"example.ini"}, want: dotEnvAndINIExpectation}, + {name: ".env and example.json", template: "example.tmpl", checkDotEnv: true, data: []string{"example.json"}, want: dotEnvAndJSONExpectation}, + {name: ".env and example.toml", template: "example.tmpl", checkDotEnv: true, data: []string{"example.toml"}, want: dotEnvAndJSONExpectation}, + {name: ".env and example.yaml", template: "example.tmpl", checkDotEnv: true, data: []string{"example.yaml"}, want: dotEnvAndJSONExpectation}, + {name: ".env, example.ini, and example.toml", template: "example.tmpl", checkDotEnv: true, data: []string{"example.ini", "example.toml"}, want: dotEnvINIAndTOMLExpectation}, + {name: "example.env", template: "example.tmpl", checkDotEnv: false, data: []string{"example.env"}, want: exampleDotEnvExpectation}, + {name: "no.env", template: "example.tmpl", checkDotEnv: false, want: noDotEnvExpectation}, + } + + for _, tc := range tests { + debug := DebugWarn + Reinitialize(debug) + os.Setenv("CLI_ENV_VAR", "Sound and fury") + os.Setenv("CLI_VAR", "As you like it") + if len(tc.data) == 0 { + InitData(tc.checkDotEnv) + } else { + for _, file := range tc.data { + InitData(tc.checkDotEnv, file) + } + } + got, _ := Render(tc.template) + if tc.want != got { + t.Fatalf(fmt.Sprintf("%q:\n\texpected: %v\n\tgot: %v\n\t | tc.checkDotEnv = %t\n", tc.name, tc.want, got, tc.checkDotEnv)) + } + } } - -// func TestDotEnv(t *testing.T) { -// Reinitialize() -// os.Setenv("CLI_ENV_VAR", "Sound and fury") -// os.Setenv("CLI_VAR", "As you like it") -// checkDotEnv := true -// want := dotEnvExpectation -// InitData(checkDotEnv) -// got, _ := Render("example.tmpl") -// if got != want { -// t.Fatalf("expected: %v, got: %v", want, got) -// } -// } - -// func TestDotEnvAndINI(t *testing.T) { -// Reinitialize() -// os.Setenv("CLI_ENV_VAR", "Sound and fury") -// os.Setenv("CLI_VAR", "As you like it") -// checkDotEnv := true -// want := dotEnvAndINIExpectation -// InitData(checkDotEnv, "example.ini") -// got, _ := Render("example.tmpl") -// if got != want { -// t.Fatalf("expected: %v, got: %v", want, got) -// } -// } - -// func TestDotEnvAndJSON(t *testing.T) { -// Reinitialize() -// os.Setenv("CLI_ENV_VAR", "Sound and fury") -// os.Setenv("CLI_VAR", "As you like it") -// checkDotEnv := true -// want := dotEnvAndJSONExpectation -// InitData(checkDotEnv, "example.json") -// got, _ := Render("example.tmpl") -// if got != want { -// t.Fatalf("expected: %v, got: %v", want, got) -// } -// } - -// func TestNoDotEnv(t *testing.T) { -// Reinitialize() -// os.Setenv("CLI_ENV_VAR", "Sound and fury") -// os.Setenv("CLI_VAR", "As you like it") -// checkDotEnv := false -// want := noDotEnvExpectation -// InitData(checkDotEnv, "example.env") -// got, _ := Render("example.tmpl") -// if got != want { -// t.Fatalf("expected: %v, got: %v", want, got) -// } -// }