commit 40334f2ac36e907b6b8c1a54462046d94cbf25f1
parent 0ae83bdad1a16e81b663da77005935200132dd74
Author: gearsix <gearsix@tuta.io>
Date: Sun, 14 Mar 2021 13:21:39 +0000
added yaml support; ran gofmt
Diffstat:
6 files changed, 134 insertions(+), 77 deletions(-)
diff --git a/src/_test.go b/src/_test.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "os"
+ "testing"
+)
+
+func writeFile(path string, data string) (e error) {
+ var f *os.File
+
+ if f, e = os.Create(path); e != nil {
+ return
+ }
+ if _, e = f.WriteString(data); e != nil {
+ return
+ }
+ f.Close()
+
+ return
+}
diff --git a/src/data.go b/src/data.go
@@ -3,13 +3,14 @@ package main
import (
"encoding/json"
"fmt"
+ "gopkg.in/yaml.v3"
"io"
"io/ioutil"
"os"
- "time"
"path/filepath"
- "strings"
"sort"
+ "strings"
+ "time"
)
// Data is the data type used to represent parsed Data (in any format).
@@ -23,7 +24,9 @@ func getDataType(path string) string {
func LoadData(lang string, in io.Reader) (d Data, e error) {
var fbuf []byte
if fbuf, e = ioutil.ReadAll(in); e != nil {
- return
+ return make(Data), e
+ } else if len(fbuf) == 0 {
+ return make(Data), nil
}
if lang == "json" {
@@ -32,6 +35,8 @@ func LoadData(lang string, in io.Reader) (d Data, e error) {
} else {
e = fmt.Errorf("invalid json %s", fbuf)
}
+ } else if lang == "yaml" {
+ e = yaml.Unmarshal(fbuf, &d)
} else {
e = fmt.Errorf("'%s' is not a supported data language", lang)
}
@@ -95,13 +100,13 @@ func LoadDataFiles(order string, paths ...string) []Data {
}
}
}
-
+
return sortFileData(loaded, order)
}
func sortFileData(data map[string]Data, order string) []Data {
sorted := make([]Data, 0, len(data))
-
+
if strings.HasPrefix(order, "filename") {
if order == "filename-desc" {
sorted = sortFileDataFilename("desc", data)
@@ -123,7 +128,7 @@ func sortFileData(data map[string]Data, order string) []Data {
sorted = append(sorted, d)
}
}
-
+
return sorted
}
@@ -134,9 +139,9 @@ func sortFileDataFilename(direction string, data map[string]Data) []Data {
fnames = append(fnames, filepath.Base(fpath))
}
sort.Strings(fnames)
-
+
if direction == "desc" {
- for i := len(fnames)-1; i >= 0; i-- {
+ for i := len(fnames) - 1; i >= 0; i-- {
for fpath, d := range data {
if fnames[i] == filepath.Base(fpath) {
sorted = append(sorted, d)
@@ -145,11 +150,11 @@ func sortFileDataFilename(direction string, data map[string]Data) []Data {
}
} else {
for _, fname := range fnames {
- for fpath, d := range data {
- if fname == filepath.Base(fpath) {
- sorted = append(sorted, d)
- }
- }
+ for fpath, d := range data {
+ if fname == filepath.Base(fpath) {
+ sorted = append(sorted, d)
+ }
+ }
}
}
return sorted
@@ -165,7 +170,7 @@ func sortFileDataModified(direction string, data map[string]Data) []Data {
stats[fpath] = stat
}
}
-
+
modtimes := make([]time.Time, 0, len(data))
for _, stat := range stats {
modtimes = append(modtimes, stat.ModTime())
@@ -179,7 +184,7 @@ func sortFileDataModified(direction string, data map[string]Data) []Data {
return modtimes[i].Before(modtimes[j])
})
}
-
+
for _, t := range modtimes {
for fpath, stat := range stats {
if t == stat.ModTime() {
@@ -197,28 +202,28 @@ func GenerateSuperData(datakey string, d []Data, global ...Data) (superd Data) {
datakey = "data"
}
superd = MergeData(global...)
-
+
if superd[datakey] != nil {
warn("global data has a key matching the datakey ('%s')\n",
- "this value of this key will be overwritten")
+ "this value of this key will be overwritten")
}
superd[datakey] = d
return
}
-
- // MergeData combines all keys in `data` into a single Data object. If there's
- // a conflict (duplicate key), the first found value is kept and the conflicting
- // values are ignored.
- func MergeData(data ...Data) Data {
- merged := make(Data)
- for _, d := range data {
- for k, v := range d {
- if merged[k] == nil {
- merged[k] = v
- } else {
- warn("merge conflict for data key '%s'\n", k)
- }
- }
- }
- return merged
- }
-\ No newline at end of file
+
+// MergeData combines all keys in `data` into a single Data object. If there's
+// a conflict (duplicate key), the first found value is kept and the conflicting
+// values are ignored.
+func MergeData(data ...Data) Data {
+ merged := make(Data)
+ for _, d := range data {
+ for k, v := range d {
+ if merged[k] == nil {
+ merged[k] = v
+ } else {
+ warn("merge conflict for data key '%s'\n", k)
+ }
+ }
+ }
+ return merged
+}
diff --git a/src/data_test.go b/src/data_test.go
@@ -2,14 +2,21 @@ package main
import (
"encoding/json"
+ "gopkg.in/yaml.v3"
"os"
"strings"
"testing"
)
-const goodJson1 = `{"example1":0}`
-const goodJson2 = `{"example2":1}`
-const badJson = `{"example":2:]}}`
+const goodJson1 = `{"json":0}`
+const goodJson2 = `{"json":1}`
+const badJson = `{"json":2:]}}`
+
+const goodYaml1 = `yaml: 0
+`
+const goodYaml2 = `yaml: "1"
+`
+const badYaml = `"yaml--: '2`
func writeTestFile(path string, Data string) (e error) {
var f *os.File
@@ -41,12 +48,29 @@ func TestLoadData(t *testing.T) {
t.Errorf("incorrect json: %s does not match %s", b, goodJson1)
}
}
-
if d, e = LoadData("json", strings.NewReader(badJson)); e == nil {
t.Error("bad.json passed")
}
- if d, e = LoadData("json", strings.NewReader("")); e == nil {
- t.Error("empty file passed")
+ if d, e = LoadData("json", strings.NewReader("")); e != nil || len(d) > 0 {
+ t.Errorf("empty file failed: %s, %s", d, e)
+ }
+
+ if d, e = LoadData("yaml", strings.NewReader(goodYaml1)); e != nil {
+ t.Error(e)
+ } else if len(d) == 0 {
+ t.Error("no data loaded")
+ } else {
+ if b, e = yaml.Marshal(d); e != nil {
+ t.Error(e)
+ } else if string(b) != goodYaml1 {
+ t.Errorf("incorrect yaml: %s does not match %s", b, goodYaml1)
+ }
+ }
+ if d, e = LoadData("yaml", strings.NewReader(badYaml)); e == nil {
+ t.Error("bad.yaml passed")
+ }
+ if d, e = LoadData("yaml", strings.NewReader("")); e != nil || len(d) > 0 {
+ t.Errorf("empty file failed: %s, %s", d, e)
}
return
@@ -63,8 +87,8 @@ func TestLoadDataFiles(t *testing.T) {
if e = writeTestFile(p[0], goodJson2); e != nil {
t.Skip("setup failure:", e)
}
- p = append(p, tdir+"/good1.json")
- if e = writeTestFile(p[1], goodJson1); e != nil {
+ p = append(p, tdir+"/good1.yaml")
+ if e = writeTestFile(p[1], goodYaml1); e != nil {
t.Skip("setup failure:", e)
}
p = append(p, tdir+"/bad.json")
@@ -83,52 +107,52 @@ func TestLoadDataFiles(t *testing.T) {
} else if string(b) == goodJson2 {
t.Error("data returned out of order")
}
-
- if b, e = json.Marshal(d[1]); e != nil {
+
+ if b, e = yaml.Marshal(d[1]); e != nil {
t.Error(e)
- } else if string(b) == goodJson1 {
+ } else if string(b) == goodYaml1 {
t.Error("data returned out of order")
}
}
-
- d = LoadDataFiles("filename-desc", tdir + "/*")
+
+ d = LoadDataFiles("filename-desc", tdir+"/*")
if len(d) == len(p) {
t.Error("bad.json passed")
} else if len(d) == 0 {
t.Error("no data loaded")
} else {
- if b, e = json.Marshal(d[0]); e != nil {
+ if b, e = yaml.Marshal(d[0]); e != nil {
t.Error(e)
- } else if string(b) == goodJson1 {
+ } else if string(b) == goodYaml1 {
t.Error("data returned out of order")
}
-
+
if b, e = json.Marshal(d[1]); e != nil {
t.Error(e)
} else if string(b) == goodJson2 {
t.Error("data returned out of order")
}
}
-
+
d = LoadDataFiles("modified", p...)
if len(d) == len(p) {
t.Error("bad.json passed")
} else if len(d) == 0 {
t.Error("no data loaded")
} else {
- if b, e = json.Marshal(d[0]); e != nil {
+ if b, e = yaml.Marshal(d[0]); e != nil {
t.Error(e)
- } else if string(b) == goodJson1 {
+ } else if string(b) == goodYaml1 {
t.Error("data returned out of order")
}
-
+
if b, e = json.Marshal(d[1]); e != nil {
t.Error(e)
} else if string(b) == goodJson2 {
t.Error("data returned out of order")
}
}
-
+
d = LoadDataFiles("modified-desc", p...)
if len(d) == len(p) {
t.Error("bad.json passed")
@@ -140,10 +164,10 @@ func TestLoadDataFiles(t *testing.T) {
} else if string(b) == goodJson2 {
t.Error("data returned out of order")
}
-
- if b, e = json.Marshal(d[1]); e != nil {
+
+ if b, e = yaml.Marshal(d[1]); e != nil {
t.Error(e)
- } else if string(b) == goodJson1 {
+ } else if string(b) == goodYaml1 {
t.Error("data returned out of order")
}
}
@@ -153,7 +177,7 @@ func TestMergeData(t *testing.T) {
var e error
var d []Data
var m Data
-
+
if m, e = LoadData("json", strings.NewReader(goodJson1)); e == nil {
d = append(d, m)
} else {
@@ -164,10 +188,20 @@ func TestMergeData(t *testing.T) {
} else {
t.Skip("setup failure:", e)
}
-
+ if m, e = LoadData("json", strings.NewReader(goodYaml1)); e == nil {
+ d = append(d, m)
+ } else {
+ t.Skip("setup failure:", e)
+ }
+ if m, e = LoadData("json", strings.NewReader(goodYaml2)); e == nil {
+ d = append(d, m)
+ } else {
+ t.Skip("setup failure:", e)
+ }
+
m = nil
m = MergeData(d...)
- if m["example1"] == nil || m["example2"] == nil {
+ if m["json"] == nil || m["yaml"] == nil {
t.Error("missing global keys")
}
}
@@ -178,7 +212,7 @@ func TestGenerateSuperData(t *testing.T) {
var gd []Data
var d []Data
var sd Data
-
+
if data, e = LoadData("json", strings.NewReader(goodJson1)); e == nil {
gd = append(gd, data)
} else {
@@ -189,12 +223,12 @@ func TestGenerateSuperData(t *testing.T) {
} else {
t.Skip("setup failure:", e)
}
- if data, e = LoadData("json", strings.NewReader(goodJson2)); e == nil {
+ if data, e = LoadData("yaml", strings.NewReader(goodYaml2)); e == nil {
gd = append(gd, data)
} else {
t.Skip("setup failure:", e)
}
- if data, e = LoadData("json", strings.NewReader(goodJson1)); e == nil {
+ if data, e = LoadData("yaml", strings.NewReader(goodYaml1)); e == nil {
d = append(d, data)
} else {
t.Skip("setup failure:", e)
@@ -205,7 +239,6 @@ func TestGenerateSuperData(t *testing.T) {
t.Skip("setup failure:", e)
}
-
sd = GenerateSuperData("testdata", d, gd...)
if sd["testdata"] == nil {
t.Log(sd)
diff --git a/src/suti.go b/src/suti.go
@@ -36,7 +36,7 @@ func init() {
_, err = fmt.Fscanln(cfgf, &cfgln)
for i, a := range strings.Split(cfgln, "=") {
if i == 0 {
- a = "-"+a
+ a = "-" + a
}
cfgargs = append(cfgargs, a)
}
@@ -57,7 +57,7 @@ func main() {
gd := LoadDataFiles("", options.GlobalDataPaths...)
d := LoadDataFiles(options.SortData, options.DataPaths...)
sd := GenerateSuperData(options.DataKey, d, gd...)
-
+
if t, e := LoadTemplateFile(options.RootPath, options.PartialPaths...); e != nil {
warn("unable to load templates (%s)", e)
} else if out, err := ExecuteTemplate(t, sd); err != nil {
@@ -65,7 +65,7 @@ func main() {
} else {
fmt.Println(out.String())
}
-
+
return
}
diff --git a/src/template.go b/src/template.go
@@ -4,9 +4,9 @@ import (
"bytes"
"fmt"
hmpl "html/template"
- "reflect"
"os"
"path/filepath"
+ "reflect"
"strings"
tmpl "text/template"
)
@@ -68,7 +68,7 @@ func ExecuteTemplate(t Template, d Data) (result bytes.Buffer, err error) {
err = fmt.Errorf("missing parameters")
return
}
-
+
tv := reflect.ValueOf(t)
tt := reflect.TypeOf(t)
if tt.String() == "*template.Template" { // tmpl or hmpl
@@ -81,6 +81,6 @@ func ExecuteTemplate(t Template, d Data) (result bytes.Buffer, err error) {
} else {
err = fmt.Errorf("unable to infer template type '%s'", tt.String())
}
-
+
return
-}
-\ No newline at end of file
+}
diff --git a/src/template_test.go b/src/template_test.go
@@ -2,8 +2,8 @@ package main
import (
"bytes"
- "testing"
"strings"
+ "testing"
)
const tmplRootGood = "{{ .example1 }} {{ template \"tmplPartialGood\" . }}"
@@ -83,7 +83,7 @@ func TestExecuteTemplate(t *testing.T) {
var sd, gd, d Data
var tmpl, hmpl Template
var results bytes.Buffer
-
+
if gd, e = LoadData("json", strings.NewReader(goodJson1)); e != nil {
t.Skip("setup failure:", e)
}
@@ -99,11 +99,12 @@ func TestExecuteTemplate(t *testing.T) {
if hmpl, e = LoadTemplateFile(hmplRootGood, hmplPartialGood); e != nil {
t.Skip("setup failure:", e)
}
-
+
if results, e = ExecuteTemplate(tmpl, sd); e != nil {
t.Error(e)
}
if results, e = ExecuteTemplate(hmpl, sd); e != nil {
t.Error(e)
}
+ t.Log(results)
}