1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-25 17:18:05 +08:00
icebergs/cmd.go
2021-10-13 01:47:51 +08:00

118 lines
2.9 KiB
Go

package ice
import (
"reflect"
"strings"
kit "shylinux.com/x/toolkits"
)
func ref(obj interface{}) (reflect.Type, reflect.Value) {
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if t.Kind() == reflect.Ptr {
t, v = t.Elem(), v.Elem()
}
return t, v
}
func val(m *Message, arg ...string) []reflect.Value {
args := []reflect.Value{reflect.ValueOf(m)}
for _, v := range arg {
args = append(args, reflect.ValueOf(v))
}
return args
}
func transMethod(config *Config, command *Command, obj interface{}) {
t, v := ref(obj)
for i := 0; i < v.NumMethod(); i++ {
method := v.Method(i)
var h func(*Message, ...string)
switch method.Interface().(type) {
case func(*Message, ...string):
h = func(m *Message, arg ...string) { method.Call(val(m, arg...)) }
case func(*Message):
h = func(m *Message, arg ...string) { method.Call(val(m)) }
default:
continue
}
if key := strings.ToLower(t.Method(i).Name); key == "list" {
command.Hand = func(m *Message, c *Context, cmd string, arg ...string) { h(m, arg...) }
} else {
if action, ok := command.Action[key]; !ok {
command.Action[key] = &Action{Hand: h}
} else {
action.Hand = h
}
}
}
}
func transField(config *Config, command *Command, obj interface{}) {
t, v := ref(obj)
for i := 0; i < v.NumField(); i++ {
if t.Field(i).Type.Kind() == reflect.Struct {
if v.Field(i).CanInterface() {
transField(config, command, v.Field(i).Interface())
}
}
}
meta := kit.Value(config.Value, kit.MDB_META)
for i := 0; i < v.NumField(); i++ {
key, tag := t.Field(i).Name, t.Field(i).Tag
if data := tag.Get("data"); data != "" {
kit.Value(meta, key, data)
}
if name := tag.Get("name"); name != "" {
if help := tag.Get("help"); key == "list" {
command.Name, command.Help = name, help
config.Name, config.Help = name, help
} else if action, ok := command.Action[key]; ok {
action.Name, action.Help = name, help
}
}
}
}
func Cmd(key string, obj interface{}) {
if obj == nil {
return
}
command := &Command{Action: map[string]*Action{}}
config := &Config{Value: kit.Data()}
transMethod(config, command, obj)
transField(config, command, obj)
last := Index
list := strings.Split(key, ".")
for i := 1; i < len(list); i++ {
has := false
Pulse.Search(strings.Join(list[:i], ".")+".", func(p *Context, s *Context) {
has, last = true, s
})
if !has {
context := &Context{Name: list[i-1]}
last.Register(context, nil)
last = context
}
if i < len(list)-1 {
continue
}
last.Merge(&Context{Commands: map[string]*Command{
CTX_INIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) {
if action, ok := command.Action["init"]; ok {
action.Hand(m, arg...)
} else {
m.Load()
}
}},
CTX_EXIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) {
m.Save()
}},
list[i]: command,
}, Configs: map[string]*Config{list[i]: config}})
}
}