diff --git a/Makefile b/Makefile
index a280f4ca..aa421c3c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,24 +1,22 @@
-BENCH=src/examples/bench.go
+BENCH=src/examples/app/bench.go
install:
- @go get github.com/go-sql-driver/mysql
- @go get github.com/go-cas/cas
@go get github.com/nsf/termbox-go
@go get github.com/skip2/go-qrcode
+ @go get github.com/go-sql-driver/mysql
@go get github.com/gomarkdown/markdown
@go get github.com/PuerkitoBio/goquery
+ @go get github.com/go-cas/cas
GOPATH=$(PWD):$(GOPATH) go install $(BENCH)
@date
# bench web.code.counter nmake 1
install_all: install
- touch etc/local.shy
- touch etc/local_exit.shy
touch etc/init.shy
touch etc/exit.shy
- touch etc/login.txt
- touch etc/history.txt
+ touch etc/local.shy
+ touch etc/local_exit.shy
run:
etc/bootstrap.sh
@@ -51,33 +49,30 @@ tar_all: tar linux64 darwin win64
mv bench.win64.exe tar/bin/
tar zcvf tar.tgz tar
-linux64:
- GOARCH=amd64 GOOS=linux go build -o bench.linux64 $(BENCH)
-linux32:
- GOARCH=386 GOOS=linux go build -o bench.linux32 $(BENCH)
linux_arm:
GOARCH=arm GOOS=linux go build -o bench.linux.arm $(BENCH)
+linux32:
+ GOARCH=386 GOOS=linux go build -o bench.linux32 $(BENCH)
+linux64:
+ GOARCH=amd64 GOOS=linux go build -o bench.linux64 $(BENCH)
darwin:
GOARCH=amd64 GOOS=darwin go build -o bench.darwin $(BENCH)
-
-win64:
- GOARCH=amd64 GOOS=windows go build -o bench.win64.exe $(BENCH)
win32:
GOARCH=386 GOOS=windows go build -o bench.win32.exe $(BENCH)
+win64:
+ GOARCH=amd64 GOOS=windows go build -o bench.win64.exe $(BENCH)
DOTS=etc/dotsfile
back_dotsfile:
cp ~/.zshrc $(DOTS)
cp ~/.tmux.conf $(DOTS)
- # cp ~/context/.git/hooks/post-commit $(DOTS)/git_hooks
cp ~/.vimrc $(DOTS)
cp ~/.vim/syntax/shy.vim $(DOTS)
load_dotsfile:\
~/.zshrc\
~/.tmux.conf\
- ~/context/.git/hooks/post-commit\
~/.vimrc\
~/.vim/syntax/shy.vim
diff --git a/etc/init.shy b/etc/init.shy
index 1a63f04c..dbf44d8f 100644
--- a/etc/init.shy
+++ b/etc/init.shy
@@ -1,4 +1,8 @@
~ssh
remote listen :9090
+~aaa
+ user root shy shy
+~web
+ serve
~stdio
diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go
index 74e77961..65ba1049 100644
--- a/src/contexts/cli/cli.go
+++ b/src/contexts/cli/cli.go
@@ -233,7 +233,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
} else {
wait := make(chan bool, 1)
- go func() {
+ m.GoFunc(m, func(m *ctx.Message) {
out := bytes.NewBuffer(make([]byte, 0, 1024))
err := bytes.NewBuffer(make([]byte, 0, 1024))
cmd.Stdout = out
@@ -265,7 +265,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
}
wait <- true
- }()
+ })
timeout := m.Conf("cmd_timeout")
if conf["timeout"] != nil {
@@ -1073,34 +1073,31 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
if cli.Timer == nil { // 创建时间队列
cli.Timer = time.NewTimer((time.Duration)((action - now) / int64(m.Confi("time_unit")) * 1000000000))
- go func() {
- for {
- select {
- case <-cli.Timer.C:
- m.Log("info", "timer %s", m.Conf("timer_next"))
- if m.Conf("timer_next") == "" {
- break
- }
-
- if timer := m.Confm("timer", m.Conf("timer_next")); timer != nil && !kit.Right(timer["stop"]) {
- m.Log("info", "timer %s %v", m.Conf("timer_next"), timer["cmd"])
-
- msg := m.Sess("cli").Cmd("source", timer["cmd"])
- timer["result"] = msg.Meta["result"]
- timer["msg"] = msg.Code()
-
- if timer["repeat"].(bool) {
- timer["action_time"] = int64(m.Sess("cli").Cmd("time", timer["action_time"], timer["order"], timer["time"]).Appendi("timestamp"))
- } else {
- timer["done"] = true
- }
- }
-
- cli.schedule(m)
+ m.GoLoop(m, func(m *ctx.Message) {
+ select {
+ case <-cli.Timer.C:
+ m.Log("info", "timer %s", m.Conf("timer_next"))
+ if m.Conf("timer_next") == "" {
+ break
}
+
+ if timer := m.Confm("timer", m.Conf("timer_next")); timer != nil && !kit.Right(timer["stop"]) {
+ m.Log("info", "timer %s %v", m.Conf("timer_next"), timer["cmd"])
+
+ msg := m.Sess("cli").Cmd("source", timer["cmd"])
+ timer["result"] = msg.Meta["result"]
+ timer["msg"] = msg.Code()
+
+ if timer["repeat"].(bool) {
+ timer["action_time"] = int64(m.Sess("cli").Cmd("time", timer["action_time"], timer["order"], timer["time"]).Appendi("timestamp"))
+ } else {
+ timer["done"] = true
+ }
+ }
+
+ cli.schedule(m)
}
- cli.Timer = nil
- }()
+ })
}
// 调度任务
diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go
deleted file mode 100644
index fda6372f..00000000
--- a/src/contexts/ctx/ctx.go
+++ /dev/null
@@ -1,3382 +0,0 @@
-package ctx
-
-import (
- "encoding/json"
- "fmt"
- "html/template"
- "regexp"
- "runtime"
- "strconv"
- "strings"
-
- "errors"
- "io"
- "math/rand"
- "os"
- "sort"
- "time"
- "toolkit"
-)
-
-type Cache struct {
- Value string
- Name string
- Help string
- Hand func(m *Message, x *Cache, arg ...string) string
-}
-type Config struct {
- Value interface{}
- Name string
- Help string
- Hand func(m *Message, x *Config, arg ...string) string
-}
-type Command struct {
- Form map[string]int
- Name string
- Help interface{}
- Auto func(m *Message, c *Context, key string, arg ...string) (ok bool)
- Hand func(m *Message, c *Context, key string, arg ...string) (e error)
-}
-type Server interface {
- Spawn(m *Message, c *Context, arg ...string) Server
- Begin(m *Message, arg ...string) Server
- Start(m *Message, arg ...string) bool
- Close(m *Message, arg ...string) bool
-}
-type Context struct {
- Name string
- Help string
-
- Caches map[string]*Cache
- Configs map[string]*Config
- Commands map[string]*Command
-
- message *Message
- requests []*Message
- sessions []*Message
-
- contexts map[string]*Context
- context *Context
- root *Context
-
- exit chan bool
- Server
-}
-
-func (c *Context) Register(s *Context, x Server) {
- if c.contexts == nil {
- c.contexts = make(map[string]*Context)
- }
- if x, ok := c.contexts[s.Name]; ok {
- panic(errors.New(c.Name + "上下文中已存在模块:" + x.Name))
- }
-
- c.contexts[s.Name] = s
- s.context = c
- s.Server = x
-}
-func (c *Context) Spawn(m *Message, name string, help string) *Context {
- s := &Context{Name: name, Help: help, root: c.root, context: c, message: m,
- Caches: map[string]*Cache{},
- Configs: map[string]*Config{},
- Commands: map[string]*Command{},
- }
-
- if m.target = s; c.Server != nil {
- c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...))
- } else {
- c.Register(s, nil)
- }
- return s
-}
-func (c *Context) Begin(m *Message, arg ...string) *Context {
- if len(arg) > 0 {
- m.Set("detail", arg)
- }
-
- module := c.Name
- if c.context != nil {
- module = c.context.Name + "." + c.Name
- }
-
- c.Caches["module"] = &Cache{Name: "module", Value: module, Help: "模块域名"}
- c.Caches["status"] = &Cache{Name: "status(begin/start/close)", Value: "begin", Help: "模块状态, begin: 初始完成, start: 正在运行, close: 运行结束"}
- c.Caches["stream"] = &Cache{Name: "stream", Value: "", Help: "模块数据"}
-
- c.message = m
- c.requests = append(c.requests, m)
- m.source.sessions = append(m.source.sessions, m)
- c.exit = make(chan bool, 3)
-
- switch v := m.Gdb("context", "begin", c.Name).(type) {
- case string:
- kit.Log("error", "fuck %v", v)
- case nil:
- }
-
- m.Log("begin", "%d context %v %v", m.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"])
- for k, x := range c.Configs {
- if x.Hand != nil {
- m.Log("begin", "%s config %v", k, m.Conf(k, x.Value))
- }
- }
-
- if c.Server != nil {
- c.Server.Begin(m, m.Meta["detail"]...)
- }
-
- return c
-}
-func (c *Context) Start(m *Message, arg ...string) bool {
- sync := false
- if len(arg) > 0 && arg[0] == "sync" {
- sync, arg = true, arg[1:]
- }
- if len(arg) > 0 {
- m.Set("detail", arg)
- }
-
- c.requests = append(c.requests, m)
- m.source.sessions = append(m.source.sessions, m)
-
- switch v := m.Gdb("context", "start", c.Name).(type) {
- case string:
- kit.Log("error", "fuck %v", v)
- case nil:
- }
-
- if m.Hand = true; m.Cap("status") == "start" {
- return true
- }
-
- go m.TryCatch(m, true, func(m *Message) {
- m.Log(m.Cap("status", "start"), "%d server %v %v", m.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"])
-
- c.message = m
- if c.exit <- false; c.Server == nil || c.Server.Start(m, m.Meta["detail"]...) {
- c.Close(m, m.Meta["detail"]...)
- c.exit <- true
- }
- }, func(m *Message) {
- c.Close(m, m.Meta["detail"]...)
- c.exit <- true
- })
-
- if sync {
- for !<-c.exit {
- }
- return true
- }
- return <-c.exit
-}
-func (c *Context) Close(m *Message, arg ...string) bool {
- if len(c.requests) == 0 {
- return true
- }
-
- if m.target == c {
- for i := len(c.requests) - 1; i >= 0; i-- {
- if msg := c.requests[i]; msg.code == m.code {
- if c.Server == nil || c.Server.Close(m, arg...) {
- m.Log("close", "request %d/%d", i, len(c.requests)-1)
- msg.Free()
- for j := i; j < len(c.requests)-1; j++ {
- c.requests[j] = c.requests[j+1]
- }
- c.requests = c.requests[:len(c.requests)-1]
- }
- }
- }
- }
-
- if len(c.requests) > 0 {
- return false
- }
-
- if m.Cap("status") == "start" {
- m.Log(m.Cap("status", "close"), "%d server %v", m.root.Capi("nserver", -1), arg)
- for _, msg := range c.sessions {
- if msg.Cap("status") != "close" {
- msg.target.Close(msg, arg...)
- }
- }
- }
-
- if c.context != nil {
- m.Log("close", "%d context %v", m.root.Capi("ncontext", -1), arg)
- delete(c.context.contexts, c.Name)
- c.exit <- true
- }
- return true
-}
-
-func (c *Context) Context() *Context {
- return c.context
-}
-func (c *Context) Message() *Message {
- return c.message
-}
-func (c *Context) Has(key ...string) bool {
- switch len(key) {
- case 2:
- if _, ok := c.Commands[key[0]]; ok && key[1] == "command" {
- return true
- }
- if _, ok := c.Configs[key[0]]; ok && key[1] == "config" {
- return true
- }
- if _, ok := c.Caches[key[0]]; ok && key[1] == "cache" {
- return true
- }
- case 1:
- if _, ok := c.Commands[key[0]]; ok {
- return true
- }
- if _, ok := c.Configs[key[0]]; ok {
- return true
- }
- if _, ok := c.Caches[key[0]]; ok {
- return true
- }
- }
- return false
-}
-func (c *Context) Travel(m *Message, hand func(m *Message, n int) (stop bool)) *Context {
- target := m.target
-
- cs := []*Context{c}
- for i := 0; i < len(cs); i++ {
- if m.target = cs[i]; hand(m, i) {
- return cs[i]
- }
-
- keys := []string{}
- for k, _ := range cs[i].contexts {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- cs = append(cs, cs[i].contexts[k])
- }
- }
-
- m.target = target
- return target
-}
-func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Context {
- target := m.target
-
- for s := m.target; s != nil; s = s.context {
- if m.target = s; hand(m) {
- return s
- }
- }
-
- m.target = target
- return target
-}
-func (c *Context) Sub(key string) *Context {
- return c.contexts[key]
-}
-
-type LOGGER interface {
- Log(*Message, string, string, ...interface{})
-}
-type DEBUG interface {
- Wait(*Message, ...interface{}) interface{}
- Goon(interface{}, ...interface{})
-}
-type Message struct {
- time time.Time
- code int
-
- source *Context
- target *Context
-
- Meta map[string][]string
- Data map[string]interface{}
-
- callback func(msg *Message) (sub *Message)
- freedoms []func(msg *Message) (done bool)
- Sessions map[string]*Message
-
- messages []*Message
- message *Message
- root *Message
-
- Remote chan bool
- Hand bool
-}
-
-func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
-
- if l := m.Sess("log", false); l != nil {
- if log, ok := l.target.Server.(LOGGER); ok {
- if action == "error" {
- log.Log(m, "error", "chain: %s", m.Format("chain"))
- }
- log.Log(m, action, str, arg...)
- if action == "error" {
- log.Log(m, "error", "stack: %s", m.Format("stack"))
- }
- return m
- }
- }
-
- if action == "error" {
- kit.Log("error", fmt.Sprintf("chain: %s", m.Format("chain")))
- kit.Log("error", fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...)))
- kit.Log("error", fmt.Sprintf("stack: %s", m.Format("stack")))
- }
-
- return m
-}
-func (m *Message) Gdb(arg ...interface{}) interface{} {
- if g := m.Sess("gdb", false); g != nil {
- if gdb, ok := g.target.Server.(DEBUG); ok {
- return gdb.Wait(m, arg...)
- }
- }
- return nil
-}
-func (m *Message) Spawn(arg ...interface{}) *Message {
- c := m.target
- if len(arg) > 0 {
- switch v := arg[0].(type) {
- case *Context:
- c = v
- case *Message:
- c = v.target
- }
- }
-
- msg := &Message{
- time: time.Now(),
- code: m.Capi("nmessage", 1),
- source: m.target,
- target: c,
- message: m,
- root: m.root,
- }
-
- m.messages = append(m.messages, msg)
- return msg
-}
-func (m *Message) Time(arg ...interface{}) string {
- t := m.time
-
- if len(arg) > 0 {
- if d, e := time.ParseDuration(arg[0].(string)); e == nil {
- arg = arg[1:]
- t.Add(d)
- }
- }
-
- str := m.Conf("time_format")
- if len(arg) > 1 {
- str = fmt.Sprintf(arg[0].(string), arg[1:]...)
- } else if len(arg) > 0 {
- str = fmt.Sprintf("%v", arg[0])
- }
- return t.Format(str)
-}
-func (m *Message) Code() int {
- return m.code
-}
-func (m *Message) Source() *Context {
- return m.source
-}
-func (m *Message) Target() *Context {
- return m.target
-}
-func (m *Message) Message() *Message {
- return m.message
-}
-func (m *Message) Format(arg ...interface{}) string {
- if len(arg) == 0 {
- arg = append(arg, "time", "ship")
- }
-
- meta := []string{}
- for _, v := range arg {
- switch kit.Format(v) {
- case "summary":
- msg := arg[1].(*Message)
- ms := make([]*Message, 0, 1024)
- ms = append(ms, msg.message, msg)
-
- for i := 0; i < len(ms); i++ {
- msg := ms[i]
- if m.Add("append", "index", i); msg == nil {
- m.Add("append", "message", "")
- m.Add("append", "time", "")
- m.Add("append", "code", "")
- m.Add("append", "source", "")
- m.Add("append", "target", "")
- m.Add("append", "details", "")
- m.Add("append", "options", "")
- continue
- }
-
- if msg.message != nil {
- m.Add("append", "message", msg.message.code)
- } else {
- m.Add("append", "message", "")
- }
- m.Add("append", "time", msg.time.Format("15:04:05"))
- m.Add("append", "code", msg.code)
- m.Add("append", "source", msg.source.Name)
- m.Add("append", "target", msg.target.Name)
- m.Add("append", "details", fmt.Sprintf("%v", msg.Meta["detail"]))
- m.Add("append", "options", fmt.Sprintf("%v", msg.Meta["option"]))
-
- if i == 0 {
- continue
- }
-
- if len(ms) < 30 && len(arg) > 2 && arg[2] == "deep" {
- ms = append(ms, ms[i].messages...)
- }
- }
- m.Table()
- case "time":
- meta = append(meta, m.Time())
- case "code":
- meta = append(meta, kit.Format(m.code))
- case "ship":
- meta = append(meta, fmt.Sprintf("%d(%s->%s)", m.code, m.source.Name, m.target.Name))
- case "source":
- target := m.target
- m.target = m.source
- meta = append(meta, m.Cap("module"))
- m.target = target
- case "target":
- meta = append(meta, m.Cap("module"))
-
- case "detail":
- meta = append(meta, fmt.Sprintf("%v", m.Meta["detail"]))
- case "option":
- meta = append(meta, fmt.Sprintf("%v", m.Meta["option"]))
- case "append":
- meta = append(meta, fmt.Sprintf("%v", m.Meta["append"]))
- case "result":
- meta = append(meta, fmt.Sprintf("%v", m.Meta["result"]))
-
- case "full":
- case "chain":
- ms := []*Message{}
- if v == "full" {
- ms = append(ms, m)
- } else {
- for msg := m; msg != nil; msg = msg.message {
- ms = append(ms, msg)
- }
- }
-
- for i := len(ms) - 1; i >= 0; i-- {
- msg := ms[i]
-
- meta = append(meta, fmt.Sprintf("\n%s\n", msg.Format("time", "ship")))
- meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
- meta = append(meta, fmt.Sprintf(" option: %d %v\n", len(msg.Meta["option"]), msg.Meta["option"]))
- for _, k := range msg.Meta["option"] {
- if v, ok := msg.Data[k]; ok {
- meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
- } else if v, ok := msg.Meta[k]; ok {
- meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
- }
- }
- meta = append(meta, fmt.Sprintf(" append: %d %v\n", len(msg.Meta["append"]), msg.Meta["append"]))
- for _, k := range msg.Meta["append"] {
- if v, ok := msg.Data[k]; ok {
- meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
- } else if v, ok := msg.Meta[k]; ok {
- meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
- }
- }
- meta = append(meta, fmt.Sprintf(" result: %d %v\n", len(msg.Meta["result"]), msg.Meta["result"]))
- }
- case "stack":
- pc := make([]uintptr, 100)
- pc = pc[:runtime.Callers(2, pc)]
- frames := runtime.CallersFrames(pc)
-
- for {
- frame, more := frames.Next()
- file := strings.Split(frame.File, "/")
- name := strings.Split(frame.Function, "/")
- meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1]))
- if !more {
- break
- }
- }
-
- default:
- meta = append(meta, kit.FileName(kit.Format(v), "time"))
- }
- }
- return strings.Join(meta, " ")
-}
-func (m *Message) Tree(code int) *Message {
- ms := []*Message{m}
- for i := 0; i < len(ms); i++ {
- if ms[i].Code() == code {
- return ms[i]
- }
- ms = append(ms, ms[i].messages...)
- }
- return nil
-}
-
-func (m *Message) Add(meta string, key string, value ...interface{}) *Message {
- if m.Meta == nil {
- m.Meta = make(map[string][]string)
- }
- if _, ok := m.Meta[meta]; !ok {
- m.Meta[meta] = make([]string, 0, 3)
- }
-
- switch meta {
- case "detail", "result":
- m.Meta[meta] = append(m.Meta[meta], key)
- m.Meta[meta] = append(m.Meta[meta], kit.Trans(value...)...)
-
- case "option", "append":
- if _, ok := m.Meta[key]; !ok {
- m.Meta[key] = make([]string, 0, 3)
- }
- m.Meta[key] = append(m.Meta[key], kit.Trans(value...)...)
-
- for _, v := range m.Meta[meta] {
- if v == key {
- return m
- }
- }
- m.Meta[meta] = append(m.Meta[meta], key)
-
- default:
- m.Log("error", "add meta error %s %s %v", meta, key, value)
- }
-
- return m
-}
-func (m *Message) Set(meta string, arg ...interface{}) *Message {
- switch meta {
- case "detail", "result":
- if m != nil && m.Meta != nil {
- delete(m.Meta, meta)
- }
- case "option", "append":
- if len(arg) > 0 {
- delete(m.Meta, kit.Format(arg[0]))
- } else {
- for _, k := range m.Meta[meta] {
- delete(m.Data, k)
- delete(m.Meta, k)
- }
- delete(m.Meta, meta)
- }
- default:
- m.Log("error", "set meta error %s %s %v", meta, arg)
- }
-
- if args := kit.Trans(arg...); len(args) > 0 {
- m.Add(meta, args[0], args[1:])
- }
- return m
-}
-func (m *Message) Put(meta string, key string, value interface{}) *Message {
- switch meta {
- case "option", "append":
- if m.Set(meta, key); m.Data == nil {
- m.Data = make(map[string]interface{})
- }
- m.Data[key] = value
-
- default:
- m.Log("error", "put data error %s %s %v", meta, key, value)
- }
- return m
-}
-func (m *Message) Get(key string, arg ...interface{}) string {
- if meta, ok := m.Meta[key]; ok && len(meta) > 0 {
- index := 0
- if len(arg) > 0 {
- index = kit.Int(arg[0])
- }
-
- index = (index+2)%(len(meta)+2) - 2
- if index >= 0 && index < len(meta) {
- return meta[index]
- }
- }
- return ""
-}
-func (m *Message) Has(key ...string) bool {
- switch len(key) {
- case 1:
- if _, ok := m.Data[key[0]]; ok {
- return true
- }
- if _, ok := m.Meta[key[0]]; ok {
- return true
- }
- }
- return false
-}
-func (m *Message) CopyTo(msg *Message, arg ...string) *Message {
- msg.Copy(m, arg...)
- return m
-}
-func (m *Message) Copy(msg *Message, arg ...string) *Message {
- if m == msg {
- return m
- }
- if len(arg) == 0 {
- if msg.Hand {
- arg = append(arg, "append", "result")
- } else {
- arg = append(arg, "option")
- }
- }
-
- for i := 0; i < len(arg); i++ {
- meta := arg[i]
-
- switch meta {
- case "target":
- m.target = msg.target
- case "callback":
- m.callback = msg.callback
- // case "session":
- // if len(arg) == 0 {
- // for k, v := range msg.Sessions {
- // m.Sessions[k] = v
- // }
- // } else {
- // for _, k := range arg {
- // m.Sessions[k] = msg.Sessions[k]
- // }
- // }
- case "detail", "result":
- if len(msg.Meta[meta]) > 0 {
- m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
- }
- case "option", "append":
- if i == len(arg)-1 {
- arg = append(arg, msg.Meta[meta]...)
- }
-
- for i++; i < len(arg); i++ {
- if v, ok := msg.Data[arg[i]]; ok {
- m.Put(meta, arg[i], v)
- }
- if v, ok := msg.Meta[arg[i]]; ok {
- m.Add(meta, arg[i], v)
- }
- }
- default:
- if msg.Hand {
- meta = "append"
- } else {
- meta = "option"
- }
-
- if v, ok := msg.Data[arg[i]]; ok {
- m.Put(meta, arg[i], v)
- }
- if v, ok := msg.Meta[arg[i]]; ok {
- m.Add(meta, arg[i], v)
- }
- }
- }
-
- return m
-}
-func (m *Message) Echo(str string, arg ...interface{}) *Message {
- if len(arg) > 0 {
- return m.Add("result", fmt.Sprintf(str, arg...))
- }
- return m.Add("result", str)
-}
-
-func (m *Message) Insert(meta string, index int, arg ...interface{}) string {
- if m.Meta == nil {
- m.Meta = make(map[string][]string)
- }
- m.Meta[meta] = kit.Array(m.Meta[meta], index, arg)
-
- if -1 < index && index < len(m.Meta[meta]) {
- return m.Meta[meta][index]
- }
- return ""
-}
-func (m *Message) Detail(arg ...interface{}) string {
- noset, index := true, 0
- if len(arg) > 0 {
- switch v := arg[0].(type) {
- case int:
- noset, index, arg = false, v, arg[1:]
- }
- }
- if noset && len(arg) > 0 {
- index = -2
- }
-
- return m.Insert("detail", index, arg...)
-}
-func (m *Message) Detaili(arg ...interface{}) int {
- return kit.Int(m.Detail(arg...))
-}
-func (m *Message) Details(arg ...interface{}) bool {
- return kit.Right(m.Detail(arg...))
-}
-func (m *Message) Result(arg ...interface{}) string {
- noset, index := true, 0
- if len(arg) > 0 {
- switch v := arg[0].(type) {
- case int:
- noset, index, arg = false, v, arg[1:]
- }
- }
- if noset && len(arg) > 0 {
- index = -2
- }
-
- return m.Insert("result", index, arg...)
-}
-func (m *Message) Resulti(arg ...interface{}) int {
- return kit.Int(m.Result(arg...))
-}
-func (m *Message) Results(arg ...interface{}) bool {
- return kit.Right(m.Result(arg...))
-}
-func (m *Message) Option(key string, arg ...interface{}) string {
- if len(arg) > 0 {
- m.Insert(key, 0, arg...)
- if _, ok := m.Meta[key]; ok {
- m.Add("option", key)
- }
- }
-
- for msg := m; msg != nil; msg = msg.message {
- if !msg.Has(key) {
- continue
- }
- for _, k := range msg.Meta["option"] {
- if k == key {
- return msg.Get(key)
- }
- }
- }
- return ""
-}
-func (m *Message) Optioni(key string, arg ...interface{}) int {
- return kit.Int(m.Option(key, arg...))
-
-}
-func (m *Message) Options(key string, arg ...interface{}) bool {
- return kit.Right(m.Option(key, arg...))
-}
-func (m *Message) Optionv(key string, arg ...interface{}) interface{} {
- if len(arg) > 0 {
- switch arg[0].(type) {
- case nil:
- // case []string:
- // m.Option(key, v...)
- // case string:
- // m.Option(key, v)
- default:
- m.Put("option", key, arg[0])
- }
- }
-
- for msg := m; msg != nil; msg = msg.message {
- if msg.Meta == nil || !msg.Has(key) {
- continue
- }
- for _, k := range msg.Meta["option"] {
- if k == key {
- if v, ok := msg.Data[key]; ok {
- return v
- }
- return msg.Meta[key]
- }
- }
- }
- return nil
-}
-func (m *Message) Optionx(key string, arg ...string) interface{} {
- value := m.Conf(key)
- if value == "" {
- value = m.Option(key)
- }
-
- if len(arg) > 0 {
- value = fmt.Sprintf(arg[0], value)
- }
- return value
-}
-func (m *Message) Append(key string, arg ...interface{}) string {
- if len(arg) > 0 {
- m.Insert(key, 0, arg...)
- if _, ok := m.Meta[key]; ok {
- m.Add("append", key)
- }
- }
-
- ms := []*Message{m}
- for i := 0; i < len(ms); i++ {
- ms = append(ms, ms[i].messages...)
- if !ms[i].Has(key) {
- continue
- }
- for _, k := range ms[i].Meta["append"] {
- if k == key {
- return ms[i].Get(key)
- }
- }
- }
- return ""
-}
-func (m *Message) Appendi(key string, arg ...interface{}) int {
- return kit.Int(m.Append(key, arg...))
-
-}
-func (m *Message) Appends(key string, arg ...interface{}) bool {
- return kit.Right(m.Append(key, arg...))
-}
-func (m *Message) Appendv(key string, arg ...interface{}) interface{} {
- if len(arg) > 0 {
- m.Put("append", key, arg[0])
- }
-
- ms := []*Message{m}
- for i := 0; i < len(ms); i++ {
- ms = append(ms, ms[i].messages...)
- if !ms[i].Has(key) {
- continue
- }
- for _, k := range ms[i].Meta["append"] {
- if k == key {
- if v, ok := ms[i].Data[key]; ok {
- return v
- }
- return ms[i].Meta[key]
- }
- }
- }
- return nil
-}
-func (m *Message) Table(cbs ...func(maps map[string]string, list []string, line int) (goon bool)) *Message {
- if len(m.Meta["append"]) == 0 {
- return m
- }
-
- //计算列宽
- depth, width := 0, map[string]int{}
- for _, k := range m.Meta["append"] {
- if len(m.Meta[k]) > depth {
- depth = len(m.Meta[k])
- }
- width[k] = len(k)
- for _, v := range m.Meta[k] {
- if len(v) > width[k] {
- width[k] = len(v)
- }
- }
- }
-
- space := m.Confx("table_space")
- var cb func(maps map[string]string, list []string, line int) (goon bool)
- if len(cbs) > 0 {
- cb = cbs[0]
- } else {
- row := m.Confx("table_row_sep")
- col := m.Confx("table_col_sep")
- compact := kit.Right(m.Confx("table_compact"))
- cb = func(maps map[string]string, lists []string, line int) bool {
- for i, v := range lists {
- if k := m.Meta["append"][i]; compact {
- v = maps[k]
- }
-
- if m.Echo(v); i < len(lists)-1 {
- m.Echo(col)
- }
- }
- m.Echo(row)
- return true
- }
- }
-
- // 输出表头
- row := map[string]string{}
- wor := []string{}
- for _, k := range m.Meta["append"] {
- row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-len(k)))
- }
- if !cb(row, wor, -1) {
- return m
- }
-
- // 输出数据
- for i := 0; i < depth; i++ {
- row := map[string]string{}
- wor := []string{}
- for _, k := range m.Meta["append"] {
- data := ""
- if i < len(m.Meta[k]) {
- data = m.Meta[k][i]
- }
-
- row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-len(data)))
- }
- if !cb(row, wor, i) {
- break
- }
- }
-
- return m
-}
-func (m *Message) Sort(key string, arg ...string) *Message {
- cmp := "string"
- if len(arg) > 0 {
- cmp = arg[0]
- }
-
- number := map[int]int{}
- table := []map[string]string{}
- m.Table(func(line map[string]string, lists []string, index int) bool {
- if index != -1 {
- table = append(table, line)
- switch cmp {
- case "int":
- number[index] = kit.Int(line[key])
- case "int_r":
- number[index] = -kit.Int(line[key])
- case "time":
- number[index] = kit.Time(line[key])
- case "time_r":
- number[index] = -kit.Time(line[key])
- }
- }
- return true
- })
-
- for i := 0; i < len(table)-1; i++ {
- for j := i + 1; j < len(table); j++ {
- result := false
- switch cmp {
- case "str":
- if table[i][key] > table[j][key] {
- result = true
- }
- case "str_r":
- if table[i][key] < table[j][key] {
- result = true
- }
- default:
- if number[i] > number[j] {
- result = true
- }
- }
-
- if result {
- table[i], table[j] = table[j], table[i]
- number[i], number[j] = number[j], number[i]
- }
- }
- }
-
- for _, k := range m.Meta["append"] {
- delete(m.Meta, k)
- }
-
- for _, v := range table {
- for _, k := range m.Meta["append"] {
- m.Add("append", k, v[k])
- }
- }
- return m
-}
-func (m *Message) Parse(arg interface{}) string {
- switch str := arg.(type) {
- case string:
- if len(str) > 1 && str[0] == '$' {
- return m.Cap(str[1:])
- }
- if len(str) > 1 && str[0] == '@' {
- return m.Confx(str[1:])
- }
- return str
- }
- return ""
-}
-
-func (m *Message) Find(name string, root ...bool) *Message {
- if name == "" {
- return m.Spawn()
- }
- target := m.target.root
- if len(root) > 0 && !root[0] {
- target = m.target
- }
-
- cs := target.contexts
- for _, v := range strings.Split(name, ".") {
- if x, ok := cs[v]; ok {
- target, cs = x, x.contexts
- } else if target.Name == v {
- continue
- } else {
- m.Log("error", "context not find %s", name)
- return nil
- }
- }
- return m.Spawn(target)
-}
-func (m *Message) Search(key string, root ...bool) []*Message {
- reg, e := regexp.Compile(key)
- m.Assert(e)
-
- target := m.target
- if target == nil {
- return []*Message{nil}
- }
- if len(root) > 0 && root[0] {
- target = m.target.root
- }
-
- cs := make([]*Context, 0, 3)
- target.Travel(m, func(m *Message, i int) bool {
- if reg.MatchString(m.target.Name) || reg.FindString(m.target.Help) != "" {
- m.Log("search", "%d %s match [%s]", len(cs), m.target.Name, key)
- cs = append(cs, m.target)
- }
- return false
- })
-
- ms := make([]*Message, len(cs))
- for i := 0; i < len(cs); i++ {
- ms[i] = m.Spawn(cs[i])
- }
- if len(ms) == 0 {
- ms = append(ms, nil)
- }
-
- return ms
-}
-func (m *Message) Sess(key string, arg ...interface{}) *Message {
- if key == "" {
- return m.Spawn()
- }
-
- spawn := true
- if len(arg) > 0 {
- switch v := arg[0].(type) {
- case bool:
- spawn, arg = v, arg[1:]
- }
- }
-
- if len(arg) > 0 {
- if m.Sessions == nil {
- m.Sessions = make(map[string]*Message)
- }
-
- switch value := arg[0].(type) {
- case *Message:
- m.Sessions[key] = value
- return m.Sessions[key]
- case *Context:
- m.Sessions[key] = m.Spawn(value)
- return m.Sessions[key]
- case string:
- root := len(arg) < 3 || kit.Right(arg[2])
-
- method := "find"
- if len(arg) > 1 {
- method = kit.Format(arg[1])
- }
-
- switch method {
- case "find":
- m.Sessions[key] = m.Find(value, root)
- case "search":
- m.Sessions[key] = m.Search(value, root)[0]
- }
- return m.Sessions[key]
- case nil:
- delete(m.Sessions, key)
- return nil
- }
- }
-
- for msg := m; msg != nil; msg = msg.message {
- if x, ok := msg.Sessions[key]; ok {
- if spawn {
- x = m.Spawn(x.target)
- x.callback = func(sub *Message) *Message { return sub }
- }
- return x
- }
- }
-
- return nil
-}
-func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context, c *Context, key string) bool) *Message {
- if m == nil {
- return m
- }
-
- if strings.Contains(key, ".") {
- arg := strings.Split(key, ".")
- m, key = m.Sess(arg[0], spawn), arg[1]
- }
- if m == nil {
- return m
- }
-
- context := []*Context{m.target}
- for _, v := range []string{"aaa", "cli"} {
- if msg := m.Sess(v, false); msg != nil && msg.target != nil {
- context = append(context, msg.target)
- }
- }
- context = append(context, m.source)
-
- for _, s := range context {
- for c := s; c != nil; c = c.context {
- if hand(m, s, c, key) {
- return m
- }
- }
- }
- return m
-}
-func (m *Message) Call(cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
- if m == nil {
- return m
- }
- if m.callback = cb; len(arg) > 0 || len(m.Meta["detail"]) > 0 {
- m.Log("call", m.Format("detail", "option"))
- m.Cmd(arg...)
- }
- return m
-}
-func (m *Message) Back(ms ...*Message) *Message {
- if m.callback == nil {
- return m
- }
-
- if len(ms) == 0 {
- ms = append(ms, m.Spawn(m.source).Copy(m, "append").Copy(m, "result"))
- }
-
- ns := []*Message{}
-
- for _, msg := range ms {
- if msg.Hand {
- m.Log("back", msg.Format("ship", "result", "append"))
- } else {
- m.Log("back", msg.Format("ship", "detail", "option"))
- }
-
- if sub := m.callback(msg); sub != nil && m.message != nil && m.message != m {
- ns = append(ns, sub)
- }
- }
-
- if len(ns) > 0 {
- m.message.Back(ns...)
- }
- return m
-}
-func (m *Message) Backs(msg *Message) *Message {
- m.Back(msg)
- return msg
-}
-func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
- if !sync {
- return m.Call(cb, arg...)
- }
-
- wait := make(chan *Message, 10)
- go m.Call(func(sub *Message) *Message {
- msg := cb(sub)
- m.Log("sync", m.Format("done", "result", "append"))
- wait <- m
- return msg
- }, arg...)
-
- m.Log("sync", m.Format("wait", "result", "append"))
- return <-wait
-}
-func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
- if len(cbs) == 0 {
- for i := len(m.freedoms) - 1; i >= 0; i-- {
- m.Log("free", "%d/%d", i, len(m.freedoms)-1)
- if !m.freedoms[i](m) {
- break
- }
- m.freedoms = m.freedoms[:i]
- }
- return m
- }
-
- m.freedoms = append(m.freedoms, cbs...)
- return m
-}
-
-func (m *Message) Assert(e interface{}, msg ...string) bool {
- switch v := e.(type) {
- case nil:
- return true
- case *Message:
- if v.Result(0) != "error: " {
- return true
- }
- e = v.Result(1)
- default:
- if kit.Right(v) {
- return true
- }
- }
-
- switch e.(type) {
- case error:
- default:
- e = errors.New(kit.Format(msg))
- }
-
- m.Log("error", "%v", e)
- panic(e)
-}
-func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
- defer func() {
- e := recover()
- switch e {
- case io.EOF:
- case nil:
- default:
- m.Log("bench", "chain: %s", msg.Format("chain"))
- m.Log("bench", "catch: %s", e)
- m.Log("bench", "stack: %s", msg.Format("stack"))
-
- m.Log("error", "catch: %s", e)
-
- if len(hand) > 1 {
- m.TryCatch(msg, safe, hand[1:]...)
- } else if !safe {
- msg.Assert(e)
- }
- }
- }()
-
- if len(hand) > 0 {
- hand[0](msg)
- }
-
- return m
-}
-func (m *Message) Start(name string, help string, arg ...string) bool {
- return m.Set("detail", arg).target.Spawn(m, name, help).Begin(m).Start(m)
-}
-func (m *Message) Close(arg ...string) bool {
- return m.Target().Close(m, arg...)
-}
-func (m *Message) Wait() bool {
- if m.target.exit != nil {
- return <-m.target.exit
- }
- return true
-}
-
-func (m *Message) Cmdy(args ...interface{}) *Message {
- m.Cmd(args...).CopyTo(m)
- return m
-}
-func (m *Message) Cmdx(args ...interface{}) string {
- return m.Cmd(args...).Result(0)
-}
-func (m *Message) Cmds(args ...interface{}) bool {
- return m.Cmd(args...).Results(0)
-}
-func (m *Message) Cmd(args ...interface{}) *Message {
- if m == nil {
- return m
- }
-
- if len(args) > 0 {
- m.Set("detail", kit.Trans(args...))
- }
-
- key, arg := m.Meta["detail"][0], m.Meta["detail"][1:]
-
- m = m.Match(key, true, func(m *Message, s *Context, c *Context, key string) bool {
- if x, ok := c.Commands[key]; ok && x.Hand != nil {
- m.TryCatch(m, true, func(m *Message) {
- m.Log("cmd", "%s %s %v %v", c.Name, key, arg, m.Meta["option"])
-
- if args := []string{}; x.Form != nil {
- for i := 0; i < len(arg); i++ {
- if n, ok := x.Form[arg[i]]; ok {
-
- if n < 0 {
- n += len(arg) - i
- }
- for j := i + 1; j <= i+n; j++ {
- if _, ok := x.Form[arg[j]]; ok {
- n = j - i - 1
- }
- }
- m.Add("option", arg[i], arg[i+1:i+1+n])
- i += n
- } else {
- args = append(args, arg[i])
- }
- }
- arg = args
- }
-
- target := m.target
- m.target = s
-
- m.Hand = true
- switch v := m.Gdb("command", key, arg).(type) {
- case string:
- m.Echo(v)
- case nil:
- if m.Options("auto_cmd") {
- x.Auto(m, c, key, arg...)
- } else {
- x.Hand(m, c, key, arg...)
- }
- }
- if m.target == s {
- m.target = target
- }
- })
- }
- return m.Hand
- })
-
- if !m.Hand {
- m.Log("error", "cmd run error %s", m.Format())
- }
- return m
-}
-
-func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} {
- var chain interface{}
- if len(args) > 0 {
- switch arg := args[0].(type) {
- case []interface{}:
- chain, args = arg, args[1:]
- case []string:
- chain, args = arg, args[1:]
- case string:
- chain, args = arg, args[1:]
- }
- }
-
- var v interface{}
- if chain == nil {
- v = m.Confv(key)
- } else {
- v = m.Confv(key, chain)
- }
-
- table, _ := v.([]interface{})
- value, _ := v.(map[string]interface{})
- if len(args) == 0 {
- return value
- }
-
- switch fun := args[0].(type) {
- case func(int, string) bool:
- for i, v := range table {
- if fun(i, kit.Format(v)) {
- break
- }
- }
- case func(map[string]interface{}):
- fun(value)
- case func(string, map[string]interface{}):
- for k, v := range value {
- if val, ok := v.(map[string]interface{}); ok {
- fun(k, val)
- }
- }
- case func(int, map[string]interface{}):
- for i, v := range table {
- if val, ok := v.(map[string]interface{}); ok {
- fun(i, val)
- }
- }
- }
- return value
-}
-func (m *Message) Confx(key string, args ...interface{}) string {
- value := kit.Select(m.Conf(key), m.Option(key))
- if len(args) == 0 {
- return value
- }
-
- switch arg := args[0].(type) {
- case []string:
- if len(args) > 1 {
- value, args = kit.Select(value, arg, args[1]), args[1:]
- } else {
- value = kit.Select(value, arg)
- }
- case map[string]interface{}:
- value = kit.Select(value, kit.Format(arg[key]))
- case string:
- value = kit.Select(value, arg)
- case nil:
- default:
- value = kit.Select(value, args[0])
- }
-
- format := "%s"
- if args = args[1:]; len(args) > 0 {
- format, args = kit.Format(args[0]), args[1:]
- }
- arg := []interface{}{format, value}
- for _, v := range args {
- arg = append(arg, v)
- }
-
- return kit.Format(arg...)
-}
-func (m *Message) Confs(key string, arg ...interface{}) bool {
- return kit.Right(m.Confv(key, arg...))
-}
-func (m *Message) Confi(key string, arg ...interface{}) int {
- return kit.Int(m.Confv(key, arg...))
-}
-func (m *Message) Confv(key string, args ...interface{}) interface{} {
- var config *Config
- m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
- if x, ok := c.Configs[key]; ok {
- config = x
- return true
- }
- return false
- })
-
- if len(args) == 0 {
- if config == nil {
- return nil
- }
- return config.Value
- }
-
- if config == nil {
- config = &Config{}
- m.target.Configs[key] = config
- }
-
- switch config.Value.(type) {
- case string:
- config.Value = kit.Format(args...)
- case bool:
- config.Value = kit.Right(args...)
- case int:
- config.Value = kit.Int(args...)
- case nil:
- config.Value = args[0]
- default:
- for i := 0; i < len(args); i += 2 {
- if i < len(args)-1 {
- config.Value = kit.Chain(config.Value, args[i], args[i+1])
- } else {
- return kit.Chain(config.Value, args[i])
- }
- }
- }
-
- return config.Value
-}
-func (m *Message) Conf(key string, args ...interface{}) string {
- return kit.Format(m.Confv(key, args...))
-}
-func (m *Message) Caps(key string, arg ...interface{}) bool {
- if len(arg) > 0 {
- return kit.Right(m.Cap(key, arg...))
- }
- return kit.Right(m.Cap(key))
-}
-func (m *Message) Capi(key string, arg ...interface{}) int {
- n := kit.Int(m.Cap(key))
- if len(arg) > 0 {
- return kit.Int(m.Cap(key, n+kit.Int(arg...)))
- }
- return n
-}
-func (m *Message) Cap(key string, arg ...interface{}) string {
- var cache *Cache
- m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
- if x, ok := c.Caches[key]; ok {
- cache = x
- return true
- }
- return false
- })
-
- if len(arg) == 0 {
- if cache == nil {
- return ""
- }
- if cache.Hand != nil {
- return cache.Hand(m, cache)
- }
- return cache.Value
- }
-
- if cache == nil {
- cache = &Cache{}
- m.target.Caches[key] = cache
- }
-
- if cache.Hand != nil {
- cache.Value = cache.Hand(m, cache, kit.Format(arg...))
- } else {
- cache.Value = kit.Format(arg...)
- }
- return cache.Value
-}
-
-type CTX struct {
-}
-
-var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
- Caches: map[string]*Cache{
- "begin_time": &Cache{Name: "begin_time", Value: "", Help: "启动时间"},
- "goos": &Cache{Name: "goos", Value: "linux", 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{
- "chain": &Config{Name: "chain", Value: map[string]interface{}{}, Help: "调试模式,on:打印,off:不打印)"},
- "compact_log": &Config{Name: "compact_log(true/false)", Value: "true", Help: "调试模式,on:打印,off:不打印)"},
- "auto_make": &Config{Name: "auto_make(true/false)", Value: "true", Help: "调试模式,on:打印,off:不打印)"},
- "debug": &Config{Name: "debug(on/off)", Value: "on", Help: "调试模式,on:打印,off:不打印)"},
-
- "search_method": &Config{Name: "search_method(find/search)", Value: "search", Help: "搜索方法, find: 模块名精确匹配, search: 模块名或帮助信息模糊匹配"},
- "search_choice": &Config{Name: "search_choice(first/last/rand/magic)", Value: "magic", Help: "搜索匹配, first: 匹配第一个模块, last: 匹配最后一个模块, rand: 随机选择, magic: 加权选择"},
- "search_action": &Config{Name: "search_action(list/switch)", Value: "switch", Help: "搜索操作, list: 输出模块列表, switch: 模块切换"},
- "search_root": &Config{Name: "search_root(true/false)", Value: "true", Help: "搜索起点, true: 根模块, false: 当前模块"},
-
- "insert_limit": &Config{Name: "insert_limit(true/false)", Value: "true", Help: "参数的索引"},
- "detail_index": &Config{Name: "detail_index", Value: "0", Help: "参数的索引"},
- "result_index": &Config{Name: "result_index", Value: "-2", Help: "返回值的索引"},
-
- "list_help": &Config{Name: "list_help", Value: "list command", Help: "命令列表帮助"},
- "table_compact": &Config{Name: "table_compact", Value: "false", Help: "命令列表帮助"},
- "table_col_sep": &Config{Name: "table_col_sep", Value: " ", Help: "命令列表帮助"},
- "table_row_sep": &Config{Name: "table_row_sep", Value: "\n", Help: "命令列表帮助"},
- "table_space": &Config{Name: "table_space", Value: " ", Help: "命令列表帮助"},
-
- "page_offset": &Config{Name: "page_offset", Value: "0", Help: "列表偏移"},
- "page_limit": &Config{Name: "page_limit", Value: "10", Help: "列表大小"},
-
- "time_format": &Config{Name: "time_format", Value: "2006-01-02 15:04:05", Help: "时间格式"},
- },
- Commands: map[string]*Command{
- "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")
- 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)
- }
- for k, v := range v.Form {
- m.Add("append", "arg", k)
- m.Add("append", "len", v)
- m.Echo(" option: %s(%d)\n", k, v)
- }
- 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
- }},
-
- "message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
- msg := m
- if ms := m.Find(m.Cap("ps_target")); ms != nil {
- msg = ms
- }
-
- if len(arg) > 0 {
- if code, e := strconv.Atoi(arg[0]); e == nil {
- if msg = m.root.Tree(code); msg != nil {
- arg = arg[1:]
- }
- }
- }
-
- if len(arg) == 0 {
- m.Format("summary", msg, "deep")
- msg.CopyTo(m)
- 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.message
- if len(arg) == 0 {
- for i, v := range msg.Meta["detail"] {
- m.Add("append", "index", i)
- m.Add("append", "value", v)
- }
- m.Table()
- return
- }
-
- index := m.Confi("detail_index")
- if i, e := strconv.Atoi(arg[0]); e == nil {
- index, arg = i, arg[1:]
- }
- m.Echo("%s", msg.Detail(index, arg))
- return
- }},
- "option": &Command{Name: "option [all] [key [index] [value...]]", 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:]
- }
-
- index := -100
- if len(arg) > 1 {
- if i, e := strconv.Atoi(arg[1]); e == nil {
- index = i
- for i := 1; i < len(arg)-1; i++ {
- arg[i] = arg[i+1]
- }
- arg = arg[:len(arg)-1]
- }
- }
-
- msg := m.message
- for msg = msg; msg != nil; msg = msg.message {
- for _, k := range msg.Meta["option"] {
- if len(arg) == 0 {
- m.Add("append", "key", k)
- m.Add("append", "len", len(msg.Meta[k]))
- m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k]))
- continue
- }
-
- if k != arg[0] {
- continue
- }
-
- if len(arg) > 1 {
- msg.Meta[k] = kit.Array(msg.Meta[k], index, arg[1:])
- m.Echo("%v", msg.Meta[k])
- return
- }
-
- if index != -100 {
- m.Echo(kit.Array(msg.Meta[k], index)[0])
- return
- }
-
- for i, v := range msg.Meta[k] {
- m.Add("append", "index", i)
- m.Add("append", "value", v)
- }
- m.Table()
- return
- }
-
- if !all {
- break
- }
- }
- m.Sort("key", "string").Table()
- return
- }},
- "result": &Command{Name: "result [index] [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
- msg := m.message
- if len(arg) == 0 {
- for i, v := range msg.Meta["result"] {
- m.Add("append", "index", i)
- m.Add("append", "value", strings.Replace(v, "\n", "\\n", -1))
- }
- m.Table()
- return
- }
-
- index := m.Confi("result_index")
- if i, e := strconv.Atoi(arg[0]); e == nil {
- index, arg = i, arg[1:]
- }
- m.Echo("%s", msg.Result(index, arg))
- return
- }},
- "append": &Command{Name: "append [all] [key [index] [value...]]", 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:]
- }
-
- index := -100
- if len(arg) > 1 {
- if i, e := strconv.Atoi(arg[1]); e == nil {
- index = i
- for i := 1; i < len(arg)-1; i++ {
- arg[i] = arg[i+1]
- }
- arg = arg[:len(arg)-1]
- }
- }
-
- msg := m.message
- for msg = msg; msg != nil; msg = msg.message {
- for _, k := range msg.Meta["append"] {
- if len(arg) == 0 {
- m.Add("append", "key", k)
- m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k]))
- continue
- }
-
- if k != arg[0] {
- continue
- }
-
- if len(arg) > 1 {
- msg.Meta[k] = kit.Array(msg.Meta[k], index, arg[1:])
- m.Echo("%v", msg.Meta[k])
- return
- }
-
- if index != -100 {
- m.Echo(kit.Array(msg.Meta[k], index)[0])
- return
- }
-
- for i, v := range msg.Meta[k] {
- m.Add("append", "index", i)
- m.Add("append", "value", v)
- }
- m.Table()
- return
- }
-
- if !all {
- break
- }
- }
- m.Table()
- return
- }},
- "session": &Command{Name: "session [all] [key [module]]", 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.message
- for msg = msg; msg != nil; msg = msg.message {
- for k, v := range msg.Sessions {
- if len(arg) > 1 {
- msg.Sessions[arg[0]] = msg.Find(arg[1])
- return
- } else if len(arg) > 0 {
- if k == arg[0] {
- m.Echo("%d", v.code)
- return
- }
- continue
- }
-
- m.Add("append", "key", k)
- m.Add("append", "time", v.time.Format("15:04:05"))
- m.Add("append", "code", v.code)
- m.Add("append", "source", v.source.Name)
- m.Add("append", "target", v.target.Name)
- m.Add("append", "details", fmt.Sprintf("%v", v.Meta["detail"]))
- m.Add("append", "options", fmt.Sprintf("%v", v.Meta["option"]))
- }
-
- if len(arg) == 0 && !all {
- break
- }
- }
- m.Table()
- return
- }},
- "callback": &Command{Name: "callback", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
- msg := m.message
- for msg := msg; msg != nil; msg = msg.message {
- m.Add("append", "msg", msg.code)
- m.Add("append", "fun", msg.callback)
- }
- m.Table()
- return
- }},
-
- "context": &Command{Name: "context [find|search] [root|back|home] [first|last|rand|magic] [module] [cmd|switch|list|spawn|start|close]",
- Help: "查找并操作模块;\n查找方法, find: 精确查找, search: 模糊搜索;\n查找起点, root: 根模块, back: 父模块, home: 本模块;\n过滤结果, first: 取第一个, last: 取最后一个, rand: 随机选择, magic: 智能选择;\n操作方法, cmd: 执行命令, switch: 切换为当前, list: 查看所有子模块, spwan: 创建子模块并初始化, start: 启动模块, close: 结束模块",
- Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
- if len(arg) == 1 && arg[0] == "~" && m.target.context != nil {
- m.target = m.target.context
- return
- }
-
- 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 "magic":
- 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 m.Options("sso_bench") && m.Options("sso_username") &&
- !m.Cmds("aaa.work", m.Option("sso_bench"), "right", m.Option("sso_username"), "componet", "source", "command", arg[0]) {
-
- m.Log("info", "sso check %v: %v failure", m.Option("sso_componet"), m.Option("sso_command"))
- m.Echo("error: ").Echo("no right [%s: %s %s]", m.Option("sso_componet"), m.Option("sso_command"), arg[0])
- break
- }
-
- if msg.Cmd(arg); !msg.Hand {
- msg = msg.Sess("cli").Cmd("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
- })
-
- for _, v := range cs {
- if msg.target = v; v == nil {
- m.Add("append", "name", "")
- m.Add("append", "ctx", "")
- m.Add("append", "msg", "")
- m.Add("append", "status", "")
- m.Add("append", "stream", "")
- m.Add("append", "help", "")
- continue
- }
-
- m.Add("append", "name", msg.target.Name)
- if msg.target.context != nil {
- m.Add("append", "ctx", msg.target.context.Name)
- } else {
- m.Add("append", "ctx", "")
- }
- m.Add("append", "msg", msg.target.message.code)
- m.Add("append", "status", msg.Cap("status"))
- m.Add("append", "stream", msg.Cap("stream"))
- m.Add("append", "help", msg.target.Help)
- }
-
- 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...)
- }
- }
-
- if action == "list" {
- m.Table()
- }
- return
- }},
- "command": &Command{Name: "command [all] [show]|[list [begin [end]] [prefix] test [key val]...]|[add [list_name name] [list_help help] cmd...]|[delete cmd]",
- Help: "查看或修改命令, show: 查看命令;\nlist: 查看列表命令, begin: 起始索引, end: 截止索引, prefix: 过滤前缀, test: 执行命令;\nadd: 添加命令, list_name: 命令别名, list_help: 命令帮助;\ndelete: 删除命令",
- 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:]
- }
-
- action := "show"
- if len(arg) > 0 {
- switch arg[0] {
- case "show", "list", "add", "delete":
- action, arg = arg[0], arg[1:]
- }
- }
-
- switch action {
- case "show":
- c.BackTrace(m, func(m *Message) bool {
- for k, v := range m.target.Commands {
- if len(arg) > 0 {
- if k == arg[0] {
- m.Add("append", "key", k)
- m.Add("append", "name", v.Name)
- m.Add("append", "help", v.Name)
- }
- } else {
- m.Add("append", "key", k)
- m.Add("append", "name", v.Name)
- }
- }
-
- return !all
- })
- m.Table()
- case "list":
- 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", fmt.Sprintf("%s", 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{}
- }
-
- 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").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)
- case "delete":
- c.BackTrace(m, func(m *Message) bool {
- delete(m.target.Commands, arg[0])
- return !all
- })
- }
- return
- }},
- "config": &Command{Name: "config [all] [export key..] [save|load file key...] [list|map arg...] [create map|list|string key name help] [delete key]",
- Help: "配置管理, export: 导出配置, save: 保存配置到文件, load: 从文件加载配置, create: 创建配置, delete: 删除配置",
- Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
- if len(arg) > 2 && arg[2] == "list" {
- chain := strings.Split(arg[1], ".")
- chain = append(chain, "-2")
-
- for _, val := range arg[3:] {
- m.Confv(arg[0], chain, val)
- }
- return
- }
- if len(arg) > 2 && arg[2] == "map" {
- chain := strings.Split(arg[1], ".")
-
- for i := 3; i < len(arg)-1; i += 2 {
- m.Confv(arg[0], append(chain, arg[i]), arg[i+1])
- }
- return
- }
-
- all := false
- if len(arg) > 0 && arg[0] == "all" {
- arg, all = arg[1:], true
- }
-
- action, which := "", "-1"
- have := map[string]bool{}
- if len(arg) > 0 {
- switch arg[0] {
- 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:]
- }
- }
-
- if len(arg) == 0 || action != "" {
- save := map[string]interface{}{}
- if action == "load" {
- f, e := os.Open(m.Sess("nfs").Cmd("path", which).Result(0))
- 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] {
- delete(m.target.Configs, k)
- }
- fallthrough
- 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]}
- }
- 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
- }
-
- var value interface{}
- 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
- }},
- "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
- }},
-
- "trans": &Command{Name: "trans option [type|data|json] limit 10 [index...]", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
- value, arg := m.Optionv(arg[0]), arg[1:]
-
- view := "data"
- if len(arg) > 0 {
- switch arg[0] {
- case "type", "data", "json":
- view, arg = arg[0], arg[1:]
- }
- }
-
- limit := m.Confi("page_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{}:
- for k, v := range val {
- 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)))
- }
- }
- m.Sort("key", "str").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 key value field",
- Form: map[string]int{"parse": 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["parse"]); j += 2 {
- var value interface{}
- json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value)
- if m.Meta["parse"][j+1] != "" {
- value = kit.Chain(value, m.Meta["parse"][j+1])
- }
-
- switch val := value.(type) {
- case map[string]interface{}:
- for k, _ := range val {
- keys = append(keys, k)
- }
- default:
- keys = append(keys, m.Meta["parse"][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["parse"]); j += 2 {
- var value interface{}
- json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value)
- if m.Meta["parse"][j+1] != "" {
- value = kit.Chain(value, m.Meta["parse"][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["parse"][j+1]][i] = val
- case float64:
- m.Meta[m.Meta["parse"][j+1]][i] = fmt.Sprintf("%d", int(val))
- default:
- b, _ := json.Marshal(val)
- m.Meta[m.Meta["parse"][j+1]][i] = string(b)
- }
- }
- }
-
- // 隐藏列
- hides := map[string]bool{}
- for _, k := range m.Meta["hide"] {
- hides[k] = true
- }
- for i := 0; i < nrow; i++ {
- if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) {
- for _, k := range m.Meta["append"] {
- if hides[k] {
- continue
- }
- msg.Add("append", k, m.Meta[k][i])
- }
- }
- }
-
- // 选择列
- if m.Option("fields") != "" {
- msg = m.Spawn()
- m.Hand = true
- msg.Copy(m, strings.Split(strings.Join(m.Meta["fields"], " "), " ")...)
- m.Hand = false
- m.Set("append").Copy(msg, "append")
- }
-
- // 聚合
- 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.Meta["order"][1], m.Option("order"))
- }
-
- // 分页
- offset := 0
- limit := m.Confi("page_limit")
- if m.Has("limit") {
- limit = m.Optioni("limit")
- }
- if m.Has("offset") {
- offset = m.Optioni("offset")
- }
- 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]] {
- 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
- }},
- },
-}
-var CGI = template.FuncMap{
- "meta": func(arg ...interface{}) string {
- //meta meta [key [index]]
- if len(arg) == 0 {
- return ""
- }
-
- up := ""
-
- list := []string{}
- switch data := arg[0].(type) {
- case map[string][]string:
- if len(arg) == 1 {
- list = append(list, fmt.Sprintf("detail: %s\n", data["detail"]))
- list = append(list, fmt.Sprintf("option: %s\n", data["option"]))
- list = append(list, fmt.Sprintf("result: %s\n", data["result"]))
- list = append(list, fmt.Sprintf("append: %s\n", data["append"]))
- break
- }
- if key, ok := arg[1].(string); ok {
- if list, ok = data[key]; ok {
- arg = arg[1:]
- } else {
- return up
- }
- } else {
- return fmt.Sprintf("%v", data)
- }
- case []string:
- list = data
- default:
- if data == nil {
- return ""
- }
- return fmt.Sprintf("%v", data)
- }
-
- if len(arg) == 1 {
- return strings.Join(list, "")
- }
-
- index, ok := arg[1].(int)
- if !ok {
- return strings.Join(list, "")
- }
-
- if index >= len(list) {
- return ""
- }
- return list[index]
- },
- "sess": func(arg ...interface{}) string {
- if len(arg) == 0 {
- return ""
- }
-
- if m, ok := arg[0].(*Message); ok {
- if len(arg) == 1 {
- return fmt.Sprintf("%v", m)
- }
-
- switch which := arg[1].(type) {
- case string:
- m.Sess(which, arg[2:]...)
- return ""
- }
- }
- return ""
- },
-
- "ctx": func(arg ...interface{}) string {
- if len(arg) == 0 {
- return ""
- }
- if m, ok := arg[0].(*Message); ok {
- if len(arg) == 1 {
- return fmt.Sprintf("%v", m)
- }
-
- switch which := arg[1].(type) {
- case string:
- switch which {
- case "name":
- return fmt.Sprintf("%s", m.target.Name)
- case "help":
- return fmt.Sprintf("%s", m.target.Help)
- case "context":
- return fmt.Sprintf("%s", m.target.context.Name)
- case "contexts":
- ctx := []string{}
- for _, v := range m.target.contexts {
- ctx = append(ctx, fmt.Sprintf("%d", v.Name))
- }
- return strings.Join(ctx, " ")
- case "time":
- return m.time.Format("2006-01-02 15:04:05")
- case "source":
- return m.source.Name
- case "target":
- return m.target.Name
- case "message":
- return fmt.Sprintf("%d", m.message.code)
- case "messages":
- case "sessions":
- msg := []string{}
- for k, _ := range m.Sessions {
- msg = append(msg, fmt.Sprintf("%s", k))
- }
- return strings.Join(msg, " ")
- }
- case int:
- }
- }
- return ""
- },
- "msg": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- if m, ok := arg[0].(*Message); ok {
- if len(arg) == 1 {
- return fmt.Sprintf("%v", m.Format())
- }
-
- switch which := arg[1].(type) {
- case string:
- switch which {
- case "spawn":
- return m.Spawn()
- case "code":
- return m.code
- case "time":
- return m.time.Format("2006-01-02 15:04:05")
- case "source":
- return m.source.Name
- case "target":
- return m.target.Name
- case "message":
- return m.message
- case "messages":
- return m.messages
- case "sessions":
- return m.Sessions
- default:
- return m.Sess(which)
- }
- case int:
- ms := []*Message{m}
- for i := 0; i < len(ms); i++ {
- if ms[i].code == which {
- return ms[i]
- }
- ms = append(ms, ms[i].messages...)
- }
- }
- }
- return ""
- },
-
- "cap": func(arg ...interface{}) string {
- if len(arg) == 0 {
- return ""
- }
-
- if m, ok := arg[0].(*Message); ok {
- if len(arg) == 1 {
- return fmt.Sprintf("%v", m)
- }
-
- switch which := arg[1].(type) {
- case string:
- if len(arg) == 2 {
- return m.Cap(which)
- }
-
- switch value := arg[2].(type) {
- case string:
- return m.Cap(which, value)
- case int:
- return fmt.Sprintf("%d", m.Capi(which, value))
- case bool:
- return fmt.Sprintf("%t", m.Caps(which, value))
- default:
- return m.Cap(which, fmt.Sprintf("%v", arg[2]))
- }
- }
- }
- return ""
- },
- "conf": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- if m, ok := arg[0].(*Message); ok {
- if len(arg) == 1 {
- list := []string{}
- for k, _ := range m.target.Configs {
- list = append(list, k)
- }
- return list
- }
-
- switch which := arg[1].(type) {
- case string:
- if len(arg) == 2 {
- return m.Confv(which)
- }
- return m.Confv(which, arg[2:]...)
- }
- }
- return ""
- },
- "cmd": func(arg ...interface{}) string {
- if len(arg) == 0 {
- return ""
- }
-
- return strings.Join(Pulse.Sess("cli").Cmd(arg).Meta["result"], "")
- },
-
- "detail": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- switch m := arg[0].(type) {
- case *Message:
- if len(arg) == 1 {
- return m.Meta["detail"]
- }
-
- index := 0
- switch value := arg[1].(type) {
- case int:
- index = value
- case string:
- i, e := strconv.Atoi(value)
- m.Assert(e)
- index = i
- }
-
- if len(arg) == 2 {
- return m.Detail(index)
- }
-
- return m.Detail(index, arg[2])
- case map[string][]string:
- return strings.Join(m["detail"], "")
- case []string:
- return strings.Join(m, "")
- default:
- return m
- }
- return ""
- },
- "option": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- switch m := arg[0].(type) {
- case *Message:
- if len(arg) == 1 {
- return m.Meta["option"]
- }
-
- switch value := arg[1].(type) {
- case int:
- if 0 <= value && value < len(m.Meta["option"]) {
- return m.Meta["option"][value]
- }
- case string:
- if len(arg) == 2 {
- return m.Optionv(value)
- }
-
- switch val := arg[2].(type) {
- case int:
- if 0 <= val && val < len(m.Meta[value]) {
- return m.Meta[value][val]
- }
- }
- }
- case map[string][]string:
- if len(arg) == 1 {
- return strings.Join(m["option"], "")
- }
- switch value := arg[1].(type) {
- case string:
- return strings.Join(m[value], "")
- }
- case []string:
- return strings.Join(m, "")
- default:
- return m
- }
- return ""
- },
- "result": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- switch m := arg[0].(type) {
- case *Message:
- if len(arg) == 1 {
- return m.Meta["result"]
- }
-
- index := 0
- switch value := arg[1].(type) {
- case int:
- index = value
- case string:
- i, e := strconv.Atoi(value)
- m.Assert(e)
- index = i
- }
-
- if len(arg) == 2 {
- return m.Result(index)
- }
-
- return m.Result(index, arg[2])
- case map[string][]string:
- return strings.Join(m["result"], "")
- case []string:
- return strings.Join(m, "")
- default:
- return m
- }
- return ""
- },
- "append": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- switch m := arg[0].(type) {
- case *Message:
- if len(arg) == 1 {
- return m.Meta["append"]
- }
-
- switch value := arg[1].(type) {
- case int:
- if 0 <= value && value < len(m.Meta["append"]) {
- return m.Meta["append"][value]
- }
- case string:
- if len(arg) == 2 {
- return m.Meta[value]
- }
-
- switch val := arg[2].(type) {
- case int:
- if 0 <= val && val < len(m.Meta[value]) {
- return m.Meta[value][val]
- }
- }
- }
- case map[string][]string:
- if len(arg) == 1 {
- return strings.Join(m["append"], "")
- }
- switch value := arg[1].(type) {
- case string:
- return strings.Join(m[value], "")
- }
- case []string:
- return strings.Join(m, "")
- default:
- return m
- }
- return ""
- },
- "table": func(arg ...interface{}) []interface{} {
- if len(arg) == 0 {
- return []interface{}{}
- }
-
- switch m := arg[0].(type) {
- case *Message:
- if len(m.Meta["append"]) == 0 {
- return []interface{}{}
- }
- if len(arg) == 1 {
- data := []interface{}{}
- nrow := len(m.Meta[m.Meta["append"][0]])
- for i := 0; i < nrow; i++ {
- line := map[string]string{}
- for _, k := range m.Meta["append"] {
- line[k] = m.Meta[k][i]
- if len(m.Meta[k]) != i {
- continue
- }
- }
- data = append(data, line)
- }
-
- return data
- }
- case map[string][]string:
- if len(arg) == 1 {
- data := []interface{}{}
- nrow := len(m[m["append"][0]])
-
- for i := 0; i < nrow; i++ {
- line := map[string]string{}
- for _, k := range m["append"] {
- line[k] = m[k][i]
- }
- data = append(data, line)
- }
-
- return data
- }
- }
- return []interface{}{}
- },
-
- "list": func(arg interface{}) interface{} {
- n := 0
- switch v := arg.(type) {
- case string:
- i, e := strconv.Atoi(v)
- if e == nil {
- n = i
- }
- case int:
- n = v
- }
-
- list := make([]int, n)
- for i := 1; i <= n; i++ {
- list[i-1] = i
- }
- return list
- },
- "slice": func(list interface{}, arg ...interface{}) interface{} {
- switch l := list.(type) {
- case string:
- if len(arg) == 0 {
- return l
- }
- if len(arg) == 1 {
- return l[arg[0].(int):]
- }
- if len(arg) == 2 {
- return l[arg[0].(int):arg[1].(int)]
- }
- }
-
- return ""
- },
-
- "work": func(m *Message, arg ...interface{}) interface{} {
- switch len(arg) {
- case 0:
- list := map[string]map[string]interface{}{}
- m.Confm("auth", []string{m.Option("sessid"), "ship"}, func(key string, ship map[string]interface{}) {
- if ship["type"] == "bench" {
- if work := m.Confm("auth", key); work != nil {
- list[key] = work
- }
- }
- })
- return list
- }
- return nil
- },
-
- "unescape": func(str string) interface{} {
- return template.HTML(str)
- },
- "json": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- b, _ := json.MarshalIndent(arg[0], "", " ")
- return string(b)
- },
- "so": func(arg ...interface{}) interface{} {
- if len(arg) == 0 {
- return ""
- }
-
- cli := Pulse.Sess("cli")
- cmd := strings.Join(kit.Trans(arg), " ")
- cli.Cmd("source", cmd)
-
- result := []string{}
- if len(cli.Meta["append"]) > 0 {
- result = append(result, "
")
- result = append(result, "", cmd, "")
- cli.Table(func(maps map[string]string, list []string, line int) bool {
- if line == -1 {
- result = append(result, "")
- for _, v := range list {
- result = append(result, "", v, " | ")
- }
- result = append(result, "
")
- return true
- }
- result = append(result, "")
- for _, v := range list {
- result = append(result, "", v, " | ")
- }
- result = append(result, "
")
- return true
- })
- result = append(result, "
")
- } else {
- result = append(result, "")
- result = append(result, fmt.Sprintf("%s", cli.Find("shy", false).Conf("prompt")), cmd, "\n")
- result = append(result, cli.Meta["result"]...)
- result = append(result, "
")
- }
-
- return template.HTML(strings.Join(result, ""))
- },
-}
-
-func (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server {
- s := new(CTX)
- return s
-}
-func (ctx *CTX) Begin(m *Message, arg ...string) Server {
- m.Sess(m.target.Name, m)
- m.target.root = m.target
- m.root = m
- m.Cap("begin_time", m.Time())
- m.Cap("goos", runtime.GOOS)
- for _, msg := range m.Search("") {
- msg.target.root = m.target
- if 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 {
- m.Optionv("ps_target", Index)
-
- m.Cmd("log.init")
- m.Cmd("gdb.init")
- if m.Cmd("yac.init", "lex"); len(arg) == 0 {
- m.Cap("stream", "shy")
- m.Cmd("cli.source", "init.shy").Cmd("cli.source", "stdio").Cmd("cli.source", "exit.shy")
- return true
- }
-
- m.Cmd("cli.source", arg)
- 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{}}
-
-func Start(args ...string) bool {
- if len(args) == 0 {
- args = append(args, os.Args[1:]...)
- }
-
- if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) {
- return Index.Close(Pulse, args...)
- }
-
- return Index.message.Wait()
-}
diff --git a/src/contexts/ctx/ctx_cgi.go b/src/contexts/ctx/ctx_cgi.go
new file mode 100644
index 00000000..06af7e89
--- /dev/null
+++ b/src/contexts/ctx/ctx_cgi.go
@@ -0,0 +1,536 @@
+package ctx
+
+import (
+ "encoding/json"
+ "fmt"
+ "html/template"
+ "strconv"
+ "strings"
+ "toolkit"
+)
+
+var CGI = template.FuncMap{
+ "meta": func(arg ...interface{}) string {
+ //meta meta [key [index]]
+ if len(arg) == 0 {
+ return ""
+ }
+
+ up := ""
+
+ list := []string{}
+ switch data := arg[0].(type) {
+ case map[string][]string:
+ if len(arg) == 1 {
+ list = append(list, fmt.Sprintf("detail: %s\n", data["detail"]))
+ list = append(list, fmt.Sprintf("option: %s\n", data["option"]))
+ list = append(list, fmt.Sprintf("result: %s\n", data["result"]))
+ list = append(list, fmt.Sprintf("append: %s\n", data["append"]))
+ break
+ }
+ if key, ok := arg[1].(string); ok {
+ if list, ok = data[key]; ok {
+ arg = arg[1:]
+ } else {
+ return up
+ }
+ } else {
+ return fmt.Sprintf("%v", data)
+ }
+ case []string:
+ list = data
+ default:
+ if data == nil {
+ return ""
+ }
+ return fmt.Sprintf("%v", data)
+ }
+
+ if len(arg) == 1 {
+ return strings.Join(list, "")
+ }
+
+ index, ok := arg[1].(int)
+ if !ok {
+ return strings.Join(list, "")
+ }
+
+ if index >= len(list) {
+ return ""
+ }
+ return list[index]
+ },
+ "sess": func(arg ...interface{}) string {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ if m, ok := arg[0].(*Message); ok {
+ if len(arg) == 1 {
+ return fmt.Sprintf("%v", m)
+ }
+
+ switch which := arg[1].(type) {
+ case string:
+ m.Sess(which, arg[2:]...)
+ return ""
+ }
+ }
+ return ""
+ },
+
+ "ctx": func(arg ...interface{}) string {
+ if len(arg) == 0 {
+ return ""
+ }
+ if m, ok := arg[0].(*Message); ok {
+ if len(arg) == 1 {
+ return fmt.Sprintf("%v", m)
+ }
+
+ switch which := arg[1].(type) {
+ case string:
+ switch which {
+ case "name":
+ return fmt.Sprintf("%s", m.target.Name)
+ case "help":
+ return fmt.Sprintf("%s", m.target.Help)
+ case "context":
+ return fmt.Sprintf("%s", m.target.context.Name)
+ case "contexts":
+ ctx := []string{}
+ for _, v := range m.target.contexts {
+ ctx = append(ctx, fmt.Sprintf("%d", v.Name))
+ }
+ return strings.Join(ctx, " ")
+ case "time":
+ return m.time.Format("2006-01-02 15:04:05")
+ case "source":
+ return m.source.Name
+ case "target":
+ return m.target.Name
+ case "message":
+ return fmt.Sprintf("%d", m.message.code)
+ case "messages":
+ case "sessions":
+ msg := []string{}
+ for k, _ := range m.Sessions {
+ msg = append(msg, fmt.Sprintf("%s", k))
+ }
+ return strings.Join(msg, " ")
+ }
+ case int:
+ }
+ }
+ return ""
+ },
+ "msg": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ if m, ok := arg[0].(*Message); ok {
+ if len(arg) == 1 {
+ return fmt.Sprintf("%v", m.Format())
+ }
+
+ switch which := arg[1].(type) {
+ case string:
+ switch which {
+ case "spawn":
+ return m.Spawn()
+ case "code":
+ return m.code
+ case "time":
+ return m.time.Format("2006-01-02 15:04:05")
+ case "source":
+ return m.source.Name
+ case "target":
+ return m.target.Name
+ case "message":
+ return m.message
+ case "messages":
+ return m.messages
+ case "sessions":
+ return m.Sessions
+ default:
+ return m.Sess(which)
+ }
+ case int:
+ ms := []*Message{m}
+ for i := 0; i < len(ms); i++ {
+ if ms[i].code == which {
+ return ms[i]
+ }
+ ms = append(ms, ms[i].messages...)
+ }
+ }
+ }
+ return ""
+ },
+
+ "cap": func(arg ...interface{}) string {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ if m, ok := arg[0].(*Message); ok {
+ if len(arg) == 1 {
+ return fmt.Sprintf("%v", m)
+ }
+
+ switch which := arg[1].(type) {
+ case string:
+ if len(arg) == 2 {
+ return m.Cap(which)
+ }
+
+ switch value := arg[2].(type) {
+ case string:
+ return m.Cap(which, value)
+ case int:
+ return fmt.Sprintf("%d", m.Capi(which, value))
+ case bool:
+ return fmt.Sprintf("%t", m.Caps(which, value))
+ default:
+ return m.Cap(which, fmt.Sprintf("%v", arg[2]))
+ }
+ }
+ }
+ return ""
+ },
+ "conf": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ if m, ok := arg[0].(*Message); ok {
+ if len(arg) == 1 {
+ list := []string{}
+ for k, _ := range m.target.Configs {
+ list = append(list, k)
+ }
+ return list
+ }
+
+ switch which := arg[1].(type) {
+ case string:
+ if len(arg) == 2 {
+ return m.Confv(which)
+ }
+ return m.Confv(which, arg[2:]...)
+ }
+ }
+ return ""
+ },
+ "cmd": func(arg ...interface{}) string {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ return strings.Join(Pulse.Sess("cli").Cmd(arg).Meta["result"], "")
+ },
+
+ "detail": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ switch m := arg[0].(type) {
+ case *Message:
+ if len(arg) == 1 {
+ return m.Meta["detail"]
+ }
+
+ index := 0
+ switch value := arg[1].(type) {
+ case int:
+ index = value
+ case string:
+ i, e := strconv.Atoi(value)
+ m.Assert(e)
+ index = i
+ }
+
+ if len(arg) == 2 {
+ return m.Detail(index)
+ }
+
+ return m.Detail(index, arg[2])
+ case map[string][]string:
+ return strings.Join(m["detail"], "")
+ case []string:
+ return strings.Join(m, "")
+ default:
+ return m
+ }
+ return ""
+ },
+ "option": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ switch m := arg[0].(type) {
+ case *Message:
+ if len(arg) == 1 {
+ return m.Meta["option"]
+ }
+
+ switch value := arg[1].(type) {
+ case int:
+ if 0 <= value && value < len(m.Meta["option"]) {
+ return m.Meta["option"][value]
+ }
+ case string:
+ if len(arg) == 2 {
+ return m.Optionv(value)
+ }
+
+ switch val := arg[2].(type) {
+ case int:
+ if 0 <= val && val < len(m.Meta[value]) {
+ return m.Meta[value][val]
+ }
+ }
+ }
+ case map[string][]string:
+ if len(arg) == 1 {
+ return strings.Join(m["option"], "")
+ }
+ switch value := arg[1].(type) {
+ case string:
+ return strings.Join(m[value], "")
+ }
+ case []string:
+ return strings.Join(m, "")
+ default:
+ return m
+ }
+ return ""
+ },
+ "result": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ switch m := arg[0].(type) {
+ case *Message:
+ if len(arg) == 1 {
+ return m.Meta["result"]
+ }
+
+ index := 0
+ switch value := arg[1].(type) {
+ case int:
+ index = value
+ case string:
+ i, e := strconv.Atoi(value)
+ m.Assert(e)
+ index = i
+ }
+
+ if len(arg) == 2 {
+ return m.Result(index)
+ }
+
+ return m.Result(index, arg[2])
+ case map[string][]string:
+ return strings.Join(m["result"], "")
+ case []string:
+ return strings.Join(m, "")
+ default:
+ return m
+ }
+ return ""
+ },
+ "append": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ switch m := arg[0].(type) {
+ case *Message:
+ if len(arg) == 1 {
+ return m.Meta["append"]
+ }
+
+ switch value := arg[1].(type) {
+ case int:
+ if 0 <= value && value < len(m.Meta["append"]) {
+ return m.Meta["append"][value]
+ }
+ case string:
+ if len(arg) == 2 {
+ return m.Meta[value]
+ }
+
+ switch val := arg[2].(type) {
+ case int:
+ if 0 <= val && val < len(m.Meta[value]) {
+ return m.Meta[value][val]
+ }
+ }
+ }
+ case map[string][]string:
+ if len(arg) == 1 {
+ return strings.Join(m["append"], "")
+ }
+ switch value := arg[1].(type) {
+ case string:
+ return strings.Join(m[value], "")
+ }
+ case []string:
+ return strings.Join(m, "")
+ default:
+ return m
+ }
+ return ""
+ },
+ "table": func(arg ...interface{}) []interface{} {
+ if len(arg) == 0 {
+ return []interface{}{}
+ }
+
+ switch m := arg[0].(type) {
+ case *Message:
+ if len(m.Meta["append"]) == 0 {
+ return []interface{}{}
+ }
+ if len(arg) == 1 {
+ data := []interface{}{}
+ nrow := len(m.Meta[m.Meta["append"][0]])
+ for i := 0; i < nrow; i++ {
+ line := map[string]string{}
+ for _, k := range m.Meta["append"] {
+ line[k] = m.Meta[k][i]
+ if len(m.Meta[k]) != i {
+ continue
+ }
+ }
+ data = append(data, line)
+ }
+
+ return data
+ }
+ case map[string][]string:
+ if len(arg) == 1 {
+ data := []interface{}{}
+ nrow := len(m[m["append"][0]])
+
+ for i := 0; i < nrow; i++ {
+ line := map[string]string{}
+ for _, k := range m["append"] {
+ line[k] = m[k][i]
+ }
+ data = append(data, line)
+ }
+
+ return data
+ }
+ }
+ return []interface{}{}
+ },
+
+ "list": func(arg interface{}) interface{} {
+ n := 0
+ switch v := arg.(type) {
+ case string:
+ i, e := strconv.Atoi(v)
+ if e == nil {
+ n = i
+ }
+ case int:
+ n = v
+ }
+
+ list := make([]int, n)
+ for i := 1; i <= n; i++ {
+ list[i-1] = i
+ }
+ return list
+ },
+ "slice": func(list interface{}, arg ...interface{}) interface{} {
+ switch l := list.(type) {
+ case string:
+ if len(arg) == 0 {
+ return l
+ }
+ if len(arg) == 1 {
+ return l[arg[0].(int):]
+ }
+ if len(arg) == 2 {
+ return l[arg[0].(int):arg[1].(int)]
+ }
+ }
+
+ return ""
+ },
+
+ "work": func(m *Message, arg ...interface{}) interface{} {
+ switch len(arg) {
+ case 0:
+ list := map[string]map[string]interface{}{}
+ m.Confm("auth", []string{m.Option("sessid"), "ship"}, func(key string, ship map[string]interface{}) {
+ if ship["type"] == "bench" {
+ if work := m.Confm("auth", key); work != nil {
+ list[key] = work
+ }
+ }
+ })
+ return list
+ }
+ return nil
+ },
+
+ "unescape": func(str string) interface{} {
+ return template.HTML(str)
+ },
+ "json": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ b, _ := json.MarshalIndent(arg[0], "", " ")
+ return string(b)
+ },
+ "so": func(arg ...interface{}) interface{} {
+ if len(arg) == 0 {
+ return ""
+ }
+
+ cli := Pulse.Sess("cli")
+ cmd := strings.Join(kit.Trans(arg), " ")
+ cli.Cmd("source", cmd)
+
+ result := []string{}
+ if len(cli.Meta["append"]) > 0 {
+ result = append(result, "")
+ result = append(result, "", cmd, "")
+ cli.Table(func(maps map[string]string, list []string, line int) bool {
+ if line == -1 {
+ result = append(result, "")
+ for _, v := range list {
+ result = append(result, "", v, " | ")
+ }
+ result = append(result, "
")
+ return true
+ }
+ result = append(result, "")
+ for _, v := range list {
+ result = append(result, "", v, " | ")
+ }
+ result = append(result, "
")
+ return true
+ })
+ result = append(result, "
")
+ } else {
+ result = append(result, "")
+ result = append(result, fmt.Sprintf("%s", cli.Find("shy", false).Conf("prompt")), cmd, "\n")
+ result = append(result, cli.Meta["result"]...)
+ result = append(result, "
")
+ }
+
+ return template.HTML(strings.Join(result, ""))
+ },
+}
diff --git a/src/contexts/ctx/ctx_init.go b/src/contexts/ctx/ctx_init.go
new file mode 100644
index 00000000..899976ee
--- /dev/null
+++ b/src/contexts/ctx/ctx_init.go
@@ -0,0 +1,1323 @@
+package ctx
+
+import (
+ "encoding/json"
+ "fmt"
+ "runtime"
+ "strconv"
+ "strings"
+
+ "math/rand"
+ "os"
+ "sort"
+ "time"
+ "toolkit"
+)
+
+type CTX struct {
+}
+
+var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{},
+ Caches: map[string]*Cache{
+ "begin_time": &Cache{Name: "begin_time", Value: "", Help: "启动时间"},
+ "goos": &Cache{Name: "goos", Value: "linux", Help: "启动时间"},
+ "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{
+ "chain": &Config{Name: "chain", Value: map[string]interface{}{}, Help: "调试模式,on:打印,off:不打印)"},
+ "compact_log": &Config{Name: "compact_log(true/false)", Value: "true", Help: "调试模式,on:打印,off:不打印)"},
+ "auto_make": &Config{Name: "auto_make(true/false)", Value: "true", Help: "调试模式,on:打印,off:不打印)"},
+ "debug": &Config{Name: "debug(on/off)", Value: "on", Help: "调试模式,on:打印,off:不打印)"},
+
+ "search_method": &Config{Name: "search_method(find/search)", Value: "search", Help: "搜索方法, find: 模块名精确匹配, search: 模块名或帮助信息模糊匹配"},
+ "search_choice": &Config{Name: "search_choice(first/last/rand/magic)", Value: "magic", Help: "搜索匹配, first: 匹配第一个模块, last: 匹配最后一个模块, rand: 随机选择, magic: 加权选择"},
+ "search_action": &Config{Name: "search_action(list/switch)", Value: "switch", Help: "搜索操作, list: 输出模块列表, switch: 模块切换"},
+ "search_root": &Config{Name: "search_root(true/false)", Value: "true", Help: "搜索起点, true: 根模块, false: 当前模块"},
+
+ "insert_limit": &Config{Name: "insert_limit(true/false)", Value: "true", Help: "参数的索引"},
+ "detail_index": &Config{Name: "detail_index", Value: "0", Help: "参数的索引"},
+ "result_index": &Config{Name: "result_index", Value: "-2", Help: "返回值的索引"},
+
+ "list_help": &Config{Name: "list_help", Value: "list command", Help: "命令列表帮助"},
+ "table_compact": &Config{Name: "table_compact", Value: "false", Help: "命令列表帮助"},
+ "table_col_sep": &Config{Name: "table_col_sep", Value: " ", Help: "命令列表帮助"},
+ "table_row_sep": &Config{Name: "table_row_sep", Value: "\n", Help: "命令列表帮助"},
+ "table_space": &Config{Name: "table_space", Value: " ", Help: "命令列表帮助"},
+
+ "page_offset": &Config{Name: "page_offset", Value: "0", Help: "列表偏移"},
+ "page_limit": &Config{Name: "page_limit", Value: "10", Help: "列表大小"},
+
+ "time_format": &Config{Name: "time_format", Value: "2006-01-02 15:04:05", Help: "时间格式"},
+ },
+ Commands: map[string]*Command{
+ "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")
+ 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)
+ }
+ for k, v := range v.Form {
+ m.Add("append", "arg", k)
+ m.Add("append", "len", v)
+ m.Echo(" option: %s(%d)\n", k, v)
+ }
+ 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
+ }},
+
+ "message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
+ msg := m
+ if ms := m.Find(m.Cap("ps_target")); ms != nil {
+ msg = ms
+ }
+
+ if len(arg) > 0 {
+ if code, e := strconv.Atoi(arg[0]); e == nil {
+ if msg = m.root.Tree(code); msg != nil {
+ arg = arg[1:]
+ }
+ }
+ }
+
+ if len(arg) == 0 {
+ m.Format("summary", msg, "deep")
+ msg.CopyTo(m)
+ 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.message
+ if len(arg) == 0 {
+ for i, v := range msg.Meta["detail"] {
+ m.Add("append", "index", i)
+ m.Add("append", "value", v)
+ }
+ m.Table()
+ return
+ }
+
+ index := m.Confi("detail_index")
+ if i, e := strconv.Atoi(arg[0]); e == nil {
+ index, arg = i, arg[1:]
+ }
+ m.Echo("%s", msg.Detail(index, arg))
+ return
+ }},
+ "option": &Command{Name: "option [all] [key [index] [value...]]", 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:]
+ }
+
+ index := -100
+ if len(arg) > 1 {
+ if i, e := strconv.Atoi(arg[1]); e == nil {
+ index = i
+ for i := 1; i < len(arg)-1; i++ {
+ arg[i] = arg[i+1]
+ }
+ arg = arg[:len(arg)-1]
+ }
+ }
+
+ msg := m.message
+ for msg = msg; msg != nil; msg = msg.message {
+ for _, k := range msg.Meta["option"] {
+ if len(arg) == 0 {
+ m.Add("append", "key", k)
+ m.Add("append", "len", len(msg.Meta[k]))
+ m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k]))
+ continue
+ }
+
+ if k != arg[0] {
+ continue
+ }
+
+ if len(arg) > 1 {
+ msg.Meta[k] = kit.Array(msg.Meta[k], index, arg[1:])
+ m.Echo("%v", msg.Meta[k])
+ return
+ }
+
+ if index != -100 {
+ m.Echo(kit.Array(msg.Meta[k], index)[0])
+ return
+ }
+
+ for i, v := range msg.Meta[k] {
+ m.Add("append", "index", i)
+ m.Add("append", "value", v)
+ }
+ m.Table()
+ return
+ }
+
+ if !all {
+ break
+ }
+ }
+ m.Sort("key", "string").Table()
+ return
+ }},
+ "result": &Command{Name: "result [index] [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
+ msg := m.message
+ if len(arg) == 0 {
+ for i, v := range msg.Meta["result"] {
+ m.Add("append", "index", i)
+ m.Add("append", "value", strings.Replace(v, "\n", "\\n", -1))
+ }
+ m.Table()
+ return
+ }
+
+ index := m.Confi("result_index")
+ if i, e := strconv.Atoi(arg[0]); e == nil {
+ index, arg = i, arg[1:]
+ }
+ m.Echo("%s", msg.Result(index, arg))
+ return
+ }},
+ "append": &Command{Name: "append [all] [key [index] [value...]]", 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:]
+ }
+
+ index := -100
+ if len(arg) > 1 {
+ if i, e := strconv.Atoi(arg[1]); e == nil {
+ index = i
+ for i := 1; i < len(arg)-1; i++ {
+ arg[i] = arg[i+1]
+ }
+ arg = arg[:len(arg)-1]
+ }
+ }
+
+ msg := m.message
+ for msg = msg; msg != nil; msg = msg.message {
+ for _, k := range msg.Meta["append"] {
+ if len(arg) == 0 {
+ m.Add("append", "key", k)
+ m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k]))
+ continue
+ }
+
+ if k != arg[0] {
+ continue
+ }
+
+ if len(arg) > 1 {
+ msg.Meta[k] = kit.Array(msg.Meta[k], index, arg[1:])
+ m.Echo("%v", msg.Meta[k])
+ return
+ }
+
+ if index != -100 {
+ m.Echo(kit.Array(msg.Meta[k], index)[0])
+ return
+ }
+
+ for i, v := range msg.Meta[k] {
+ m.Add("append", "index", i)
+ m.Add("append", "value", v)
+ }
+ m.Table()
+ return
+ }
+
+ if !all {
+ break
+ }
+ }
+ m.Table()
+ return
+ }},
+ "session": &Command{Name: "session [all] [key [module]]", 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.message
+ for msg = msg; msg != nil; msg = msg.message {
+ for k, v := range msg.Sessions {
+ if len(arg) > 1 {
+ msg.Sessions[arg[0]] = msg.Find(arg[1])
+ return
+ } else if len(arg) > 0 {
+ if k == arg[0] {
+ m.Echo("%d", v.code)
+ return
+ }
+ continue
+ }
+
+ m.Add("append", "key", k)
+ m.Add("append", "time", v.time.Format("15:04:05"))
+ m.Add("append", "code", v.code)
+ m.Add("append", "source", v.source.Name)
+ m.Add("append", "target", v.target.Name)
+ m.Add("append", "details", fmt.Sprintf("%v", v.Meta["detail"]))
+ m.Add("append", "options", fmt.Sprintf("%v", v.Meta["option"]))
+ }
+
+ if len(arg) == 0 && !all {
+ break
+ }
+ }
+ m.Table()
+ return
+ }},
+ "callback": &Command{Name: "callback", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
+ msg := m.message
+ for msg := msg; msg != nil; msg = msg.message {
+ m.Add("append", "msg", msg.code)
+ m.Add("append", "fun", msg.callback)
+ }
+ m.Table()
+ return
+ }},
+
+ "context": &Command{Name: "context [find|search] [root|back|home] [first|last|rand|magic] [module] [cmd|switch|list|spawn|start|close]",
+ Help: "查找并操作模块;\n查找方法, find: 精确查找, search: 模糊搜索;\n查找起点, root: 根模块, back: 父模块, home: 本模块;\n过滤结果, first: 取第一个, last: 取最后一个, rand: 随机选择, magic: 智能选择;\n操作方法, cmd: 执行命令, switch: 切换为当前, list: 查看所有子模块, spwan: 创建子模块并初始化, start: 启动模块, close: 结束模块",
+ Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
+ if len(arg) == 1 && arg[0] == "~" && m.target.context != nil {
+ m.target = m.target.context
+ return
+ }
+
+ 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 "magic":
+ 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 m.Options("sso_bench") && m.Options("sso_username") &&
+ !m.Cmds("aaa.work", m.Option("sso_bench"), "right", m.Option("sso_username"), "componet", "source", "command", arg[0]) {
+
+ m.Log("info", "sso check %v: %v failure", m.Option("sso_componet"), m.Option("sso_command"))
+ m.Echo("error: ").Echo("no right [%s: %s %s]", m.Option("sso_componet"), m.Option("sso_command"), arg[0])
+ break
+ }
+
+ if msg.Cmd(arg); !msg.Hand {
+ msg = msg.Sess("cli").Cmd("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
+ })
+
+ for _, v := range cs {
+ if msg.target = v; v == nil {
+ m.Add("append", "name", "")
+ m.Add("append", "ctx", "")
+ m.Add("append", "msg", "")
+ m.Add("append", "status", "")
+ m.Add("append", "stream", "")
+ m.Add("append", "help", "")
+ continue
+ }
+
+ m.Add("append", "name", msg.target.Name)
+ if msg.target.context != nil {
+ m.Add("append", "ctx", msg.target.context.Name)
+ } else {
+ m.Add("append", "ctx", "")
+ }
+ m.Add("append", "msg", msg.target.message.code)
+ m.Add("append", "status", msg.Cap("status"))
+ m.Add("append", "stream", msg.Cap("stream"))
+ m.Add("append", "help", msg.target.Help)
+ }
+
+ 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...)
+ }
+ }
+
+ if action == "list" {
+ m.Table()
+ }
+ return
+ }},
+ "command": &Command{Name: "command [all] [show]|[list [begin [end]] [prefix] test [key val]...]|[add [list_name name] [list_help help] cmd...]|[delete cmd]",
+ Help: "查看或修改命令, show: 查看命令;\nlist: 查看列表命令, begin: 起始索引, end: 截止索引, prefix: 过滤前缀, test: 执行命令;\nadd: 添加命令, list_name: 命令别名, list_help: 命令帮助;\ndelete: 删除命令",
+ 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:]
+ }
+
+ action := "show"
+ if len(arg) > 0 {
+ switch arg[0] {
+ case "show", "list", "add", "delete":
+ action, arg = arg[0], arg[1:]
+ }
+ }
+
+ switch action {
+ case "show":
+ c.BackTrace(m, func(m *Message) bool {
+ for k, v := range m.target.Commands {
+ if len(arg) > 0 {
+ if k == arg[0] {
+ m.Add("append", "key", k)
+ m.Add("append", "name", v.Name)
+ m.Add("append", "help", v.Name)
+ }
+ } else {
+ m.Add("append", "key", k)
+ m.Add("append", "name", v.Name)
+ }
+ }
+
+ return !all
+ })
+ m.Table()
+ case "list":
+ 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", fmt.Sprintf("%s", 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{}
+ }
+
+ 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").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)
+ case "delete":
+ c.BackTrace(m, func(m *Message) bool {
+ delete(m.target.Commands, arg[0])
+ return !all
+ })
+ }
+ return
+ }},
+ "config": &Command{Name: "config [all] [export key..] [save|load file key...] [list|map arg...] [create map|list|string key name help] [delete key]",
+ Help: "配置管理, export: 导出配置, save: 保存配置到文件, load: 从文件加载配置, create: 创建配置, delete: 删除配置",
+ Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
+ if len(arg) > 2 && arg[2] == "list" {
+ chain := strings.Split(arg[1], ".")
+ chain = append(chain, "-2")
+
+ for _, val := range arg[3:] {
+ m.Confv(arg[0], chain, val)
+ }
+ return
+ }
+ if len(arg) > 2 && arg[2] == "map" {
+ chain := strings.Split(arg[1], ".")
+
+ for i := 3; i < len(arg)-1; i += 2 {
+ m.Confv(arg[0], append(chain, arg[i]), arg[i+1])
+ }
+ return
+ }
+
+ all := false
+ if len(arg) > 0 && arg[0] == "all" {
+ arg, all = arg[1:], true
+ }
+
+ action, which := "", "-1"
+ have := map[string]bool{}
+ if len(arg) > 0 {
+ switch arg[0] {
+ 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:]
+ }
+ }
+
+ if len(arg) == 0 || action != "" {
+ save := map[string]interface{}{}
+ if action == "load" {
+ f, e := os.Open(m.Sess("nfs").Cmd("path", which).Result(0))
+ 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] {
+ delete(m.target.Configs, k)
+ }
+ fallthrough
+ 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]}
+ }
+ 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
+ }
+
+ var value interface{}
+ 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
+ }},
+ "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
+ }},
+
+ "trans": &Command{Name: "trans option [type|data|json] limit 10 [index...]", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) {
+ value, arg := m.Optionv(arg[0]), arg[1:]
+
+ view := "data"
+ if len(arg) > 0 {
+ switch arg[0] {
+ case "type", "data", "json":
+ view, arg = arg[0], arg[1:]
+ }
+ }
+
+ limit := m.Confi("page_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{}:
+ for k, v := range val {
+ 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)))
+ }
+ }
+ m.Sort("key", "str").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 key value field",
+ Form: map[string]int{"parse": 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["parse"]); j += 2 {
+ var value interface{}
+ json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value)
+ if m.Meta["parse"][j+1] != "" {
+ value = kit.Chain(value, m.Meta["parse"][j+1])
+ }
+
+ switch val := value.(type) {
+ case map[string]interface{}:
+ for k, _ := range val {
+ keys = append(keys, k)
+ }
+ default:
+ keys = append(keys, m.Meta["parse"][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["parse"]); j += 2 {
+ var value interface{}
+ json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value)
+ if m.Meta["parse"][j+1] != "" {
+ value = kit.Chain(value, m.Meta["parse"][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["parse"][j+1]][i] = val
+ case float64:
+ m.Meta[m.Meta["parse"][j+1]][i] = fmt.Sprintf("%d", int(val))
+ default:
+ b, _ := json.Marshal(val)
+ m.Meta[m.Meta["parse"][j+1]][i] = string(b)
+ }
+ }
+ }
+
+ // 隐藏列
+ hides := map[string]bool{}
+ for _, k := range m.Meta["hide"] {
+ hides[k] = true
+ }
+ for i := 0; i < nrow; i++ {
+ if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) {
+ for _, k := range m.Meta["append"] {
+ if hides[k] {
+ continue
+ }
+ msg.Add("append", k, m.Meta[k][i])
+ }
+ }
+ }
+
+ // 选择列
+ if m.Option("fields") != "" {
+ msg = m.Spawn()
+ m.Hand = true
+ msg.Copy(m, strings.Split(strings.Join(m.Meta["fields"], " "), " ")...)
+ m.Hand = false
+ m.Set("append").Copy(msg, "append")
+ }
+
+ // 聚合
+ 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.Meta["order"][1], m.Option("order"))
+ }
+
+ // 分页
+ offset := 0
+ limit := m.Confi("page_limit")
+ if m.Has("limit") {
+ limit = m.Optioni("limit")
+ }
+ if m.Has("offset") {
+ offset = m.Optioni("offset")
+ }
+ 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]] {
+ 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 (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server {
+ s := new(CTX)
+ return s
+}
+func (ctx *CTX) Begin(m *Message, arg ...string) Server {
+ m.Sess(m.target.Name, m)
+ m.target.root = m.target
+ m.root = m
+ m.Cap("begin_time", m.Time())
+ m.Cap("goos", runtime.GOOS)
+ for _, msg := range m.Search("") {
+ msg.target.root = m.target
+ if 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 {
+ m.Optionv("ps_target", Index)
+
+ m.Cmd("log.init")
+ m.Cmd("gdb.init")
+ if m.Cmd("yac.init", "lex"); len(arg) == 0 {
+ m.Cap("stream", "shy")
+ m.Cmd("cli.source", "init.shy").Cmd("cli.source", "stdio").Cmd("cli.source", "exit.shy")
+ return true
+ }
+
+ m.Cmd("cli.source", arg)
+ 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{}}
+
+func Start(args ...string) bool {
+ if len(args) == 0 {
+ args = append(args, os.Args[1:]...)
+ }
+
+ if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) {
+ return Index.Close(Pulse, args...)
+ }
+
+ return Index.message.Wait()
+}
diff --git a/src/contexts/ctx/ctx_type.go b/src/contexts/ctx/ctx_type.go
new file mode 100644
index 00000000..af0519be
--- /dev/null
+++ b/src/contexts/ctx/ctx_type.go
@@ -0,0 +1,1565 @@
+package ctx
+
+import (
+ "fmt"
+ "regexp"
+ "runtime"
+ "strings"
+
+ "errors"
+ "io"
+ "sort"
+ "time"
+ "toolkit"
+)
+
+type Cache struct {
+ Value string
+ Name string
+ Help string
+ Hand func(m *Message, x *Cache, arg ...string) string
+}
+type Config struct {
+ Value interface{}
+ Name string
+ Help string
+ Hand func(m *Message, x *Config, arg ...string) string
+}
+type Command struct {
+ Form map[string]int
+ Name string
+ Help interface{}
+ Auto func(m *Message, c *Context, key string, arg ...string) (ok bool)
+ Hand func(m *Message, c *Context, key string, arg ...string) (e error)
+}
+type Server interface {
+ Spawn(m *Message, c *Context, arg ...string) Server
+ Begin(m *Message, arg ...string) Server
+ Start(m *Message, arg ...string) bool
+ Close(m *Message, arg ...string) bool
+}
+type Context struct {
+ Name string
+ Help string
+
+ Caches map[string]*Cache
+ Configs map[string]*Config
+ Commands map[string]*Command
+
+ message *Message
+ requests []*Message
+ sessions []*Message
+
+ contexts map[string]*Context
+ context *Context
+ root *Context
+
+ exit chan bool
+ Server
+}
+
+func (c *Context) Register(s *Context, x Server) {
+ if c.contexts == nil {
+ c.contexts = make(map[string]*Context)
+ }
+ if x, ok := c.contexts[s.Name]; ok {
+ panic(errors.New(c.Name + "上下文中已存在模块:" + x.Name))
+ }
+
+ c.contexts[s.Name] = s
+ s.context = c
+ s.Server = x
+}
+func (c *Context) Spawn(m *Message, name string, help string) *Context {
+ s := &Context{Name: name, Help: help, root: c.root, context: c, message: m,
+ Caches: map[string]*Cache{},
+ Configs: map[string]*Config{},
+ Commands: map[string]*Command{},
+ }
+
+ if m.target = s; c.Server != nil {
+ c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...))
+ } else {
+ c.Register(s, nil)
+ }
+ return s
+}
+func (c *Context) Begin(m *Message, arg ...string) *Context {
+ if len(arg) > 0 {
+ m.Set("detail", arg)
+ }
+
+ module := c.Name
+ if c.context != nil {
+ module = c.context.Name + "." + c.Name
+ }
+
+ c.Caches["module"] = &Cache{Name: "module", Value: module, Help: "模块域名"}
+ c.Caches["status"] = &Cache{Name: "status(begin/start/close)", Value: "begin", Help: "模块状态, begin: 初始完成, start: 正在运行, close: 运行结束"}
+ c.Caches["stream"] = &Cache{Name: "stream", Value: "", Help: "模块数据"}
+
+ c.message = m
+ c.requests = append(c.requests, m)
+ m.source.sessions = append(m.source.sessions, m)
+ c.exit = make(chan bool, 3)
+
+ switch v := m.Gdb("context", "begin", c.Name).(type) {
+ case string:
+ kit.Log("error", "fuck %v", v)
+ case nil:
+ }
+
+ m.Log("begin", "%d context %v %v", m.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"])
+ for k, x := range c.Configs {
+ if x.Hand != nil {
+ m.Log("begin", "%s config %v", k, m.Conf(k, x.Value))
+ }
+ }
+
+ if c.Server != nil {
+ c.Server.Begin(m, m.Meta["detail"]...)
+ }
+
+ return c
+}
+func (c *Context) Start(m *Message, arg ...string) bool {
+ sync := false
+ if len(arg) > 0 && arg[0] == "sync" {
+ sync, arg = true, arg[1:]
+ }
+ if len(arg) > 0 {
+ m.Set("detail", arg)
+ }
+
+ c.requests = append(c.requests, m)
+ m.source.sessions = append(m.source.sessions, m)
+
+ switch v := m.Gdb("context", "start", c.Name).(type) {
+ case string:
+ kit.Log("error", "fuck %v", v)
+ case nil:
+ }
+
+ if m.Hand = true; m.Cap("status") == "start" {
+ return true
+ }
+
+ m.GoFunc(m, func(m *Message) {
+ m.Log(m.Cap("status", "start"), "%d server %v %v", m.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"])
+
+ c.message = m
+ if c.exit <- false; c.Server == nil || c.Server.Start(m, m.Meta["detail"]...) {
+ c.Close(m, m.Meta["detail"]...)
+ c.exit <- true
+ }
+ }, func(m *Message) {
+ c.Close(m, m.Meta["detail"]...)
+ c.exit <- true
+ })
+
+ if sync {
+ for !<-c.exit {
+ }
+ return true
+ }
+ return <-c.exit
+}
+func (c *Context) Close(m *Message, arg ...string) bool {
+ if len(c.requests) == 0 {
+ return true
+ }
+
+ if m.target == c {
+ for i := len(c.requests) - 1; i >= 0; i-- {
+ if msg := c.requests[i]; msg.code == m.code {
+ if c.Server == nil || c.Server.Close(m, arg...) {
+ m.Log("close", "request %d/%d", i, len(c.requests)-1)
+ msg.Free()
+ for j := i; j < len(c.requests)-1; j++ {
+ c.requests[j] = c.requests[j+1]
+ }
+ c.requests = c.requests[:len(c.requests)-1]
+ }
+ }
+ }
+ }
+
+ if len(c.requests) > 0 {
+ return false
+ }
+
+ if m.Cap("status") == "start" {
+ m.Log(m.Cap("status", "close"), "%d server %v", m.root.Capi("nserver", -1), arg)
+ for _, msg := range c.sessions {
+ if msg.Cap("status") != "close" {
+ msg.target.Close(msg, arg...)
+ }
+ }
+ }
+
+ if c.context != nil {
+ m.Log("close", "%d context %v", m.root.Capi("ncontext", -1), arg)
+ delete(c.context.contexts, c.Name)
+ c.exit <- true
+ }
+ return true
+}
+
+func (c *Context) Context() *Context {
+ return c.context
+}
+func (c *Context) Message() *Message {
+ return c.message
+}
+func (c *Context) Has(key ...string) bool {
+ switch len(key) {
+ case 2:
+ if _, ok := c.Commands[key[0]]; ok && key[1] == "command" {
+ return true
+ }
+ if _, ok := c.Configs[key[0]]; ok && key[1] == "config" {
+ return true
+ }
+ if _, ok := c.Caches[key[0]]; ok && key[1] == "cache" {
+ return true
+ }
+ case 1:
+ if _, ok := c.Commands[key[0]]; ok {
+ return true
+ }
+ if _, ok := c.Configs[key[0]]; ok {
+ return true
+ }
+ if _, ok := c.Caches[key[0]]; ok {
+ return true
+ }
+ }
+ return false
+}
+func (c *Context) Sub(key string) *Context {
+ return c.contexts[key]
+}
+func (c *Context) Travel(m *Message, hand func(m *Message, n int) (stop bool)) *Context {
+ target := m.target
+
+ cs := []*Context{c}
+ for i := 0; i < len(cs); i++ {
+ if m.target = cs[i]; hand(m, i) {
+ return cs[i]
+ }
+
+ keys := []string{}
+ for k, _ := range cs[i].contexts {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ cs = append(cs, cs[i].contexts[k])
+ }
+ }
+
+ m.target = target
+ return target
+}
+func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Context {
+ target := m.target
+
+ for s := m.target; s != nil; s = s.context {
+ if m.target = s; hand(m) {
+ return s
+ }
+ }
+
+ m.target = target
+ return target
+}
+
+type DEBUG interface {
+ Wait(*Message, ...interface{}) interface{}
+ Goon(interface{}, ...interface{})
+}
+type LOGGER interface {
+ Log(*Message, string, string, ...interface{})
+}
+type Message struct {
+ time time.Time
+ code int
+
+ source *Context
+ target *Context
+
+ Meta map[string][]string
+ Data map[string]interface{}
+
+ callback func(msg *Message) (sub *Message)
+ freedoms []func(msg *Message) (done bool)
+ Sessions map[string]*Message
+
+ messages []*Message
+ message *Message
+ root *Message
+
+ Remote chan bool
+ Hand bool
+}
+
+func (m *Message) Spawn(arg ...interface{}) *Message {
+ c := m.target
+ if len(arg) > 0 {
+ switch v := arg[0].(type) {
+ case *Context:
+ c = v
+ case *Message:
+ c = v.target
+ }
+ }
+
+ msg := &Message{
+ time: time.Now(),
+ code: m.Capi("nmessage", 1),
+ source: m.target,
+ target: c,
+ message: m,
+ root: m.root,
+ }
+
+ m.messages = append(m.messages, msg)
+ return msg
+}
+func (m *Message) Time(arg ...interface{}) string {
+ t := m.time
+
+ if len(arg) > 0 {
+ if d, e := time.ParseDuration(arg[0].(string)); e == nil {
+ arg = arg[1:]
+ t.Add(d)
+ }
+ }
+
+ str := m.Conf("time_format")
+ if len(arg) > 1 {
+ str = fmt.Sprintf(arg[0].(string), arg[1:]...)
+ } else if len(arg) > 0 {
+ str = fmt.Sprintf("%v", arg[0])
+ }
+ return t.Format(str)
+}
+func (m *Message) Code() int {
+ return m.code
+}
+func (m *Message) Source() *Context {
+ return m.source
+}
+func (m *Message) Target() *Context {
+ return m.target
+}
+func (m *Message) Message() *Message {
+ return m.message
+}
+func (m *Message) Format(arg ...interface{}) string {
+ if len(arg) == 0 {
+ arg = append(arg, "time", "ship")
+ }
+
+ meta := []string{}
+ for _, v := range arg {
+ switch kit.Format(v) {
+ case "summary":
+ msg := arg[1].(*Message)
+ ms := make([]*Message, 0, 1024)
+ ms = append(ms, msg.message, msg)
+
+ for i := 0; i < len(ms); i++ {
+ msg := ms[i]
+ if m.Add("append", "index", i); msg == nil {
+ m.Add("append", "message", "")
+ m.Add("append", "time", "")
+ m.Add("append", "code", "")
+ m.Add("append", "source", "")
+ m.Add("append", "target", "")
+ m.Add("append", "details", "")
+ m.Add("append", "options", "")
+ continue
+ }
+
+ if msg.message != nil {
+ m.Add("append", "message", msg.message.code)
+ } else {
+ m.Add("append", "message", "")
+ }
+ m.Add("append", "time", msg.time.Format("15:04:05"))
+ m.Add("append", "code", msg.code)
+ m.Add("append", "source", msg.source.Name)
+ m.Add("append", "target", msg.target.Name)
+ m.Add("append", "details", fmt.Sprintf("%v", msg.Meta["detail"]))
+ m.Add("append", "options", fmt.Sprintf("%v", msg.Meta["option"]))
+
+ if i == 0 {
+ continue
+ }
+
+ if len(ms) < 30 && len(arg) > 2 && arg[2] == "deep" {
+ ms = append(ms, ms[i].messages...)
+ }
+ }
+ m.Table()
+ case "time":
+ meta = append(meta, m.Time())
+ case "code":
+ meta = append(meta, kit.Format(m.code))
+ case "ship":
+ meta = append(meta, fmt.Sprintf("%d(%s->%s)", m.code, m.source.Name, m.target.Name))
+ case "source":
+ target := m.target
+ m.target = m.source
+ meta = append(meta, m.Cap("module"))
+ m.target = target
+ case "target":
+ meta = append(meta, m.Cap("module"))
+
+ case "detail":
+ meta = append(meta, fmt.Sprintf("%v", m.Meta["detail"]))
+ case "option":
+ meta = append(meta, fmt.Sprintf("%v", m.Meta["option"]))
+ case "append":
+ meta = append(meta, fmt.Sprintf("%v", m.Meta["append"]))
+ case "result":
+ meta = append(meta, fmt.Sprintf("%v", m.Meta["result"]))
+
+ case "full":
+ case "chain":
+ ms := []*Message{}
+ if v == "full" {
+ ms = append(ms, m)
+ } else {
+ for msg := m; msg != nil; msg = msg.message {
+ ms = append(ms, msg)
+ }
+ }
+
+ for i := len(ms) - 1; i >= 0; i-- {
+ msg := ms[i]
+
+ meta = append(meta, fmt.Sprintf("\n%s\n", msg.Format("time", "ship")))
+ meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
+ meta = append(meta, fmt.Sprintf(" option: %d %v\n", len(msg.Meta["option"]), msg.Meta["option"]))
+ for _, k := range msg.Meta["option"] {
+ if v, ok := msg.Data[k]; ok {
+ meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
+ } else if v, ok := msg.Meta[k]; ok {
+ meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
+ }
+ }
+ meta = append(meta, fmt.Sprintf(" append: %d %v\n", len(msg.Meta["append"]), msg.Meta["append"]))
+ for _, k := range msg.Meta["append"] {
+ if v, ok := msg.Data[k]; ok {
+ meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
+ } else if v, ok := msg.Meta[k]; ok {
+ meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
+ }
+ }
+ meta = append(meta, fmt.Sprintf(" result: %d %v\n", len(msg.Meta["result"]), msg.Meta["result"]))
+ }
+ case "stack":
+ pc := make([]uintptr, 100)
+ pc = pc[:runtime.Callers(2, pc)]
+ frames := runtime.CallersFrames(pc)
+
+ for {
+ frame, more := frames.Next()
+ file := strings.Split(frame.File, "/")
+ name := strings.Split(frame.Function, "/")
+ meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1]))
+ if !more {
+ break
+ }
+ }
+
+ default:
+ meta = append(meta, kit.FileName(kit.Format(v), "time"))
+ }
+ }
+ return strings.Join(meta, " ")
+}
+func (m *Message) Tree(code int) *Message {
+ ms := []*Message{m}
+ for i := 0; i < len(ms); i++ {
+ if ms[i].Code() == code {
+ return ms[i]
+ }
+ ms = append(ms, ms[i].messages...)
+ }
+ return nil
+}
+
+func (m *Message) Add(meta string, key string, value ...interface{}) *Message {
+ if m.Meta == nil {
+ m.Meta = make(map[string][]string)
+ }
+ if _, ok := m.Meta[meta]; !ok {
+ m.Meta[meta] = make([]string, 0, 3)
+ }
+
+ switch meta {
+ case "detail", "result":
+ m.Meta[meta] = append(m.Meta[meta], key)
+ m.Meta[meta] = append(m.Meta[meta], kit.Trans(value...)...)
+
+ case "option", "append":
+ if _, ok := m.Meta[key]; !ok {
+ m.Meta[key] = make([]string, 0, 3)
+ }
+ m.Meta[key] = append(m.Meta[key], kit.Trans(value...)...)
+
+ for _, v := range m.Meta[meta] {
+ if v == key {
+ return m
+ }
+ }
+ m.Meta[meta] = append(m.Meta[meta], key)
+
+ default:
+ m.Log("error", "add meta error %s %s %v", meta, key, value)
+ }
+
+ return m
+}
+func (m *Message) Set(meta string, arg ...interface{}) *Message {
+ switch meta {
+ case "detail", "result":
+ if m != nil && m.Meta != nil {
+ delete(m.Meta, meta)
+ }
+ case "option", "append":
+ if len(arg) > 0 {
+ delete(m.Meta, kit.Format(arg[0]))
+ } else {
+ for _, k := range m.Meta[meta] {
+ delete(m.Data, k)
+ delete(m.Meta, k)
+ }
+ delete(m.Meta, meta)
+ }
+ default:
+ m.Log("error", "set meta error %s %s %v", meta, arg)
+ }
+
+ if args := kit.Trans(arg...); len(args) > 0 {
+ m.Add(meta, args[0], args[1:])
+ }
+ return m
+}
+func (m *Message) Put(meta string, key string, value interface{}) *Message {
+ switch meta {
+ case "option", "append":
+ if m.Set(meta, key); m.Data == nil {
+ m.Data = make(map[string]interface{})
+ }
+ m.Data[key] = value
+
+ default:
+ m.Log("error", "put data error %s %s %v", meta, key, value)
+ }
+ return m
+}
+func (m *Message) Get(key string, arg ...interface{}) string {
+ if meta, ok := m.Meta[key]; ok && len(meta) > 0 {
+ index := 0
+ if len(arg) > 0 {
+ index = kit.Int(arg[0])
+ }
+
+ index = (index+2)%(len(meta)+2) - 2
+ if index >= 0 && index < len(meta) {
+ return meta[index]
+ }
+ }
+ return ""
+}
+func (m *Message) Has(key ...string) bool {
+ switch len(key) {
+ case 1:
+ if _, ok := m.Data[key[0]]; ok {
+ return true
+ }
+ if _, ok := m.Meta[key[0]]; ok {
+ return true
+ }
+ }
+ return false
+}
+func (m *Message) CopyTo(msg *Message, arg ...string) *Message {
+ msg.Copy(m, arg...)
+ return m
+}
+func (m *Message) Copy(msg *Message, arg ...string) *Message {
+ if m == msg {
+ return m
+ }
+ if len(arg) == 0 {
+ if msg.Hand {
+ arg = append(arg, "append", "result")
+ } else {
+ arg = append(arg, "option")
+ }
+ }
+
+ for i := 0; i < len(arg); i++ {
+ meta := arg[i]
+
+ switch meta {
+ case "target":
+ m.target = msg.target
+ case "callback":
+ m.callback = msg.callback
+ // case "session":
+ // if len(arg) == 0 {
+ // for k, v := range msg.Sessions {
+ // m.Sessions[k] = v
+ // }
+ // } else {
+ // for _, k := range arg {
+ // m.Sessions[k] = msg.Sessions[k]
+ // }
+ // }
+ case "detail", "result":
+ if len(msg.Meta[meta]) > 0 {
+ m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
+ }
+ case "option", "append":
+ if i == len(arg)-1 {
+ arg = append(arg, msg.Meta[meta]...)
+ }
+
+ for i++; i < len(arg); i++ {
+ if v, ok := msg.Data[arg[i]]; ok {
+ m.Put(meta, arg[i], v)
+ }
+ if v, ok := msg.Meta[arg[i]]; ok {
+ m.Add(meta, arg[i], v)
+ }
+ }
+ default:
+ if msg.Hand {
+ meta = "append"
+ } else {
+ meta = "option"
+ }
+
+ if v, ok := msg.Data[arg[i]]; ok {
+ m.Put(meta, arg[i], v)
+ }
+ if v, ok := msg.Meta[arg[i]]; ok {
+ m.Add(meta, arg[i], v)
+ }
+ }
+ }
+
+ return m
+}
+func (m *Message) Echo(str string, arg ...interface{}) *Message {
+ if len(arg) > 0 {
+ return m.Add("result", fmt.Sprintf(str, arg...))
+ }
+ return m.Add("result", str)
+}
+
+func (m *Message) Insert(meta string, index int, arg ...interface{}) string {
+ if m.Meta == nil {
+ m.Meta = make(map[string][]string)
+ }
+ m.Meta[meta] = kit.Array(m.Meta[meta], index, arg)
+
+ if -1 < index && index < len(m.Meta[meta]) {
+ return m.Meta[meta][index]
+ }
+ return ""
+}
+func (m *Message) Detail(arg ...interface{}) string {
+ noset, index := true, 0
+ if len(arg) > 0 {
+ switch v := arg[0].(type) {
+ case int:
+ noset, index, arg = false, v, arg[1:]
+ }
+ }
+ if noset && len(arg) > 0 {
+ index = -2
+ }
+
+ return m.Insert("detail", index, arg...)
+}
+func (m *Message) Detaili(arg ...interface{}) int {
+ return kit.Int(m.Detail(arg...))
+}
+func (m *Message) Details(arg ...interface{}) bool {
+ return kit.Right(m.Detail(arg...))
+}
+func (m *Message) Result(arg ...interface{}) string {
+ noset, index := true, 0
+ if len(arg) > 0 {
+ switch v := arg[0].(type) {
+ case int:
+ noset, index, arg = false, v, arg[1:]
+ }
+ }
+ if noset && len(arg) > 0 {
+ index = -2
+ }
+
+ return m.Insert("result", index, arg...)
+}
+func (m *Message) Resulti(arg ...interface{}) int {
+ return kit.Int(m.Result(arg...))
+}
+func (m *Message) Results(arg ...interface{}) bool {
+ return kit.Right(m.Result(arg...))
+}
+func (m *Message) Option(key string, arg ...interface{}) string {
+ if len(arg) > 0 {
+ m.Insert(key, 0, arg...)
+ if _, ok := m.Meta[key]; ok {
+ m.Add("option", key)
+ }
+ }
+
+ for msg := m; msg != nil; msg = msg.message {
+ if !msg.Has(key) {
+ continue
+ }
+ for _, k := range msg.Meta["option"] {
+ if k == key {
+ return msg.Get(key)
+ }
+ }
+ }
+ return ""
+}
+func (m *Message) Optioni(key string, arg ...interface{}) int {
+ return kit.Int(m.Option(key, arg...))
+
+}
+func (m *Message) Options(key string, arg ...interface{}) bool {
+ return kit.Right(m.Option(key, arg...))
+}
+func (m *Message) Optionv(key string, arg ...interface{}) interface{} {
+ if len(arg) > 0 {
+ switch arg[0].(type) {
+ case nil:
+ // case []string:
+ // m.Option(key, v...)
+ // case string:
+ // m.Option(key, v)
+ default:
+ m.Put("option", key, arg[0])
+ }
+ }
+
+ for msg := m; msg != nil; msg = msg.message {
+ if msg.Meta == nil || !msg.Has(key) {
+ continue
+ }
+ for _, k := range msg.Meta["option"] {
+ if k == key {
+ if v, ok := msg.Data[key]; ok {
+ return v
+ }
+ return msg.Meta[key]
+ }
+ }
+ }
+ return nil
+}
+func (m *Message) Optionx(key string, arg ...string) interface{} {
+ value := m.Conf(key)
+ if value == "" {
+ value = m.Option(key)
+ }
+
+ if len(arg) > 0 {
+ value = fmt.Sprintf(arg[0], value)
+ }
+ return value
+}
+func (m *Message) Append(key string, arg ...interface{}) string {
+ if len(arg) > 0 {
+ m.Insert(key, 0, arg...)
+ if _, ok := m.Meta[key]; ok {
+ m.Add("append", key)
+ }
+ }
+
+ ms := []*Message{m}
+ for i := 0; i < len(ms); i++ {
+ ms = append(ms, ms[i].messages...)
+ if !ms[i].Has(key) {
+ continue
+ }
+ for _, k := range ms[i].Meta["append"] {
+ if k == key {
+ return ms[i].Get(key)
+ }
+ }
+ }
+ return ""
+}
+func (m *Message) Appendi(key string, arg ...interface{}) int {
+ return kit.Int(m.Append(key, arg...))
+
+}
+func (m *Message) Appends(key string, arg ...interface{}) bool {
+ return kit.Right(m.Append(key, arg...))
+}
+func (m *Message) Appendv(key string, arg ...interface{}) interface{} {
+ if len(arg) > 0 {
+ m.Put("append", key, arg[0])
+ }
+
+ ms := []*Message{m}
+ for i := 0; i < len(ms); i++ {
+ ms = append(ms, ms[i].messages...)
+ if !ms[i].Has(key) {
+ continue
+ }
+ for _, k := range ms[i].Meta["append"] {
+ if k == key {
+ if v, ok := ms[i].Data[key]; ok {
+ return v
+ }
+ return ms[i].Meta[key]
+ }
+ }
+ }
+ return nil
+}
+func (m *Message) Table(cbs ...func(maps map[string]string, list []string, line int) (goon bool)) *Message {
+ if len(m.Meta["append"]) == 0 {
+ return m
+ }
+
+ //计算列宽
+ depth, width := 0, map[string]int{}
+ for _, k := range m.Meta["append"] {
+ if len(m.Meta[k]) > depth {
+ depth = len(m.Meta[k])
+ }
+ width[k] = len(k)
+ for _, v := range m.Meta[k] {
+ if len(v) > width[k] {
+ width[k] = len(v)
+ }
+ }
+ }
+
+ space := m.Confx("table_space")
+ var cb func(maps map[string]string, list []string, line int) (goon bool)
+ if len(cbs) > 0 {
+ cb = cbs[0]
+ } else {
+ row := m.Confx("table_row_sep")
+ col := m.Confx("table_col_sep")
+ compact := kit.Right(m.Confx("table_compact"))
+ cb = func(maps map[string]string, lists []string, line int) bool {
+ for i, v := range lists {
+ if k := m.Meta["append"][i]; compact {
+ v = maps[k]
+ }
+
+ if m.Echo(v); i < len(lists)-1 {
+ m.Echo(col)
+ }
+ }
+ m.Echo(row)
+ return true
+ }
+ }
+
+ // 输出表头
+ row := map[string]string{}
+ wor := []string{}
+ for _, k := range m.Meta["append"] {
+ row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-len(k)))
+ }
+ if !cb(row, wor, -1) {
+ return m
+ }
+
+ // 输出数据
+ for i := 0; i < depth; i++ {
+ row := map[string]string{}
+ wor := []string{}
+ for _, k := range m.Meta["append"] {
+ data := ""
+ if i < len(m.Meta[k]) {
+ data = m.Meta[k][i]
+ }
+
+ row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-len(data)))
+ }
+ if !cb(row, wor, i) {
+ break
+ }
+ }
+
+ return m
+}
+func (m *Message) Sort(key string, arg ...string) *Message {
+ cmp := "string"
+ if len(arg) > 0 {
+ cmp = arg[0]
+ }
+
+ number := map[int]int{}
+ table := []map[string]string{}
+ m.Table(func(line map[string]string, lists []string, index int) bool {
+ if index != -1 {
+ table = append(table, line)
+ switch cmp {
+ case "int":
+ number[index] = kit.Int(line[key])
+ case "int_r":
+ number[index] = -kit.Int(line[key])
+ case "time":
+ number[index] = kit.Time(line[key])
+ case "time_r":
+ number[index] = -kit.Time(line[key])
+ }
+ }
+ return true
+ })
+
+ for i := 0; i < len(table)-1; i++ {
+ for j := i + 1; j < len(table); j++ {
+ result := false
+ switch cmp {
+ case "str":
+ if table[i][key] > table[j][key] {
+ result = true
+ }
+ case "str_r":
+ if table[i][key] < table[j][key] {
+ result = true
+ }
+ default:
+ if number[i] > number[j] {
+ result = true
+ }
+ }
+
+ if result {
+ table[i], table[j] = table[j], table[i]
+ number[i], number[j] = number[j], number[i]
+ }
+ }
+ }
+
+ for _, k := range m.Meta["append"] {
+ delete(m.Meta, k)
+ }
+
+ for _, v := range table {
+ for _, k := range m.Meta["append"] {
+ m.Add("append", k, v[k])
+ }
+ }
+ return m
+}
+func (m *Message) Parse(arg interface{}) string {
+ switch str := arg.(type) {
+ case string:
+ if len(str) > 1 && str[0] == '$' {
+ return m.Cap(str[1:])
+ }
+ if len(str) > 1 && str[0] == '@' {
+ return m.Confx(str[1:])
+ }
+ return str
+ }
+ return ""
+}
+
+func (m *Message) Gdb(arg ...interface{}) interface{} {
+ if g := m.Sess("gdb", false); g != nil {
+ if gdb, ok := g.target.Server.(DEBUG); ok {
+ return gdb.Wait(m, arg...)
+ }
+ }
+ return nil
+}
+func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
+
+ if l := m.Sess("log", false); l != nil {
+ if log, ok := l.target.Server.(LOGGER); ok {
+ if action == "error" {
+ log.Log(m, "error", "chain: %s", m.Format("chain"))
+ }
+ log.Log(m, action, str, arg...)
+ if action == "error" {
+ log.Log(m, "error", "stack: %s", m.Format("stack"))
+ }
+ return m
+ }
+ }
+
+ if action == "error" {
+ kit.Log("error", fmt.Sprintf("chain: %s", m.Format("chain")))
+ kit.Log("error", fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...)))
+ kit.Log("error", fmt.Sprintf("stack: %s", m.Format("stack")))
+ }
+
+ return m
+}
+func (m *Message) Assert(e interface{}, msg ...string) bool {
+ switch v := e.(type) {
+ case nil:
+ return true
+ case *Message:
+ if v.Result(0) != "error: " {
+ return true
+ }
+ e = v.Result(1)
+ default:
+ if kit.Right(v) {
+ return true
+ }
+ }
+
+ switch e.(type) {
+ case error:
+ default:
+ e = errors.New(kit.Format(msg))
+ }
+
+ m.Log("error", "%v", e)
+ panic(e)
+}
+func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
+ defer func() {
+ e := recover()
+ switch e {
+ case io.EOF:
+ case nil:
+ default:
+ m.Log("bench", "chain: %s", msg.Format("chain"))
+ m.Log("bench", "catch: %s", e)
+ m.Log("bench", "stack: %s", msg.Format("stack"))
+
+ m.Log("error", "catch: %s", e)
+
+ if len(hand) > 1 {
+ m.TryCatch(msg, safe, hand[1:]...)
+ } else if !safe {
+ msg.Assert(e)
+ }
+ }
+ }()
+
+ if len(hand) > 0 {
+ hand[0](msg)
+ }
+
+ return m
+}
+func (m *Message) GoFunc(msg *Message, hand ...func(msg *Message)) *Message {
+ go func() {
+ m.Log("info", "%v safe go begin", m.Capi("ngo", 1))
+ m.TryCatch(msg, true, hand...)
+ m.Log("info", "%v safe go end", m.Capi("ngo", -1)+1)
+ }()
+ return m
+}
+func (m *Message) GoLoop(msg *Message, hand ...func(msg *Message)) *Message {
+ go func() {
+ m.Log("info", "%v safe go begin", m.Capi("ngo", 1))
+ for {
+ m.TryCatch(msg, true, hand...)
+ }
+ m.Log("info", "%v safe go end", m.Capi("ngo", -1)+1)
+ }()
+ return m
+}
+func (m *Message) Start(name string, help string, arg ...string) bool {
+ return m.Set("detail", arg).target.Spawn(m, name, help).Begin(m).Start(m)
+}
+func (m *Message) Close(arg ...string) bool {
+ return m.Target().Close(m, arg...)
+}
+func (m *Message) Wait() bool {
+ if m.target.exit != nil {
+ return <-m.target.exit
+ }
+ return true
+}
+
+func (m *Message) Find(name string, root ...bool) *Message {
+ if name == "" {
+ return m.Spawn()
+ }
+ target := m.target.root
+ if len(root) > 0 && !root[0] {
+ target = m.target
+ }
+
+ cs := target.contexts
+ for _, v := range strings.Split(name, ".") {
+ if x, ok := cs[v]; ok {
+ target, cs = x, x.contexts
+ } else if target.Name == v {
+ continue
+ } else {
+ m.Log("error", "context not find %s", name)
+ return nil
+ }
+ }
+ return m.Spawn(target)
+}
+func (m *Message) Search(key string, root ...bool) []*Message {
+ reg, e := regexp.Compile(key)
+ m.Assert(e)
+
+ target := m.target
+ if target == nil {
+ return []*Message{nil}
+ }
+ if len(root) > 0 && root[0] {
+ target = m.target.root
+ }
+
+ cs := make([]*Context, 0, 3)
+ target.Travel(m, func(m *Message, i int) bool {
+ if reg.MatchString(m.target.Name) || reg.FindString(m.target.Help) != "" {
+ m.Log("search", "%d %s match [%s]", len(cs), m.target.Name, key)
+ cs = append(cs, m.target)
+ }
+ return false
+ })
+
+ ms := make([]*Message, len(cs))
+ for i := 0; i < len(cs); i++ {
+ ms[i] = m.Spawn(cs[i])
+ }
+ if len(ms) == 0 {
+ ms = append(ms, nil)
+ }
+
+ return ms
+}
+func (m *Message) Sess(key string, arg ...interface{}) *Message {
+ if key == "" {
+ return m.Spawn()
+ }
+
+ spawn := true
+ if len(arg) > 0 {
+ switch v := arg[0].(type) {
+ case bool:
+ spawn, arg = v, arg[1:]
+ }
+ }
+
+ if len(arg) > 0 {
+ if m.Sessions == nil {
+ m.Sessions = make(map[string]*Message)
+ }
+
+ switch value := arg[0].(type) {
+ case *Message:
+ m.Sessions[key] = value
+ return m.Sessions[key]
+ case *Context:
+ m.Sessions[key] = m.Spawn(value)
+ return m.Sessions[key]
+ case string:
+ root := len(arg) < 3 || kit.Right(arg[2])
+
+ method := "find"
+ if len(arg) > 1 {
+ method = kit.Format(arg[1])
+ }
+
+ switch method {
+ case "find":
+ m.Sessions[key] = m.Find(value, root)
+ case "search":
+ m.Sessions[key] = m.Search(value, root)[0]
+ }
+ return m.Sessions[key]
+ case nil:
+ delete(m.Sessions, key)
+ return nil
+ }
+ }
+
+ for msg := m; msg != nil; msg = msg.message {
+ if x, ok := msg.Sessions[key]; ok {
+ if spawn {
+ x = m.Spawn(x.target)
+ x.callback = func(sub *Message) *Message { return sub }
+ }
+ return x
+ }
+ }
+
+ return nil
+}
+func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context, c *Context, key string) bool) *Message {
+ if m == nil {
+ return m
+ }
+
+ if strings.Contains(key, ".") {
+ arg := strings.Split(key, ".")
+ m, key = m.Sess(arg[0], spawn), arg[1]
+ }
+ if m == nil {
+ return m
+ }
+
+ context := []*Context{m.target}
+ for _, v := range []string{"aaa", "cli"} {
+ if msg := m.Sess(v, false); msg != nil && msg.target != nil {
+ context = append(context, msg.target)
+ }
+ }
+ context = append(context, m.source)
+
+ for _, s := range context {
+ for c := s; c != nil; c = c.context {
+ if hand(m, s, c, key) {
+ return m
+ }
+ }
+ }
+ return m
+}
+func (m *Message) Call(cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
+ if m == nil {
+ return m
+ }
+ if m.callback = cb; len(arg) > 0 || len(m.Meta["detail"]) > 0 {
+ m.Log("call", m.Format("detail", "option"))
+ m.Cmd(arg...)
+ }
+ return m
+}
+func (m *Message) Back(ms ...*Message) *Message {
+ if m.callback == nil {
+ return m
+ }
+
+ if len(ms) == 0 {
+ ms = append(ms, m.Spawn(m.source).Copy(m, "append").Copy(m, "result"))
+ }
+
+ ns := []*Message{}
+
+ for _, msg := range ms {
+ if msg.Hand {
+ m.Log("back", msg.Format("ship", "result", "append"))
+ } else {
+ m.Log("back", msg.Format("ship", "detail", "option"))
+ }
+
+ if sub := m.callback(msg); sub != nil && m.message != nil && m.message != m {
+ ns = append(ns, sub)
+ }
+ }
+
+ if len(ns) > 0 {
+ m.message.Back(ns...)
+ }
+ return m
+}
+func (m *Message) Backs(msg *Message) *Message {
+ m.Back(msg)
+ return msg
+}
+func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
+ if !sync {
+ return m.Call(cb, arg...)
+ }
+
+ wait := make(chan *Message, 10)
+ m.GoFunc(m, func(m *Message) {
+ m.Call(func(sub *Message) *Message {
+ msg := cb(sub)
+ m.Log("sync", m.Format("done", "result", "append"))
+ wait <- m
+ return msg
+ }, arg...)
+ })
+
+ m.Log("sync", m.Format("wait", "result", "append"))
+ return <-wait
+}
+func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
+ if len(cbs) == 0 {
+ for i := len(m.freedoms) - 1; i >= 0; i-- {
+ m.Log("free", "%d/%d", i, len(m.freedoms)-1)
+ if !m.freedoms[i](m) {
+ break
+ }
+ m.freedoms = m.freedoms[:i]
+ }
+ return m
+ }
+
+ m.freedoms = append(m.freedoms, cbs...)
+ return m
+}
+
+func (m *Message) Cmdy(args ...interface{}) *Message {
+ m.Cmd(args...).CopyTo(m)
+ return m
+}
+func (m *Message) Cmdx(args ...interface{}) string {
+ return m.Cmd(args...).Result(0)
+}
+func (m *Message) Cmds(args ...interface{}) bool {
+ return m.Cmd(args...).Results(0)
+}
+func (m *Message) Cmd(args ...interface{}) *Message {
+ if m == nil {
+ return m
+ }
+
+ if len(args) > 0 {
+ m.Set("detail", kit.Trans(args...))
+ }
+
+ key, arg := m.Meta["detail"][0], m.Meta["detail"][1:]
+
+ m = m.Match(key, true, func(m *Message, s *Context, c *Context, key string) bool {
+ if x, ok := c.Commands[key]; ok && x.Hand != nil {
+ m.TryCatch(m, true, func(m *Message) {
+ m.Log("cmd", "%s %s %v %v", c.Name, key, arg, m.Meta["option"])
+
+ if args := []string{}; x.Form != nil {
+ for i := 0; i < len(arg); i++ {
+ if n, ok := x.Form[arg[i]]; ok {
+
+ if n < 0 {
+ n += len(arg) - i
+ }
+ for j := i + 1; j <= i+n; j++ {
+ if _, ok := x.Form[arg[j]]; ok {
+ n = j - i - 1
+ }
+ }
+ m.Add("option", arg[i], arg[i+1:i+1+n])
+ i += n
+ } else {
+ args = append(args, arg[i])
+ }
+ }
+ arg = args
+ }
+
+ target := m.target
+ m.target = s
+
+ m.Hand = true
+ switch v := m.Gdb("command", key, arg).(type) {
+ case string:
+ m.Echo(v)
+ case nil:
+ if m.Options("auto_cmd") {
+ x.Auto(m, c, key, arg...)
+ } else {
+ x.Hand(m, c, key, arg...)
+ }
+ }
+ if m.target == s {
+ m.target = target
+ }
+ })
+ }
+ return m.Hand
+ })
+
+ if !m.Hand {
+ m.Log("error", "cmd run error %s", m.Format())
+ }
+ return m
+}
+
+func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} {
+ var chain interface{}
+ if len(args) > 0 {
+ switch arg := args[0].(type) {
+ case []interface{}:
+ chain, args = arg, args[1:]
+ case []string:
+ chain, args = arg, args[1:]
+ case string:
+ chain, args = arg, args[1:]
+ }
+ }
+
+ var v interface{}
+ if chain == nil {
+ v = m.Confv(key)
+ } else {
+ v = m.Confv(key, chain)
+ }
+
+ table, _ := v.([]interface{})
+ value, _ := v.(map[string]interface{})
+ if len(args) == 0 {
+ return value
+ }
+
+ switch fun := args[0].(type) {
+ case func(int, string) bool:
+ for i, v := range table {
+ if fun(i, kit.Format(v)) {
+ break
+ }
+ }
+ case func(map[string]interface{}):
+ fun(value)
+ case func(string, map[string]interface{}):
+ for k, v := range value {
+ if val, ok := v.(map[string]interface{}); ok {
+ fun(k, val)
+ }
+ }
+ case func(int, map[string]interface{}):
+ for i, v := range table {
+ if val, ok := v.(map[string]interface{}); ok {
+ fun(i, val)
+ }
+ }
+ }
+ return value
+}
+func (m *Message) Confx(key string, args ...interface{}) string {
+ value := kit.Select(m.Conf(key), m.Option(key))
+ if len(args) == 0 {
+ return value
+ }
+
+ switch arg := args[0].(type) {
+ case []string:
+ if len(args) > 1 {
+ value, args = kit.Select(value, arg, args[1]), args[1:]
+ } else {
+ value = kit.Select(value, arg)
+ }
+ case map[string]interface{}:
+ value = kit.Select(value, kit.Format(arg[key]))
+ case string:
+ value = kit.Select(value, arg)
+ case nil:
+ default:
+ value = kit.Select(value, args[0])
+ }
+
+ format := "%s"
+ if args = args[1:]; len(args) > 0 {
+ format, args = kit.Format(args[0]), args[1:]
+ }
+ arg := []interface{}{format, value}
+ for _, v := range args {
+ arg = append(arg, v)
+ }
+
+ return kit.Format(arg...)
+}
+func (m *Message) Confs(key string, arg ...interface{}) bool {
+ return kit.Right(m.Confv(key, arg...))
+}
+func (m *Message) Confi(key string, arg ...interface{}) int {
+ return kit.Int(m.Confv(key, arg...))
+}
+func (m *Message) Confv(key string, args ...interface{}) interface{} {
+ var config *Config
+ m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
+ if x, ok := c.Configs[key]; ok {
+ config = x
+ return true
+ }
+ return false
+ })
+
+ if len(args) == 0 {
+ if config == nil {
+ return nil
+ }
+ return config.Value
+ }
+
+ if config == nil {
+ config = &Config{}
+ m.target.Configs[key] = config
+ }
+
+ switch config.Value.(type) {
+ case string:
+ config.Value = kit.Format(args...)
+ case bool:
+ config.Value = kit.Right(args...)
+ case int:
+ config.Value = kit.Int(args...)
+ case nil:
+ config.Value = args[0]
+ default:
+ for i := 0; i < len(args); i += 2 {
+ if i < len(args)-1 {
+ config.Value = kit.Chain(config.Value, args[i], args[i+1])
+ } else {
+ return kit.Chain(config.Value, args[i])
+ }
+ }
+ }
+
+ return config.Value
+}
+func (m *Message) Conf(key string, args ...interface{}) string {
+ return kit.Format(m.Confv(key, args...))
+}
+func (m *Message) Caps(key string, arg ...interface{}) bool {
+ if len(arg) > 0 {
+ return kit.Right(m.Cap(key, arg...))
+ }
+ return kit.Right(m.Cap(key))
+}
+func (m *Message) Capi(key string, arg ...interface{}) int {
+ n := kit.Int(m.Cap(key))
+ if len(arg) > 0 {
+ return kit.Int(m.Cap(key, n+kit.Int(arg...)))
+ }
+ return n
+}
+func (m *Message) Cap(key string, arg ...interface{}) string {
+ var cache *Cache
+ m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
+ if x, ok := c.Caches[key]; ok {
+ cache = x
+ return true
+ }
+ return false
+ })
+
+ if len(arg) == 0 {
+ if cache == nil {
+ return ""
+ }
+ if cache.Hand != nil {
+ return cache.Hand(m, cache)
+ }
+ return cache.Value
+ }
+
+ if cache == nil {
+ cache = &Cache{}
+ m.target.Caches[key] = cache
+ }
+
+ if cache.Hand != nil {
+ cache.Value = cache.Hand(m, cache, kit.Format(arg...))
+ } else {
+ cache.Value = kit.Format(arg...)
+ }
+ return cache.Value
+}
diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go
index 356827fc..3e0f20e1 100644
--- a/src/contexts/nfs/nfs.go
+++ b/src/contexts/nfs/nfs.go
@@ -878,29 +878,27 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
nfs.echo = make(chan *ctx.Message, 10)
nfs.hand = map[int]*ctx.Message{}
- go func() { //发送消息队列
- for {
- msg, code, meta, body := m, 0, "detail", "option"
- select {
- case msg = <-nfs.send:
- code = msg.Code()
- nfs.hand[code] = msg
- case msg = <-nfs.echo:
- code, meta, body = msg.Optioni("remote_code"), "result", "append"
- }
-
- nfs.Send("code", code)
- for _, v := range msg.Meta[meta] {
- nfs.Send(meta, v)
- }
- for _, k := range msg.Meta[body] {
- for _, v := range msg.Meta[k] {
- nfs.Send(k, v)
- }
- }
- nfs.Send("")
+ m.GoLoop(m, func(m *ctx.Message) {
+ msg, code, meta, body := m, 0, "detail", "option"
+ select {
+ case msg = <-nfs.send:
+ code = msg.Code()
+ nfs.hand[code] = msg
+ case msg = <-nfs.echo:
+ code, meta, body = msg.Optioni("remote_code"), "result", "append"
}
- }()
+
+ nfs.Send("code", code)
+ for _, v := range msg.Meta[meta] {
+ nfs.Send(meta, v)
+ }
+ for _, k := range msg.Meta[body] {
+ for _, v := range msg.Meta[k] {
+ nfs.Send(k, v)
+ }
+ }
+ nfs.Send("")
+ })
//接收消息队列
msg, code, head, body := m, "0", "result", "append"
diff --git a/src/examples/bench.go b/src/examples/app/bench.go
similarity index 100%
rename from src/examples/bench.go
rename to src/examples/app/bench.go
diff --git a/src/examples/findgrep.go b/src/examples/app/findgrep.go
similarity index 100%
rename from src/examples/findgrep.go
rename to src/examples/app/findgrep.go