mirror of
https://github.com/wader/fq.git
synced 2024-11-23 09:56:07 +03:00
0d0147643a
Add cmp package from go 1.21 to have cmp.Compare to make sort easier
128 lines
2.6 KiB
Go
128 lines
2.6 KiB
Go
package interp
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/wader/fq/internal/cmpex"
|
|
"github.com/wader/fq/internal/gojqex"
|
|
"github.com/wader/fq/pkg/decode"
|
|
"golang.org/x/exp/slices"
|
|
)
|
|
|
|
type EnvFuncFn func(env *Interp) gojqex.Function
|
|
|
|
type Registry struct {
|
|
allGroup *decode.Group
|
|
groups map[string]*decode.Group
|
|
formatResolveOnce sync.Once
|
|
formatResolved bool
|
|
|
|
EnvFuncFns []EnvFuncFn
|
|
|
|
FSs []fs.ReadDirFS
|
|
}
|
|
|
|
func NewRegistry() *Registry {
|
|
return &Registry{
|
|
allGroup: &decode.Group{Name: "all"},
|
|
groups: map[string]*decode.Group{},
|
|
formatResolveOnce: sync.Once{},
|
|
}
|
|
}
|
|
|
|
func (r *Registry) Format(group *decode.Group, format *decode.Format) *decode.Format {
|
|
if r.formatResolved {
|
|
// for now can't change after resolved
|
|
panic("registry already resolved")
|
|
}
|
|
|
|
if _, ok := r.groups[group.Name]; ok {
|
|
panic(fmt.Sprintf("%s: format already registered", group.Name))
|
|
}
|
|
group.Formats = append(group.Formats, format)
|
|
r.groups[group.Name] = group
|
|
format.Name = group.Name
|
|
|
|
for _, g := range format.Groups {
|
|
r.groups[g.Name] = g
|
|
g.Formats = append(g.Formats, format)
|
|
}
|
|
|
|
r.allGroup.Formats = append(r.allGroup.Formats, format)
|
|
|
|
return format
|
|
}
|
|
|
|
func (r *Registry) FS(fs fs.ReadDirFS) {
|
|
r.FSs = append(r.FSs, fs)
|
|
}
|
|
|
|
func (r *Registry) Func(funcFn EnvFuncFn) {
|
|
r.EnvFuncFns = append(r.EnvFuncFns, funcFn)
|
|
}
|
|
|
|
func sortFormats(g *decode.Group) {
|
|
slices.SortFunc(g.Formats, func(a, b *decode.Format) int {
|
|
if a.ProbeOrder == b.ProbeOrder {
|
|
return strings.Compare(a.Name, b.Name)
|
|
}
|
|
return cmpex.Compare(a.ProbeOrder, b.ProbeOrder)
|
|
})
|
|
}
|
|
|
|
func (r *Registry) resolveGroups() {
|
|
r.formatResolveOnce.Do(func() {
|
|
for _, g := range r.groups {
|
|
for _, f := range g.Formats {
|
|
for _, d := range f.Dependencies {
|
|
if len(d.Out.Formats) != 0 {
|
|
// already resolved
|
|
continue
|
|
}
|
|
|
|
for _, dg := range d.Groups {
|
|
d.Out.Formats = append(d.Out.Formats, dg.Formats...)
|
|
}
|
|
sortFormats(d.Out)
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, g := range r.groups {
|
|
sortFormats(g)
|
|
}
|
|
|
|
r.formatResolved = true
|
|
})
|
|
}
|
|
|
|
func (r *Registry) Group(name string) (*decode.Group, error) {
|
|
r.resolveGroups()
|
|
if g, ok := r.groups[name]; ok {
|
|
return g, nil
|
|
}
|
|
return nil, errors.New("format group not found")
|
|
}
|
|
|
|
func (r *Registry) MustGroup(name string) *decode.Group {
|
|
g, err := r.Group(name)
|
|
if err == nil {
|
|
return g
|
|
}
|
|
panic(err)
|
|
}
|
|
|
|
func (r *Registry) Groups() map[string]*decode.Group {
|
|
r.resolveGroups()
|
|
return r.groups
|
|
}
|
|
|
|
func (r *Registry) MustAll() *decode.Group {
|
|
r.resolveGroups()
|
|
return r.allGroup
|
|
}
|