8f3b860cc7
animation added an optional root "Order" field to the config. scripts/ini will warn if you've used this and forgot to include any sections. added more/most sections to a group now. groups have their maxHeight set to 9999px once animation finishes, and have it quickly set back to ~scrollHeight before they're animated closed.
175 lines
4.3 KiB
Go
175 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/hrfee/jfa-go/common"
|
|
"gopkg.in/ini.v1"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
func fixDescription(desc string) string {
|
|
return "; " + strings.ReplaceAll(desc, "\n", "\n; ")
|
|
}
|
|
|
|
func generateIni(yamlPath string, iniPath string) {
|
|
yamlFile, err := os.ReadFile(yamlPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
configBase := common.Config{}
|
|
err = yaml.Unmarshal(yamlFile, &configBase)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// Validate that all groups/sections are listed in the root order, if it exists
|
|
if len(configBase.Order) > 0 {
|
|
// Expand order
|
|
var traverseGroup func(groupName string) []string
|
|
traverseGroup = func(groupName string) []string {
|
|
out := []string{}
|
|
for _, group := range configBase.Groups {
|
|
if group.Group == groupName {
|
|
for _, groupMember := range group.Members {
|
|
if groupMember.Group != "" {
|
|
out = append(out, traverseGroup(groupMember.Group)...)
|
|
} else if groupMember.Section != "" {
|
|
out = append(out, groupMember.Section)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
listedSects := map[string]bool{}
|
|
for _, member := range configBase.Order {
|
|
if member.Group != "" {
|
|
for _, sect := range traverseGroup(member.Group) {
|
|
listedSects[sect] = true
|
|
}
|
|
} else if member.Section != "" {
|
|
listedSects[member.Section] = true
|
|
}
|
|
}
|
|
|
|
missingSections := false
|
|
for _, section := range configBase.Sections {
|
|
if _, ok := listedSects[section.Section]; !ok {
|
|
if !missingSections {
|
|
color.Red("WARNING: Root order specified but the following sections were not listed, directly or indirectly:")
|
|
missingSections = true
|
|
}
|
|
color.Red("\t%s", section.Section)
|
|
}
|
|
}
|
|
}
|
|
|
|
conf := ini.Empty()
|
|
|
|
for _, section := range configBase.Sections {
|
|
cSection, err := conf.NewSection(section.Section)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if section.Meta.Description != "" {
|
|
cSection.Comment = fixDescription(section.Meta.Description)
|
|
}
|
|
for _, setting := range section.Settings {
|
|
if setting.Type == common.NoteType {
|
|
continue
|
|
}
|
|
val := ""
|
|
if setting.Value != nil {
|
|
// Easy way to convert bools and numbers to strings,
|
|
// Instead of checking setting.Type
|
|
val = fmt.Sprintf("%v", setting.Value)
|
|
}
|
|
cKey, err := cSection.NewKey(setting.Setting, val)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if setting.Description != "" {
|
|
cKey.Comment = fixDescription(setting.Description)
|
|
}
|
|
// Explain how to use list type
|
|
if setting.Type == common.ListType {
|
|
if cKey.Comment != "" {
|
|
cKey.Comment += "\n"
|
|
}
|
|
cKey.Comment += `List type: duplicate and edit the line to add more entries.`
|
|
}
|
|
}
|
|
}
|
|
|
|
err = conf.SaveTo(iniPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Compares two inis, used to check this script does the equivalent of the old generate_ini.py.
|
|
func compareInis(p1, p2 string) {
|
|
cA, err := ini.ShadowLoad(p1)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
cB, err := ini.ShadowLoad(p2)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
for _, pair := range [][2]*ini.File{{cA, cB}, {cB, cA}} {
|
|
s1 := pair[0].Sections()
|
|
s2 := pair[1].Sections()
|
|
for i := range s1 {
|
|
if s1[i].Name() != s2[i].Name() {
|
|
panic(fmt.Errorf("mismatching section order: s0[i]=%s, s1[i]=%s", s1[i].Name(), s2[i].Name()))
|
|
}
|
|
// fmt.Println("Section order matches")
|
|
st1 := s1[i].Keys()
|
|
st2 := s2[i].Keys()
|
|
for i := range st1 {
|
|
if st1[i].Name() != st2[i].Name() {
|
|
panic(fmt.Errorf("mismatching setting order: st1[i]=%s, st2[i]=%s", st1[i].Name(), st2[i].Name()))
|
|
}
|
|
if st1[i].Value() != st2[i].Value() {
|
|
panic(fmt.Errorf("mismatching setting values: st1[i]=%s, st2[i]=%s", st1[i].Value(), st2[i].Value()))
|
|
}
|
|
// fmt.Println("Setting matches")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
var yamlPath string
|
|
var iniPath string
|
|
var comparePath string
|
|
flag.StringVar(&yamlPath, "in", "", "Input of the config base in yaml.")
|
|
flag.StringVar(&iniPath, "out", "", "Output path of an ini file.")
|
|
flag.StringVar(&comparePath, "comp", "", "Path to ini file to compare against.")
|
|
|
|
flag.Parse()
|
|
|
|
if yamlPath == "" {
|
|
panic(errors.New("invalid yaml path"))
|
|
}
|
|
if iniPath == "" {
|
|
panic(errors.New("invalid ini path"))
|
|
}
|
|
|
|
generateIni(yamlPath, iniPath)
|
|
|
|
if comparePath != "" {
|
|
compareInis(iniPath, comparePath)
|
|
fmt.Println("Passed.")
|
|
}
|
|
}
|