167 lines
4.8 KiB
Go
167 lines
4.8 KiB
Go
package agent
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
|
|
"aego/scene/mutate"
|
|
"aego/scene/sceneio"
|
|
"aego/schema"
|
|
)
|
|
|
|
type FieldView struct {
|
|
Name string `json:"name"`
|
|
Kind string `json:"kind"`
|
|
Elem string `json:"elem,omitempty"`
|
|
Enum []string `json:"enum,omitempty"`
|
|
Asset string `json:"asset,omitempty"`
|
|
Min *float64 `json:"min,omitempty"`
|
|
Max *float64 `json:"max,omitempty"`
|
|
Unit string `json:"unit,omitempty"`
|
|
Default string `json:"default,omitempty"`
|
|
ReadOnly bool `json:"readOnly,omitempty"`
|
|
Saved bool `json:"saved"`
|
|
Live bool `json:"live,omitempty"`
|
|
Doc string `json:"doc,omitempty"`
|
|
}
|
|
|
|
type TypeView struct {
|
|
Name string `json:"name"`
|
|
Kind string `json:"kind"`
|
|
Display string `json:"display,omitempty"`
|
|
Category string `json:"category,omitempty"`
|
|
Owner string `json:"owner,omitempty"`
|
|
Requires []string `json:"requires,omitempty"`
|
|
Doc string `json:"doc,omitempty"`
|
|
Fields []FieldView `json:"fields,omitempty"`
|
|
}
|
|
|
|
func schemaCommands() []*Command {
|
|
return []*Command{
|
|
{Name: "schema.list", Doc: "component and data types", Args: []Arg{{Name: "kind", Type: "string", Doc: "component, data or all (default)"}}, Run: (*Session).schemaList},
|
|
{Name: "schema.show", Doc: "fields of a type: kind, range, unit, default, flags and docs", Args: []Arg{{Name: "type", Type: "string", Doc: "full name or a unique suffix", Required: true, Pos: true}}, Run: (*Session).schemaShow},
|
|
}
|
|
}
|
|
|
|
func (s *Session) types(kind string) []*schema.TypeDescriptor {
|
|
reg := s.Types.Schema()
|
|
var out []*schema.TypeDescriptor
|
|
if kind == "" || kind == "all" || kind == "component" {
|
|
out = append(out, reg.Components()...)
|
|
}
|
|
if kind == "" || kind == "all" || kind == "data" {
|
|
out = append(out, reg.DataTypes()...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func kindName(td *schema.TypeDescriptor) string {
|
|
if td.Kind == schema.TypeAsset {
|
|
return "data"
|
|
}
|
|
return "component"
|
|
}
|
|
|
|
func summary(doc string) string {
|
|
line, _, _ := strings.Cut(strings.TrimSpace(doc), "\n")
|
|
return line
|
|
}
|
|
|
|
func (s *Session) schemaList(a Args) (*Output, error) {
|
|
var list []TypeView
|
|
var b strings.Builder
|
|
for _, td := range s.types(a.Str("kind")) {
|
|
if td.Hidden {
|
|
continue
|
|
}
|
|
list = append(list, TypeView{Name: td.FullName, Kind: kindName(td), Display: td.DisplayName, Category: td.Category, Owner: td.Owner, Doc: summary(td.Doc)})
|
|
b.WriteString(td.FullName + " " + kindName(td) + " " + summary(td.Doc) + "\n")
|
|
}
|
|
return &Output{Value: list, Text: b.String()}, nil
|
|
}
|
|
|
|
func (s *Session) lookupType(name string) (*schema.TypeDescriptor, error) {
|
|
if td, ok := s.Types.Schema().ByName(name); ok {
|
|
return td, nil
|
|
}
|
|
var found []*schema.TypeDescriptor
|
|
for _, td := range s.types("") {
|
|
if strings.HasSuffix(td.FullName, "."+name) || strings.EqualFold(td.DisplayName, name) {
|
|
found = append(found, td)
|
|
}
|
|
}
|
|
switch len(found) {
|
|
case 1:
|
|
return found[0], nil
|
|
case 0:
|
|
return nil, errors.New("unknown type " + name)
|
|
}
|
|
var names []string
|
|
for _, td := range found {
|
|
names = append(names, td.FullName)
|
|
}
|
|
return nil, errors.New("ambiguous type " + name + ": " + strings.Join(names, ", "))
|
|
}
|
|
|
|
func defaultText(reg *schema.Registry, td *schema.TypeDescriptor, fd *schema.FieldDescriptor) string {
|
|
var v schema.Value
|
|
switch {
|
|
case td.Default != nil:
|
|
fd.Get(td.Default(), &v)
|
|
case td.New != nil:
|
|
fd.Get(td.New(), &v)
|
|
case fd.HasDefault:
|
|
v = fd.Default
|
|
default:
|
|
return ""
|
|
}
|
|
return mutate.FormatValue(sceneio.WriteValue(reg, fd, v))
|
|
}
|
|
|
|
func (s *Session) schemaShow(a Args) (*Output, error) {
|
|
td, err := s.lookupType(a.Str("type"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
reg := s.Types.Schema()
|
|
v := TypeView{Name: td.FullName, Kind: kindName(td), Display: td.DisplayName, Category: td.Category, Owner: td.Owner, Requires: td.Requires, Doc: td.Doc}
|
|
var b strings.Builder
|
|
b.WriteString(td.FullName + " (" + kindName(td) + ")\n")
|
|
if d := summary(td.Doc); d != "" {
|
|
b.WriteString(d + "\n")
|
|
}
|
|
for i := range td.Fields {
|
|
fd := &td.Fields[i]
|
|
if fd.Hints.Hidden {
|
|
continue
|
|
}
|
|
f := FieldView{Name: fd.Name, Kind: fd.Kind.String(), Asset: fd.AssetKind, Unit: fd.Hints.Unit, Doc: summary(fd.Doc),
|
|
ReadOnly: fd.Flags.Has(schema.FlagReadOnly), Saved: fd.Flags.Has(schema.FlagSerialize), Live: fd.Flags.Has(schema.FlagLive),
|
|
Default: defaultText(reg, td, fd)}
|
|
if fd.Kind == schema.KindList {
|
|
f.Elem = fd.Elem.String()
|
|
}
|
|
for _, e := range fd.Enum {
|
|
f.Enum = append(f.Enum, e.Name)
|
|
}
|
|
if fd.HasMin {
|
|
m := fd.Min
|
|
f.Min = &m
|
|
}
|
|
if fd.HasMax {
|
|
m := fd.Max
|
|
f.Max = &m
|
|
}
|
|
v.Fields = append(v.Fields, f)
|
|
b.WriteString(" " + f.Name + " " + f.Kind)
|
|
if f.Default != "" {
|
|
b.WriteString(" = " + f.Default)
|
|
}
|
|
if f.Doc != "" {
|
|
b.WriteString(" — " + f.Doc)
|
|
}
|
|
b.WriteString("\n")
|
|
}
|
|
return &Output{Value: v, Text: b.String()}, nil
|
|
}
|