1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-26 01:04:06 +08:00
2019-08-13 21:07:19 +08:00

1369 lines
36 KiB
Go

package ctx
import (
"toolkit"
"encoding/json"
"fmt"
"math/rand"
"os"
"regexp"
"sort"
"strconv"
"strings"
"time"
)
type CTX struct {
*Context
}
func (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server {
return &CTX{Context: c}
}
func (ctx *CTX) Begin(m *Message, arg ...string) Server {
m.Option("ctx.routine", 0)
m.Option("log.disable", true)
m.Option("ctx.chain", "aaa", "ssh", "cli", "nfs")
m.Option("table.limit", 10)
m.Option("table.offset", 0)
m.Optionv("ctx.form", map[string]int{
"table.limit": 1, "table.offset": 1,
})
m.root = m
m.Sess(m.target.Name, m)
for _, msg := range m.Search("") {
if msg.target.root = m.target; msg.target == m.target {
continue
}
msg.target.Begin(msg, arg...)
m.Sess(msg.target.Name, msg)
}
return ctx
}
func (ctx *CTX) Start(m *Message, arg ...string) bool {
if m.Optionv("bio.ctx", Index); len(arg) == 0 {
kit.DisableLog = false
m.Option("log.debug", kit.Right(os.Getenv("ctx_log_debug")))
m.Option("log.disable", kit.Right(os.Getenv("ctx_log_disable")))
m.Option("gdb.enable", kit.Right(os.Getenv("ctx_gdb_enable")))
m.Cmd("log._init")
m.Cmd("gdb._init")
m.Cmd("ctx._init")
m.Option("bio.modal", "active")
m.Optionv("bio.ctx", m.Target())
m.Optionv("bio.msg", m)
m.Cap("stream", "stdio")
m.Cmd("aaa.role", "root", "user", m.Option("username", m.Conf("runtime", "boot.username")))
m.Option("sessid", m.Cmdx("aaa.user", "session", "select"))
m.Cmd("nfs.source", m.Conf("cli.system", "script.init")).Cmd("nfs.source", "stdio").Cmd("nfs.source", m.Conf("cli.system", "script.exit"))
} else {
m.Cmd("ctx._init")
m.Option("bio.modal", "action")
for _, v := range m.Sess("cli").Cmd(arg).Meta["result"] {
fmt.Printf("%s", v)
}
}
m.Cmd("ctx._exit")
return true
}
func (ctx *CTX) Close(m *Message, arg ...string) bool {
return true
}
var Pulse = &Message{code: 0, time: time.Now(), source: Index, target: Index, Meta: map[string][]string{}}
var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
Caches: map[string]*Cache{
"ngo": &Cache{Name: "ngo", Value: "0", Help: "协程数量"},
"nserver": &Cache{Name: "nserver", Value: "0", Help: "服务数量"},
"ncontext": &Cache{Name: "ncontext", Value: "0", Help: "模块数量"},
"nmessage": &Cache{Name: "nmessage", Value: "1", Help: "消息数量"},
},
Configs: map[string]*Config{
"time": &Config{Name: "timer", Value: map[string]interface{}{
"unit": 1000, "close": "open", "format": "2006-01-02 15:04:05",
}, Help: "时间参数"},
"table": &Config{Name: "table", Value: map[string]interface{}{
"space": " ", "compact": "false", "col_sep": " ", "row_sep": "\n",
"offset": 0, "limit": 10,
}, Help: "制表"},
"call_timeout": &Config{Name: "call_timeout", Value: "60s", Help: "回调超时"},
},
Commands: map[string]*Command{
"_init": &Command{Name: "_init", Help: "启动", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
for _, x := range []string{"lex", "cli", "yac", "nfs", "aaa", "ssh", "web"} {
m.Cmd(x + "._init")
}
return
}},
"_exit": &Command{Name: "_exit", Help: "退出", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
for _, x := range []string{"nfs", "cli"} {
m.Cmd(x + "._exit")
}
return
}},
"help": &Command{Name: "help topic", Help: "帮助", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Echo("usage: help context [module [command|config|cache name]]\n")
m.Echo(" : 查看模块信息, module: 模块名, command: 模块命令, config: 模块配置, cache: 模块缓存, name: 模块参数\n")
m.Echo("usage: help command [name]\n")
m.Echo(" : 查看当前环境下命令, name: 命令名\n")
m.Echo("usage: help config [name]\n")
m.Echo(" : 查看当前环境下配置, name: 配置名\n")
m.Echo("usage: help cache [name]\n")
m.Echo(" : 查看当前环境下缓存, name: 缓存名\n")
m.Echo("\n")
m.Echo("^_^ Welcome to context world ^_^\n")
m.Echo("Version: 1.0 A New Language, A New Framework\n")
m.Echo("More: https://github.com/shylinux/context\n")
m.Echo("More: https://shylinux.com/\n")
return
}
switch arg[0] {
case "context":
switch len(arg) {
case 1:
keys := []string{}
values := map[string]*Context{}
m.Target().root.Travel(m, func(m *Message, i int) bool {
if _, ok := values[m.Cap("module")]; !ok {
keys = append(keys, m.Cap("module"))
values[m.Cap("module")] = m.Target()
}
return false
})
sort.Strings(keys)
for _, k := range keys {
m.Echo("%s: %s %s\n", k, values[k].Name, values[k].Help)
}
break
case 2:
if msg := m.Find(arg[1]); msg != nil {
m.Echo("%s: %s %s\n", arg[1], msg.Target().Name, msg.Target().Help)
m.Echo("commands:\n")
for k, v := range msg.Target().Commands {
m.Echo(" %s: %s\n", k, v.Name)
}
m.Echo("configs:\n")
for k, v := range msg.Target().Configs {
m.Echo(" %s: %s\n", k, v.Name)
}
m.Echo("caches:\n")
for k, v := range msg.Target().Caches {
m.Echo(" %s: %s\n", k, v.Name)
}
}
default:
if msg := m.Find(arg[1]); msg != nil {
m.Echo("%s: %s %s\n", arg[1], msg.Target().Name, msg.Target().Help)
switch arg[2] {
case "command":
for k, v := range msg.Target().Commands {
if k == arg[3] {
m.Echo("%s: %s\n%s\n", k, v.Name, v.Help)
}
}
case "config":
for k, v := range msg.Target().Configs {
if k == arg[3] {
m.Echo("%s: %s\n %s\n", k, v.Name, v.Help)
}
}
case "cache":
for k, v := range msg.Target().Caches {
if k == arg[3] {
m.Echo("%s: %s\n %s\n", k, v.Name, v.Help)
}
}
}
}
}
case "command":
keys := []string{}
values := map[string]*Command{}
for s := m.Target(); s != nil; s = s.context {
for k, v := range s.Commands {
if _, ok := values[k]; ok {
continue
}
if len(arg) > 1 && k == arg[1] {
switch help := v.Help.(type) {
case []string:
m.Echo("%s: %s\n", k, v.Name)
for _, v := range help {
m.Echo(" %s\n", v)
}
case string:
m.Echo("%s: %s\n%s\n", k, v.Name, v.Help)
}
return
}
keys = append(keys, k)
values[k] = v
}
}
sort.Strings(keys)
for _, k := range keys {
m.Echo("%s: %s\n", k, values[k].Name)
}
case "config":
keys := []string{}
values := map[string]*Config{}
for s := m.Target(); s != nil; s = s.context {
for k, v := range s.Configs {
if _, ok := values[k]; ok {
continue
}
if len(arg) > 1 && k == arg[1] {
m.Echo("%s(%s): %s %s\n", k, v.Value, v.Name, v.Help)
return
}
keys = append(keys, k)
values[k] = v
}
}
sort.Strings(keys)
for _, k := range keys {
m.Echo("%s(%s): %s\n", k, values[k].Value, values[k].Name)
}
case "cache":
keys := []string{}
values := map[string]*Cache{}
for s := m.Target(); s != nil; s = s.context {
for k, v := range s.Caches {
if _, ok := values[k]; ok {
continue
}
if len(arg) > 1 && k == arg[1] {
m.Echo("%s(%s): %s %s\n", k, v.Value, v.Name, v.Help)
return
}
keys = append(keys, k)
values[k] = v
}
}
sort.Strings(keys)
for _, k := range keys {
m.Echo("%s(%s): %s\n", k, values[k].Value, values[k].Name)
}
}
return
}},
"cache": &Command{Name: "cache [all] |key [value]|key = value|key name value help|delete key]", Help: "查看、读写、赋值、新建、删除缓存变量", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
all := false
if len(arg) > 0 && arg[0] == "all" {
arg, all = arg[1:], true
}
switch len(arg) {
case 0:
c.BackTrace(m, func(m *Message) bool {
for k, v := range m.target.Caches {
m.Add("append", "key", k)
m.Add("append", "value", m.Cap(k))
m.Add("append", "name", v.Name)
}
return !all
})
m.Sort("key", "str").Table()
return
case 1:
m.Echo(m.Cap(arg[0]))
case 2:
if arg[0] == "delete" {
delete(m.target.Caches, arg[1])
return
}
m.Cap(arg[0], arg[1])
case 3:
m.Cap(arg[0], arg[0], arg[2], arg[0])
default:
m.Echo(m.Cap(arg[0], arg[1:]))
return
}
return
}},
"config": &Command{Name: "config [all]", Help: []string{"配置管理",
"brow: 配置列表",
"key [chain [value]]: 读写配置",
"export key...: 导出配置",
"save|load file key...: 保存、加载配置",
"create map|list|string key name help: 创建配置",
"delete key: 删除配置",
}, Form: map[string]int{"format": 1, "fields": -1}, Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
all := false
if len(arg) > 0 && arg[0] == "all" {
arg, all = arg[1:], true
}
if len(arg) == 0 {
arg = append(arg, "brow")
}
action, which := "", "-1"
have := map[string]bool{}
switch arg[0] {
case "brow":
case "export":
action, arg = arg[0], arg[1:]
for _, v := range arg {
have[v] = true
}
case "save", "load":
action, which, arg = arg[0], arg[1], arg[2:]
for _, v := range arg {
have[v] = true
}
case "create", "delete":
action, arg = arg[0], arg[1:]
default:
var value interface{}
if len(arg) > 2 && arg[2] == "map" {
for i := 3; i < len(arg)-1; i += 2 {
m.Confv(arg[0], []interface{}{arg[1], arg[i]}, arg[i+1])
}
value = m.Confv(arg[0], arg[1])
} else if len(arg) > 2 && arg[2] == "list" {
for i := 3; i < len(arg)-1; i += 1 {
m.Confv(arg[0], []interface{}{arg[1], -2}, arg[i])
}
value = m.Confv(arg[0], arg[1])
} else if len(arg) > 1 && arg[1] == "list" {
for i := 2; i < len(arg)-1; i += 1 {
m.Confv(arg[0], -2, arg[i])
}
value = m.Confv(arg[0])
} else if len(arg) > 1 && arg[1] == "map" {
for i := 2; i < len(arg)-1; i += 2 {
m.Confv(arg[0], arg[i], arg[i+1])
}
value = m.Confv(arg[0])
} else if len(arg) > 2 {
value = m.Confv(arg[0], arg[1], arg[2])
} else if len(arg) > 1 {
value = m.Confv(arg[0], arg[1])
} else {
value = m.Confv(arg[0])
}
msg := m.Spawn().Put("option", "_cache", value).Cmd("trans", "_cache")
m.Copy(msg, "append").Copy(msg, "result")
return
}
save := map[string]interface{}{}
if action == "load" {
f, e := os.Open(m.Cmdx("nfs.path", which))
if e != nil {
return e
}
defer f.Close()
de := json.NewDecoder(f)
if e = de.Decode(&save); e != nil {
m.Log("info", "e: %v", e)
}
}
c.BackTrace(m, func(m *Message) bool {
for k, v := range m.target.Configs {
switch action {
case "export", "save":
if len(have) == 0 || have[k] {
save[k] = v.Value
}
case "load":
if x, ok := save[k]; ok && (len(have) == 0 || have[k]) {
v.Value = x
}
case "create":
m.Assert(k != arg[1], "%s exists", arg[1])
case "delete":
if k == arg[0] {
m.Echo(kit.Formats(v.Value))
delete(m.target.Configs, k)
}
default:
m.Add("append", "key", k)
m.Add("append", "value", strings.Replace(strings.Replace(m.Conf(k), "\n", "\\n", -1), "\t", "\\t", -1))
m.Add("append", "name", v.Name)
}
}
switch action {
case "create":
var value interface{}
switch arg[0] {
case "map":
value = map[string]interface{}{}
case "list":
value = []interface{}{}
default:
value = ""
}
m.target.Configs[arg[1]] = &Config{Name: arg[2], Value: value, Help: arg[3]}
m.Echo(arg[1])
return true
}
return !all
})
m.Sort("key", "str").Table()
switch action {
case "save":
buf, e := json.MarshalIndent(save, "", " ")
m.Assert(e)
m.Sess("nfs").Add("option", "data", string(buf)).Cmd("save", which)
case "export":
buf, e := json.MarshalIndent(save, "", " ")
m.Assert(e)
m.Echo("%s", string(buf))
}
return
}},
"command": &Command{Name: "command", Help: []string{"查看或操作命令",
"brow [all|cmd]: 查看命令",
"help cmd: 查看帮助",
"cmd...: 执行命令",
"list [begin [end]] [prefix] [test [key value]...]: 命令列表",
"add [list_name name] [list_help help] [cmd|__|_|_val]...: 添加命令, __: 可选参数, _: 必选参数, _val: 默认参数",
}, Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
arg = append(arg, "brow")
}
switch arg[0] {
case "brow":
c.BackTrace(m, func(m *Message) bool {
for k, v := range m.target.Commands {
if strings.HasPrefix(k, "_") {
continue
}
if len(arg) == 1 || arg[1] == "all" {
m.Add("append", "key", k)
m.Add("append", "name", v.Name)
} else if arg[1] == k {
m.Add("append", "key", k)
m.Add("append", "name", v.Name)
m.Add("append", "help", v.Name)
}
}
return len(arg) == 1 || arg[1] != "all"
})
m.Sort("key").Table()
case "help":
m.Cmdy("ctx.help", "command", arg[1:])
case "list":
arg = arg[1:]
if m.Cap("list_count") == "" {
break
}
begin, end := 0, m.Capi("list_count")
if len(arg) > 0 {
if n, e := strconv.Atoi(arg[0]); e == nil {
begin, arg = n, arg[1:]
}
}
if len(arg) > 0 {
if n, e := strconv.Atoi(arg[0]); e == nil {
end, arg = n, arg[1:]
}
}
prefix := ""
if len(arg) > 0 && arg[0] != "test" {
prefix, arg = arg[0], arg[1:]
}
test := false
if len(arg) > 0 && arg[0] == "test" {
test, arg = true, arg[1:]
for i := 0; i < len(arg)-1; i += 2 {
m.Add("option", arg[i], arg[i+1])
}
}
for i := begin; i < end; i++ {
index := fmt.Sprintf("%d", i)
if c, ok := m.target.Commands[index]; ok {
if prefix != "" && !strings.HasPrefix(c.Help.(string), prefix) {
continue
}
if test {
msg := m.Spawn().Cmd(index)
m.Add("append", "index", i)
m.Add("append", "help", c.Help)
m.Add("append", "msg", msg.messages[0].code)
m.Add("append", "res", msg.Result(0))
} else {
m.Add("append", "index", i)
m.Add("append", "help", c.Help)
m.Add("append", "command", fmt.Sprintf("%s", strings.Replace(c.Name, "\n", "\\n", -1)))
}
}
}
m.Table()
case "add":
if m.target.Caches == nil {
m.target.Caches = map[string]*Cache{}
}
if _, ok := m.target.Caches["list_count"]; !ok {
m.target.Caches["list_count"] = &Cache{Name: "list_count", Value: "0", Help: "list_count"}
}
if m.target.Commands == nil {
m.target.Commands = map[string]*Command{}
}
arg = arg[1:]
list_name, list_help := "", "list_cmd"
if len(arg) > 1 && arg[0] == "list_name" {
list_name, arg = arg[1], arg[2:]
}
if len(arg) > 1 && arg[0] == "list_help" {
list_help, arg = arg[1], arg[2:]
}
m.target.Commands[m.Cap("list_count")] = &Command{Name: strings.Join(arg, " "), Help: list_help, Hand: func(cmd *Message, c *Context, key string, args ...string) (e error) {
list := []string{}
for _, v := range arg {
if v == "__" {
if len(args) > 0 {
v, args = args[0], args[1:]
} else {
continue
}
} else if strings.HasPrefix(v, "_") {
if len(args) > 0 {
v, args = args[0], args[1:]
} else if len(v) > 1 {
v = v[1:]
} else {
v = "''"
}
}
list = append(list, v)
}
list = append(list, args...)
msg := cmd.Sess("cli").Set("option", "current_ctx", m.target.Name).Cmd("source", strings.Join(list, " "))
cmd.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target")
return
}}
if list_name != "" {
m.target.Commands[list_name] = m.target.Commands[m.Cap("list_count")]
}
m.Capi("list_count", 1)
default:
m.Cmdy(arg)
}
return
}},
"context": &Command{Name: "context [find|search] [root|back|home] [first|last|rand|magic] [module] [cmd...|switch|list|spawn|start|close]",
Help: []string{"查找并操作模块",
"查找方法, find: 精确查找, search: 模糊搜索",
"查找起点, root: 根模块, back: 父模块, home: 本模块",
"过滤结果, first: 取第一个, last: 取最后一个, rand: 随机选择, magics: 智能选择",
"操作方法, cmd...: 执行命令, switch: 切换为当前, list: 查看所有子模块, spwan: 创建子模块并初始化, start: 启动模块, close: 结束模块",
}, Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
action := "switch"
if len(arg) == 0 {
action = "list"
}
method := "search"
if len(arg) > 0 {
switch arg[0] {
case "find", "search":
method, arg = arg[0], arg[1:]
}
}
root := true
if len(arg) > 0 {
switch arg[0] {
case "root":
root, arg = true, arg[1:]
case "home":
root, arg = false, arg[1:]
case "back":
root, arg = false, arg[1:]
if m.target.context != nil {
m.target = m.target.context
}
}
}
ms := []*Message{}
if len(arg) > 0 {
switch method {
case "find":
if msg := m.Find(arg[0], root); msg != nil {
ms, arg = append(ms, msg), arg[1:]
}
case "search":
msg := m.Search(arg[0], root)
if len(msg) > 1 || msg[0] != nil {
if len(arg) > 1 {
switch arg[1] {
case "first":
ms, arg = append(ms, msg[0]), arg[2:]
case "last":
ms, arg = append(ms, msg[len(msg)-1]), arg[2:]
case "rand":
ms, arg = append(ms, msg[rand.Intn(len(msg))]), arg[2:]
case "magics":
ms, arg = append(ms, msg...), arg[2:]
default:
ms, arg = append(ms, msg[0]), arg[1:]
}
} else {
ms, arg = append(ms, msg[0]), arg[1:]
}
}
}
}
if len(ms) == 0 {
ms = append(ms, m)
}
if len(arg) > 0 {
switch arg[0] {
case "switch", "list", "spawn", "start", "close":
action, arg = arg[0], arg[1:]
default:
action = "cmd"
}
}
for _, msg := range ms {
if msg == nil {
continue
}
switch action {
case "cmd":
if len(arg) == 0 {
arg = append(arg, "command")
} else if arg[0] == "command" && len(arg) > 1 {
arg = arg[1:]
}
if msg.Cmd(arg); !msg.Hand {
msg = msg.Cmd("nfs.cmd", arg)
}
msg.CopyTo(m)
case "switch":
m.target = msg.target
case "list":
cs := []*Context{}
if msg.target.Name != "ctx" {
cs = append(cs, msg.target.context)
}
msg.target.Travel(msg, func(msg *Message, n int) bool {
cs = append(cs, msg.target)
return false
})
msg = m.Spawn()
for _, v := range cs {
if msg.target = v; v == nil {
m.Add("append", "names", "")
m.Add("append", "ctx", "")
m.Add("append", "msg", "")
m.Add("append", "status", "")
m.Add("append", "stream", "")
m.Add("append", "helps", "")
continue
}
m.Add("append", "names", msg.target.Name)
if msg.target.context != nil {
m.Add("append", "ctx", msg.target.context.Name)
} else {
m.Add("append", "ctx", "")
}
if msg.target.message != nil {
m.Add("append", "msg", msg.target.message.code)
} else {
m.Add("append", "msg", "")
}
m.Add("append", "status", msg.Cap("status"))
m.Add("append", "stream", msg.Cap("stream"))
m.Add("append", "helps", msg.target.Help)
}
m.Table()
case "spawn":
msg.target.Spawn(msg, arg[0], arg[1]).Begin(msg, arg[2:]...)
m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target")
case "start":
msg.target.Start(msg, arg...)
m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target")
case "close":
msg := m.Spawn()
m.target = msg.target.context
msg.target.Close(msg.target.message, arg...)
}
}
return
}},
"message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m
if len(arg) > 0 {
if code, e := strconv.Atoi(arg[0]); e == nil {
ms := []*Message{m.root}
for i := 0; i < len(ms); i++ {
if ms[i].Code() == code {
msg = ms[i]
arg = arg[1:]
break
}
ms = append(ms, ms[i].messages...)
}
}
}
m.Optionv("bio.msg", msg)
m.Log("fuck", "what %v", arg)
if len(arg) == 0 {
ms := []*Message{msg.message, msg}
for i := 0; i < len(ms); i++ {
if ms[i] == nil {
continue
}
if m.Push("code", ms[i].code); ms[i].message != nil {
m.Push("message", ms[i].message.code)
} else {
m.Push("message", 0)
}
m.Push("time", ms[i].Time())
m.Push("source", ms[i].source.Name)
m.Push("target", ms[i].target.Name)
m.Push("detail", kit.Format(ms[i].Meta["detail"]))
if i > 0 {
ms = append(ms, ms[i].messages...)
}
}
m.Table()
return
}
switch arg[0] {
case "time", "code", "ship", "full", "chain", "stack":
m.Echo(msg.Format(arg[0]))
case "spawn":
sub := msg.Spawn()
m.Echo("%d", sub.code)
case "call":
case "back":
msg.Back(m)
case "free":
msg.Free()
default:
msg = msg.Spawn().Cmd(arg)
m.Copy(msg, "append").Copy(msg, "result")
}
return
}},
"detail": &Command{Name: "detail [index] [value...]", Help: "查看或添加参数", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m.Optionv("bio.msg").(*Message)
if len(arg) == 0 {
for i, v := range msg.Meta["detail"] {
m.Push("index", i)
m.Push("value", v)
}
m.Table()
return
}
index := 0
if i, e := strconv.Atoi(arg[0]); e == nil {
index, arg = i, arg[1:]
}
m.Echo("%s", msg.Detail(index, arg))
return
}},
"copy": &Command{Name: "copy", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m.Optionv("bio.msg").(*Message)
// 去年尾参
for i := len(arg) - 1; i >= 0; i-- {
if arg[i] == "" {
arg = arg[:i]
} else {
break
}
}
// 默认参数
args := make([]string, 0, len(arg))
for i, j := 0, 1; i < len(arg); i++ {
if strings.HasPrefix(arg[i], "__") {
if j < len(msg.Meta["detail"]) {
args = append(args, msg.Meta["detail"][j:]...)
}
j = len(msg.Meta["detail"])
} else if strings.HasPrefix(arg[i], "_") {
args = append(args, kit.Select(arg[i][1:], msg.Detail(j)))
j++
} else {
args = append(args, arg[i])
}
}
msg.Cmdy(args)
return
}},
"table": &Command{Name: "table", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m.Optionv("bio.msg").(*Message)
if len(msg.Meta["append"]) == 0 {
msg.Meta["append"] = arg
} else {
for i, k := range msg.Meta["append"] {
msg.Push(k, kit.Select("", arg, i))
}
}
msg.Log("fuck", "waht %v", msg.Meta)
return
}},
"option": &Command{Name: "option", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
all := false
if len(arg) > 0 && arg[0] == "all" {
all, arg = true, arg[1:]
}
msg := m.Optionv("bio.msg").(*Message)
switch len(arg) {
case 0:
vals := map[string]interface{}{}
list := []string{}
for back := msg; back != nil; back = back.message {
for _, k := range back.Meta["option"] {
if _, ok := vals[k]; !ok {
if _, ok := back.Data[k]; ok {
vals[k] = back.Data[k]
} else {
vals[k] = back.Meta[k]
}
list = append(list, k)
}
}
if !all {
break
}
}
sort.Strings(list)
for _, k := range list {
m.Push("key", k)
m.Push("val", kit.Format(vals[k]))
}
m.Table()
case 1:
switch v := msg.Optionv(arg[0]).(type) {
case []string:
m.Echo(strings.Join(v, ""))
default:
m.Echo(kit.Format(v))
}
default:
m.Echo(m.Option(arg[0], arg[1]))
}
return
}},
"append": &Command{Name: "append", Help: "查看或添加附加值", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m.Optionv("bio.msg").(*Message)
if len(arg) == 0 {
m.Copy(msg, "append")
m.Table()
return
}
if len(arg) == 1 {
for i, v := range msg.Meta[arg[0]] {
m.Push("index", i)
m.Push("value", v)
}
m.Table()
return
}
msg.Push(arg[0], arg[1])
return
}},
"result": &Command{Name: "result [index] [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m.Optionv("bio.msg").(*Message)
if len(arg) == 0 {
for i, v := range msg.Meta["result"] {
m.Push("index", i)
m.Push("value", strings.Replace(v, "\n", "\\n", -1))
}
m.Table()
return
}
index := -2
if i, e := strconv.Atoi(arg[0]); e == nil {
index, arg = i, arg[1:]
}
m.Echo("%s", msg.Result(index, arg))
return
}},
"trans": &Command{Name: "trans option [type|data|json] limit 10 [index...]", Help: "数据转换",
Form: map[string]int{"format": 1, "fields": -1},
Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
value, arg := m.Optionv(arg[0]), arg[1:]
if v, ok := value.(string); ok {
json.Unmarshal([]byte(v), &value)
}
view := "data"
if len(arg) > 0 {
switch arg[0] {
case "type", "data", "json":
view, arg = arg[0], arg[1:]
}
}
limit := kit.Int(kit.Select(m.Conf("table", "limit"), m.Option("table.limit")))
if len(arg) > 0 && arg[0] == "limit" {
limit, arg = kit.Int(arg[1]), arg[2:]
}
chain := strings.Join(arg, ".")
if chain != "" {
value = kit.Chain(value, chain)
}
switch view {
case "type": // 查看数据类型
switch value := value.(type) {
case map[string]interface{}:
for k, v := range value {
m.Add("append", "key", k)
m.Add("append", "type", fmt.Sprintf("%T", v))
}
m.Sort("key", "str").Table()
case []interface{}:
for k, v := range value {
m.Add("append", "key", k)
m.Add("append", "type", fmt.Sprintf("%T", v))
}
m.Sort("key", "int").Table()
case nil:
default:
m.Add("append", "key", chain)
m.Add("append", "type", fmt.Sprintf("%T", value))
m.Sort("key", "str").Table()
}
return
case "data":
case "json": // 查看文本数据
b, e := json.MarshalIndent(value, "", " ")
m.Assert(e)
m.Echo(string(b))
return nil
}
switch val := value.(type) {
case map[string]interface{}:
if m.Option("format") == "table" {
fields := []string{}
has := map[string]bool{}
if m.Options("fields") {
fields = m.Optionv("fields").([]string)
} else {
i := 0
for _, v := range val {
if i++; i > kit.Int(kit.Select(m.Conf("table", "limit"), m.Option("table.limit"))) {
break
}
if line, ok := v.(map[string]interface{}); ok {
for k, _ := range line {
if h, ok := has[k]; ok && h {
continue
}
has[k], fields = true, append(fields, k)
}
}
}
sort.Strings(fields)
}
i := 0
for k, v := range val {
if i++; i > kit.Int(kit.Select(m.Conf("table", "limit"), m.Option("table.limit"))) {
break
}
if line, ok := v.(map[string]interface{}); ok {
m.Add("append", "key", k)
for _, field := range fields {
m.Add("append", field, kit.Format(line[field]))
}
}
}
m.Table()
break
}
for k, v := range val {
if m.Option("format") == "object" {
m.Add("append", k, v)
continue
}
m.Add("append", "key", k)
switch val := v.(type) {
case nil:
m.Add("append", "value", "")
case string:
m.Add("append", "value", val)
case float64:
m.Add("append", "value", fmt.Sprintf("%d", int(val)))
default:
b, _ := json.Marshal(val)
m.Add("append", "value", fmt.Sprintf("%s", string(b)))
}
}
if m.Option("format") != "object" {
m.Sort("key", "str")
}
m.Table()
case map[string]string:
for k, v := range val {
m.Add("append", "key", k)
m.Add("append", "value", v)
}
m.Sort("key", "str").Table()
case []interface{}:
fields := map[string]int{}
for i, v := range val {
if i >= limit {
break
}
switch val := v.(type) {
case map[string]interface{}:
for k, _ := range val {
fields[k]++
}
}
}
if len(fields) > 0 {
for i, v := range val {
if i >= limit {
break
}
switch val := v.(type) {
case map[string]interface{}:
for k, _ := range fields {
switch value := val[k].(type) {
case nil:
m.Add("append", k, "")
case string:
m.Add("append", k, value)
case float64:
m.Add("append", k, fmt.Sprintf("%d", int(value)))
default:
b, _ := json.Marshal(value)
m.Add("append", k, fmt.Sprintf("%v", string(b)))
}
}
}
}
} else {
for i, v := range val {
switch val := v.(type) {
case nil:
m.Add("append", "index", i)
m.Add("append", "value", "")
case string:
m.Add("append", "index", i)
m.Add("append", "value", val)
case float64:
m.Add("append", "index", i)
m.Add("append", "value", fmt.Sprintf("%v", int(val)))
default:
m.Add("append", "index", i)
b, _ := json.Marshal(val)
m.Add("append", "value", fmt.Sprintf("%v", string(b)))
}
}
}
m.Table()
case []string:
for i, v := range val {
m.Add("append", "index", i)
m.Add("append", "value", v)
}
m.Table()
case string:
m.Echo("%s", val)
case float64:
m.Echo("%d", int(val))
case nil:
default:
b, _ := json.Marshal(val)
m.Echo("%s", string(b))
}
return
}},
"select": &Command{Name: "select field...",
Form: map[string]int{"reg": 2, "eq": 2, "expand": 2, "hide": -1, "fields": -1, "group": 1, "order": 2, "limit": 1, "offset": 1, "format": -1, "trans_map": -1, "vertical": 0},
Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
msg := m.Set("result").Spawn()
// 解析
if len(m.Meta["append"]) == 0 {
return
}
nrow := len(m.Meta[m.Meta["append"][0]])
keys := []string{}
for i := 0; i < nrow; i++ {
for j := 0; j < len(m.Meta["expand"]); j += 2 {
var value interface{}
json.Unmarshal([]byte(m.Meta[m.Meta["expand"][j]][i]), &value)
if m.Meta["expand"][j+1] != "" {
value = kit.Chain(value, m.Meta["expand"][j+1])
}
switch val := value.(type) {
case map[string]interface{}:
for k, _ := range val {
keys = append(keys, k)
}
default:
keys = append(keys, m.Meta["expand"][j+1])
}
}
}
for i := 0; i < nrow; i++ {
for _, k := range keys {
m.Add("append", k, "")
}
}
for i := 0; i < nrow; i++ {
for j := 0; j < len(m.Meta["expand"]); j += 2 {
var value interface{}
json.Unmarshal([]byte(m.Meta[m.Meta["expand"][j]][i]), &value)
if m.Meta["expand"][j+1] != "" {
value = kit.Chain(value, m.Meta["expand"][j+1])
}
switch val := value.(type) {
case map[string]interface{}:
for k, v := range val {
switch val := v.(type) {
case string:
m.Meta[k][i] = val
case float64:
m.Meta[k][i] = fmt.Sprintf("%d", int(val))
default:
b, _ := json.Marshal(val)
m.Meta[k][i] = string(b)
}
}
case string:
m.Meta[m.Meta["expand"][j+1]][i] = val
default:
m.Meta[m.Meta["expand"][j+1]][i] = kit.Format(val)
}
}
}
// 隐藏列
hides := map[string]bool{}
for _, k := range m.Meta["hide"] {
hides[k] = true
}
if len(arg) == 0 {
arg = append(arg, m.Meta["append"]...)
}
for i := 0; i < nrow; i++ {
// if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) {
if m.Has("eq") {
if m.Meta[m.Meta["eq"][0]][i] != m.Meta["eq"][1] {
continue
}
}
if m.Has("reg") {
if b, e := regexp.MatchString(m.Meta["reg"][1], m.Meta[m.Meta["reg"][0]][i]); e != nil || !b {
continue
}
}
for _, k := range arg {
if hides[k] {
continue
}
msg.Add("append", k, kit.Select("", m.Meta[k], i))
}
}
if len(msg.Meta["append"]) == 0 {
return
}
if len(msg.Meta[msg.Meta["append"][0]]) == 0 {
return
}
// 聚合
if m.Set("append"); m.Has("group") {
group := m.Option("group")
nrow := len(msg.Meta[msg.Meta["append"][0]])
for i := 0; i < nrow; i++ {
count := 1
if group != "" && msg.Meta[group][i] == "" {
msg.Add("append", "count", 0)
continue
}
for j := i + 1; j < nrow; j++ {
if group == "" || msg.Meta[group][i] == msg.Meta[group][j] {
count++
for _, k := range msg.Meta["append"] {
if k == "count" {
continue
}
if k == group {
continue
}
m, e := strconv.Atoi(msg.Meta[k][i])
if e != nil {
continue
}
n, e := strconv.Atoi(msg.Meta[k][j])
if e != nil {
continue
}
msg.Meta[k][i] = fmt.Sprintf("%d", m+n)
}
if group != "" {
msg.Meta[group][j] = ""
}
}
}
msg.Add("append", "count", count)
for _, k := range msg.Meta["append"] {
m.Add("append", k, msg.Meta[k][i])
}
if group == "" {
break
}
}
} else {
m.Copy(msg, "append")
}
// 排序
if m.Has("order") {
m.Sort(m.Option("order"), kit.Select("str", m.Meta["order"], 1))
}
// 分页
offset := kit.Int(kit.Select("0", m.Option("offset")))
limit := kit.Int(kit.Select(m.Conf("table", "limit"), m.Option("table.limit")))
nrow = len(m.Meta[m.Meta["append"][0]])
if offset > nrow {
offset = nrow
}
if limit+offset > nrow {
limit = nrow - offset
}
for _, k := range m.Meta["append"] {
m.Meta[k] = m.Meta[k][offset : offset+limit]
}
// 值转换
for i := 0; i < len(m.Meta["trans_map"]); i += 3 {
trans := m.Meta["trans_map"][i:]
for j := 0; j < len(m.Meta[trans[0]]); j++ {
if m.Meta[trans[0]][j] == trans[1] {
m.Meta[trans[0]][j] = trans[2]
}
}
}
// 格式化
for i := 0; i < len(m.Meta["format"])-1; i += 2 {
format := m.Meta["format"]
for j, v := range m.Meta[format[i]] {
if v != "" {
m.Meta[format[i]][j] = fmt.Sprintf(format[i+1], v)
}
}
}
// 变换列
if m.Has("vertical") {
msg := m.Spawn()
nrow := len(m.Meta[m.Meta["append"][0]])
sort.Strings(m.Meta["append"])
msg.Add("append", "field", "")
msg.Add("append", "value", "")
for i := 0; i < nrow; i++ {
for _, k := range m.Meta["append"] {
msg.Add("append", "field", k)
msg.Add("append", "value", m.Meta[k][i])
}
msg.Add("append", "field", "")
msg.Add("append", "value", "")
}
m.Set("append").Copy(msg, "append")
}
// 取单值
// if len(arg) > 2 {
// if len(m.Meta[arg[2]]) > 0 {
// m.Echo(m.Meta[arg[2]][0])
// }
// return
// }
m.Set("result").Table()
return
}},
},
}
func Start(args ...string) bool {
if len(args) == 0 {
args = append(args, os.Args[1:]...)
}
if len(args) > 0 && args[0] == "start" {
args = args[1:]
}
if len(args) > 0 && args[0] == "daemon" {
Pulse.Options("bio.modal", "daemon")
Pulse.Options("daemon", true)
args = args[1:]
}
kit.DisableLog = true
if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) {
return Index.Close(Pulse, args...)
}
return Index.message.Wait()
}