-
Notifications
You must be signed in to change notification settings - Fork 0
/
embed.go
122 lines (107 loc) · 2.2 KB
/
embed.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package zc
import (
"cmp"
"embed"
"fmt"
"io/fs"
"path"
"slices"
"strings"
"unicode"
"github.com/blackchip-org/scan"
"gopkg.in/yaml.v3"
)
const DefsDir = "app/defs"
//go:embed app/defs/*
var Defs embed.FS
func LoadDefs() ([]VolDef, error) {
var defs []VolDef
fs.WalkDir(Defs, DefsDir, func(p string, d fs.DirEntry, e error) error {
if !strings.HasSuffix(p, ".yaml") {
return nil
}
def, err := loadDef(path.Dir(p), d)
if err != nil {
panic(err)
}
defs = append(defs, def)
return nil
})
return defs, nil
}
func loadDef(dir string, f fs.DirEntry) (VolDef, error) {
var def VolDef
filename := path.Join(dir, f.Name())
data, err := Defs.ReadFile(filename)
if err != nil {
return def, err
}
err = yaml.Unmarshal(data, &def)
if err != nil {
return def, fmt.Errorf("%v: %v", filename, err)
}
overview := strings.TrimSuffix(f.Name(), ".yaml") + ".md"
overviewFile := path.Join(dir, overview)
data, err = Defs.ReadFile(overviewFile)
if err == nil {
def.Overview = string(data)
}
if def.Name == "" {
panic("no volume name in file: " + filename)
}
if def.Ident == "" {
def.Ident = identFor(def.Name)
if def.Ident == "" {
panic("no identifier for: " + def.Name)
}
}
for i, op := range def.Ops {
if op.Ident == "" {
op.Ident = identFor(op.Name)
if op.Ident == "" {
panic("no identifier for: " + op.Name)
}
def.Ops[i] = op
}
for i, fn := range op.Funcs {
if fn.Name == "" && fn.Ident == "" {
fn.Ident = identFor(op.Name)
} else if fn.Ident == "" {
fn.Ident = identFor(fn.Name)
}
op.Funcs[i] = fn
}
}
slices.SortFunc(def.Ops, func(a OpDef, b OpDef) int {
return cmp.Compare(a.Name, b.Name)
})
return def, nil
}
func identFor(v string) string {
if v == "" {
return ""
}
s := scan.NewScannerFromString("", v)
if !scan.IsLetter(s.This) {
return ""
}
s.Val.WriteRune(unicode.ToUpper(s.This))
s.Skip()
for s.HasMore() {
switch {
case (s.This == '.' || s.This == '/' || s.This == '-'):
s.Skip()
s.Val.WriteRune(unicode.ToUpper(s.This))
s.Skip()
case s.This == '?':
s.Skip()
s.Val.WriteString("Q")
case s.This == '=':
s.Skip()
s.Val.WriteString("E")
default:
s.Keep()
}
}
return s.Emit().Val
}