hcl/extras/grammar/build.go
James Bardin 4d82d52bfa
update go.mod (#60)
Fix import for howett.net/plist, and update go.mod.
2018-11-29 15:21:51 -05:00

120 lines
2.3 KiB
Go

// This is a helper to transform the HCL.yaml-tmLanguage file (the source of
// record) into both HCL.json-tmLanguage and HCL.tmLanguage (in plist XML
// format).
//
// Run this after making updates to HCL.yaml-tmLanguage to generate the other
// formats.
//
// This file is intended to be run with "go run":
//
// go run ./build.go
//
// This file is also set up to run itself under "go generate":
//
// go generate .
package main
//go:generate go run ./build.go
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
yaml "gopkg.in/yaml.v2"
plist "howett.net/plist"
multierror "github.com/hashicorp/go-multierror"
)
func main() {
err := realMain()
if err != nil {
log.Fatal(err)
}
os.Exit(0)
}
func realMain() error {
var err error
buildErr := build("HCL")
if buildErr != nil {
err = multierror.Append(err, fmt.Errorf("in HCL: %s", buildErr))
}
buildErr = build("HCLTemplate")
if buildErr != nil {
err = multierror.Append(err, fmt.Errorf("in HCLTemplate: %s", buildErr))
}
buildErr = build("HCLExpression")
if buildErr != nil {
err = multierror.Append(err, fmt.Errorf("in HCLExpression: %s", buildErr))
}
return err
}
func build(basename string) error {
yamlSrc, err := ioutil.ReadFile(basename + ".yaml-tmLanguage")
if err != nil {
return err
}
var content interface{}
err = yaml.Unmarshal(yamlSrc, &content)
if err != nil {
return err
}
// Normalize the value so it's both JSON- and plist-friendly.
content = prepare(content)
jsonSrc, err := json.MarshalIndent(content, "", " ")
if err != nil {
return err
}
plistSrc, err := plist.MarshalIndent(content, plist.XMLFormat, " ")
if err != nil {
return err
}
err = ioutil.WriteFile(basename+".json-tmLanguage", jsonSrc, os.ModePerm)
if err != nil {
return err
}
err = ioutil.WriteFile(basename+".tmLanguage", plistSrc, os.ModePerm)
if err != nil {
return err
}
return nil
}
func prepare(v interface{}) interface{} {
switch tv := v.(type) {
case map[interface{}]interface{}:
var ret map[string]interface{}
if len(tv) == 0 {
return ret
}
ret = make(map[string]interface{}, len(tv))
for k, v := range tv {
ret[k.(string)] = prepare(v)
}
return ret
case []interface{}:
for i := range tv {
tv[i] = prepare(tv[i])
}
return tv
default:
return v
}
}