From abdf1711bb9d9951bac1a004cc28b5bff4be4351 Mon Sep 17 00:00:00 2001 From: shylinux Date: Sun, 30 Jun 2019 13:37:11 +0800 Subject: [PATCH] opt context --- Makefile | 2 +- bin/boot.sh | 4 +- src/contexts/aaa/aaa.go | 11 +- src/contexts/cli/cli.go | 55 +- src/contexts/cli/version.go | 2 +- src/contexts/ctx/cgi.go | 12 +- src/contexts/ctx/core.go | 391 +++++ src/contexts/ctx/shy.go | 1859 ----------------------- src/contexts/ctx/type.go | 805 +++++++++- src/contexts/ctx/what.go | 660 ++++++++ src/contexts/nfs/nfs.go | 23 +- src/contexts/ssh/ssh.go | 7 +- src/contexts/tcp/tcp.go | 2 +- src/examples/app/bench.go | 30 - src/examples/app/findgrep.go | 83 - src/examples/app/test.go | 68 - src/examples/wiki/wiki.go | 5 +- src/toolkit/core.go | 298 ++++ src/toolkit/kit.go | 764 ---------- src/toolkit/type.go | 246 +++ src/toolkit/what.go | 190 +++ usr/librarys/wiki.js | 6 + usr/wiki/自然/编程/终端工具链/golang.md | 111 +- 23 files changed, 2764 insertions(+), 2870 deletions(-) create mode 100644 src/contexts/ctx/core.go delete mode 100644 src/contexts/ctx/shy.go create mode 100644 src/contexts/ctx/what.go delete mode 100644 src/examples/app/bench.go delete mode 100644 src/examples/app/findgrep.go delete mode 100644 src/examples/app/test.go create mode 100644 src/toolkit/core.go delete mode 100644 src/toolkit/kit.go create mode 100644 src/toolkit/type.go create mode 100644 src/toolkit/what.go 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, "") - 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, "") } result = append(result, "") - return true } result = append(result, "") - for _, v := range list { - result = append(result, "") + for _, k := range cli.Meta["append"] { + result = append(result, "") } result = append(result, "") - return true }) result = append(result, "
", cmd, "
", v, "
", v, "", maps[k], "
") } 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, "") - 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, "") - } - result = append(result, "") - return true - } - result = append(result, "") - for _, v := range list { - result = append(result, "") - } - result = append(result, "") - return true - }) - result = append(result, "
", cmd, "
", v, "
", v, "
") - } else { - result = append(result, "
")
-		result = append(result, fmt.Sprintf("%s", 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, "") + m.Table(func(line int, maps map[string]string) { + if line == 0 { + result = append(result, "") + for _, v := range m.Meta["append"] { + result = append(result, "") + } + result = append(result, "") + return + } + result = append(result, "") + for _, k := range m.Meta["append"] { + result = append(result, "") + } + result = append(result, "") + }) + result = append(result, "
", cmd, "
", v, "
", maps[k], "
") + } 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