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, "") - 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, "") - } - result = append(result, "") - return true - } - result = append(result, "") - for _, v := range list { - result = append(result, "") - } - result = append(result, "") - return true - }) - result = append(result, "
", cmd, "
", v, "
", v, "
") - } 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, "") + 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, "") + } + result = append(result, "") + return true + } + result = append(result, "") + for _, v := range list { + result = append(result, "") + } + result = append(result, "") + return true + }) + result = append(result, "
", cmd, "
", v, "
", v, "
") + } 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