diff --git a/Makefile b/Makefile
index b6f4403e..ea41a43e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-BENCH=src/examples/app/bench.go
+BENCH=src/extend/bench.go
upgrade=usr/upgrade/
install:
diff --git a/bin/boot.sh b/bin/boot.sh
index ee28baac..03e6f32e 100755
--- a/bin/boot.sh
+++ b/bin/boot.sh
@@ -46,9 +46,9 @@ hup() {
}
main() {
trap HUP hup
+ log "\nstarting..."
while true; do
- date
- ${ctx_bin} "$@" && break
+ date && ${ctx_bin} "$@" && break
log "\nrestarting..." && sleep 1
done
}
diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go
index caba23e2..95bb0afc 100644
--- a/src/contexts/aaa/aaa.go
+++ b/src/contexts/aaa/aaa.go
@@ -36,13 +36,10 @@ type AAA struct {
func Auto(m *ctx.Message, arg ...string) {
msg := m.Spawn().Add("option", "auto_cmd", "").Cmd("auth", arg)
- msg.Table(func(maps map[string]string, list []string, line int) bool {
- if line >= 0 {
- m.Add("append", "value", maps["key"])
- m.Add("append", "name", fmt.Sprintf("%s: %s", maps["type"], maps["meta"]))
- m.Add("append", "help", fmt.Sprintf("%s", maps["create_time"]))
- }
- return true
+ msg.Table(func(line int, maps map[string]string) {
+ m.Add("append", "value", maps["key"])
+ m.Add("append", "name", fmt.Sprintf("%s: %s", maps["type"], maps["meta"]))
+ m.Add("append", "help", fmt.Sprintf("%s", maps["create_time"]))
})
}
diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go
index e50ca968..25ffc1fb 100644
--- a/src/contexts/cli/cli.go
+++ b/src/contexts/cli/cli.go
@@ -152,7 +152,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
},
}, Help: "运行环境"},
"compile": &ctx.Config{Name: "compile", Value: map[string]interface{}{
- "bench": "src/examples/app/bench.go",
+ "bench": "src/extend/bench.go",
"tmp": "var/tmp/go",
"env": []interface{}{"GOPATH", "PATH"},
}, Help: "运行环境"},
@@ -444,7 +444,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Echo(h)
// 执行命令
- m.GoFunc(m, func(m *ctx.Message) {
+ m.Gos(m, func(m *ctx.Message) {
if e := cmd.Start(); e != nil {
m.Echo("error: ").Echo("%s\n", e)
} else if e := cmd.Wait(); e != nil {
@@ -457,7 +457,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
// 管道命令
wait := make(chan bool, 1)
- m.GoFunc(m, func(m *ctx.Message) {
+ m.Gos(m, func(m *ctx.Message) {
defer func() { wait <- true }()
out := bytes.NewBuffer(make([]byte, 0, 1024))
@@ -745,17 +745,30 @@ var version = struct {
"missyou": &ctx.Command{Name: "missyou", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Option("dir_root", "")
- m.Cmdy("nfs.dir", m.Conf("missyou", "path"))
+ m.Cmd("nfs.dir", m.Conf("missyou", "path")).Table(func() {
+ })
return
}
- p := path.Join(m.Conf("missyou", "path"), m.Time("20060102-")+arg[0])
- m.Cmd("nfs.copy", path.Join(p, "etc/local.shy"), "usr/missyou/job.shy")
+ if !strings.Contains(arg[0], "-") {
+ arg[0] = m.Time("20060102-") + arg[0]
+ }
+ if m.Confs("ssh.node", arg[0]) {
+ m.Echo(arg[0])
+ return
+ }
+
+ p := path.Join(m.Conf("missyou", "path"), arg[0])
+ if s, e := os.Stat(p); e == nil && s.IsDir() {
+ m.Cmdy("cli.system", "node.sh", "create", p, "daemon", "cmd_daemon", "true")
+ return e
+ }
+
+ m.Cmdy("nfs.copy", path.Join(p, "etc/local.shy"), "usr/missyou/job.shy")
m.Confm("missyou", "local", func(index string, local string) {
m.Cmd("nfs.git", "clone", local, path.Join(p, "usr/local", index))
})
- m.Cmdy("cli.system", "node.sh", "create", p, "daemon", "cmd_daemon", "true")
return
}},
"quit": &ctx.Command{Name: "quit code", Help: "停止服务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@@ -779,7 +792,7 @@ var version = struct {
m.Append("code", code)
m.Echo(", wait 1s\n").Table()
- m.GoFunc(m, func(m *ctx.Message) {
+ m.Gos(m, func(m *ctx.Message) {
defer func() {
os.Exit(kit.Int(code))
}()
@@ -798,25 +811,25 @@ var version = struct {
}
begin := time.Now()
- f, e := os.Open(args[0])
- defer f.Close()
- bio := bufio.NewScanner(f)
+ f, e := os.Open(args[0])
+ defer f.Close()
+ bio := bufio.NewScanner(f)
output := map[string]*os.File{}
nreq := 0
- for bio.Scan() {
- word := strings.Split(bio.Text(), " ")
- if len(word) != 2 {
- continue
+ for bio.Scan() {
+ word := strings.Split(bio.Text(), " ")
+ if len(word) != 2 {
+ continue
}
- uri := word[0][prefix0:len(word[0])-1]
- arg := word[1][prefix1:len(word[1])-1]
- if output[uri] == nil {
- output[uri], e = os.Create(path.Join("tmp", strings.Replace(uri, "/", "_", -1)+".txt"))
- defer output[uri].Close()
+ uri := word[0][prefix0 : len(word[0])-1]
+ arg := word[1][prefix1 : len(word[1])-1]
+ if output[uri] == nil {
+ output[uri], e = os.Create(path.Join("tmp", strings.Replace(uri, "/", "_", -1)+".txt"))
+ defer output[uri].Close()
}
nreq++
- br := bytes.NewReader([]byte(arg))
+ br := bytes.NewReader([]byte(arg))
res, e := http.Post(args[1]+uri, "application/json", br)
fmt.Fprintf(output[uri], uri)
fmt.Fprintf(output[uri], " ")
diff --git a/src/contexts/cli/version.go b/src/contexts/cli/version.go
index db64c968..fca0b62f 100644
--- a/src/contexts/cli/version.go
+++ b/src/contexts/cli/version.go
@@ -4,5 +4,5 @@ var version = struct {
host string
self int
}{
- "2019-06-28 19:50:49", "ZYB-20190522USI", 24,
+ "2019-06-30 12:52:58", "com", 26,
}
diff --git a/src/contexts/ctx/cgi.go b/src/contexts/ctx/cgi.go
index ab06b041..e5ee36c8 100644
--- a/src/contexts/ctx/cgi.go
+++ b/src/contexts/ctx/cgi.go
@@ -554,21 +554,19 @@ var CGI = template.FuncMap{
if len(cli.Meta["append"]) > 0 {
result = append(result, "
")
result = append(result, "", cmd, "")
- cli.Table(func(maps map[string]string, list []string, line int) bool {
- if line == -1 {
+ cli.Table(func(line int, maps map[string]string) {
+ if line == 0 {
result = append(result, "")
- for _, v := range list {
+ for _, v := range cli.Meta["append"] {
result = append(result, "", v, " | ")
}
result = append(result, "
")
- return true
}
result = append(result, "")
- for _, v := range list {
- result = append(result, "", v, " | ")
+ for _, k := range cli.Meta["append"] {
+ result = append(result, "", maps[k], " | ")
}
result = append(result, "
")
- return true
})
result = append(result, "
")
} else {
diff --git a/src/contexts/ctx/core.go b/src/contexts/ctx/core.go
new file mode 100644
index 00000000..2007beae
--- /dev/null
+++ b/src/contexts/ctx/core.go
@@ -0,0 +1,391 @@
+package ctx
+
+import (
+ "errors"
+ "io"
+ "strings"
+ "time"
+ "toolkit"
+)
+
+func (c *Context) Register(s *Context, x Server, args ...interface{}) {
+ force := false
+ if len(args) > 0 {
+ switch arg := args[0].(type) {
+ case bool:
+ force = arg
+ }
+ }
+
+ if c.contexts == nil {
+ c.contexts = make(map[string]*Context)
+ }
+ if x, ok := c.contexts[s.Name]; ok && !force {
+ panic(errors.New(c.Name + "上下文中已存在模块:" + x.Name))
+ }
+
+ c.contexts[s.Name] = s
+ s.context = c
+ s.Server = x
+}
+func (c *Context) Plugin(args []string) string {
+ Index.Register(c, nil)
+ m := &Message{code: 0, time: time.Now(), source: c, target: c, Meta: map[string][]string{}}
+ if len(args) == 0 {
+ m.Echo("%s: %s\n", c.Name, c.Help)
+ for k, v := range c.Commands {
+ m.Echo("%s: %s %v\n", k, v.Name, v.Help)
+ }
+ } else if cs, ok := c.Commands[args[0]]; ok {
+ h := cs.Hand
+ if e := h(m, c, args[0], args[1:]...); e != nil {
+ m.Echo("error: ").Echo("%v\n", e)
+ }
+ } else {
+ m.Echo("error: ").Echo("not found: %v\n", args[0])
+ }
+ return strings.Join(m.Meta["result"], "")
+}
+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 && c.context.Caches != nil && c.context.Caches["module"] != nil {
+ module = c.context.Caches["module"].Value + "." + 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)
+
+ /*
+ 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)
+
+ if m.Hand = true; m.Cap("status") == "start" {
+ return true
+ }
+
+ m.Gos(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 (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 = errors.New(strings.Join(v.Meta["result"], ""))
+ default:
+ if kit.Right(v) {
+ return true
+ }
+ }
+
+ switch e.(type) {
+ case error:
+ default:
+ e = errors.New(kit.Format(msg))
+ }
+
+ kit.Log("error", "%v", e)
+ panic(e)
+}
+func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
+ defer func() {
+ switch e := recover(); 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"))
+
+ if m.Log("error", "catch: %s", e); len(hand) > 1 {
+ m.TryCatch(msg, safe, hand[1:]...)
+ } else if !safe {
+ m.Assert(e)
+ }
+ }
+ }()
+
+ if len(hand) > 0 {
+ hand[0](msg)
+ }
+ return m
+}
+func (m *Message) Gos(msg *Message, hand ...func(msg *Message)) *Message {
+ go func() {
+ msg.Option("routine", m.Capi("ngo", 1))
+ m.TryCatch(msg, true, hand...)
+ }()
+ return m
+}
+
+func (m *Message) Spawn(arg ...interface{}) *Message {
+ temp := false
+ c := m.target
+ if len(arg) > 0 {
+ switch v := arg[0].(type) {
+ case *Context:
+ c = v
+ case *Message:
+ c = v.target
+ case string:
+ temp = kit.Right(v)
+ }
+ }
+
+ msg := &Message{
+ time: time.Now(),
+ code: m.Capi("nmessage", 1),
+ source: m.target,
+ target: c,
+ message: m,
+ root: m.root,
+ }
+
+ if temp {
+ return msg
+ }
+
+ m.messages = append(m.messages, msg)
+ return msg
+}
+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) 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) 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.Gos(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"))
+ select {
+ case <-time.After(kit.Duration(m.Conf("call_timeout"))):
+ m.Log("sync", m.Format("timeout", "result", "append"))
+ case <-wait:
+ }
+ return m
+}
+func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
+ if len(cbs) == 0 {
+ for i := len(m.freeback) - 1; i >= 0; i-- {
+ m.Log("free", "%d/%d", i, len(m.freeback)-1)
+ if !m.freeback[i](m) {
+ break
+ }
+ m.freeback = m.freeback[:i]
+ }
+ return m
+ }
+
+ m.freeback = append(m.freeback, cbs...)
+ return m
+}
diff --git a/src/contexts/ctx/shy.go b/src/contexts/ctx/shy.go
deleted file mode 100644
index 2ca6826c..00000000
--- a/src/contexts/ctx/shy.go
+++ /dev/null
@@ -1,1859 +0,0 @@
-package ctx
-
-import (
- "fmt"
- "log"
- "math/rand"
- "regexp"
- "runtime"
- "strconv"
- "strings"
-
- "errors"
- "io"
- "sort"
- "time"
- "toolkit"
-)
-
-func (c *Context) Register(s *Context, x Server, args ...interface{}) {
- force := false
- if len(args) > 0 {
- switch arg := args[0].(type) {
- case bool:
- force = arg
- }
- }
-
- if c.contexts == nil {
- c.contexts = make(map[string]*Context)
- }
- if x, ok := c.contexts[s.Name]; ok && !force {
- 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 && c.context.Caches != nil && c.context.Caches["module"] != nil {
- module = c.context.Caches["module"].Value + "." + 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)
-
- /*
- 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)
-
- 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 {
- if c == nil {
- return nil
- }
- 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) Plugin(args []string) string {
- Index.Register(c, nil)
- m := &Message{code: 0, time: time.Now(), source: c, target: c, Meta: map[string][]string{}}
- if len(args) == 0 {
- m.Echo("%s: %s\n", c.Name, c.Help)
- for k, v := range c.Commands {
- m.Echo("%s: %s %v\n", k, v.Name, v.Help)
- }
- } else if cs, ok := c.Commands[args[0]]; ok {
- h := cs.Hand
- if e := h(m, c, args[0], args[1:]...); e != nil {
- m.Echo("error: ").Echo("%v\n", e)
- }
- } else {
- m.Echo("error: ").Echo("not found: %v\n", args[0])
- }
- return strings.Join(m.Meta["result"], "")
-}
-
-func (m *Message) Spawn(arg ...interface{}) *Message {
- temp := false
- c := m.target
- if len(arg) > 0 {
- switch v := arg[0].(type) {
- case *Context:
- c = v
- case *Message:
- c = v.target
- case string:
- temp = kit.Right(v)
- }
- }
-
- msg := &Message{
- time: time.Now(),
- code: m.Capi("nmessage", 1),
- source: m.target,
- target: c,
- message: m,
- root: m.root,
- }
-
- if temp {
- return msg
- }
-
- 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])
- }
- if str == "stamp" {
- return kit.Format(t.Unix())
- }
- 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("%s:%d(%s->%s)", m.Option("routine"), 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)
- }
- }
-
- meta = append(meta, "\n")
- for i := len(ms) - 1; i >= 0; i-- {
- msg := ms[i]
-
- meta = append(meta, fmt.Sprintf("%s\n", msg.Format("time", "ship")))
- if len(msg.Meta["detail"]) > 0 {
- meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
- }
- if len(msg.Meta["option"]) > 0 {
- 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))
- }
- }
- }
- if len(msg.Meta["append"]) > 0 {
- 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))
- }
- }
- }
- if len(msg.Meta["result"]) > 0 {
- 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(6, 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, "append").Copy(m, "result")
- return m
-}
-func (m *Message) Copy(msg *Message, arg ...string) *Message {
- if msg == nil || m == msg {
- return m
- }
-
- 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 "detail", "result":
- if len(msg.Meta[meta]) > 0 {
- m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
- }
- case "option", "append":
- if msg.Meta == nil {
- msg.Meta = map[string][]string{}
- }
- if msg.Meta[meta] == nil {
- break
- }
- 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)
- } else if v, ok := msg.Meta[arg[i]]; ok {
- m.Set(meta, arg[i], v) // TODO fuck Add
- }
- }
- 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) CopyFuck(msg *Message, arg ...string) *Message {
- if m == msg {
- return m
- }
-
- 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 "detail", "result":
- if len(msg.Meta[meta]) > 0 {
- m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
- }
- case "option", "append":
- if msg.Meta == nil {
- msg.Meta = map[string][]string{}
- }
- if msg.Meta[meta] == nil {
- break
- }
- 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)
- } else if v, ok := msg.Meta[arg[i]]; ok {
- m.Add(meta, arg[i], v) // TODO fuck Add
- }
- }
- 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) Auto(arg ...string) *Message {
- for i := 0; i < len(arg); i += 3 {
- m.Add("append", "value", arg[i])
- m.Add("append", "name", arg[i+1])
- m.Add("append", "help", arg[i+2])
- }
- return m
-}
-
-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) Magic(begin string, chain interface{}, args ...interface{}) interface{} {
- auth := []string{"bench", "session", "user", "role", "componet", "command"}
- key := []string{"bench", "sessid", "username", "role", "componet", "command"}
- aaa := m.Sess("aaa", false)
- for i, v := range auth {
- if v == begin {
- h := m.Option(key[i])
- if v == "user" {
- h, _ = kit.Hash("username", m.Option("username"))
- }
-
- data := aaa.Confv("auth", []string{h, "data"})
-
- if kit.Format(chain) == "" {
- return data
- }
-
- if len(args) > 0 {
- value := kit.Chain(data, chain, args[0])
- aaa.Conf("auth", []string{m.Option(key[i]), "data"}, value)
- return value
- }
-
- value := kit.Chain(data, chain)
- if value != nil {
- return value
- }
-
- if i < len(auth)-1 {
- begin = auth[i+1]
- }
- }
- }
- return nil
-}
-func (m *Message) Current(text string) string {
- cs := []string{}
- if pod := kit.Format(m.Magic("session", "current.pod")); pod != "" {
- cs = append(cs, "context", "ssh", "remote", "'"+pod+"'")
- }
- if ctx := kit.Format(m.Magic("session", "current.ctx")); ctx != "" {
- cs = append(cs, "context", ctx)
- }
- if cmd := kit.Format(m.Magic("session", "current.cmd")); cmd != "" {
- cs = append(cs, cmd)
- }
- m.Log("info", "%s %s current %v", m.Option("username"), m.Option("sessid"), cs)
- cs = append(cs, text)
- return strings.Join(cs, " ")
-}
-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{}) int64 {
- i, _ := strconv.ParseInt(m.Append(key, arg...), 10, 64)
- return i
-}
-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 ...interface{}) *Message {
- if len(m.Meta["append"]) == 0 {
- return m
- }
-
- // 遍历函数
- if len(cbs) > 0 {
- switch cb := cbs[0].(type) {
- case func(map[string]string) bool:
- nrow := len(m.Meta[m.Meta["append"][0]])
- line := map[string]string{}
- for i := 0; i < nrow; i++ {
- for _, k := range m.Meta["append"] {
- line[k] = m.Meta[k][i]
- }
- if !cb(line) {
- break
- }
- }
- return m
- case func(map[string]string):
- 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]
- }
- cb(line)
- }
- return m
- case func(int, map[string]string):
- 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]
- }
- cb(i, line)
- }
- return m
- }
- }
-
- //计算列宽
- space := m.Confx("table_space")
- 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] = kit.Width(k, len(space))
- for _, v := range m.Meta[k] {
- if kit.Width(v, len(space)) > width[k] {
- width[k] = kit.Width(v, len(space))
- }
- }
- }
-
- // 回调函数
- var cb func(maps map[string]string, list []string, line int) (goon bool)
- if len(cbs) > 0 {
- cb = cbs[0].(func(maps map[string]string, list []string, line int) (goon bool))
- } 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]-kit.Width(k, len(space))))
- }
- 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]-kit.Width(data, len(space))))
- }
- if !cb(row, wor, i) {
- break
- }
- }
-
- return m
-}
-func (m *Message) Sort(key string, arg ...string) *Message {
- cmp := "str"
- 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] == '@' {
- if v := m.Option(str[1:]); v != "" {
- return v
- }
- if v := kit.Format(m.Magic("bench", str[1:])); v != "" {
- return v
- }
- v := m.Conf(str[1:])
- return v
- }
- return str
- }
- return ""
-}
-func (m *Message) ToHTML(style string) string {
- cmd := strings.Join(m.Meta["detail"], " ")
- result := []string{}
- if len(m.Meta["append"]) > 0 {
- result = append(result, fmt.Sprintf("", style))
- result = append(result, "", cmd, "")
- m.Table(func(maps map[string]string, list []string, line int) bool {
- if line == -1 {
- result = append(result, "")
- for _, v := range list {
- result = append(result, "", v, " | ")
- }
- result = append(result, "
")
- return true
- }
- result = append(result, "")
- for _, v := range list {
- result = append(result, "", v, " | ")
- }
- result = append(result, "
")
- return true
- })
- result = append(result, "
")
- } else {
- result = append(result, "")
- result = append(result, fmt.Sprintf("%s", m.Find("shy", false).Conf("prompt")), cmd, "\n")
- result = append(result, m.Meta["result"]...)
- result = append(result, "
")
- }
- return strings.Join(result, "")
-}
-
-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 m.Options("log.disable") {
- return m
- }
-
- 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
- }
- } else {
- log.Printf(str, arg...)
- }
-
- 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) Show(args ...interface{}) *Message {
- if m.Option("cli.modal") == "action" {
- fmt.Printf(kit.Format(args...))
- } else if kit.STDIO != nil {
- kit.STDIO.Show(args...)
- }
- 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)
- e = errors.New(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() {
- switch e := recover(); 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"))
-
- if m.Log("error", "catch: %s", e); 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() {
- msg.Option("routine", m.Capi("ngo", 1))
- // msg.Log("info", "%v safe go begin", ngo)
- // kit.Log("error", "%s ngo %s start", msg.Format(), ngo)
- m.TryCatch(msg, true, hand...)
- // kit.Log("error", "%s ngo %s end", msg.Format(), ngo)
- // msg.Log("info", "%v safe go end", ngo)
- }()
- return m
-}
-func (m *Message) GoLoop(msg *Message, hand ...func(msg *Message)) *Message {
- m.GoFunc(msg, func(msg *Message) {
- for {
- 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) 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
- }
- }
-
- if len(root) > 1 && root[1] {
- m.target = target
- return m
- }
-
- 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
- }
-
- context := []*Context{m.target}
- for _, v := range []string{"aaa", "ssh", "cli", "nfs"} {
- if msg := m.Sess(v, false); msg != nil && msg.target != nil {
- context = append(context, msg.target)
- }
- }
- // if m.target.root != nil && m.target.root.Configs != nil && m.target.root.Configs["search"] != nil && m.target.root.Configs["search"].Value != nil {
- // target := m.target
- // for _, v := range kit.Trans(kit.Chain(m.target.root.Configs["search"].Value, "context")) {
- // if t := m.Find(v, true, true); t != nil {
- // kit.Log("error", "%v", t)
- // // // context = append(context, t.target)
- // }
- // }
- // m.target = 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"))
- select {
- case <-time.After(kit.Duration(m.Conf("call_timeout"))):
- m.Log("sync", m.Format("timeout", "result", "append"))
- case <-wait:
- }
- return m
-}
-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) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message {
- if head != nil && len(head) > 0 {
- m.Show(strings.Join(head, " "), "...\n")
- }
-
- for i, v := range suffix {
- m.Show(fmt.Sprintf("%v/%v %v...\n", i+1, len(suffix), v))
- m.CopyFuck(m.Cmd(prefix, v), "append")
- time.Sleep(t)
- }
- m.Show("\n")
- m.Table()
- return m
-}
-func (m *Message) Cmdm(args ...interface{}) *Message {
- m.Log("info", "current: %v", m.Magic("session", "current"))
-
- arg := []string{}
- if pod := kit.Format(m.Magic("session", "current.pod")); pod != "" {
- arg = append(arg, "context", "ssh", "remote", pod)
- }
- if ctx := kit.Format(m.Magic("session", "current.ctx")); ctx != "" {
- arg = append(arg, "context", ctx)
- }
- arg = append(arg, kit.Trans(args...)...)
-
- // 执行命令
- m.Spawn().Cmd(arg).CopyTo(m)
- // m.Magic("session", "current.ctx", msg.target.Name)
- return m
-}
-func (m *Message) Cmdy(args ...interface{}) *Message {
- m.Cmd(args...).CopyTo(m)
- return m
-}
-func (m *Message) Cmdx(args ...interface{}) string {
- msg := m.Cmd(args...)
- if msg.Result(0) == "error: " {
- return msg.Result(1)
- }
- return msg.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:]
-
- msg := m
- if strings.Contains(key, ":") {
- ps := strings.Split(key, ":")
- msg, key, arg = msg.Sess("ssh"), "_route", append([]string{"sync", ps[0], ps[1]}, arg...)
- defer func() { m.Copy(msg, "append").Copy(msg, "result") }()
- m.Hand = true
-
- } else if strings.Contains(key, ".") {
- arg := strings.Split(key, ".")
- msg, key = msg.Sess(arg[0]), arg[1]
- msg.Option("remote_code", "")
- }
- if msg == nil {
- return msg
- }
-
- msg = msg.Match(key, true, func(msg *Message, s *Context, c *Context, key string) bool {
- msg.Hand = false
- if x, ok := c.Commands[key]; ok && x.Hand != nil {
- msg.TryCatch(msg, true, func(msg *Message) {
- msg.Log("cmd", "%s %s %v %v", c.Name, key, arg, msg.Meta["option"])
-
- for _, form := range []map[string]int{map[string]int{"page.limit": 1, "page.offset": 1}, x.Form} {
-
- if args := []string{}; form != nil {
- for i := 0; i < len(arg); i++ {
- if n, ok := form[arg[i]]; ok {
- if n < 0 {
- n += len(arg) - i
- }
- for j := i + 1; j <= i+n && j < len(arg); j++ {
- if _, ok := form[arg[j]]; ok {
- n = j - i - 1
- }
- }
- if i+1+n > len(arg) {
- msg.Add("option", arg[i], arg[i+1:])
- } else {
- msg.Add("option", arg[i], arg[i+1:i+1+n])
- }
- i += n
- } else {
- args = append(args, arg[i])
- }
- }
- arg = args
- }
- }
-
- target := msg.target
- msg.target = s
-
- msg.Hand = true
- switch v := msg.Gdb("command", key, arg).(type) {
- case string:
- msg.Echo(v)
- case nil:
- if msg.Options("auto_cmd") {
- if x.Auto != nil {
- x.Auto(msg, c, key, arg...)
- }
- } else {
- x.Hand(msg, c, key, arg...)
- }
- }
- if msg.target == s {
- msg.target = target
- }
- })
- }
- return msg.Hand
- })
-
- if !msg.Hand {
- msg.Log("error", "cmd run error %s", msg.Format())
- }
- return msg
-}
-
-func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} {
- random := ""
- 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:
- switch arg {
- case "%", "*":
- random, args = arg, args[1:]
- default:
- 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):
- for i, v := range table {
- fun(i, kit.Format(v))
- }
- case func(int, string) bool:
- for i, v := range table {
- if fun(i, kit.Format(v)) {
- break
- }
- }
- case func(string, string):
- for k, v := range value {
- fun(k, kit.Format(v))
- }
- case func(string, string) bool:
- for k, v := range value {
- if fun(k, kit.Format(v)) {
- break
- }
- }
- case func(map[string]interface{}):
- if len(value) == 0 {
- return nil
- }
- fun(value)
- case func(string, map[string]interface{}):
- switch random {
- case "%":
- n, i := rand.Intn(len(value)), 0
- for k, v := range value {
- if val, ok := v.(map[string]interface{}); i == n && ok {
- fun(k, val)
- break
- }
- i++
- }
- case "*":
- fallthrough
- default:
- for k, v := range value {
- if val, ok := v.(map[string]interface{}); ok {
- fun(k, val)
- }
- }
- }
- case func(string, int, map[string]interface{}):
- for k, v := range value {
- if val, ok := v.([]interface{}); ok {
- for i, v := range val {
- if val, ok := v.(map[string]interface{}); ok {
- fun(k, i, val)
- }
- }
- }
- }
-
- case func(string, map[string]interface{}) bool:
- for k, v := range value {
- if val, ok := v.(map[string]interface{}); ok {
- if fun(k, val) {
- break
- }
- }
- }
- case func(int, map[string]interface{}):
- for i := m.Optioni("page.begin"); i < len(table); i++ {
- if val, ok := table[i].(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 = kit.Select(value, arg, args[1])
- } else {
- value = kit.Select(value, arg)
- }
- args = args[1:]
- 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{} {
- if strings.Contains(key, ".") {
- target := m.target
- defer func() { m.target = target }()
-
- ps := strings.Split(key, ".")
- if msg := m.Sess(ps[0], false); msg != nil {
- m.target, key = msg.target, ps[1]
- }
- }
-
- 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/ctx/type.go b/src/contexts/ctx/type.go
index a7b1c8be..4845dd9c 100644
--- a/src/contexts/ctx/type.go
+++ b/src/contexts/ctx/type.go
@@ -1,7 +1,12 @@
package ctx
import (
+ "fmt"
+ "math/rand"
+ "strconv"
+ "strings"
"time"
+ "toolkit"
)
type Cache struct {
@@ -48,6 +53,14 @@ type Server interface {
Start(m *Message, arg ...string) bool
Close(m *Message, arg ...string) bool
}
+
+func (c *Context) Context() *Context {
+ return c.context
+}
+func (c *Context) Message() *Message {
+ return c.message
+}
+
type Message struct {
time time.Time
code int
@@ -55,19 +68,17 @@ type Message struct {
source *Context
target *Context
+ Hand bool
Meta map[string][]string
Data map[string]interface{}
callback func(msg *Message) (sub *Message)
- freedoms []func(msg *Message) (done bool)
+ freeback []func(msg *Message) (done bool)
Sessions map[string]*Message
messages []*Message
message *Message
root *Message
-
- Remote chan bool
- Hand bool
}
type LOGGER interface {
Log(*Message, string, string, ...interface{})
@@ -76,3 +87,789 @@ type DEBUG interface {
Wait(*Message, ...interface{}) interface{}
Goon(interface{}, ...interface{})
}
+
+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])
+ }
+
+ if str == "stamp" {
+ return kit.Format(t.Unix())
+ }
+ 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) 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) 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{}) int64 {
+ i, _ := strconv.ParseInt(m.Append(key, arg...), 10, 64)
+ return i
+}
+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) 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) Table(cbs ...interface{}) *Message {
+ if len(m.Meta["append"]) == 0 {
+ return m
+ }
+
+ // 遍历函数
+ if len(cbs) > 0 {
+ 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]
+ }
+
+ switch cb := cbs[0].(type) {
+ case func(map[string]string):
+ cb(line)
+ case func(map[string]string) bool:
+ if !cb(line) {
+ return m
+ }
+ case func(int, map[string]string):
+ cb(i, line)
+ }
+ }
+ return m
+ }
+
+ //计算列宽
+ space := m.Confx("table_space")
+ 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] = kit.Width(k, len(space))
+ for _, v := range m.Meta[k] {
+ if kit.Width(v, len(space)) > width[k] {
+ width[k] = kit.Width(v, len(space))
+ }
+ }
+ }
+
+ // 回调函数
+ var cb func(maps map[string]string, list []string, line int) (goon bool)
+ if len(cbs) > 0 {
+ cb = cbs[0].(func(maps map[string]string, list []string, line int) (goon bool))
+ } 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]-kit.Width(k, len(space))))
+ }
+ 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]-kit.Width(data, len(space))))
+ }
+ m.Log("fuck", "waht %v", row)
+ if !cb(row, wor, i) {
+ break
+ }
+ }
+
+ return m
+}
+func (m *Message) Sort(key string, arg ...string) *Message {
+ cmp := "str"
+ if len(arg) > 0 {
+ cmp = arg[0]
+ }
+
+ number := map[int]int{}
+ table := []map[string]string{}
+ m.Table(func(index int, line map[string]string) {
+ 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])
+ }
+ })
+
+ 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) Copy(msg *Message, arg ...string) *Message {
+ if msg == nil || m == msg {
+ return m
+ }
+
+ 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 "detail", "result":
+ if len(msg.Meta[meta]) > 0 {
+ m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
+ }
+ case "option", "append":
+ if msg.Meta == nil {
+ msg.Meta = map[string][]string{}
+ }
+ if msg.Meta[meta] == nil {
+ break
+ }
+ 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)
+ } else if v, ok := msg.Meta[arg[i]]; ok {
+ m.Set(meta, arg[i], v) // TODO fuck Add
+ }
+ }
+ 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) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message {
+ if head != nil && len(head) > 0 {
+ m.Show(strings.Join(head, " "), "...\n")
+ }
+
+ for i, v := range suffix {
+ m.Show(fmt.Sprintf("%v/%v %v...\n", i+1, len(suffix), v))
+ m.CopyFuck(m.Cmd(prefix, v), "append")
+ time.Sleep(t)
+ }
+ m.Show("\n")
+ m.Table()
+ return m
+}
+func (m *Message) Cmdm(args ...interface{}) *Message {
+ m.Log("info", "current: %v", m.Magic("session", "current"))
+
+ arg := []string{}
+ if pod := kit.Format(m.Magic("session", "current.pod")); pod != "" {
+ arg = append(arg, "context", "ssh", "remote", pod)
+ }
+ if ctx := kit.Format(m.Magic("session", "current.ctx")); ctx != "" {
+ arg = append(arg, "context", ctx)
+ }
+ arg = append(arg, kit.Trans(args...)...)
+
+ m.Spawn().Cmd(arg).CopyTo(m)
+ return m
+}
+func (m *Message) Cmdy(args ...interface{}) *Message {
+ m.Cmd(args...).CopyTo(m)
+ return m
+}
+func (m *Message) Cmdx(args ...interface{}) string {
+ msg := m.Cmd(args...)
+ if msg.Result(0) == "error: " {
+ return msg.Result(1)
+ }
+ return msg.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:]
+
+ msg := m
+ if strings.Contains(key, ":") {
+ ps := strings.Split(key, ":")
+ msg, key, arg = msg.Sess("ssh"), "_route", append([]string{"sync", ps[0], ps[1]}, arg...)
+ defer func() { m.Copy(msg, "append").Copy(msg, "result") }()
+ m.Hand = true
+
+ } else if strings.Contains(key, ".") {
+ arg := strings.Split(key, ".")
+ msg, key = msg.Sess(arg[0]), arg[1]
+ msg.Option("remote_code", "")
+ }
+ if msg == nil {
+ return msg
+ }
+
+ msg = msg.Match(key, true, func(msg *Message, s *Context, c *Context, key string) bool {
+ msg.Hand = false
+ if x, ok := c.Commands[key]; ok && x.Hand != nil {
+ msg.TryCatch(msg, true, func(msg *Message) {
+ msg.Log("cmd", "%s %s %v %v", c.Name, key, arg, msg.Meta["option"])
+
+ for _, form := range []map[string]int{map[string]int{"page.limit": 1, "page.offset": 1}, x.Form} {
+
+ if args := []string{}; form != nil {
+ for i := 0; i < len(arg); i++ {
+ if n, ok := form[arg[i]]; ok {
+ if n < 0 {
+ n += len(arg) - i
+ }
+ for j := i + 1; j <= i+n && j < len(arg); j++ {
+ if _, ok := form[arg[j]]; ok {
+ n = j - i - 1
+ }
+ }
+ if i+1+n > len(arg) {
+ msg.Add("option", arg[i], arg[i+1:])
+ } else {
+ msg.Add("option", arg[i], arg[i+1:i+1+n])
+ }
+ i += n
+ } else {
+ args = append(args, arg[i])
+ }
+ }
+ arg = args
+ }
+ }
+
+ target := msg.target
+ msg.target = s
+
+ msg.Hand = true
+ switch v := msg.Gdb("command", key, arg).(type) {
+ case string:
+ msg.Echo(v)
+ case nil:
+ if msg.Options("auto_cmd") {
+ if x.Auto != nil {
+ x.Auto(msg, c, key, arg...)
+ }
+ } else {
+ x.Hand(msg, c, key, arg...)
+ }
+ }
+ if msg.target == s {
+ msg.target = target
+ }
+ })
+ }
+ return msg.Hand
+ })
+
+ if !msg.Hand {
+ msg.Log("error", "cmd run error %s", msg.Format())
+ }
+ return msg
+}
+
+func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} {
+ random := ""
+ 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:
+ switch arg {
+ case "%", "*":
+ random, args = arg, args[1:]
+ default:
+ 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):
+ for i, v := range table {
+ fun(i, kit.Format(v))
+ }
+ case func(int, string) bool:
+ for i, v := range table {
+ if fun(i, kit.Format(v)) {
+ break
+ }
+ }
+ case func(string, string):
+ for k, v := range value {
+ fun(k, kit.Format(v))
+ }
+ case func(string, string) bool:
+ for k, v := range value {
+ if fun(k, kit.Format(v)) {
+ break
+ }
+ }
+ case func(map[string]interface{}):
+ if len(value) == 0 {
+ return nil
+ }
+ fun(value)
+ case func(string, map[string]interface{}):
+ switch random {
+ case "%":
+ n, i := rand.Intn(len(value)), 0
+ for k, v := range value {
+ if val, ok := v.(map[string]interface{}); i == n && ok {
+ fun(k, val)
+ break
+ }
+ i++
+ }
+ case "*":
+ fallthrough
+ default:
+ for k, v := range value {
+ if val, ok := v.(map[string]interface{}); ok {
+ fun(k, val)
+ }
+ }
+ }
+ case func(string, int, map[string]interface{}):
+ for k, v := range value {
+ if val, ok := v.([]interface{}); ok {
+ for i, v := range val {
+ if val, ok := v.(map[string]interface{}); ok {
+ fun(k, i, val)
+ }
+ }
+ }
+ }
+
+ case func(string, map[string]interface{}) bool:
+ for k, v := range value {
+ if val, ok := v.(map[string]interface{}); ok {
+ if fun(k, val) {
+ break
+ }
+ }
+ }
+ case func(int, map[string]interface{}):
+ for i := m.Optioni("page.begin"); i < len(table); i++ {
+ if val, ok := table[i].(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 = kit.Select(value, arg, args[1])
+ } else {
+ value = kit.Select(value, arg)
+ }
+ args = args[1:]
+ 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{} {
+ if strings.Contains(key, ".") {
+ target := m.target
+ defer func() { m.target = target }()
+
+ ps := strings.Split(key, ".")
+ if msg := m.Sess(ps[0], false); msg != nil {
+ m.target, key = msg.target, ps[1]
+ }
+ }
+
+ 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/ctx/what.go b/src/contexts/ctx/what.go
new file mode 100644
index 00000000..7675c201
--- /dev/null
+++ b/src/contexts/ctx/what.go
@@ -0,0 +1,660 @@
+package ctx
+
+import (
+ "fmt"
+ "log"
+ "regexp"
+ "runtime"
+ "strings"
+
+ "sort"
+ "toolkit"
+)
+
+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 {
+ if c == nil {
+ return nil
+ }
+ 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 (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("%s:%d(%s->%s)", m.Option("routine"), 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)
+ }
+ }
+
+ meta = append(meta, "\n")
+ for i := len(ms) - 1; i >= 0; i-- {
+ msg := ms[i]
+
+ meta = append(meta, fmt.Sprintf("%s\n", msg.Format("time", "ship")))
+ if len(msg.Meta["detail"]) > 0 {
+ meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
+ }
+ if len(msg.Meta["option"]) > 0 {
+ 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))
+ }
+ }
+ }
+ if len(msg.Meta["append"]) > 0 {
+ 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))
+ }
+ }
+ }
+ if len(msg.Meta["result"]) > 0 {
+ 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(6, 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, "append").Copy(m, "result")
+ return m
+}
+func (m *Message) CopyFuck(msg *Message, arg ...string) *Message {
+ if m == msg {
+ return m
+ }
+
+ 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 "detail", "result":
+ if len(msg.Meta[meta]) > 0 {
+ m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
+ }
+ case "option", "append":
+ if msg.Meta == nil {
+ msg.Meta = map[string][]string{}
+ }
+ if msg.Meta[meta] == nil {
+ break
+ }
+ 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)
+ } else if v, ok := msg.Meta[arg[i]]; ok {
+ m.Add(meta, arg[i], v) // TODO fuck Add
+ }
+ }
+ 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) Auto(arg ...string) *Message {
+ for i := 0; i < len(arg); i += 3 {
+ m.Add("append", "value", arg[i])
+ m.Add("append", "name", arg[i+1])
+ m.Add("append", "help", arg[i+2])
+ }
+ return m
+}
+
+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) Magic(begin string, chain interface{}, args ...interface{}) interface{} {
+ auth := []string{"bench", "session", "user", "role", "componet", "command"}
+ key := []string{"bench", "sessid", "username", "role", "componet", "command"}
+ aaa := m.Sess("aaa", false)
+ for i, v := range auth {
+ if v == begin {
+ h := m.Option(key[i])
+ if v == "user" {
+ h, _ = kit.Hash("username", m.Option("username"))
+ }
+
+ data := aaa.Confv("auth", []string{h, "data"})
+
+ if kit.Format(chain) == "" {
+ return data
+ }
+
+ if len(args) > 0 {
+ value := kit.Chain(data, chain, args[0])
+ aaa.Conf("auth", []string{m.Option(key[i]), "data"}, value)
+ return value
+ }
+
+ value := kit.Chain(data, chain)
+ if value != nil {
+ return value
+ }
+
+ if i < len(auth)-1 {
+ begin = auth[i+1]
+ }
+ }
+ }
+ return nil
+}
+func (m *Message) Current(text string) string {
+ cs := []string{}
+ if pod := kit.Format(m.Magic("session", "current.pod")); pod != "" {
+ cs = append(cs, "context", "ssh", "remote", "'"+pod+"'")
+ }
+ if ctx := kit.Format(m.Magic("session", "current.ctx")); ctx != "" {
+ cs = append(cs, "context", ctx)
+ }
+ if cmd := kit.Format(m.Magic("session", "current.cmd")); cmd != "" {
+ cs = append(cs, cmd)
+ }
+ m.Log("info", "%s %s current %v", m.Option("username"), m.Option("sessid"), cs)
+ cs = append(cs, text)
+ return strings.Join(cs, " ")
+}
+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] == '@' {
+ if v := m.Option(str[1:]); v != "" {
+ return v
+ }
+ if v := kit.Format(m.Magic("bench", str[1:])); v != "" {
+ return v
+ }
+ v := m.Conf(str[1:])
+ return v
+ }
+ return str
+ }
+ return ""
+}
+func (m *Message) ToHTML(style string) string {
+ cmd := strings.Join(m.Meta["detail"], " ")
+ result := []string{}
+ if len(m.Meta["append"]) > 0 {
+ result = append(result, fmt.Sprintf("", style))
+ result = append(result, "", cmd, "")
+ m.Table(func(line int, maps map[string]string) {
+ if line == 0 {
+ result = append(result, "")
+ for _, v := range m.Meta["append"] {
+ result = append(result, "", v, " | ")
+ }
+ result = append(result, "
")
+ return
+ }
+ result = append(result, "")
+ for _, k := range m.Meta["append"] {
+ result = append(result, "", maps[k], " | ")
+ }
+ result = append(result, "
")
+ })
+ result = append(result, "
")
+ } else {
+ result = append(result, "")
+ result = append(result, fmt.Sprintf("%s", m.Find("shy", false).Conf("prompt")), cmd, "\n")
+ result = append(result, m.Meta["result"]...)
+ result = append(result, "
")
+ }
+ return strings.Join(result, "")
+}
+
+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 m.Options("log.disable") {
+ return m
+ }
+
+ 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
+ }
+ } else {
+ log.Printf(str, arg...)
+ }
+
+ 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) Show(args ...interface{}) *Message {
+ if m.Option("cli.modal") == "action" {
+ fmt.Printf(kit.Format(args...))
+ } else if kit.STDIO != nil {
+ kit.STDIO.Show(args...)
+ }
+ return m
+}
+func (m *Message) GoLoop(msg *Message, hand ...func(msg *Message)) *Message {
+ m.Gos(msg, func(msg *Message) {
+ for {
+ 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) 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
+ }
+ }
+
+ if len(root) > 1 && root[1] {
+ m.target = target
+ return m
+ }
+
+ 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) Match(key string, spawn bool, hand func(m *Message, s *Context, c *Context, key string) bool) *Message {
+ if m == nil {
+ return m
+ }
+
+ context := []*Context{m.target}
+ for _, v := range []string{"aaa", "ssh", "cli", "nfs"} {
+ if msg := m.Sess(v, false); msg != nil && msg.target != nil {
+ context = append(context, msg.target)
+ }
+ }
+ // if m.target.root != nil && m.target.root.Configs != nil && m.target.root.Configs["search"] != nil && m.target.root.Configs["search"].Value != nil {
+ // target := m.target
+ // for _, v := range kit.Trans(kit.Chain(m.target.root.Configs["search"].Value, "context")) {
+ // if t := m.Find(v, true, true); t != nil {
+ // kit.Log("error", "%v", t)
+ // // // context = append(context, t.target)
+ // }
+ // }
+ // m.target = 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) Backs(msg *Message) *Message {
+ m.Back(msg)
+ return msg
+}
diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go
index b7c697e8..be3acc37 100644
--- a/src/contexts/nfs/nfs.go
+++ b/src/contexts/nfs/nfs.go
@@ -452,16 +452,13 @@ func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame
}
table = []map[string]string{}
- m.Spawn(auto_target).Cmd(cmd...).Table(func(maps map[string]string, list []string, line int) bool {
- if line >= 0 {
- fields := []interface{}{}
- for _, v := range auto["fields"].([]interface{}) {
- fields = append(fields, maps[kit.Format(v)])
- }
- maps["format"] = fmt.Sprintf(kit.Format(auto["format"]), fields...)
- table = append(table, maps)
+ m.Spawn(auto_target).Cmd(cmd...).Table(func(line int, maps map[string]string) {
+ fields := []interface{}{}
+ for _, v := range auto["fields"].([]interface{}) {
+ fields = append(fields, maps[kit.Format(v)])
}
- return true
+ maps["format"] = fmt.Sprintf(kit.Format(auto["format"]), fields...)
+ table = append(table, maps)
})
m.Conf("term", []interface{}{"help_table", auto["table"]}, table)
@@ -996,14 +993,14 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
if head == "detail" { // 接收请求
msg.Detail(-1, "_route")
msg.Option("remote_code", code)
- m.GoFunc(msg, func(msg *ctx.Message) {
+ m.Gos(msg, func(msg *ctx.Message) {
msg.Call(func(msg *ctx.Message) *ctx.Message {
nfs.echo <- msg
return nil
})
})
} else { // 接收响应
- m.Set("option", "code", code).GoFunc(msg, func(msg *ctx.Message) {
+ m.Set("option", "code", code).Gos(msg, func(msg *ctx.Message) {
if h, ok := nfs.hand[kit.Int(m.Option("code"))]; ok {
h.CopyFuck(msg, "result").CopyFuck(msg, "append").Back(h)
}
@@ -1405,7 +1402,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
for _, from := range arg[1:] {
f, e := os.Open(from)
- m.Assert(e)
+ if e != nil {
+ continue
+ }
defer f.Close()
n, e := io.Copy(to, f)
diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go
index 6c65f292..fa409e06 100644
--- a/src/contexts/ssh/ssh.go
+++ b/src/contexts/ssh/ssh.go
@@ -164,9 +164,10 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
"favor": []interface{}{
map[string]interface{}{"componet_name": "clip", "componet_help": "粘贴板",
"componet_tmpl": "componet", "componet_view": "Context", "componet_init": "",
- "componet_type": "public", "componet_ctx": "aaa", "componet_cmd": "clip",
- "componet_args": []interface{}{}, "inputs": []interface{}{
- map[string]interface{}{"type": "text", "name": "content", "view": "long"},
+ "componet_type": "public", "componet_ctx": "ssh", "componet_cmd": "_route",
+ "componet_args": []interface{}{"$$", "context", "aaa", "clip"}, "inputs": []interface{}{
+ map[string]interface{}{"type": "text", "name": "you", "imports": "plugin_you"},
+ map[string]interface{}{"type": "text", "name": "txt", "view": "long"},
map[string]interface{}{"type": "button", "value": "运行"},
},
},
diff --git a/src/contexts/tcp/tcp.go b/src/contexts/tcp/tcp.go
index 0a199016..cb0d09b1 100644
--- a/src/contexts/tcp/tcp.go
+++ b/src/contexts/tcp/tcp.go
@@ -25,7 +25,7 @@ func (tcp *TCP) Fuck(address []string, action func(address string) (net.Conn, er
for i := 0; i < m.Confi("retry", "counts"); i++ {
for _, p := range address {
m.Cap("address", p)
- m.GoFunc(m, func(m *ctx.Message) {
+ m.Gos(m, func(m *ctx.Message) {
p := m.Cap("address")
if c, e := action(p); e == nil {
tcp.Conn = c
diff --git a/src/examples/app/bench.go b/src/examples/app/bench.go
deleted file mode 100644
index 88f10093..00000000
--- a/src/examples/app/bench.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package main
-
-import (
- // 数据层
- _ "contexts/mdb" //数据中心
- _ "contexts/nfs" //存储中心
- _ "contexts/ssh" //集群中心
- _ "contexts/tcp" //网络中心
- // 控制层
- _ "contexts/gdb" //调试中心
- _ "contexts/lex" //词法中心
- _ "contexts/log" //日志中心
- _ "contexts/yac" //语法中心
- // 服务层
- _ "contexts/aaa" //认证中心
- _ "contexts/cli" //管理中心
- c "contexts/ctx" //模块中心
- _ "contexts/web" //应用中心
-
- // 应用层
- _ "examples/chat" //会议中心
- _ "examples/code" //代码中心
- _ "examples/wiki" //文档中心
- // _ "examples/jira" //任务中心
- // _ "examples/mall" //交易中心
-)
-
-func main() {
- c.Start()
-}
diff --git a/src/examples/app/findgrep.go b/src/examples/app/findgrep.go
deleted file mode 100644
index 286f9f20..00000000
--- a/src/examples/app/findgrep.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package main
-
-import (
- "bufio"
- "fmt"
- "io"
- "os"
- "regexp"
- "toolkit"
-)
-
-var files = ".*\\.(xml|html|css|js)$"
-var words = "[[:^ascii:]]+"
-
-func main() {
- if len(os.Args) == 1 {
- fmt.Println("usage", os.Args[0], "dirs [files [words]]")
- fmt.Println("在目录dirs中,查找匹配files的文件,并查找匹配words的单词")
- os.Exit(1)
- }
-
- if len(os.Args) > 2 {
- files = os.Args[2]
- }
- if len(os.Args) > 3 {
- words = os.Args[3]
- }
-
- word, e := regexp.Compile(words)
- kit.Check(e)
- // out, e := os.Create(os.Args[2])
- // kit.Check(e)
- out := os.Stdout
-
- total := 0
- count := 0
- chars := 0
- kit.DirWalk(os.Args[1], func(file string) {
- s, _ := os.Stat(file)
- if s.IsDir() {
- return
- }
- if m, e := regexp.MatchString(files, file); !kit.Check(e) || !m {
- return
- }
-
- f, e := os.Open(file)
- kit.Check(e)
- bio := bufio.NewReader(f)
-
- fmt.Fprintln(out, kit.FmtSize(s.Size()), file)
- line := 0
-
- cs := 0
- for i := 1; true; i++ {
- l, e := bio.ReadString('\n')
- if e == io.EOF {
- break
- }
- kit.Check(e)
- if i == 1 {
- continue
- }
-
- a := word.FindAllString(l, 20)
- for _, v := range a {
- n := len([]rune(v))
- fmt.Fprintf(out, "l:%d c:%d %s\n", i, n, v)
- total++
- line++
- chars += n
- cs += n
- }
- }
- fmt.Fprintln(out, "lines:", line, "chars:", cs, file)
- fmt.Fprintln(out)
- if line > 0 {
- count++
- }
- })
- fmt.Fprintln(out, "files:", count, "lines:", total, "chars:", chars, os.Args[1])
- return
-}
diff --git a/src/examples/app/test.go b/src/examples/app/test.go
deleted file mode 100644
index cb48c2f3..00000000
--- a/src/examples/app/test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package main
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "io"
- "net/http"
- "os"
- "path"
- "strings"
- "time"
-)
-
-func main() {
- if len(os.Args) < 3 {
- fmt.Printf("usage: %s file server", os.Args[0])
- return
- }
-
- prefix0 := len("uri[")
- prefix1 := len("request_param[")
-
- if os.Mkdir("tmp", 0777) != nil {
- }
-
- begin := time.Now()
- f, e := os.Open(os.Args[1])
- if e != nil {
- fmt.Printf("%s\n", e)
- os.Exit(1)
- }
- defer f.Close()
- bio := bufio.NewScanner(f)
- output := map[string]*os.File{}
- nreq := 0
-
- for bio.Scan() {
- word := strings.Split(bio.Text(), " ")
- if len(word) != 2 {
- continue
- }
- uri := word[0][prefix0:len(word[0])-1]
- arg := word[1][prefix1:len(word[1])-1]
- if output[uri] == nil {
- name := path.Join("tmp", strings.Replace(uri, "/", "_", -1)+".txt")
- f, e = os.Create(name)
- output[uri] = f
- }
- nreq++
- br := bytes.NewReader([]byte(arg))
- fmt.Printf("%d post: %v\n", nreq, os.Args[2]+uri)
- res, e := http.Post(os.Args[2]+uri, "application/json", br)
- fmt.Fprintf(output[uri], uri)
- fmt.Fprintf(output[uri], " arguments:")
- fmt.Fprintf(output[uri], arg)
- fmt.Fprintf(output[uri], " result:")
- if e != nil {
- fmt.Fprintf(output[uri], "%v", e)
- } else if res.StatusCode != http.StatusOK {
- fmt.Fprintf(output[uri], res.Status)
- } else {
- io.Copy(output[uri], res.Body)
- }
- fmt.Fprintf(output[uri], "\n")
- }
- fmt.Printf("nuri: %v nreq: %v cost: %v", len(output), nreq, time.Since(begin))
-}
diff --git a/src/examples/wiki/wiki.go b/src/examples/wiki/wiki.go
index 7cef006b..f33f8ae1 100644
--- a/src/examples/wiki/wiki.go
+++ b/src/examples/wiki/wiki.go
@@ -153,11 +153,10 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
m.Sort(sort_field, sort_order).Table()
m.Target().Configs["wiki_list"].Value = []interface{}{}
- m.Table(func(maps map[string]string, list []string, line int) bool {
- if line > 0 {
+ m.Table(func(line int, maps map[string]string) {
+ if line > 1 {
m.Confv("wiki_list", -2, maps)
}
- return true
})
return
}},
diff --git a/src/toolkit/core.go b/src/toolkit/core.go
new file mode 100644
index 00000000..4b0d40da
--- /dev/null
+++ b/src/toolkit/core.go
@@ -0,0 +1,298 @@
+package kit
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "math/rand"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+)
+
+var DisableLog = false
+
+func Env(key string) {
+ os.Getenv(key)
+}
+func Log(action string, str string, args ...interface{}) {
+ if DisableLog {
+ return
+ }
+
+ if len(args) > 0 {
+ str = fmt.Sprintf(str, args...)
+ }
+ fmt.Fprintf(os.Stderr, "%s: %s\n", action, str)
+}
+func Errorf(str string, args ...interface{}) {
+ Log("error", str, args...)
+}
+func Debugf(str string, args ...interface{}) {
+ Log("debug", str, args...)
+}
+
+func Time(arg ...string) int {
+ if len(arg) == 0 {
+ return Int(time.Now())
+ }
+
+ if len(arg) > 1 {
+ if t, e := time.ParseInLocation(arg[1], arg[0], time.Local); e == nil {
+ return Int(t)
+ }
+ }
+
+ for _, v := range []string{
+ "2006-01-02 15:04:05",
+ "2006-01-02 15:04",
+ "2006-01-02",
+ "2006/01/02",
+ "01-02 15:04",
+ } {
+ if t, e := time.ParseInLocation(v, arg[0], time.Local); e == nil {
+ return Int(t)
+ }
+ }
+ return 0
+}
+func Duration(arg ...string) time.Duration {
+ d, _ := time.ParseDuration(arg[0])
+ return d
+}
+func Hash(arg ...interface{}) (string, []string) {
+ args := []string{}
+ for _, v := range Trans(arg...) {
+ switch v {
+ case "time":
+ args = append(args, Format(time.Now()))
+ case "rand":
+ args = append(args, Format(rand.Int()))
+ case "uniq":
+ args = append(args, Format(time.Now()))
+ args = append(args, Format(rand.Int()))
+ default:
+ if s, e := os.Stat(v); e == nil && !s.IsDir() {
+ if f, e := os.Open(v); e == nil {
+ defer f.Close()
+ m := md5.New()
+ io.Copy(m, f)
+ h := m.Sum(nil)
+ args = append(args, hex.EncodeToString(h[:]))
+ return hex.EncodeToString(h[:]), args
+ }
+ }
+ args = append(args, v)
+ }
+ }
+
+ h := md5.Sum([]byte(strings.Join(args, "")))
+ return hex.EncodeToString(h[:]), args
+}
+func Hashs(arg ...interface{}) string {
+ h, _ := Hash(arg...)
+ return h
+}
+func Chain(root interface{}, args ...interface{}) interface{} {
+ for i := 0; i < len(args); i += 2 {
+ if arg, ok := args[i].(map[string]interface{}); ok {
+ argn := []interface{}{}
+ for k, v := range arg {
+ argn = append(argn, k, v)
+ }
+ argn = append(argn, args[i+1:])
+ args, i = argn, -2
+ continue
+ }
+
+ var parent interface{}
+ parent_key, parent_index := "", 0
+
+ keys := []string{}
+ for _, v := range Trans(args[i]) {
+ keys = append(keys, strings.Split(v, ".")...)
+ }
+
+ data := root
+ for j, key := range keys {
+ index, e := strconv.Atoi(key)
+
+ // Log("error", "chain [%v %v] [%v %v] [%v/%v %v/%v] %v", parent_key, parent_index, key, index, i, len(args), j, len(keys), data)
+
+ var next interface{}
+ switch value := data.(type) {
+ case nil:
+ if i == len(args)-1 {
+ return nil
+ }
+ if j == len(keys)-1 {
+ next = args[i+1]
+ }
+
+ if e == nil {
+ data, index = []interface{}{next}, 0
+ } else {
+ data = map[string]interface{}{key: next}
+ }
+ case []string:
+ index = (index+2+len(value)+2)%(len(value)+2) - 2
+
+ if j == len(keys)-1 {
+ if i == len(args)-1 {
+ if index < 0 {
+ return ""
+ }
+ return value[index]
+ }
+ next = args[i+1]
+ }
+
+ if index == -1 {
+ data, index = append([]string{Format(next)}, value...), 0
+ } else {
+ data, index = append(value, Format(next)), len(value)
+ }
+ next = value[index]
+ case map[string]string:
+ if j == len(keys)-1 {
+ if i == len(args)-1 {
+ return value[key] // 读取数据
+ }
+ value[key] = Format(next) // 修改数据
+ }
+ next = value[key]
+ case map[string]interface{}:
+ if j == len(keys)-1 {
+ if i == len(args)-1 {
+ return value[key] // 读取数据
+ }
+ value[key] = args[i+1] // 修改数据
+ if !Right(args[i+1]) {
+ delete(value, key)
+ }
+ }
+ next = value[key]
+ case []interface{}:
+ index = (index+2+len(value)+2)%(len(value)+2) - 2
+
+ if j == len(keys)-1 {
+ if i == len(args)-1 {
+ if index < 0 {
+ return nil
+ }
+ return value[index] // 读取数据
+ }
+ next = args[i+1] // 修改数据
+ }
+
+ if index == -1 {
+ value, index = append([]interface{}{next}, value...), 0
+ } else if index == -2 {
+ value, index = append(value, next), len(value)
+ } else if j == len(keys)-1 {
+ value[index] = next
+ }
+ data, next = value, value[index]
+ }
+
+ switch p := parent.(type) {
+ case map[string]interface{}:
+ p[parent_key] = data
+ case []interface{}:
+ p[parent_index] = data
+ case nil:
+ root = data
+ }
+
+ parent, data = data, next
+ parent_key, parent_index = key, index
+ }
+ }
+
+ return root
+}
+func Chains(root interface{}, args ...interface{}) string {
+ return Format(Chain(root, args...))
+}
+
+func Select(value string, args ...interface{}) string {
+ if len(args) == 0 {
+ return value
+ }
+
+ switch arg := args[0].(type) {
+ case string:
+ if len(args) > 1 {
+ switch b := args[1].(type) {
+ case bool:
+ if b && arg != "" {
+ return arg
+ }
+ return value
+ }
+ }
+ if arg != "" {
+ return arg
+ }
+ case []interface{}:
+ index := 0
+ if len(args) > 1 {
+ index = Int(args[1])
+ }
+ if index < len(arg) && Format(arg[index]) != "" {
+ return Format(arg[index])
+ }
+ case []string:
+ index := 0
+ if len(args) > 1 {
+ index = Int(args[1])
+ }
+ if index < len(arg) && arg[index] != "" {
+ return arg[index]
+ }
+ default:
+ if v := Format(args...); v != "" {
+ return v
+ }
+ }
+ return value
+}
+func Slice(arg []string, args ...interface{}) ([]string, string) {
+ if len(arg) == 0 {
+ return arg, ""
+ }
+ if len(args) == 0 {
+ return arg[1:], arg[0]
+ }
+
+ result := ""
+ switch v := args[0].(type) {
+ case int:
+ case string:
+ if arg[0] == v && len(arg) > 1 {
+ return arg[2:], arg[1]
+ }
+ if len(args) > 1 {
+ return arg, Format(args[1])
+ }
+ }
+
+ return arg, result
+}
+func View(args []string, conf map[string]interface{}) []string {
+ if len(args) == 0 {
+ args = append(args, "default")
+ }
+
+ keys := []string{}
+ for _, k := range args {
+ if v, ok := conf[k]; ok {
+ keys = append(keys, Trans(v)...)
+ } else {
+ keys = append(keys, k)
+ }
+ }
+ return keys
+}
diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go
deleted file mode 100644
index 4e41526b..00000000
--- a/src/toolkit/kit.go
+++ /dev/null
@@ -1,764 +0,0 @@
-package kit
-
-import (
- "crypto/md5"
- "encoding/hex"
- "encoding/json"
- "fmt"
- "io"
- "strconv"
- "strings"
-
- "io/ioutil"
- "math/rand"
- "os"
- "path"
- "time"
-)
-
-type TERM interface {
- Show(...interface{}) bool
-}
-
-var STDIO TERM
-
-var DisableLog = false
-var EnableDebug = false
-
-func Log(action string, str string, args ...interface{}) {
- if DisableLog {
- return
- }
-
- if len(args) > 0 {
- str = fmt.Sprintf(str, args...)
- }
- fmt.Fprintf(os.Stderr, "%s: %s\n", action, str)
-}
-func Errorf(str string, args ...interface{}) {
- Log("error", str, args...)
-}
-func Debugf(str string, args ...interface{}) {
- Log("debug", str, args...)
-}
-
-func Key(name string) string {
- return strings.Replace(name, ".", "_", -1)
-}
-func Env(key string) {
- os.Getenv(key)
-}
-func Width(str string, mul int) int {
- return len([]rune(str)) + (len(str)-len([]rune(str)))/2/mul
-}
-func Len(arg interface{}) int {
- switch arg := arg.(type) {
- case []interface{}:
- return len(arg)
- case map[string]interface{}:
- return len(arg)
- }
- return 0
-}
-func Int(arg ...interface{}) int {
- result := 0
- for _, v := range arg {
- switch val := v.(type) {
- case int:
- result += val
- case int8:
- result += int(val)
- case int16:
- result += int(val)
- // case int32:
- // result += int(val)
- case int64:
- result += int(val)
- // case uint8:
- // result += int(val)
- case uint16:
- result += int(val)
- case uint32:
- result += int(val)
- case uint64:
- result += int(val)
- case float64:
- result += int(val)
- case byte: // uint8
- result += int(val)
- case rune: // int32
- result += int(val)
- case string:
- if i, e := strconv.Atoi(val); e == nil {
- result += i
- }
- case bool:
- if val {
- result += 1
- }
- case time.Time:
- result += int(val.Unix())
- case []string:
- result += len(val)
- case map[string]string:
- result += len(val)
- case []interface{}:
- result += len(val)
- case map[string]interface{}:
- result += len(val)
- }
- }
- return result
-}
-func Int64(arg ...interface{}) int64 {
- var result int64
- for _, v := range arg {
- switch val := v.(type) {
- case int:
- result += int64(val)
- case int8:
- result += int64(val)
- case int16:
- result += int64(val)
- // case int32:
- // result += int64(val)
- case int64:
- result += int64(val)
- // case uint8:
- // result += int64(val)
- case uint16:
- result += int64(val)
- case uint32:
- result += int64(val)
- case uint64:
- result += int64(val)
- case float64:
- result += int64(val)
- case byte: // uint8
- result += int64(val)
- case rune: // int32
- result += int64(val)
- case string:
- if i, e := strconv.ParseInt(val, 10, 64); e == nil {
- result += i
- }
- case bool:
- if val {
- result += 1
- }
- case time.Time:
- result += int64(val.Unix())
- case []string:
- result += int64(len(val))
- case map[string]string:
- result += int64(len(val))
- case []interface{}:
- result += int64(len(val))
- case map[string]interface{}:
- result += int64(len(val))
- }
- }
- return result
-}
-func Right(arg ...interface{}) bool {
- result := false
- for _, v := range arg {
- switch val := v.(type) {
- case int:
- result = result || val != 0
- case bool:
- result = result || val
- case string:
- switch val {
- case "", "0", "false", "off", "no", "error: ":
- result = result || false
- default:
- result = result || true
- }
- case error:
- result = result || false
- case []string:
- result = result || len(val) > 0
- case map[string]string:
- result = result || len(val) > 0
- case []interface{}:
- result = result || len(val) > 0
- case map[string]interface{}:
- result = result || len(val) > 0
- default:
- result = result || val != nil
- }
- }
- return result
-}
-func Format(arg ...interface{}) string {
- result := []string{}
- for _, v := range arg {
- switch val := v.(type) {
- case nil:
- result = result[:0]
- case int, int8, int16, int32, int64:
- result = append(result, fmt.Sprintf("%d", val))
- case uint, uint8, uint16, uint32, uint64:
- result = append(result, fmt.Sprintf("%d", val))
- case float64:
- result = append(result, fmt.Sprintf("%d", int(val)))
- case bool:
- result = append(result, fmt.Sprintf("%t", val))
- case string:
- result = append(result, val)
- case []byte:
- result = append(result, string(val))
- case []rune:
- result = append(result, string(val))
- case []string:
- result = append(result, val...)
- // case []interface{}:
- //
- // result = append(result, "[")
- // for i, value := range val {
- // result = append(result, Format(value))
- // if i < len(val)-1 {
- // result = append(result, ",")
- // }
- // }
- // result = append(result, "]")
- case time.Time:
- result = append(result, fmt.Sprintf("%s", val.Format("2006-01-02 15:03:04")))
- case *os.File:
- if s, e := val.Stat(); e == nil {
- result = append(result, fmt.Sprintf("%T [name: %s]", v, s.Name()))
- } else {
- result = append(result, fmt.Sprintf("%T", v))
- }
- // case error:
- // result = append(result, fmt.Sprintf("%v", val))
- default:
- if b, e := json.Marshal(val); e == nil {
- result = append(result, string(b))
- }
- }
- }
-
- if len(result) > 1 {
- args := []interface{}{}
- if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n {
- for i := 1; i < n+1; i++ {
- args = append(args, result[i])
- }
- return fmt.Sprintf(result[0], args...) + strings.Join(result[n+1:], "")
- } else if len(result) == n+1 {
- for i := 1; i < len(result); i++ {
- args = append(args, result[i])
- }
- return fmt.Sprintf(result[0], args...)
- }
- }
- return strings.Join(result, "")
-}
-func Simple(str string) string {
- return strings.Replace(strings.TrimSpace(str), "\n", "\\n", -1)
-}
-func Formats(arg ...interface{}) string {
- result := []string{}
- for _, v := range arg {
- switch val := v.(type) {
- // case []interface{}:
- // for _, v := range val {
- // result = append(result, Format(v))
- // }
- default:
- if b, e := json.MarshalIndent(val, "", " "); e == nil {
- result = append(result, string(b))
- } else {
- result = append(result, fmt.Sprintf("%#v", val))
- }
- }
- }
- return strings.Join(result, " ")
-}
-func Trans(arg ...interface{}) []string {
- ls := []string{}
- for _, v := range arg {
- switch val := v.(type) {
- // case *Message:
- // if val.Hand {
- // ls = append(ls, val.Meta["result"]...)
- // } else {
- // ls = append(ls, val.Meta["detail"]...)
- // }
- case nil:
- case []float64:
- for _, v := range val {
- ls = append(ls, fmt.Sprintf("%d", int(v)))
- }
- case []int:
- for _, v := range val {
- ls = append(ls, fmt.Sprintf("%d", v))
- }
- case []bool:
- for _, v := range val {
- ls = append(ls, fmt.Sprintf("%t", v))
- }
- case []string:
- ls = append(ls, val...)
- case map[string]string:
- for k, v := range val {
- ls = append(ls, k, v)
- }
- case map[string]interface{}:
- for k, v := range val {
- ls = append(ls, k, Format(v))
- }
- case []interface{}:
- for _, v := range val {
- ls = append(ls, Format(v))
- }
- default:
- ls = append(ls, Format(val))
- }
- }
- return ls
-}
-func Struct(arg ...interface{}) map[string]interface{} {
- value := map[string]interface{}{}
- if len(arg) == 0 {
- return value
- }
- switch val := arg[0].(type) {
- case map[string]interface{}:
- return val
- case string:
- json.Unmarshal([]byte(val), value)
- }
-
- return value
-}
-func Structm(args ...interface{}) map[string]interface{} {
- value := Struct(args...)
- for _, arg := range args {
- switch val := arg.(type) {
- case func(k string, v string):
- for k, v := range value {
- val(k, Format(v))
- }
- }
- }
- return value
-}
-func Array(list []string, index int, arg ...interface{}) []string {
- if len(arg) == 0 {
- if -1 < index && index < len(list) {
- return []string{list[index]}
- }
- return []string{""}
- }
-
- str := Trans(arg...)
-
- index = (index+2)%(len(list)+2) - 2
- if index == -1 {
- list = append(str, list...)
- } else if index == -2 {
- list = append(list, str...)
- } else {
- if index < -2 {
- index += len(list) + 2
- }
- if index < 0 {
- index = 0
- }
-
- for i := len(list); i < index+len(str); i++ {
- list = append(list, "")
- }
- for i := 0; i < len(str); i++ {
- list[index+i] = str[i]
- }
- }
-
- return list
-}
-func Slice(arg []string, args ...interface{}) ([]string, string) {
- if len(arg) == 0 {
- return arg, ""
- }
- if len(args) == 0 {
- return arg[1:], arg[0]
- }
-
- result := ""
- switch v := args[0].(type) {
- case int:
- case string:
- if arg[0] == v && len(arg) > 1 {
- return arg[2:], arg[1]
- }
- if len(args) > 1 {
- return arg, Format(args[1])
- }
- }
-
- return arg, result
-}
-func Elect(last interface{}, args ...interface{}) string {
- if len(args) > 0 {
- switch arg := args[0].(type) {
- case []string:
- index := 0
- if len(args) > 1 {
- switch a := args[1].(type) {
- case string:
- i, e := strconv.Atoi(a)
- if e == nil {
- index = i
- }
- case int:
- index = a
- }
- }
-
- if 0 <= index && index < len(arg) && arg[index] != "" {
- return arg[index]
- }
- case string:
- if arg != "" {
- return arg
- }
- }
- }
-
- switch l := last.(type) {
- case string:
- return l
- }
- return ""
-}
-func Select(value string, args ...interface{}) string {
- if len(args) == 0 {
- return value
- }
-
- switch arg := args[0].(type) {
- case string:
- if len(args) > 1 {
- switch b := args[1].(type) {
- case bool:
- if b && arg != "" {
- return arg
- }
- return value
- }
- }
- if arg != "" {
- return arg
- }
- case []interface{}:
- index := 0
- if len(args) > 1 {
- index = Int(args[1])
- }
- if index < len(arg) && Format(arg[index]) != "" {
- return Format(arg[index])
- }
- case []string:
- index := 0
- if len(args) > 1 {
- index = Int(args[1])
- }
- if index < len(arg) && arg[index] != "" {
- return arg[index]
- }
- default:
- if v := Format(args...); v != "" {
- return v
- }
- }
- return value
-}
-func Chain(root interface{}, args ...interface{}) interface{} {
- for i := 0; i < len(args); i += 2 {
- if arg, ok := args[i].(map[string]interface{}); ok {
- argn := []interface{}{}
- for k, v := range arg {
- argn = append(argn, k, v)
- }
- argn = append(argn, args[i+1:])
- args, i = argn, -2
- continue
- }
-
- var parent interface{}
- parent_key, parent_index := "", 0
-
- keys := []string{}
- for _, v := range Trans(args[i]) {
- keys = append(keys, strings.Split(v, ".")...)
- }
-
- data := root
- for j, key := range keys {
- index, e := strconv.Atoi(key)
-
- // Log("error", "chain [%v %v] [%v %v] [%v/%v %v/%v] %v", parent_key, parent_index, key, index, i, len(args), j, len(keys), data)
-
- var next interface{}
- switch value := data.(type) {
- case nil:
- if i == len(args)-1 {
- return nil
- }
- if j == len(keys)-1 {
- next = args[i+1]
- }
-
- if e == nil {
- data, index = []interface{}{next}, 0
- } else {
- data = map[string]interface{}{key: next}
- }
- case []string:
- index = (index+2+len(value)+2)%(len(value)+2) - 2
-
- if j == len(keys)-1 {
- if i == len(args)-1 {
- if index < 0 {
- return ""
- }
- return value[index]
- }
- next = args[i+1]
- }
-
- if index == -1 {
- data, index = append([]string{Format(next)}, value...), 0
- } else {
- data, index = append(value, Format(next)), len(value)
- }
- next = value[index]
- case map[string]string:
- if j == len(keys)-1 {
- if i == len(args)-1 {
- return value[key] // 读取数据
- }
- value[key] = Format(next) // 修改数据
- }
- next = value[key]
- case map[string]interface{}:
- if j == len(keys)-1 {
- if i == len(args)-1 {
- return value[key] // 读取数据
- }
- value[key] = args[i+1] // 修改数据
- if !Right(args[i+1]) {
- delete(value, key)
- }
- }
- next = value[key]
- case []interface{}:
- index = (index+2+len(value)+2)%(len(value)+2) - 2
-
- if j == len(keys)-1 {
- if i == len(args)-1 {
- if index < 0 {
- return nil
- }
- return value[index] // 读取数据
- }
- next = args[i+1] // 修改数据
- }
-
- if index == -1 {
- value, index = append([]interface{}{next}, value...), 0
- } else if index == -2 {
- value, index = append(value, next), len(value)
- } else if j == len(keys)-1 {
- value[index] = next
- }
- data, next = value, value[index]
- }
-
- switch p := parent.(type) {
- case map[string]interface{}:
- p[parent_key] = data
- case []interface{}:
- p[parent_index] = data
- case nil:
- root = data
- }
-
- parent, data = data, next
- parent_key, parent_index = key, index
- }
- }
-
- return root
-}
-func Chains(root interface{}, args ...interface{}) string {
- return Format(Chain(root, args...))
-}
-
-func View(args []string, conf map[string]interface{}) []string {
- if len(args) == 0 {
- args = append(args, "default")
- }
-
- keys := []string{}
- for _, k := range args {
- if v, ok := conf[k]; ok {
- keys = append(keys, Trans(v)...)
- } else {
- keys = append(keys, k)
- }
- }
- return keys
-}
-
-func Link(name string, url string) string {
- return fmt.Sprintf("%s", url, name)
-}
-func Time(arg ...string) int {
- if len(arg) == 0 {
- return Int(time.Now())
- }
-
- if len(arg) > 1 {
- if t, e := time.ParseInLocation(arg[1], arg[0], time.Local); e == nil {
- return Int(t)
- }
- }
-
- for _, v := range []string{
- "2006-01-02 15:04:05",
- "2006-01-02 15:04",
- "2006-01-02",
- "2006/01/02",
- "01-02 15:04",
- } {
- if t, e := time.ParseInLocation(v, arg[0], time.Local); e == nil {
- return Int(t)
- }
- }
- return 0
-}
-func Duration(arg ...string) time.Duration {
- d, _ := time.ParseDuration(arg[0])
- return d
-}
-func FileName(name string, meta ...string) string {
- result, app := strings.Split(name, "."), ""
- if len(result) > 1 {
- app, result = result[len(result)-1], result[:len(result)-1]
- }
-
- for _, v := range meta {
- switch v {
- case "year":
- result = append(result, "_", time.Now().Format("2006"))
- case "date":
- result = append(result, "_", time.Now().Format("0102"))
- case "time":
- result = append(result, "_", time.Now().Format("2006_0102_1504"))
- case "rand":
- result = append(result, "_", Format(rand.Int()))
- case "uniq":
- result = append(result, "_", Format(Time()))
- result = append(result, "_", Format(rand.Int()))
- }
- }
-
- if app != "" {
- result = append(result, ".", app)
- }
- return strings.Join(result, "")
-}
-func FmtSize(size uint64) string {
- if size > 1<<30 {
- return fmt.Sprintf("%d.%dG", size>>30, (size>>20)%1024*100/1024)
- }
-
- if size > 1<<20 {
- return fmt.Sprintf("%d.%dM", size>>20, (size>>10)%1024*100/1024)
- }
-
- if size > 1<<10 {
- return fmt.Sprintf("%d.%dK", size>>10, size%1024*100/1024)
- }
-
- return fmt.Sprintf("%dB", size)
-}
-func FmtNano(nano int64) string {
- if nano > 1000000000 {
- return fmt.Sprintf("%d.%ds", nano/1000000000, nano/100000000%100)
- }
-
- if nano > 1000000 {
- return fmt.Sprintf("%d.%dms", nano/100000, nano/100000%100)
- }
-
- if nano > 1000 {
- return fmt.Sprintf("%d.%dus", nano/1000, nano/100%100)
- }
-
- return fmt.Sprintf("%dns", nano)
-}
-
-func Hash(arg ...interface{}) (string, []string) {
- args := []string{}
- for _, v := range Trans(arg...) {
- switch v {
- case "time":
- args = append(args, Format(time.Now()))
- case "rand":
- args = append(args, Format(rand.Int()))
- case "uniq":
- args = append(args, Format(time.Now()))
- args = append(args, Format(rand.Int()))
- default:
- if s, e := os.Stat(v); e == nil && !s.IsDir() {
- if f, e := os.Open(v); e == nil {
- defer f.Close()
- m := md5.New()
- io.Copy(m, f)
- h := m.Sum(nil)
- args = append(args, hex.EncodeToString(h[:]))
- return hex.EncodeToString(h[:]), args
- }
- }
- args = append(args, v)
- }
- }
-
- h := md5.Sum([]byte(strings.Join(args, "")))
- return hex.EncodeToString(h[:]), args
-}
-func Hashs(arg ...interface{}) string {
- h, _ := Hash(arg...)
- return h
-}
-
-func Block(root interface{}, args ...interface{}) interface{} {
-
- return root
-}
-
-func Check(e error) bool {
- if e != nil {
- panic(e)
- }
- return true
-}
-func DirWalk(file string, hand func(file string)) {
- s, e := os.Stat(file)
- Check(e)
- hand(file)
-
- if s.IsDir() {
- fs, e := ioutil.ReadDir(file)
- Check(e)
-
- for _, v := range fs {
- DirWalk(path.Join(file, v.Name()), hand)
- }
- }
-}
diff --git a/src/toolkit/type.go b/src/toolkit/type.go
new file mode 100644
index 00000000..049f2987
--- /dev/null
+++ b/src/toolkit/type.go
@@ -0,0 +1,246 @@
+package kit
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func Right(arg ...interface{}) bool {
+ result := false
+ for _, v := range arg {
+ switch val := v.(type) {
+ case int:
+ result = result || val != 0
+ case bool:
+ result = result || val
+ case string:
+ switch val {
+ case "", "0", "false", "off", "no", "error: ":
+ result = result || false
+ default:
+ result = result || true
+ }
+ case error:
+ result = result || false
+ case []string:
+ result = result || len(val) > 0
+ case map[string]string:
+ result = result || len(val) > 0
+ case []interface{}:
+ result = result || len(val) > 0
+ case map[string]interface{}:
+ result = result || len(val) > 0
+ default:
+ result = result || val != nil
+ }
+ }
+ return result
+}
+func Int64(arg ...interface{}) int64 {
+ var result int64
+ for _, v := range arg {
+ switch val := v.(type) {
+ case int:
+ result += int64(val)
+ case int8:
+ result += int64(val)
+ case int16:
+ result += int64(val)
+ // case int32:
+ // result += int64(val)
+ case int64:
+ result += int64(val)
+ // case uint8:
+ // result += int64(val)
+ case uint16:
+ result += int64(val)
+ case uint32:
+ result += int64(val)
+ case uint64:
+ result += int64(val)
+ case float64:
+ result += int64(val)
+ case byte: // uint8
+ result += int64(val)
+ case rune: // int32
+ result += int64(val)
+ case string:
+ if i, e := strconv.ParseInt(val, 10, 64); e == nil {
+ result += i
+ }
+ case bool:
+ if val {
+ result += 1
+ }
+ case time.Time:
+ result += int64(val.Unix())
+ case []string:
+ result += int64(len(val))
+ case map[string]string:
+ result += int64(len(val))
+ case []interface{}:
+ result += int64(len(val))
+ case map[string]interface{}:
+ result += int64(len(val))
+ }
+ }
+ return result
+}
+func Int(arg ...interface{}) int {
+ return int(Int64(arg...))
+}
+func Key(name string) string {
+ return strings.Replace(name, ".", "_", -1)
+}
+func Format(arg ...interface{}) string {
+ result := []string{}
+ for _, v := range arg {
+ switch val := v.(type) {
+ case nil:
+ result = result[:0]
+ case int, int8, int16, int32, int64:
+ result = append(result, fmt.Sprintf("%d", val))
+ case uint, uint8, uint16, uint32, uint64:
+ result = append(result, fmt.Sprintf("%d", val))
+ case float64:
+ result = append(result, fmt.Sprintf("%d", int(val)))
+ case bool:
+ result = append(result, fmt.Sprintf("%t", val))
+ case string:
+ result = append(result, val)
+ case []byte:
+ result = append(result, string(val))
+ case []rune:
+ result = append(result, string(val))
+ case []string:
+ result = append(result, val...)
+ // case []interface{}:
+ //
+ // result = append(result, "[")
+ // for i, value := range val {
+ // result = append(result, Format(value))
+ // if i < len(val)-1 {
+ // result = append(result, ",")
+ // }
+ // }
+ // result = append(result, "]")
+ case time.Time:
+ result = append(result, fmt.Sprintf("%s", val.Format("2006-01-02 15:03:04")))
+ case *os.File:
+ if s, e := val.Stat(); e == nil {
+ result = append(result, fmt.Sprintf("%T [name: %s]", v, s.Name()))
+ } else {
+ result = append(result, fmt.Sprintf("%T", v))
+ }
+ // case error:
+ // result = append(result, fmt.Sprintf("%v", val))
+ default:
+ if b, e := json.Marshal(val); e == nil {
+ result = append(result, string(b))
+ }
+ }
+ }
+
+ if len(result) > 1 {
+ args := []interface{}{}
+ if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n {
+ for i := 1; i < n+1; i++ {
+ args = append(args, result[i])
+ }
+ return fmt.Sprintf(result[0], args...) + strings.Join(result[n+1:], "")
+ } else if len(result) == n+1 {
+ for i := 1; i < len(result); i++ {
+ args = append(args, result[i])
+ }
+ return fmt.Sprintf(result[0], args...)
+ }
+ }
+ return strings.Join(result, "")
+}
+func Formats(arg ...interface{}) string {
+ result := []string{}
+ for _, v := range arg {
+ switch val := v.(type) {
+ default:
+ if b, e := json.MarshalIndent(val, "", " "); e == nil {
+ result = append(result, string(b))
+ } else {
+ result = append(result, fmt.Sprintf("%#v", val))
+ }
+ }
+ }
+ return strings.Join(result, " ")
+}
+func Trans(arg ...interface{}) []string {
+ ls := []string{}
+ for _, v := range arg {
+ switch val := v.(type) {
+ // case *Message:
+ // if val.Hand {
+ // ls = append(ls, val.Meta["result"]...)
+ // } else {
+ // ls = append(ls, val.Meta["detail"]...)
+ // }
+ case nil:
+ case []float64:
+ for _, v := range val {
+ ls = append(ls, fmt.Sprintf("%d", int(v)))
+ }
+ case []int:
+ for _, v := range val {
+ ls = append(ls, fmt.Sprintf("%d", v))
+ }
+ case []bool:
+ for _, v := range val {
+ ls = append(ls, fmt.Sprintf("%t", v))
+ }
+ case []string:
+ ls = append(ls, val...)
+ case map[string]string:
+ for k, v := range val {
+ ls = append(ls, k, v)
+ }
+ case map[string]interface{}:
+ for k, v := range val {
+ ls = append(ls, k, Format(v))
+ }
+ case []interface{}:
+ for _, v := range val {
+ ls = append(ls, Format(v))
+ }
+ default:
+ ls = append(ls, Format(val))
+ }
+ }
+ return ls
+}
+func Struct(arg ...interface{}) map[string]interface{} {
+ value := map[string]interface{}{}
+ if len(arg) == 0 {
+ return value
+ }
+ switch val := arg[0].(type) {
+ case map[string]interface{}:
+ return val
+ case string:
+ json.Unmarshal([]byte(val), value)
+ }
+
+ return value
+}
+func Structm(args ...interface{}) map[string]interface{} {
+ value := Struct(args...)
+ for _, arg := range args {
+ switch val := arg.(type) {
+ case func(k string, v string):
+ for k, v := range value {
+ val(k, Format(v))
+ }
+ }
+ }
+ return value
+}
diff --git a/src/toolkit/what.go b/src/toolkit/what.go
new file mode 100644
index 00000000..d7bd9694
--- /dev/null
+++ b/src/toolkit/what.go
@@ -0,0 +1,190 @@
+package kit
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "path"
+ "time"
+)
+
+type TERM interface {
+ Show(...interface{}) bool
+}
+
+var STDIO TERM
+
+var EnableDebug = false
+
+func Width(str string, mul int) int {
+ return len([]rune(str)) + (len(str)-len([]rune(str)))/2/mul
+}
+func Len(arg interface{}) int {
+ switch arg := arg.(type) {
+ case []interface{}:
+ return len(arg)
+ case map[string]interface{}:
+ return len(arg)
+ }
+ return 0
+}
+func Simple(str string) string {
+ return strings.Replace(strings.TrimSpace(str), "\n", "\\n", -1)
+}
+func Array(list []string, index int, arg ...interface{}) []string {
+ if len(arg) == 0 {
+ if -1 < index && index < len(list) {
+ return []string{list[index]}
+ }
+ return []string{""}
+ }
+
+ str := Trans(arg...)
+
+ index = (index+2)%(len(list)+2) - 2
+ if index == -1 {
+ list = append(str, list...)
+ } else if index == -2 {
+ list = append(list, str...)
+ } else {
+ if index < -2 {
+ index += len(list) + 2
+ }
+ if index < 0 {
+ index = 0
+ }
+
+ for i := len(list); i < index+len(str); i++ {
+ list = append(list, "")
+ }
+ for i := 0; i < len(str); i++ {
+ list[index+i] = str[i]
+ }
+ }
+
+ return list
+}
+func Elect(last interface{}, args ...interface{}) string {
+ if len(args) > 0 {
+ switch arg := args[0].(type) {
+ case []string:
+ index := 0
+ if len(args) > 1 {
+ switch a := args[1].(type) {
+ case string:
+ i, e := strconv.Atoi(a)
+ if e == nil {
+ index = i
+ }
+ case int:
+ index = a
+ }
+ }
+
+ if 0 <= index && index < len(arg) && arg[index] != "" {
+ return arg[index]
+ }
+ case string:
+ if arg != "" {
+ return arg
+ }
+ }
+ }
+
+ switch l := last.(type) {
+ case string:
+ return l
+ }
+ return ""
+}
+
+func Link(name string, url string) string {
+ return fmt.Sprintf("%s", url, name)
+}
+func FileName(name string, meta ...string) string {
+ result, app := strings.Split(name, "."), ""
+ if len(result) > 1 {
+ app, result = result[len(result)-1], result[:len(result)-1]
+ }
+
+ for _, v := range meta {
+ switch v {
+ case "year":
+ result = append(result, "_", time.Now().Format("2006"))
+ case "date":
+ result = append(result, "_", time.Now().Format("0102"))
+ case "time":
+ result = append(result, "_", time.Now().Format("2006_0102_1504"))
+ case "rand":
+ result = append(result, "_", Format(rand.Int()))
+ case "uniq":
+ result = append(result, "_", Format(Time()))
+ result = append(result, "_", Format(rand.Int()))
+ }
+ }
+
+ if app != "" {
+ result = append(result, ".", app)
+ }
+ return strings.Join(result, "")
+}
+func FmtSize(size uint64) string {
+ if size > 1<<30 {
+ return fmt.Sprintf("%d.%dG", size>>30, (size>>20)%1024*100/1024)
+ }
+
+ if size > 1<<20 {
+ return fmt.Sprintf("%d.%dM", size>>20, (size>>10)%1024*100/1024)
+ }
+
+ if size > 1<<10 {
+ return fmt.Sprintf("%d.%dK", size>>10, size%1024*100/1024)
+ }
+
+ return fmt.Sprintf("%dB", size)
+}
+func FmtNano(nano int64) string {
+ if nano > 1000000000 {
+ return fmt.Sprintf("%d.%ds", nano/1000000000, nano/100000000%100)
+ }
+
+ if nano > 1000000 {
+ return fmt.Sprintf("%d.%dms", nano/100000, nano/100000%100)
+ }
+
+ if nano > 1000 {
+ return fmt.Sprintf("%d.%dus", nano/1000, nano/100%100)
+ }
+
+ return fmt.Sprintf("%dns", nano)
+}
+
+func Block(root interface{}, args ...interface{}) interface{} {
+
+ return root
+}
+
+func Check(e error) bool {
+ if e != nil {
+ panic(e)
+ }
+ return true
+}
+func DirWalk(file string, hand func(file string)) {
+ s, e := os.Stat(file)
+ Check(e)
+ hand(file)
+
+ if s.IsDir() {
+ fs, e := ioutil.ReadDir(file)
+ Check(e)
+
+ for _, v := range fs {
+ DirWalk(path.Join(file, v.Name()), hand)
+ }
+ }
+}
diff --git a/usr/librarys/wiki.js b/usr/librarys/wiki.js
index 4841fb1f..40de6817 100644
--- a/usr/librarys/wiki.js
+++ b/usr/librarys/wiki.js
@@ -123,6 +123,8 @@ var page = Page({
page.onlayout()
})
+ ctx.Search("layout") == "max" && (page.Conf("tree.display", "none"), page.Conf("menu.display", "none"))
+
ctx.Runs(page, form, function(msg) {
ui.menu.innerHTML = "", ui.text.innerHTML = msg.result? msg.result.join(""): ""
kit.AppendChild(ui.menu, [{"tree": kit.OrderText(field, ui.text)}])
@@ -144,6 +146,10 @@ var page = Page({
case "tree":
page.tree.Pane.Tree()
break
+ case "title":
+ ctx.Search("layout", ctx.Search("layout")? "": "max")
+ break
+
default:
page.confirm("logout?") && page.login.Pane.Exit()
}
diff --git a/usr/wiki/自然/编程/终端工具链/golang.md b/usr/wiki/自然/编程/终端工具链/golang.md
index b0972d36..77d146c8 100644
--- a/usr/wiki/自然/编程/终端工具链/golang.md
+++ b/usr/wiki/自然/编程/终端工具链/golang.md
@@ -1,11 +1,113 @@
## golang
-- 官网:
-- 文档:
+- 官网:
+- 下载:
+- 文档:
- 源码:
-- 开源:
+- 开源:
-## 基本命令
+bash tmux golang git vim
+
+## 命令
+
+```
+env help version
+run test install
+get list
+```
+
+## 文件
+```
+package
+import
+const
+type
+func
+var
+```
+
+## 语句
+```
+if else for range break continue
+switch case default fallthrough
+defer recover panic
+goto return
+go select
+```
+
+## 表达式
+```
+//
+```
+```
+0 iota true false nil "" '' ``
+
+int float
+bool error
+rune string
+byte uintptr
+
+interface struct
+map chan
+
+make len cap
+append copy delete close
+new complex real imag
+```
+
+## 官方包
+```
+os flag path time
+io bufio
+fmt
+sync
+
+math
+bytes
+image
+unicode
+strings
+strconv
+
+net
+log
+```
+
+io fmt log net bufio bytes database
+os flag time path errors syscall plugin
+runtime context sync expvar testing debug reflect unsafe
+math hash crypto sort container index
+unicode strings strconv regexp
+encoding archive compress
+mime text html image
+
+go/ast
+go/build
+go/constant
+go/doc
+go/format
+go/importer
+go/internal/gccgoimporter
+go/internal/gcimporter
+go/internal/srcimporter
+go/parser
+go/printer
+go/scanner
+go/token
+go/types
+internal/bytealg
+internal/cpu
+internal/nettrace
+internal/poll
+internal/race
+internal/singleflight
+internal/syscall/unix
+internal/syscall/windows
+internal/syscall/windows/registry
+internal/syscall/windows/sysdll
+internal/testenv
+internal/testlog
+internal/trace
```
run clean build install
fmt fix vet bug
@@ -13,6 +115,7 @@ mod get doc list
env help version
test tool generate
```
+
## 编译过程
```
main() // cmd/compile/main.go:40