diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go index 32e15bf1..c3442b42 100644 --- a/src/contexts/aaa/aaa.go +++ b/src/contexts/aaa/aaa.go @@ -20,6 +20,7 @@ import ( "os" "strings" "time" + "toolkit" ) type AAA struct { @@ -125,7 +126,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", "key": &ctx.Config{Name: "key", Value: "etc/pem/key.pem", Help: "私钥文件"}, }, Commands: map[string]*ctx.Command{ - "hash": &ctx.Command{Name: "hash type data... time rand", Help: "数字摘要", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "hash": &ctx.Command{Name: "hash type data... time rand", Help: "数字摘要", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Cmdy("ctx.config", "hash") return @@ -159,8 +160,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Log("info", "%s: %v", hs, meta) m.Confv("hash", hs, meta) m.Echo(hs) + return }}, - "auth": &ctx.Command{Name: "auth [id] [[ship] type [meta]] [[data] key [val]] [[node] key [val]]", Help: "权限区块链", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "auth": &ctx.Command{Name: "auth [id] [[ship] type [meta]] [[data] key [val]] [[node] key [val]]", Help: "权限区块链", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { // 节点列表 m.Confm("auth", func(key string, node map[string]interface{}) { up := false @@ -446,8 +448,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", for _, c := range chain { // 添加链接 m.Confv("auth", []interface{}{c["node"], "ship", c["hash"]}, map[string]interface{}{"ship": c["ship"], "type": c["type"], "meta": c["meta"]}) } + return }}, - "role": &ctx.Command{Name: "role [name [[componet] componet [[command] command]]]", Help: "用户角色", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "role": &ctx.Command{Name: "role [name [[componet] componet [[command] command]]]", Help: "用户角色", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch len(arg) { case 0: m.Cmdy("aaa.auth", "ship", "userrole") @@ -469,8 +472,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } } } + return }}, - "user": &ctx.Command{Name: "user [role username password] [username]", Help: "用户认证", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "user": &ctx.Command{Name: "user [role username password] [username]", Help: "用户认证", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch len(arg) { case 0: m.Cmdy("aaa.auth", "ship", "username") @@ -489,8 +493,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } } } + return }}, - "sess": &ctx.Command{Name: "sess [sessid [username]]", Help: "会话管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "sess": &ctx.Command{Name: "sess [sessid [username]]", Help: "会话管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch len(arg) { case 0: m.Cmdy("aaa.auth", "ship", "session") @@ -520,8 +525,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } m.Cmdy("aaa.auth", arg[0], "ship", "username", arg[1], arg[2], arg[3]) } + return }}, - "work": &ctx.Command{Name: "work [sessid create|select]|[benchid] [right [userrole [componet name [command name [argument name]]]]]", Help: "工作任务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "work": &ctx.Command{Name: "work [sessid create|select]|[benchid] [right [userrole [componet name [command name [argument name]]]]]", Help: "工作任务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Cmdy("aaa.auth", "ship", "bench") return @@ -589,7 +595,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Echo("true") return false } - if cid := m.Cmdx("aaa.auth", bid, "ship", "userrole", userrole, "componet", arg[3], "check", arg[5]); ctx.Right(cid) { + if cid := m.Cmdx("aaa.auth", bid, "ship", "userrole", userrole, "componet", arg[3], "check", arg[5]); kit.Right(cid) { m.Cmd("aaa.auth", bid, cid) m.Echo("true") return false @@ -599,7 +605,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Echo("true") return false } - if cid := m.Cmdx("aaa.auth", bid, "ship", "userrole", userrole, "check", arg[3]); ctx.Right(cid) { + if cid := m.Cmdx("aaa.auth", bid, "ship", "userrole", userrole, "check", arg[3]); kit.Right(cid) { m.Cmd("aaa.auth", bid, cid) m.Echo("true") return false @@ -611,13 +617,14 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", default: m.Cmdx("aaa.auth", bid, "data", arg) } + return }}, "login": &ctx.Command{Name: "login [sessid]|[username password]", Form: map[string]int{"ip": 1, "openid": 1, "cert": 1, "pub": 1, "key": 1}, Help: []string{"会话管理", "sessid: 令牌", "username: 账号", "password: 密码", "ip: 主机地址", "openid: 微信登录", "cert: 证书", "pub: 公钥", "key: 私钥"}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := c.Server.(*AAA); m.Assert(ok) { method := "" for _, v := range []string{"ip", "openid", "cert", "pub", "key"} { @@ -626,7 +633,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } } if method != "" { - m.Travel(func(m *ctx.Message, n int) bool { + c.Travel(m, func(m *ctx.Message, n int) bool { if n > 0 && m.Cap("method") == method { switch method { case "ip", "openid": @@ -643,8 +650,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } } } - return true - }, c) + return false + }) if m.Results(0) { return @@ -657,15 +664,15 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", switch len(arg) { case 2: - m.Travel(func(m *ctx.Message, n int) bool { + c.Travel(m, func(m *ctx.Message, n int) bool { if n > 0 && m.Cap("method") == "password" && m.Cap("stream") == arg[0] { m.Assert(m.Cap("password") == Password(arg[1])) m.Cap("expire_time", fmt.Sprintf("%d", time.Now().Unix()+int64(m.Confi("expire")))) m.Echo(m.Cap("sessid")) return false } - return true - }, c) + return false + }) if m.Results(0) { m.Append("sessid", m.Result(0)) @@ -690,7 +697,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", return case 1: m.Sess("login", nil) - m.Travel(func(m *ctx.Message, n int) bool { + c.Travel(m, func(m *ctx.Message, n int) bool { if n > 0 && m.Cap("sessid") == arg[0] { if int64(m.Capi("expire_time")) > time.Now().Unix() { m.Sess("login", m.Target().Message()) @@ -703,21 +710,22 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", return false } return true - }, c) + }) case 0: - m.Travel(func(m *ctx.Message, n int) bool { + c.Travel(m, func(m *ctx.Message, n int) bool { if n > 0 { m.Add("append", "method", m.Cap("method")) m.Add("append", "stream", m.Cap("stream")) } - return true - }, c) + return false + }) m.Table() } } + return }}, - "userinfo": &ctx.Command{Name: "userinfo sessid", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Travel(func(m *ctx.Message, n int) bool { + "userinfo": &ctx.Command{Name: "userinfo sessid", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + c.Travel(m, func(m *ctx.Message, n int) bool { if m.Cap("sessid") == arg[0] { m.Append("method", m.Cap("method")) m.Append("stream", m.Cap("stream")) @@ -725,12 +733,13 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Append("login_time", m.Cap("login_time")) m.Append("expire_time", m.Cap("expire_time")) } - return true + return false }) m.Table() + return }}, - "right": &ctx.Command{Name: "right [user [check|owner|share group [order] [add|del]]]", Form: map[string]int{"from": 1}, Help: "权限管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Travel(func(m *ctx.Message, n int) bool { + "right": &ctx.Command{Name: "right [user [check|owner|share group [order] [add|del]]]", Form: map[string]int{"from": 1}, Help: "权限管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + c.Travel(m, func(m *ctx.Message, n int) bool { if n == 0 { return true } @@ -817,9 +826,10 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", } return false } - return true - }, c) + return false + }) m.Table() + return }}, "rsa": &ctx.Command{Name: "rsa gen|sign|verify|encrypt|decrypt|cert", @@ -830,7 +840,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", "签名: rsa sign key content [signfile]", "验签: rsa verify pub content", }, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { switch arg[0] { case "gen": @@ -961,16 +971,18 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Echo("%c", c) } } + return }}, - "cert": &ctx.Command{Name: "cert [filename]", Help: "导出证书", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "cert": &ctx.Command{Name: "cert [filename]", Help: "导出证书", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.certificate != nil { certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: aaa.certificate.Raw})) if m.Echo(certificate); len(arg) > 0 { m.Assert(ioutil.WriteFile(arg[0], []byte(certificate), 0666)) } } + return }}, - "pub": &ctx.Command{Name: "pub [filename]", Help: "导出公钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "pub": &ctx.Command{Name: "pub [filename]", Help: "导出公钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { pub, e := x509.MarshalPKIXPublicKey(aaa.public) m.Assert(e) @@ -979,16 +991,18 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Assert(ioutil.WriteFile(arg[0], []byte(public), 0666)) } } + return }}, - "keys": &ctx.Command{Name: "keys [filename]", Help: "导出私钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "keys": &ctx.Command{Name: "keys [filename]", Help: "导出私钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { private := string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(aaa.private)})) if m.Echo(private); len(arg) > 0 { m.Assert(ioutil.WriteFile(arg[0], []byte(private), 0666)) } } + return }}, - "sign": &ctx.Command{Name: "sign content [signfile]", Help: "数字签名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "sign": &ctx.Command{Name: "sign content [signfile]", Help: "数字签名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { h := md5.Sum(Input(arg[0])) b, e := rsa.SignPKCS1v15(crand.Reader, aaa.private, crypto.MD5, h[:]) @@ -999,8 +1013,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Assert(ioutil.WriteFile(arg[1], []byte(res), 0666)) } } + return }}, - "verify": &ctx.Command{Name: "verify content signature", Help: "数字验签", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "verify": &ctx.Command{Name: "verify content signature", Help: "数字验签", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { buf := make([]byte, 1024) n, e := base64.StdEncoding.Decode(buf, Input(arg[1])) @@ -1010,8 +1025,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", h := md5.Sum(Input(arg[0])) m.Echo("%t", rsa.VerifyPKCS1v15(aaa.public, crypto.MD5, h[:], buf) == nil) } + return }}, - "seal": &ctx.Command{Name: "seal content [sealfile]", Help: "数字加密", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "seal": &ctx.Command{Name: "seal content [sealfile]", Help: "数字加密", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.public != nil { b, e := rsa.EncryptPKCS1v15(crand.Reader, aaa.public, Input(arg[0])) m.Assert(e) @@ -1021,8 +1037,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Assert(ioutil.WriteFile(arg[1], []byte(res), 0666)) } } + return }}, - "deal": &ctx.Command{Name: "deal content", Help: "数字解密", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "deal": &ctx.Command{Name: "deal content", Help: "数字解密", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.private != nil { buf := make([]byte, 1024) n, e := base64.StdEncoding.Decode(buf, Input(arg[0])) @@ -1033,9 +1050,10 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Assert(e) m.Echo(string(b)) } + return }}, - "newcipher": &ctx.Command{Name: "newcipher salt", Help: "加密算法", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "newcipher": &ctx.Command{Name: "newcipher salt", Help: "加密算法", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) { salt := md5.Sum(Input(arg[0])) block, e := aes.NewCipher(salt[:]) @@ -1043,8 +1061,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", aaa.encrypt = cipher.NewCBCEncrypter(block, salt[:]) aaa.decrypt = cipher.NewCBCDecrypter(block, salt[:]) } + return }}, - "encrypt": &ctx.Command{Name: "encrypt content [enfile]", Help: "加密数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "encrypt": &ctx.Command{Name: "encrypt content [enfile]", Help: "加密数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.encrypt != nil { content := Input(arg[0]) @@ -1072,8 +1091,9 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Assert(ioutil.WriteFile(arg[1], []byte(res), 0666)) } } + return }}, - "decrypt": &ctx.Command{Name: "decrypt content [defile]", Help: "解密数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "decrypt": &ctx.Command{Name: "decrypt content [defile]", Help: "解密数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.decrypt != nil { content := Input(arg[0]) @@ -1089,6 +1109,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", m.Assert(ioutil.WriteFile(arg[1], res, 0666)) } } + return }}, }, } diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 93748095..c87fb8fc 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -182,7 +182,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", Commands: map[string]*ctx.Command{ "alias": &ctx.Command{Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名, import导入模块所有命令", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { switch len(arg) { case 0: @@ -230,8 +230,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } } + return }}, - "cmd": &ctx.Command{Name: "cmd word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "cmd": &ctx.Command{Name: "cmd word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { detail := []string{} if a, ok := cli.alias[arg[0]]; ok { @@ -285,13 +286,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", for i := 0; i < len(detail); i++ { switch detail[i] { case "?": - if !ctx.Right(detail[i+1]) { + if !kit.Right(detail[i+1]) { return } i++ case "??": exec = false - execexec = execexec || ctx.Right(detail[i+1]) + execexec = execexec || kit.Right(detail[i+1]) i++ case "<": pipe := m.Sess("nfs").Cmd("import", detail[i+1]) @@ -331,7 +332,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } detail = args - msg.Set("detail", detail...) + msg.Set("detail", detail) if msg.Cmd(); msg.Hand { m.Cap("ps_target", msg.Cap("module")) @@ -374,11 +375,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", // m.Capi("last_msg", 0, msg.Code()) // m.Capi("ps_count", 1) } + return }}, - "str": &ctx.Command{Name: "str word", Help: "解析字符串", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "str": &ctx.Command{Name: "str word", Help: "解析字符串", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Echo(arg[0][1 : len(arg[0])-1]) + return }}, - "exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { switch len(arg) { case 1: @@ -404,9 +407,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Result(0, arg[2:len(arg)-1]) } } + return } //}}} + return }}, - "val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { result := "false" switch len(arg) { case 0: @@ -537,8 +542,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } m.Echo(result) + return }}, - "exp": &ctx.Command{Name: "exp word", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "exp": &ctx.Command{Name: "exp word", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 0 && arg[0] == "{" { msg := m.Spawn() for i := 1; i < len(arg); i++ { @@ -578,8 +584,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } m.Echo("%s", num[0]) + return }}, - "let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch arg[2] { case "=": m.Cap(arg[1], arg[3]) @@ -587,8 +594,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Cap(arg[1], m.Cap("last_msg")) } m.Echo(m.Cap(arg[1])) + return }}, - "var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 { switch arg[2] { case "=": @@ -598,23 +606,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } m.Echo(m.Cap(arg[1])) + return }}, - "expr": &ctx.Command{Name: "expr arg...", Help: "输出表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "expr": &ctx.Command{Name: "expr arg...", Help: "输出表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Echo("%s", strings.Join(arg[1:], "")) + return }}, - "return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); ok { msg := cli.Message() msg.Result(-2, arg[1:]) } m.Add("append", "return", arg[1:]) + return }}, "source": &ctx.Command{Name: "source [stdio [init.shy [exit.shy]]]|[filename [async]]|string", Help: "解析脚本, filename: 文件名, async: 异步执行", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Source().Server.(*CLI); ok { msg := m.Spawn(c) m.Copy(msg, "target") } + m.Cmd("yac.init") + m.Cmd("aaa.init") if len(arg) == 0 || arg[0] == "stdio" { m.Sess("log", false).Cmd("init") @@ -666,14 +679,16 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } return nil }, "parse", "line", "void", strings.Join(arg, " ")) + return }}, - "arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Source().Server.(*CLI); ok { msg := cli.Message().Spawn().Cmd("detail", arg) m.Copy(msg, "append").Copy(msg, "result") } + return }}, - "run": &ctx.Command{Name: "run", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "run": &ctx.Command{Name: "run", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { name := path.Join(m.Option("dir_root"), m.Option("download_dir")) msg := m.Sess("nfs").Add("option", "dir_reg", ".*\\.(sh|shy|py)$").Add("option", "dir_root", "").Cmd("dir", name, "dir_deep") @@ -684,9 +699,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", // name := path.Join(m.Option("dir_root"), m.Option("download_dir"), arg[0]) msg := m.Spawn(c).Cmd("cmd", arg[0], arg[1:]) m.Copy(msg, "append").Copy(msg, "result") + return }}, - "tmux": &ctx.Command{Name: "tmux buffer", Help: "终端管理, buffer: 查看复制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "tmux": &ctx.Command{Name: "tmux buffer", Help: "终端管理, buffer: 查看复制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch arg[0] { case "buffer": bufs := strings.Split(m.Spawn().Cmd("system", "tmux", "list-buffers").Result(0), "\n") @@ -714,11 +730,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Echo(m.Spawn().Cmd("system", "tmux", "show-buffer", "-b", m.Option("index")).Result(0)) } } + return }}, "system": &ctx.Command{Name: "system word...", Help: []string{"调用系统命令, word: 命令", "cmd_active(true/false): 是否交互", "cmd_timeout: 命令超时", "cmd_env: 环境变量", "cmd_dir: 工作目录"}, Form: map[string]int{"cmd_active": 1, "cmd_timeout": 1, "cmd_env": 2, "cmd_dir": 1, "cmd_error": 0, "cmd_parse": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(m.Meta["result"]) > 0 { for _, v := range m.Meta["result"] { if strings.TrimSpace(v) != "" { @@ -776,7 +793,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", cmd.Dir = m.Option("cmd_dir") } - if m.Options("cmd_active") || ctx.Right(conf["active"]) { + if m.Options("cmd_active") || kit.Right(conf["active"]) { cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr if e := cmd.Start(); e != nil { m.Echo("error: ").Echo("%s\n", e) @@ -848,9 +865,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", case <-wait: } } + return }}, "sysinfo": &ctx.Command{Name: "sysinfo", Help: "sysinfo", Hand: sysinfo}, - "runtime": &ctx.Command{Name: "runtime", Help: "runtime", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "runtime": &ctx.Command{Name: "runtime", Help: "runtime", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { mem := &runtime.MemStats{} runtime.ReadMemStats(mem) m.Append("NumGo", runtime.NumGoroutine()) @@ -874,8 +892,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", // m.Append("mper", fmt.Sprintf("%d%%", sys.Freeram*100/sys.Totalram)) // m.Table() + return }}, - "windows": &ctx.Command{Name: "windows", Help: "windows", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "windows": &ctx.Command{Name: "windows", Help: "windows", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Append("nclient", strings.Count(m.Spawn().Cmd("system", "tmux", "list-clients").Result(0), "\n")) m.Append("nsession", strings.Count(m.Spawn().Cmd("system", "tmux", "list-sessions").Result(0), "\n")) m.Append("nwindow", strings.Count(m.Spawn().Cmd("system", "tmux", "list-windows", "-a").Result(0), "\n")) @@ -885,35 +904,39 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Append("ncmd", strings.Count(m.Spawn().Cmd("system", "tmux", "list-commands").Result(0), "\n")) m.Append("nkey", strings.Count(m.Spawn().Cmd("system", "tmux", "list-keys").Result(0), "\n")) m.Table() + return }}, - "label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if cli.label == nil { cli.label = map[string]string{} } cli.label[arg[1]] = m.Option("file_pos") } + return }}, - "goto": &ctx.Command{Name: "goto label [exp] condition", Help: "向上跳转到指定位置, label: 跳转位置, condition: 跳转条件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "goto": &ctx.Command{Name: "goto label [exp] condition", Help: "向上跳转到指定位置, label: 跳转位置, condition: 跳转条件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if pos, ok := cli.label[arg[1]]; ok { - if !ctx.Right(arg[len(arg)-1]) { + if !kit.Right(arg[len(arg)-1]) { return } m.Append("file_pos0", pos) } } + return }}, - "if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { - run := m.Caps("parse") && ctx.Right(arg[1]) + run := m.Caps("parse") && kit.Right(arg[1]) cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run}) m.Capi("level", 1) m.Caps("parse", run) } + return }}, - "else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if !m.Caps("parse") { m.Caps("parse", true) @@ -926,8 +949,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } } + return }}, - "end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.run { m.Append("file_pos0", frame.pos) @@ -940,10 +964,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Caps("parse", true) } } + return }}, "for": &ctx.Command{Name: "for [[express ;] condition]|[index message meta value]", Help: "循环语句, express: 每次循环运行的表达式, condition: 循环条件, index: 索引消息, message: 消息编号, meta: value: ", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { run := m.Caps("parse") defer func() { m.Caps("parse", run) }() @@ -962,7 +987,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } } else { - run = run && ctx.Right(arg[len(arg)-1]) + run = run && kit.Right(arg[len(arg)-1]) } if len(cli.stack) > 0 { @@ -998,19 +1023,21 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Cap(arg[3], arg[3], frame.list[0], "临时变量") } } + return }}, - "sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if d, e := time.ParseDuration(arg[0]); m.Assert(e) { m.Log("info", "sleep %v", d) time.Sleep(d) m.Log("info", "sleep %v done", d) } + return }}, "time": &ctx.Command{Name: "time when [begin|end|yestoday|tommorow|monday|sunday|first|last|new|eve] [offset]", Help: "查看时间, when: 输入的时间戳, 剩余参数是时间偏移", Form: map[string]int{"time_format": 1, "time_close": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { t, stamp := time.Now(), true if len(arg) > 0 { if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil { @@ -1092,8 +1119,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { m.Echo(t.Format(m.Confx("time_format"))) } + return }}, - "timer": &ctx.Command{Name: "timer [begin time] [repeat] [order time] time cmd", Help: "定时任务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "timer": &ctx.Command{Name: "timer [begin time] [repeat] [order time] time cmd", Help: "定时任务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if cli, ok := c.Server.(*CLI); m.Assert(ok) { if len(arg) == 0 { // 查看任务列表 for k, v := range m.Confv("timer").(map[string]interface{}) { @@ -1178,6 +1206,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", cli.schedule(m) m.Echo(hash) } + return }}, }, } diff --git a/src/contexts/cli/cli_darwin.go b/src/contexts/cli/cli_darwin.go index 3fe3fa74..58d55aea 100644 --- a/src/contexts/cli/cli_darwin.go +++ b/src/contexts/cli/cli_darwin.go @@ -8,7 +8,7 @@ import ( "toolkit" ) -func sysinfo(m *ctx.Message, c *ctx.Context, key string, arg ...string) { +func sysinfo(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Append("NumCPU", runtime.NumCPU()) fs := &syscall.Statfs_t{} @@ -17,4 +17,5 @@ func sysinfo(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Append("bavail", kit.FmtSize(fs.Bavail*uint64(fs.Bsize))) m.Append("bper", fmt.Sprintf("%d%%", fs.Bavail*100/fs.Blocks)) m.Table() + return } diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index db7ef447..eaf93114 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -1,8 +1,6 @@ package ctx import ( - "crypto/md5" - "encoding/hex" "encoding/json" "fmt" "html/template" @@ -17,378 +15,27 @@ import ( "runtime/debug" "sort" "time" + "toolkit" ) -func Int(arg ...interface{}) int { - result := 0 - for _, v := range arg { - switch val := v.(type) { - case int: - result += val - case bool: - if val { - result += 1 - } - case string: - if i, e := strconv.Atoi(val); e == nil { - result += i - } - default: - } - } - 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 - break - } - result = result || true - case error: - result = result || false - 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 uint, uint8, uint16, uint32, uint64: - result = append(result, fmt.Sprintf("%d", val)) - case int, int8, int16, int32, int64: - result = append(result, fmt.Sprintf("%d", val)) - case bool: - result = append(result, fmt.Sprintf("%t", val)) - case string: - result = append(result, val) - case float64: - result = append(result, fmt.Sprintf("%d", int(val))) - case time.Time: - result = append(result, fmt.Sprintf("%d", val.Unix())) - default: - if b, e := json.Marshal(val); e == nil { - result = append(result, string(b)) - } - } - } - - if len(result) > 1 { - if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n+1 { - return fmt.Sprintf(result[0], result[1:n+1]) + strings.Join(result[n+1:], "") - } else if len(result) == n+1 { - return fmt.Sprintf(result[0], result[1:]) - } - } - 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 []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{}: - ls = append(ls, Format(val...)) - default: - ls = append(ls, Format(val)) - } - } - return ls -} -func Chain(m *Message, 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) - - var next interface{} - switch value := data.(type) { - case nil: - if j == len(keys)-1 { - next = args[i+1] - } - - if i == len(args)-1 { - return nil - } - - 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] // 修改数据 - } - 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 { - data, index = append([]interface{}{next}, value...), 0 - } else if index == -2 { - data, index = append(value, next), len(value) - } else if j == len(keys)-1 { - value[index] = next - } - next = 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 Action(cmd string, arg ...interface{}) string { - switch cmd { - case "time": - return Format(time.Now()) - case "rand": - return Format(rand.Int()) - case "uniq": - return Format(time.Now(), rand.Int()) - default: - if len(arg) > 0 { - return Format(arg...) - } - } - return cmd -} -func Hash(arg ...interface{}) (string, []string) { - meta := Trans(arg...) - for i, v := range meta { - meta[i] = Action(v) - } - - h := md5.Sum([]byte(strings.Join(meta, ""))) - return hex.EncodeToString(h[:]), meta -} - -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 "" -} - -type LOGGER interface { - LOG(*Message, string, string) -} - type Cache struct { - Name string Value string + Name string Help string Hand func(m *Message, x *Cache, arg ...string) string } type Config struct { - Name string Value interface{} + Name string Help string Hand func(m *Message, x *Config, arg ...string) string } type Command struct { + Form map[string]int Name string Help interface{} - Form map[string]int - Hand func(m *Message, c *Context, key string, arg ...string) - - Shares map[string][]string + Hand func(m *Message, c *Context, key string, arg ...string) (e error) } - type Server interface { Spawn(m *Message, c *Context, arg ...string) Server Begin(m *Message, arg ...string) Server @@ -402,11 +49,10 @@ type Context struct { Caches map[string]*Cache Configs map[string]*Config Commands map[string]*Command - Index map[string]*Context + message *Message requests []*Message sessions []*Message - message *Message contexts map[string]*Context context *Context @@ -429,51 +75,41 @@ func (c *Context) Register(s *Context, x Server) { 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} + 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) - s.Caches = map[string]*Cache{} - s.Configs = map[string]*Config{} } - - item := []string{name} - for s := c; s != nil; s = s.context { - item = append(item, s.Name) - } - for i := 0; i < len(item)/2; i++ { - item[i], item[len(item)-i-1] = item[len(item)-i-1], item[i] - } - s.Caches["module"] = &Cache{Name: "module", Value: strings.Join(item, "."), Help: "模块域名"} - s.message = m return s } func (c *Context) Begin(m *Message, arg ...string) *Context { if len(arg) > 0 { - m.Meta["detail"] = arg + m.Set("detail", arg) } - item := []string{} - for s := c; s != nil; s = s.context { - item = append(item, s.Name) + module := c.Name + if c.context != nil { + module = c.context.Name + "." + c.Name } - for i := 0; i < len(item)/2; i++ { - item[i], item[len(item)-i-1] = item[len(item)-i-1], item[i] - } - c.Caches["module"] = &Cache{Name: "module", Value: strings.Join(item, "."), Help: "模块域名"} - c.Caches["status"] = &Cache{Name: "status(begin/start/close)", Value: "begin", Help: "模块状态,begin:初始完成,start:正在运行,close:未在运行"} + + 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.message = m - m.Log("begin", "%d context %v %v", m.root.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"]) + 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.Conf(k, x.Value.(string)) + m.Log("begin", "%s config %v", k, m.Conf(k, x.Value)) } } @@ -484,9 +120,11 @@ func (c *Context) Begin(m *Message, arg ...string) *Context { return c } func (c *Context) Start(m *Message, arg ...string) bool { - if len(arg) > 0 { - m.Set("detail", arg...) + sync := false + if len(arg) > 0 && arg[0] == "sync" { + sync, arg = true, arg[1:] } + m.Set("detail", arg) c.requests = append(c.requests, m) m.source.sessions = append(m.source.sessions, m) @@ -494,37 +132,35 @@ func (c *Context) Start(m *Message, arg ...string) bool { return true } - m.Sess("log", m.Sess("log")) - m.Sess("lex", m.Sess("lex")) - if c.Name == "aaa" { - debug.PrintStack() - panic(1) - } - - running := make(chan bool) + c.exit = make(chan bool, 2) go m.TryCatch(m, true, func(m *Message) { m.Log(m.Cap("status", "start"), "%d server %v %v", m.root.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) c.message = m - c.exit = make(chan bool, 2) - if running <- true; c.Server != nil && c.Server.Start(m, m.Meta["detail"]...) { + if c.exit <- false; c.Server == nil || c.Server.Start(m, m.Meta["detail"]...) { c.Close(m, m.Meta["detail"]...) + c.exit <- true } }) - return <-running + + 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 } - m.Log("close", "%d:%d %v", len(c.requests), len(c.sessions), arg) + m.Log("close", "%d:%d %v", len(c.requests), len(c.sessions), arg) 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...) { for j := i; j < len(c.requests)-1; j++ { - m.Log("close", "requests: %v %s", j, c.requests[j].Format()) c.requests[j] = c.requests[j+1] } c.requests = c.requests[:len(c.requests)-1] @@ -533,21 +169,22 @@ func (c *Context) Close(m *Message, arg ...string) bool { } } + m.Log("close", "%d:%d %v", len(c.requests), len(c.sessions), arg) 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)+1, arg) + m.Log(m.Cap("status", "close"), "%d server %v", m.root.Capi("nserver", -1), arg) for _, msg := range c.sessions { - if msg.Cap("status") == "start" { + 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)+1, arg) + m.Log("close", "%d context %v", m.root.Capi("ncontext", -1), arg) if c.Name != "stdio" { delete(c.context.contexts, c.Name) } @@ -555,6 +192,7 @@ func (c *Context) Close(m *Message, arg ...string) bool { } return true } + func (c *Context) Context() *Context { return c.context } @@ -563,35 +201,78 @@ func (c *Context) Message() *Message { } func (c *Context) Has(key ...string) bool { switch len(key) { - case 1: - if _, ok := c.Caches[key[0]]; ok { - return true - } - if _, ok := c.Configs[key[0]]; ok { - return true - } case 2: - if _, ok := c.Caches[key[0]]; ok && key[1] == "cache" { + 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.Commands[key[0]]; ok && key[1] == "command" { + if _, ok := c.Caches[key[0]]; ok && key[1] == "cache" { + return true + } + case 1: + if _, ok := c.Commands[key[0]]; ok { + return true + } + if _, ok := c.Configs[key[0]]; ok { + return true + } + if _, ok := c.Caches[key[0]]; ok { return true } } return false } +func (c *Context) Travel(m *Message, hand func(m *Message, n int) (stop bool)) *Context { + target := m.target + cs := []*Context{c} + for i := 0; i < len(cs); i++ { + if m.target = cs[i]; hand(m, i) { + return cs[i] + } + + keys := []string{} + for k, _ := range cs[i].contexts { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + cs = append(cs, cs[i].contexts[k]) + } + } + + m.target = target + return target +} +func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Context { + target := m.target + + for s := m.target; s != nil; s = s.context { + if m.target = s; hand(m) { + return s + } + } + + m.target = target + return target +} + +type LOGGER interface { + LOG(*Message, string, string) +} +type DEBUG interface { + Wait(*Message, ...interface{}) interface{} + Goon(interface{}, ...interface{}) +} type Message struct { - code int time time.Time + code int source *Context target *Context - Hand bool Meta map[string][]string Data map[string]interface{} @@ -603,10 +284,54 @@ type Message struct { root *Message Remote chan bool + Hand bool } -func (m *Message) Code() int { - return m.code +func (m *Message) Log(action string, str string, arg ...interface{}) *Message { + kit.Errorf(fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...))) + return m + if action == "error" { + kit.Errorf(str, arg...) + } + + if l := m.Sess("log", false); l != nil { + if log, ok := l.target.Server.(LOGGER); ok { + log.LOG(m, action, fmt.Sprintf(str, arg...)) + } + } + + return m +} +func (m *Message) Gdb(arg ...interface{}) interface{} { + if g := m.Sess("gdb", false); g != nil { + if gdb, ok := g.target.Server.(DEBUG); ok { + return gdb.Wait(m, arg...) + } + } + return nil +} +func (m *Message) Spawn(arg ...interface{}) *Message { + c := m.target + if len(arg) > 0 { + switch v := arg[0].(type) { + case *Context: + c = v + case *Message: + c = v.target + } + } + + msg := &Message{ + time: time.Now(), + code: m.root.Capi("nmessage", 1), + source: m.target, + target: c, + message: m, + root: m.root, + } + + m.messages = append(m.messages, msg) + return msg } func (m *Message) Time(arg ...interface{}) string { t := m.time @@ -626,8 +351,8 @@ func (m *Message) Time(arg ...interface{}) string { } return t.Format(str) } -func (m *Message) Message() *Message { - return m.message +func (m *Message) Code() int { + return m.code } func (m *Message) Source() *Context { return m.source @@ -635,10 +360,35 @@ func (m *Message) Source() *Context { func (m *Message) Target() *Context { return m.target } -func (m *Message) Format() string { - return fmt.Sprintf("%d(%s->%s): %s %v %v", m.code, m.source.Name, m.target.Name, m.time.Format("15:04:05"), m.Meta["detail"], m.Meta["option"]) +func (m *Message) Message() *Message { + return m.message } +func (m *Message) Format(arg ...string) string { + if len(arg) == 0 { + arg = append(arg, "time", "ship") + } + meta := []string{} + for _, v := range arg { + switch v { + case "time": + meta = append(meta, m.Time()) + case "code": + meta = append(meta, kit.Format(m.code)) + case "ship": + meta = append(meta, fmt.Sprintf("%d(%s->%s)", m.code, m.source.Name, m.target.Name)) + case "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"])) + } + } + return strings.Join(meta, " ") +} func (m *Message) Tree(code int) *Message { ms := []*Message{m} for i := 0; i < len(ms); i++ { @@ -649,194 +399,503 @@ func (m *Message) Tree(code int) *Message { } return nil } -func (m *Message) Copy(msg *Message, meta string, arg ...string) *Message { + +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 "target": - m.target = msg.target - case "callback": - m.callback = msg.callback - case "session": - if len(arg) == 0 { - for k, v := range msg.Sessions { - m.Sessions[k] = v - } - } else { - for _, k := range arg { - m.Sessions[k] = msg.Sessions[k] + case "detail", "result": + 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 len(msg.Meta[meta]) > 0 { - m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:]) + if m != nil && m.Meta != nil { + delete(m.Meta, meta) } case "option", "append": - if len(arg) == 0 { - arg = msg.Meta[meta] - } - - for _, k := range arg { - if v, ok := msg.Data[k]; ok { - m.Put(meta, k, v) - } - if v, ok := msg.Meta[k]; ok { - m.Add(meta, k, v) + 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) } - return m -} -func (m *Message) CopyTo(msg *Message) *Message { - msg.Copy(m, "append").Copy(m, "result") - return m -} -func (m *Message) Log(action string, str string, arg ...interface{}) *Message { - if l := m.Sess("log", false); l != nil { - if log, ok := l.target.Server.(LOGGER); ok { - log.LOG(m, action, fmt.Sprintf(str, 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 -func (m *Message) Assert(e interface{}, msg ...string) bool { - switch v := e.(type) { - case nil: - return true - case bool: - if v { + 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 } - case string: - if Right(v) { - return true - } - case *Message: - if result, ok := v.Meta["result"]; ok && len(result) > 0 && result[0] == "error: " { - e = v.Result(1) - break - } - return true - } - - if len(msg) > 1 { - arg := make([]interface{}, 0, len(msg)-1) - for _, m := range msg[1:] { - arg = append(arg, m) - } - e = errors.New(fmt.Sprintf(msg[0], arg...)) - } else if len(msg) > 0 { - e = errors.New(msg[0]) - } - - m.Log("error", "%s", fmt.Sprintln(e)) - panic(m.Set("result", "error: ", fmt.Sprintln(e), "\n")) -} -func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message { - defer func() { - if e := recover(); e != nil && e != io.EOF { - // switch v := e.(type) { - // case *Message: - // // msg.Log("error", "error: %v", strings.Join(v.Meta["result"][1:], "")) - // default: - // // msg.Log("error", "error: %v", e) - // } - - if msg.root.Conf("debug") == "on" { - fmt.Printf("\n\033[31m%s error: %v\033[0m\n", msg.target.Name, e) - debug.PrintStack() - fmt.Printf("\033[31m%s error: %v\033[0m\n\n", msg.target.Name, e) - } - - if len(hand) > 1 { - m.TryCatch(msg, safe, hand[1:]...) - } else if !safe { - msg.Assert(e) - } - } - }() - - if len(hand) > 0 { - hand[0](msg) - } - - return m -} - -func (m *Message) Instance(msg *Message, source ...bool) bool { - c := m.target - if len(source) > 0 && source[0] == true { - c = m.source - } - - for s := c; s != nil; s = s.context { - if s == msg.target { + if _, ok := m.Meta[key[0]]; ok { return true } } return false } -func (m *Message) BackTrace(hand func(m *Message) bool, c ...*Context) *Message { - target := m.target - if len(c) > 0 { - m.target = c[0] +func (m *Message) CopyTo(msg *Message, arg ...string) *Message { + if m == msg { + return m } - for s := m.target; s != nil; s = s.context { - if m.target = s; !hand(m) { - break + if len(arg) == 0 { + if msg.Hand { + msg.Copy(m, "append").Copy(m, "result") + } else { + msg.Copy(m, "option") } + } else { + msg.Copy(m, arg...) } - m.target = target return m } -func (m *Message) Travel(hand func(m *Message, i int) bool, c ...*Context) { - target := m.target - if len(c) > 0 { - m.target = c[0] +func (m *Message) Copy(msg *Message, arg ...string) *Message { + if m == msg { + return m } - - cs := []*Context{m.target} - for i := 0; i < len(cs); i++ { - if m.target = cs[i]; !hand(m, i) { - break - } - - 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]) + if len(arg) == 0 { + if msg.Hand { + arg = append(arg, "append") + } else { + arg = append(arg, "option") } } - m.target = target + for i := 0; i < len(arg); i++ { + meta := arg[i] + + switch meta { + case "target": + m.target = msg.target + case "callback": + m.callback = msg.callback + // case "session": + // if len(arg) == 0 { + // for k, v := range msg.Sessions { + // m.Sessions[k] = v + // } + // } else { + // for _, k := range arg { + // m.Sessions[k] = msg.Sessions[k] + // } + // } + case "detail", "result": + if len(msg.Meta[meta]) > 0 { + m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:]) + } + case "option", "append": + if i == len(arg)-1 { + arg = append(arg, msg.Meta[meta]...) + } + + for i++; i < len(arg); i++ { + if v, ok := msg.Data[arg[i]]; ok { + m.Put(meta, arg[i], v) + } + if v, ok := msg.Meta[arg[i]]; ok { + m.Add(meta, arg[i], v) + } + } + default: + if msg.Hand { + meta = "append" + } else { + meta = "option" + } + + if v, ok := msg.Data[arg[i]]; ok { + m.Put(meta, arg[i], v) + } + if v, ok := msg.Meta[arg[i]]; ok { + m.Add(meta, arg[i], v) + } + } + } + + return m +} +func (m *Message) Echo(str string, arg ...interface{}) *Message { + if len(arg) > 0 { + return m.Add("result", fmt.Sprintf(str, arg...)) + } + return m.Add("result", str) } -func (m *Message) Spawn(arg ...interface{}) *Message { - c := m.target +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 *Context: - c = v - case *Message: - c = v.target + 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) } } - msg := &Message{ - code: m.root.Capi("nmessage", 1), - time: time.Now(), - source: m.target, - target: c, - message: m, - root: m.root, + 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]) + } } - m.messages = append(m.messages, msg) - return msg + for msg := m; msg != nil; msg = msg.message { + if msg.Meta == nil || !msg.Has(key) { + continue + } + for _, k := range msg.Meta["option"] { + if k == key { + if v, ok := msg.Data[key]; ok { + return v + } + return msg.Meta[key] + } + } + } + return nil } +func (m *Message) Optionx(key string, arg ...string) interface{} { + value := m.Conf(key) + if value == "" { + value = m.Option(key) + } + + if len(arg) > 0 { + value = fmt.Sprintf(arg[0], value) + } + return value +} +func (m *Message) Append(key string, arg ...interface{}) string { + if len(arg) > 0 { + m.Insert(key, 0, arg...) + if _, ok := m.Meta[key]; ok { + m.Add("append", key) + } + } + + ms := []*Message{m} + for i := 0; i < len(ms); i++ { + ms = append(ms, ms[i].messages...) + if !ms[i].Has(key) { + continue + } + for _, k := range ms[i].Meta["append"] { + if k == key { + return ms[i].Get(key) + } + } + } + return "" +} +func (m *Message) Appendi(key string, arg ...interface{}) int { + return kit.Int(m.Append(key, arg...)) + +} +func (m *Message) Appends(key string, arg ...interface{}) bool { + return kit.Right(m.Append(key, arg...)) +} +func (m *Message) Appendv(key string, arg ...interface{}) interface{} { + if len(arg) > 0 { + m.Put("append", key, arg[0]) + } + + ms := []*Message{m} + for i := 0; i < len(ms); i++ { + ms = append(ms, ms[i].messages...) + if !ms[i].Has(key) { + continue + } + for _, k := range ms[i].Meta["append"] { + if k == key { + if v, ok := ms[i].Data[key]; ok { + return v + } + return ms[i].Meta[key] + } + } + } + return nil +} +func (m *Message) Table(cbs ...func(maps map[string]string, list []string, line int) (goon bool)) *Message { + if len(m.Meta["append"]) == 0 { + return m + } + + //计算列宽 + depth, width := 0, map[string]int{} + for _, k := range m.Meta["append"] { + if len(m.Meta[k]) > depth { + depth = len(m.Meta[k]) + } + for _, v := range m.Meta[k] { + if len(v) > width[k] { + width[k] = len(v) + } + } + } + + space := m.Confx("table_space") + var cb func(maps map[string]string, list []string, line int) (goon bool) + if len(cbs) > 0 { + cb = cbs[0] + } else { + row := m.Confx("table_row_sep") + col := m.Confx("table_col_sep") + compact := kit.Right(m.Confx("table_compact")) + cb = func(maps map[string]string, lists []string, line int) bool { + for i, v := range lists { + if k := m.Meta["append"][i]; compact { + v = maps[k] + } + + if m.Echo(v); i < len(lists)-1 { + m.Echo(col) + } + } + m.Echo(row) + return true + } + } + + // 输出表头 + row := map[string]string{} + wor := []string{} + for _, k := range m.Meta["append"] { + row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-len(k))) + } + if !cb(row, wor, -1) { + return m + } + + // 输出数据 + for i := 0; i < depth; i++ { + row := map[string]string{} + wor := []string{} + for _, k := range m.Meta["append"] { + data := "" + if i < len(m.Meta[k]) { + data = m.Meta[k][i] + } + + row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-len(data))) + } + if !cb(row, wor, i) { + break + } + } + + return m +} +func (m *Message) Sort(key string, arg ...string) *Message { + cmp := "string" + if len(arg) > 0 { + cmp = arg[0] + } + + number := map[int]int{} + table := []map[string]string{} + m.Table(func(line map[string]string, lists []string, index int) bool { + if index != -1 { + table = append(table, line) + switch cmp { + case "int": + number[index] = kit.Int(line[key]) + case "int_r": + number[index] = -kit.Int(line[key]) + case "time": + number[index] = kit.Time(line[key]) + case "time_r": + number[index] = -kit.Time(line[key]) + } + } + return true + }) + + for i := 0; i < len(table)-1; i++ { + for j := i + 1; j < len(table); j++ { + result := false + switch cmp { + case "str": + if table[i][key] > table[j][key] { + result = true + } + case "str_r": + if table[i][key] < table[j][key] { + result = true + } + default: + if number[i] > number[j] { + result = true + } + } + + if result { + table[i], table[j] = table[j], table[i] + number[i], number[j] = number[j], number[i] + } + } + } + + for _, k := range m.Meta["append"] { + delete(m.Meta, k) + } + + for _, v := range table { + for _, k := range m.Meta["append"] { + m.Add("append", k, v[k]) + } + } + return m +} +func (m *Message) Parse(arg interface{}) string { + switch str := arg.(type) { + case string: + if len(str) > 1 && str[0] == '$' { + return m.Cap(str[1:]) + } + if len(str) > 1 && str[0] == '@' { + return m.Confx(str[1:]) + } + return m.Cmdx(str) + } + return "" +} + func (m *Message) Find(name string, root ...bool) *Message { target := m.target.root if len(root) > 0 && !root[0] { @@ -850,11 +909,10 @@ func (m *Message) Find(name string, root ...bool) *Message { } else if target.Name == v { continue } else { - m.Log("find", "not find %s", v) + m.Log("error", "context not find %s", name) return nil } } - m.Log("find", "find %s", name) return m.Spawn(target) } func (m *Message) Search(key string, root ...bool) []*Message { @@ -870,13 +928,13 @@ func (m *Message) Search(key string, root ...bool) []*Message { } cs := make([]*Context, 0, 3) - m.Travel(func(m *Message, i int) bool { + target.Travel(m, func(m *Message, i int) bool { if reg.MatchString(m.target.Name) || reg.FindString(m.target.Help) != "" { - m.Log("search", "%d match [%s]", len(cs)+1, key) + m.Log("search", "%d %s match [%s]", len(cs), m.target.Name, key) cs = append(cs, m.target) } - return true - }, target) + return false + }) ms := make([]*Message, len(cs)) for i := 0; i < len(cs); i++ { @@ -889,6 +947,10 @@ func (m *Message) Search(key string, root ...bool) []*Message { 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) { @@ -910,22 +972,11 @@ func (m *Message) Sess(key string, arg ...interface{}) *Message { m.Sessions[key] = m.Spawn(value) return m.Sessions[key] case string: - root := true - if len(arg) > 2 { - switch v := arg[2].(type) { - case string: - root = Right(v) - case bool: - root = v - } - } + root := len(arg) < 3 || kit.Right(arg[2]) method := "find" if len(arg) > 1 { - switch v := arg[1].(type) { - case string: - method = v - } + method = kit.Format(arg[1]) } switch method { @@ -936,15 +987,11 @@ func (m *Message) Sess(key string, arg ...interface{}) *Message { } return m.Sessions[key] case nil: - m.Sessions[key] = nil + delete(m.Sessions, key) return nil } } - if key == "" { - return m.Spawn() - } - for msg := m; msg != nil; msg = msg.message { if x, ok := msg.Sessions[key]; ok { if spawn { @@ -956,6 +1003,26 @@ func (m *Message) Sess(key string, arg ...interface{}) *Message { return nil } +func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context, c *Context, key string) bool) *Message { + if strings.Contains(key, ".") { + arg := strings.Split(key, ".") + m, key = m.Sess(arg[0], spawn), arg[1] + } + + context := []*Context{m.target} + for _, v := range []string{"aaa", "cli"} { + if msg := m.Sess(v, false); msg != nil && msg.target != nil { + context = append(context, msg.target) + } + } + context = append(context, m.source) + + for _, s := range context { + for c := s; c != nil && !hand(m, s, c, key) && c != c.context; c = c.context { + } + } + return m +} func (m *Message) Call(cb func(msg *Message) (sub *Message), arg ...interface{}) *Message { if m.callback = cb; len(arg) > 0 || len(m.Meta["detail"]) > 0 { m.Cmd(arg...) @@ -994,555 +1061,55 @@ func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg return <-wait } -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], 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], Trans(value...)...) - - for _, v := range m.Meta[meta] { - if v == key { - return m - } - } - m.Meta[meta] = append(m.Meta[meta], key) - - default: - return m - m.Assert(true, "%s 消息参数错误", meta) - } - - return m -} -func (m *Message) Set(meta string, arg ...string) *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, arg[0]) - } else { - for _, k := range m.Meta[meta] { - delete(m.Data, k) - delete(m.Meta, k) - } - delete(m.Meta, meta) - } - default: - return m - m.Assert(true, "%s 消息参数错误", meta) - } - - if len(arg) > 0 { - m.Add(meta, arg[0], arg[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: - return m - m.Assert(true, "%s 消息参数错误", meta) - } - return m -} -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) Get(key string) string { - if meta, ok := m.Meta[key]; ok && len(meta) > 0 { - return meta[0] - } - return "" -} -func (m *Message) Geti(key string) int { - n, e := strconv.Atoi(m.Get(key)) - m.Assert(e) - return n -} -func (m *Message) Gets(key string) bool { - return Right(m.Get(key)) -} -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) Color(color int, str string, arg ...interface{}) *Message { - if len(arg) > 0 { - str = fmt.Sprintf(str, arg...) - } - if m.Options("terminal_color") { - str = fmt.Sprintf("\033[%dm%s\033[0m", color, str) - } - return m.Add("result", str) -} -func (m *Message) Table(cbs ...func(maps map[string]string, list []string, line int) (goon bool)) *Message { - var cb func(maps map[string]string, list []string, line int) (goon bool) - if len(cbs) > 0 { - cb = cbs[0] - } else { - row := m.Confx("table_row_sep") - col := m.Confx("table_col_sep") - compact := 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 - } - } - if len(m.Meta["append"]) == 0 { - return m - } - - //计算列宽 - width := make(map[string]int, len(m.Meta[m.Meta["append"][0]])) - for _, k := range m.Meta["append"] { - title := k - if m.Options("extras") && k == "extra" { - title = "extra." + m.Option("extras") - } - width[k] = len(title) - } - for i := 0; i < len(m.Meta[m.Meta["append"][0]]); i++ { - for _, k := range m.Meta["append"] { - if i >= len(m.Meta[k]) { - m.Meta[k] = append(m.Meta[k], "") - } - - data := m.Meta[k][i] - if len(data) > width[k] { - width[k] = len(data) - } - } - } - - //输出字段名 - row := map[string]string{} - wor := []string{} - for _, k := range m.Meta["append"] { - title := k - if m.Options("extras") && k == "extra" { - title = "extra." + m.Option("extras") - } - row[k] = title - title += strings.Repeat(" ", width[k]-len(title)) - wor = append(wor, title) - } - if !cb(row, wor, -1) { - return m - } - - for i := 0; i < len(m.Meta[m.Meta["append"][0]]); i++ { - row := map[string]string{} - wor := []string{} - for _, k := range m.Meta["append"] { - data := m.Meta[k][i] - //解析extra字段 - if m.Options("extras") && k == "extra" { - var extra interface{} - json.Unmarshal([]byte(data), &extra) - for _, k := range m.Meta["extras"] { - if i, e := strconv.Atoi(k); e == nil && i >= 0 { - if d, ok := extra.([]interface{}); ok && i < len(d) { - extra = d[i] - continue - } - } - - if d, ok := extra.(map[string]interface{}); ok { - extra = d[k] - continue - } - - extra = nil - break - } - - if extra == nil { - data = "" - } else { - format := m.Confx("extra_format") - if format == "" { - format = "%v" - } - data = fmt.Sprintf(format, extra) - } - } - - if i < len(m.Meta[k]) { - row[k] = data - data += strings.Repeat(" ", width[k]-len(data)) - wor = append(wor, data) - } - } - if !cb(row, wor, i) { - break - } - } - - return m -} -func (m *Message) Matrix(index int, arg ...interface{}) string { - if len(m.Meta["append"]) == 0 || index < 0 { - return "" - } - - key := m.Meta["append"][0] - if len(arg) > 0 { - switch v := arg[0].(type) { - case string: - for _, k := range m.Meta["append"] { - if k == v { - key = v - } - } - if key != v { - return "" - } - case int: - if v < len(m.Meta["append"]) { - key = m.Meta["append"][v] - } else { - return "" - } - } - } - if index < len(m.Meta[key]) { - return m.Meta[key][index] - - } - return "" -} -func (m *Message) Sort(key string, arg ...string) *Message { - table := []map[string]string{} - m.Table(func(line map[string]string, lists []string, index int) bool { - if index != -1 { - table = append(table, line) - } +func (m *Message) Assert(e interface{}, msg ...string) bool { + switch v := e.(type) { + case nil: return true - }) - - cmp := "string" - if len(arg) > 0 { - cmp = arg[0] - } - - 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 - } - case "int": - a, e := strconv.Atoi(table[i][key]) - m.Assert(e) - b, e := strconv.Atoi(table[j][key]) - m.Assert(e) - if a > b { - result = true - } - case "int_r": - a, e := strconv.Atoi(table[i][key]) - m.Assert(e) - b, e := strconv.Atoi(table[j][key]) - m.Assert(e) - if a < b { - result = true - } - case "time": - ti, e := time.ParseInLocation(m.Confx("time_format"), table[i][key], time.Local) - m.Assert(e) - tj, e := time.ParseInLocation(m.Confx("time_format"), table[j][key], time.Local) - m.Assert(e) - if tj.Before(ti) { - result = true - } - case "time_r": - ti, e := time.ParseInLocation(m.Confx("time_format"), table[i][key], time.Local) - m.Assert(e) - tj, e := time.ParseInLocation(m.Confx("time_format"), table[j][key], time.Local) - m.Assert(e) - if ti.Before(tj) { - result = true - } - } - - if result { - table[i], table[j] = table[j], table[i] - } + case *Message: + if v.Result(0) != "error: " { + return true + } + e = v.Result(1) + default: + if kit.Right(v) { + return true } } - for _, k := range m.Meta["append"] { - delete(m.Meta, k) + switch e.(type) { + case error: + default: + e = errors.New(kit.Format(msg)) } - for _, v := range table { - for _, k := range m.Meta["append"] { - m.Add("append", k, v[k]) + m.Log("error", "%v", e) + panic(m.Set("result", "error: ", kit.Format(e), "\n")) +} +func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message { + defer func() { + e := recover() + switch e { + case io.EOF: + case nil: + default: + if len(hand) > 1 { + m.TryCatch(msg, safe, hand[1:]...) + } else if !safe { + m.Log("error", "%s not catch %v", msg.Format(), e) + debug.PrintStack() + msg.Assert(e) + } } + }() + + if len(hand) > 0 { + hand[0](msg) } + return m } - -func (m *Message) Insert(meta string, index int, arg ...interface{}) string { - if m.Meta == nil { - m.Meta = make(map[string][]string) - } - if len(arg) == 0 { - if -1 < index && index < len(m.Meta[meta]) { - return m.Meta[meta][index] - } - return "" - } - - str := Trans(arg...) - if m.Confs("insert_limit") { - index = (index+2)%(len(m.Meta[meta])+2) - 2 - } - - if index == -1 { - index, m.Meta[meta] = 0, append(str, m.Meta[meta]...) - } else if index == -2 { - index, m.Meta[meta] = len(m.Meta[meta]), append(m.Meta[meta], str...) - } else { - if index < -2 { - index += len(m.Meta[meta]) + 2 - } - if index < 0 { - index = 0 - } - - for i := len(m.Meta[meta]); i < index+len(str); i++ { - m.Meta[meta] = append(m.Meta[meta], "") - } - for i := 0; i < len(str); i++ { - m.Meta[meta][index+i] = str[i] - } - } - - 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 { - i, e := strconv.Atoi(m.Detail(arg...)) - m.Assert(e) - return i -} -func (m *Message) Details(arg ...interface{}) bool { - return 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 { - i, e := strconv.Atoi(m.Result(arg...)) - m.Assert(e) - return i -} -func (m *Message) Results(arg ...interface{}) bool { - return len(m.Meta["result"]) > 0 && 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 { - i, e := strconv.Atoi(m.Option(key, arg...)) - m.Assert(e) - return i -} -func (m *Message) Options(key string, arg ...interface{}) bool { - return 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, format string) interface{} { - if value := m.Option(key); value != "" { - return fmt.Sprintf(format, value) - } - return "" -} -func (m *Message) Append(key string, arg ...interface{}) string { - if len(arg) > 0 { - m.Insert(key, 0, arg...) - if _, ok := m.Meta[key]; ok { - m.Add("append", key) - } - } - - ms := []*Message{m} - for i := 0; i < len(ms); i++ { - ms = append(ms, ms[i].messages...) - if !ms[i].Has(key) { - continue - } - for _, k := range ms[i].Meta["append"] { - if k == key { - return ms[i].Get(key) - } - } - } - return "" -} -func (m *Message) Appendi(key string, arg ...interface{}) int { - i, e := strconv.Atoi(m.Append(key, arg...)) - m.Assert(e) - return i -} -func (m *Message) Appends(key string, arg ...interface{}) bool { - return 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) Parse(arg interface{}) string { - switch str := arg.(type) { - case string: - if len(str) > 1 && str[0] == '$' { - return m.Cap(str[1:]) - } - if len(str) > 1 && str[0] == '@' { - return m.Confx(str[1:]) - } - return str - } - return "" +func (m *Message) 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) Wait() bool { if m.target.exit != nil { @@ -1550,459 +1117,247 @@ func (m *Message) Wait() bool { } return true } -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) Cmdx(args ...interface{}) string { - return m.Cmd(args...).Result(0) -} func (m *Message) Cmdy(args ...interface{}) *Message { m.Cmd(args...).CopyTo(m) return m } +func (m *Message) Cmdx(args ...interface{}) string { + return m.Cmd(args...).Result(0) +} func (m *Message) Cmds(args ...interface{}) bool { return m.Cmd(args...).Results(0) } -func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} { - if len(args) > 0 { - switch fun := args[0].(type) { - case func(string, map[string]interface{}): - if value, ok := m.Confv(key).(map[string]interface{}); ok { - for k, v := range value { - if val, ok := v.(map[string]interface{}); ok { - fun(k, val) - } - } - return value - } - return nil - } - } - if len(args) > 1 { - switch fun := args[1].(type) { - case func(map[string]interface{}): - if value, ok := m.Confv(key, args[0]).(map[string]interface{}); ok { - fun(value) - } - return nil - case func(int, map[string]interface{}): - if value, ok := m.Confv(key, args[0]).([]interface{}); ok { - for i, v := range value { - if val, ok := v.(map[string]interface{}); ok { - fun(i, val) - } - } - return nil - } - return nil - case func(string, map[string]interface{}): - if value, ok := m.Confv(key, args[0]).(map[string]interface{}); ok { - for k, v := range value { - if val, ok := v.(map[string]interface{}); ok { - fun(k, val) - } - } - return value - } - return nil - } - } - - if v, ok := m.Confv(key, args...).(map[string]interface{}); ok { - return v - } - return nil -} - func (m *Message) Cmd(args ...interface{}) *Message { if m == nil { return m } if len(args) > 0 { - m.Set("detail", Trans(args...)...) + m.Set("detail", kit.Trans(args...)) } + key, arg := m.Meta["detail"][0], m.Meta["detail"][1:] - if strings.Contains(key, ".") { - arg := strings.Split(key, ".") - m, key = m.Sess(arg[0]), arg[1] - } + m = m.Match(key, true, func(m *Message, s *Context, c *Context, key string) bool { + if x, ok := c.Commands[key]; ok && x.Hand != nil { + m.TryCatch(m, true, func(m *Message) { + m.Log("cmd", "%s:%s %s %v %v", c.Name, s.Name, key, arg, m.Meta["option"]) - for _, c := range []*Context{m.target, m.source, m.Sess("aaa", false).target, m.Sess("cli", false).target} { - for s := c; s != nil; s = s.context { - - if x, ok := s.Commands[key]; ok && x.Hand != nil { - m.TryCatch(m, true, func(m *Message) { - m.Log("cmd", "%s:%s %s %v %v", s.Name, c.Name, key, arg, m.Meta["option"]) - if args := []string{}; x.Form != nil { - for i := 0; i < len(arg); i++ { - n, ok := x.Form[arg[i]] - if n == -1 { - j := i + 1 - for ; j < len(arg); j++ { - if _, ok := x.Form[arg[j]]; ok { - break - } - m.Add("option", arg[i], arg[j]) - } - i = j - 1 - continue - } - if !ok { - args = append(args, arg[i]) - continue - } + if args := []string{}; x.Form != nil { + for i := 0; i < len(arg); i++ { + if n, ok := x.Form[arg[i]]; ok { if n < 0 { n += len(arg) - i } - + for j := i + 1; j <= i+n; j++ { + if _, ok := x.Form[arg[j]]; ok { + n = j - i - 1 + } + } m.Add("option", arg[i], arg[i+1:i+1+n]) i += n + } else { + args = append(args, arg[i]) } - arg = args } + arg = args + } - m.Hand = true - x.Hand(m, s, key, arg...) - - }) - return m - } + m.Hand = true + x.Hand(m, c, key, arg...) + }) } + return m.Hand + }) + + if !m.Hand { + m.Log("error", "cmd run error %s", m.Format()) } return m } -func (m *Message) Confx(key string, arg ...interface{}) string { - conf := m.Conf(key) - if len(arg) == 0 { - value := m.Option(key) - if value == "" { - value = conf + +func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} { + var chain interface{} + if len(args) > 0 { + switch arg := args[0].(type) { + case []interface{}: + case []string: + chain, args = arg, args[1:] } + } + + var v interface{} + if chain == nil { + v = m.Confv(key) + } else { + v = m.Confv(key, chain) + } + + table, _ := v.([]interface{}) + value, _ := v.(map[string]interface{}) + if len(args) == 0 { return value } - value := "" - switch v := arg[0].(type) { - case map[string]interface{}: - conf = v[key].(string) - value = m.Option(key) - arg = arg[1:] - case string: - value, arg = v, arg[1:] - case []string: - which := 0 - if len(arg) > 1 { - if x, ok := arg[1].(int); ok { - which, arg = x, arg[2:] + switch fun := args[0].(type) { + case func(map[string]interface{}): + fun(value) + case func(string, map[string]interface{}): + for k, v := range value { + if val, ok := v.(map[string]interface{}); ok { + fun(k, val) } } - if which < len(v) { - value = v[which] + case func(int, map[string]interface{}): + for i, v := range table { + if val, ok := v.(map[string]interface{}); ok { + fun(i, val) + } } - default: - if x := fmt.Sprintf("%v", v); v != nil && x != "" { - value, arg = x, arg[1:] - } - } - - force := false - if len(arg) > 0 { - if v, ok := arg[0].(bool); ok { - force, arg = v, arg[1:] - } - } - if !force && value == "" { - value = conf - } - - format := "%s" - if len(arg) > 0 { - if v, ok := arg[0].(string); ok { - format, arg = v, arg[1:] - } - } - if value != "" { - args := []interface{}{value} - for _, v := range arg { - args = append(args, v) - } - value = fmt.Sprintf(format, args...) } return value } -func (m *Message) Confs(key string, arg ...interface{}) bool { - index, value := "", m.Conf(key) - if len(arg) > 0 { - switch v := arg[0].(type) { - case string: - index, arg, value = v, arg[1:], m.Conf(key, v) - case []string: - index = strings.Join(v, ".") - arg, value = arg[1:], m.Conf(key, index) - } +func (m *Message) Confx(key string, args ...interface{}) string { + value := kit.Select(m.Conf(key), m.Option(key)) + if len(args) == 0 { + return value } - if len(arg) > 0 { - val := "0" - if t, ok := arg[0].(bool); ok && t { - val = "1" - } - - if index != "" { - value = m.Conf(key, index, val) + switch arg := args[0].(type) { + case []string: + if len(args) > 1 { + value, args = kit.Select(value, arg, args[1]), args[1:] } else { - value = m.Conf(key, val) + value = kit.Select(value, arg) } + case map[string]interface{}: + value = kit.Select(value, kit.Format(arg[key])) + case string: + value = kit.Select(value, arg) + case nil: + default: + value = kit.Select(value, args[0]) } - return Right(value) || Right(m.Confv(key, arg...)) + 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 { + args = append(args, 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 { - index, value := "", m.Conf(key) - if len(arg) > 0 { - if i, ok := arg[0].(string); ok { - arg, index, value = arg[1:], i, m.Conf(key, i) - } - } - - n, e := strconv.Atoi(value) - m.Assert(e) - - if len(arg) > 0 { - if index != "" { - n, e = strconv.Atoi(m.Conf(key, index, fmt.Sprintf("%d", arg[0]))) - } else { - n, e = strconv.Atoi(m.Conf(key, fmt.Sprintf("%d", arg[0]))) - } - m.Assert(e) - } - - return n + return kit.Int(m.Confv(key, arg...)) } func (m *Message) Confv(key string, args ...interface{}) interface{} { - var hand func(m *Message, x *Config, arg ...string) string - arg := Trans(args...) - - for _, c := range []*Context{m.target, m.source, m.Sess("aaa", false).target, m.Sess("cli", false).target} { - for s := c; s != nil; s = s.context { - if x, ok := s.Configs[key]; ok { - if len(args) == 0 { - return x.Value - } - if len(arg) == 3 { - hand = x.Hand - } - - switch x.Value.(type) { - case string: - x.Value = fmt.Sprintf("%v", arg[0]) - case bool: - x.Value = Right(fmt.Sprintf("%v", args[0])) - case int: - i, e := strconv.Atoi(fmt.Sprintf("%v", args[0])) - m.Assert(e) - x.Value = i - case nil: - x.Value = args[0] - default: - for i := 0; i < len(args); i += 2 { - if i < len(args)-1 { - x.Value = Chain(m, x.Value, args[i], args[i+1]) - } - if i == len(args)-2 { - return Chain(m, x.Value, args[len(args)-2]) - } - if i == len(args)-1 { - return Chain(m, x.Value, args[len(args)-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 { - return nil + if config == nil { + return nil + } + return config.Value } - m.Log("conf", "%s %v", key, args) - if m.target.Configs == nil { - m.target.Configs = make(map[string]*Config) - } - if len(arg) == 3 { - m.target.Configs[key] = &Config{Name: arg[0], Value: arg[1], Help: arg[2], Hand: hand} - return m.Conf(key, arg[1]) - } - if !m.Confs("auto_make") { - return nil + if config == nil { + config = &Config{} + m.target.Configs[key] = config } - if len(arg) == 1 { - m.target.Configs[key] = &Config{Name: key, Value: arg[0], Help: "auto make", Hand: hand} - return m.Conf(key, arg[0]) + 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]) + } + } } - m.target.Configs[key] = &Config{Name: key, Value: Chain(m, nil, args), Help: "auto make", Hand: hand} - return Chain(m, key, args[len(args)-2+(len(args)%2)]) + + return config.Value } func (m *Message) Conf(key string, args ...interface{}) string { - var hand func(m *Message, x *Config, arg ...string) string - - for _, c := range []*Context{m.target, m.source} { - for s := c; s != nil; s = s.context { - if x, ok := s.Configs[key]; ok { - switch value := x.Value.(type) { - case string: - val := "" - if len(args) > 0 { - switch v := args[0].(type) { - case string: - val = v - case nil: - default: - val = fmt.Sprintf("%v", v) - - } - } - switch len(args) { - case 0: - if x.Hand != nil { - return x.Hand(m, x) - } - return value - case 1: - if x.Hand != nil { - x.Value = x.Hand(m, x, val) - } else { - x.Value = val - } - return value - default: - if hand == nil { - hand = x.Hand - } - } - case bool: - case int: - default: - values := "" - for i := 0; i < len(args); i += 2 { - if i < len(args)-1 { - x.Value = Chain(m, x.Value, args[i], args[i+1]) - } - - if val := Chain(m, x.Value, args[i]); val != nil { - values = fmt.Sprintf("%v", val) - } - } - - if len(args) == 0 && x.Value != nil { - values = fmt.Sprintf("%T", x.Value) - } - return values - } - } - } - } - - if len(args) > 0 { - m.Log("conf", "%s %v", key, args) - if m.target.Configs == nil { - m.target.Configs = make(map[string]*Config) - } - - arg := Trans(args...) - if len(arg) == 3 { - m.target.Configs[key] = &Config{Name: arg[0], Value: arg[1], Help: arg[2], Hand: hand} - return m.Conf(key, arg[1]) - } - if !m.Confs("auto_make") { - return "" - } - if len(arg) == 1 { - m.target.Configs[key] = &Config{Name: key, Value: arg[0], Help: "auto make", Hand: hand} - return m.Conf(key, arg[0]) - } - - var value interface{} - for i := 0; i < len(args)-1; i += 2 { - value = Chain(m, value, args[i], args[i+1]) - } - m.target.Configs[key] = &Config{Name: key, Value: value, Help: "auto make", Hand: hand} - if val := Chain(m, key, args[len(args)-2]); val != nil { - return fmt.Sprintf("%v", val) - } - } - - return "" + return kit.Format(m.Confv(key, args...)) } -func (m *Message) Caps(key string, arg ...bool) bool { +func (m *Message) Caps(key string, arg ...interface{}) bool { if len(arg) > 0 { - if arg[0] { - m.Cap(key, "1") - } else { - m.Cap(key, "0") - } + return kit.Right(m.Cap(key, arg...)) } - - return Right(m.Cap(key)) + return kit.Right(m.Cap(key)) } -func (m *Message) Capi(key string, arg ...int) int { - n, e := strconv.Atoi(m.Cap(key)) - m.Assert(e) - - for _, i := range arg { - if i == 0 { - i = -n - } - n, e = strconv.Atoi(m.Cap(key, fmt.Sprintf("%d", n+i))) - m.Assert(e) +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 ...string) string { - var hand func(m *Message, x *Cache, arg ...string) string - - for _, c := range []*Context{m.target, m.source} { - for s := c; s != nil; s = s.context { - if x, ok := s.Caches[key]; ok { - switch len(arg) { - case 3: - if hand == nil { - hand = x.Hand - } - case 1: - if x.Hand != nil { - x.Value = x.Hand(m, x, arg[0]) - } else { - x.Value = arg[0] - } - return x.Value - case 0: - if x.Hand != nil { - return x.Hand(m, x) - } - return x.Value - } - } +func (m *Message) Cap(key string, arg ...interface{}) string { + if len(arg) == 0 { + if val, ok := m.Gdb("cache", "read", key).(string); ok { + return val + } + } else { + if val, ok := m.Gdb("cache", "write", key, arg[0]).(string); ok { + return val } } - if len(arg) == 3 { - if m.target.Caches == nil { - m.target.Caches = make(map[string]*Cache) + 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 + }) - m.target.Caches[key] = &Cache{Name: arg[0], Value: arg[1], Help: arg[2], Hand: hand} - m.Log("cap", "%s %v", key, arg) - return m.Cap(key, arg[1]) + if len(arg) == 0 { + if cache == nil { + return "" + } + if cache.Hand != nil { + return cache.Hand(m, cache) + } + return cache.Value } - return "" + 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 } var CGI = template.FuncMap{ @@ -2496,7 +1851,7 @@ var CGI = template.FuncMap{ } cli := Pulse.Sess("cli") - cmd := strings.Join(Trans(arg), " ") + cmd := strings.Join(kit.Trans(arg), " ") cli.Cmd("source", cmd) result := []string{} @@ -2531,12 +1886,12 @@ var CGI = template.FuncMap{ }, } var Pulse = &Message{code: 0, time: time.Now(), source: Index, target: Index, Meta: map[string][]string{}} -var Index = &Context{Name: "ctx", Help: "模块中心", +var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, Caches: map[string]*Cache{ "begin_time": &Cache{Name: "begin_time", Value: "", Help: "启动时间"}, "nserver": &Cache{Name: "nserver", Value: "0", Help: "服务数量"}, "ncontext": &Cache{Name: "ncontext", Value: "0", Help: "模块数量"}, - "nmessage": &Cache{Name: "nmessage", Value: "0", Help: "消息数量"}, + "nmessage": &Cache{Name: "nmessage", Value: "1", Help: "消息数量"}, }, Configs: map[string]*Config{ "chain": &Config{Name: "chain", Value: map[string]interface{}{}, Help: "调试模式,on:打印,off:不打印)"}, @@ -2557,6 +1912,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", "table_compact": &Config{Name: "table_compact", Value: "false", Help: "命令列表帮助"}, "table_col_sep": &Config{Name: "table_col_sep", Value: "\t", Help: "命令列表帮助"}, "table_row_sep": &Config{Name: "table_row_sep", Value: "\n", Help: "命令列表帮助"}, + "table_space": &Config{Name: "table_space", Value: " ", Help: "命令列表帮助"}, "page_offset": &Config{Name: "page_offset", Value: "0", Help: "列表偏移"}, "page_limit": &Config{Name: "page_limit", Value: "10", Help: "列表大小"}, @@ -2564,7 +1920,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", "time_format": &Config{Name: "time_format", Value: "2006-01-02 15:04:05", Help: "时间格式"}, }, Commands: map[string]*Command{ - "help": &Command{Name: "help topic", Help: "帮助", Hand: func(m *Message, c *Context, key string, arg ...string) { + "help": &Command{Name: "help topic", Help: "帮助", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Echo("usage: help context [module [command|config|cache name]]\n") m.Echo(" : 查看模块信息, module: 模块名, command: 模块命令, config: 模块配置, cache: 模块缓存, name: 模块参数\n") @@ -2588,13 +1944,14 @@ var Index = &Context{Name: "ctx", Help: "模块中心", case 1: keys := []string{} values := map[string]*Context{} - m.Travel(func(m *Message, i int) bool { + m.Target().root.Travel(m, func(m *Message, i int) bool { if _, ok := values[m.Cap("module")]; !ok { keys = append(keys, m.Cap("module")) values[m.Cap("module")] = m.Target() } - return true - }, m.Target().root) + return false + }) + sort.Strings(keys) for _, k := range keys { m.Echo("%s: %s %s\n", k, values[k].Name, values[k].Help) @@ -2714,9 +2071,10 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } + return }}, - "message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { + "message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { msg := m if ms := m.Find(m.Cap("ps_target")); ms != nil { msg = ms @@ -2777,8 +2135,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Add("append", "options", fmt.Sprintf("%v", v.Meta["option"])) } m.Table() + return }}, - "detail": &Command{Name: "detail [index] [value...]", Help: "查看或添加参数", Hand: func(m *Message, c *Context, key string, arg ...string) { + "detail": &Command{Name: "detail [index] [value...]", Help: "查看或添加参数", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { msg := m.message if len(arg) == 0 { for i, v := range msg.Meta["detail"] { @@ -2794,8 +2153,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", index, arg = i, arg[1:] } m.Echo("%s", msg.Detail(index, arg)) + return }}, - "option": &Command{Name: "option [all] [key [index] [value...]]", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) { + "option": &Command{Name: "option [all] [key [index] [value...]]", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { all := false if len(arg) > 0 && arg[0] == "all" { all, arg = true, arg[1:] @@ -2827,13 +2187,13 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } if len(arg) > 1 { - msg.Meta[k] = Array(msg.Meta[k], index, arg[1:]) + msg.Meta[k] = kit.Array(msg.Meta[k], index, arg[1:]) m.Echo("%v", msg.Meta[k]) return } if index != -100 { - m.Echo(Array(msg.Meta[k], index)[0]) + m.Echo(kit.Array(msg.Meta[k], index)[0]) return } @@ -2850,8 +2210,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } m.Sort("key", "string").Table() + return }}, - "result": &Command{Name: "result [index] [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) { + "result": &Command{Name: "result [index] [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { msg := m.message if len(arg) == 0 { for i, v := range msg.Meta["result"] { @@ -2867,8 +2228,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", index, arg = i, arg[1:] } m.Echo("%s", msg.Result(index, arg)) + return }}, - "append": &Command{Name: "append [all] [key [index] [value...]]", Help: "查看或添加附加值", Hand: func(m *Message, c *Context, key string, arg ...string) { + "append": &Command{Name: "append [all] [key [index] [value...]]", Help: "查看或添加附加值", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { all := false if len(arg) > 0 && arg[0] == "all" { all, arg = true, arg[1:] @@ -2899,13 +2261,13 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } if len(arg) > 1 { - msg.Meta[k] = Array(msg.Meta[k], index, arg[1:]) + msg.Meta[k] = kit.Array(msg.Meta[k], index, arg[1:]) m.Echo("%v", msg.Meta[k]) return } if index != -100 { - m.Echo(Array(msg.Meta[k], index)[0]) + m.Echo(kit.Array(msg.Meta[k], index)[0]) return } @@ -2922,8 +2284,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } m.Table() + return }}, - "session": &Command{Name: "session [all] [key [module]]", Help: "查看或添加会话", Hand: func(m *Message, c *Context, key string, arg ...string) { + "session": &Command{Name: "session [all] [key [module]]", Help: "查看或添加会话", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { all := false if len(arg) > 0 && arg[0] == "all" { all, arg = true, arg[1:] @@ -2957,19 +2320,21 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } m.Table() + return }}, - "callback": &Command{Name: "callback", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { + "callback": &Command{Name: "callback", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { msg := m.message for msg := msg; msg != nil; msg = msg.message { m.Add("append", "msg", msg.code) m.Add("append", "fun", msg.callback) } m.Table() + return }}, "context": &Command{Name: "context [find|search] [root|back|home] [first|last|rand|magic] [module] [cmd|switch|list|spawn|start|close]", Help: "查找并操作模块;\n查找方法, find: 精确查找, search: 模糊搜索;\n查找起点, root: 根模块, back: 父模块, home: 本模块;\n过滤结果, first: 取第一个, last: 取最后一个, rand: 随机选择, magic: 智能选择;\n操作方法, cmd: 执行命令, switch: 切换为当前, list: 查看所有子模块, spwan: 创建子模块并初始化, start: 启动模块, close: 结束模块", - Hand: func(m *Message, c *Context, key string, arg ...string) { + Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { if len(arg) == 1 && arg[0] == "~" && m.target.context != nil { m.target = m.target.context return @@ -3070,7 +2435,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", case "switch": m.target = msg.target case "list": - msg.Travel(func(msg *Message, n int) bool { + m.Target().Travel(msg, func(msg *Message, n int) bool { m.Add("append", "name", msg.target.Name) if msg.target.context != nil { m.Add("append", "ctx", msg.target.context.Name) @@ -3097,10 +2462,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", if action == "list" { m.Table() } + return }}, "command": &Command{Name: "command [all] [show]|[list [begin [end]] [prefix] test [key val]...]|[add [list_name name] [list_help help] cmd...]|[delete cmd]", Help: "查看或修改命令, show: 查看命令;\nlist: 查看列表命令, begin: 起始索引, end: 截止索引, prefix: 过滤前缀, test: 执行命令;\nadd: 添加命令, list_name: 命令别名, list_help: 命令帮助;\ndelete: 删除命令", - Hand: func(m *Message, c *Context, key string, arg ...string) { + Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { all := false if len(arg) > 0 && arg[0] == "all" { all, arg = true, arg[1:] @@ -3116,7 +2482,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", switch action { case "show": - m.BackTrace(func(m *Message) bool { + c.BackTrace(m, func(m *Message) bool { for k, v := range m.target.Commands { if len(arg) > 0 { if k == arg[0] { @@ -3130,7 +2496,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } - return all + return !all }) m.Table() case "list": @@ -3201,7 +2567,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", list_help, arg = arg[1], arg[2:] } - m.target.Commands[m.Cap("list_count")] = &Command{Name: strings.Join(arg, " "), Help: list_help, Hand: func(cmd *Message, c *Context, key string, args ...string) { + m.target.Commands[m.Cap("list_count")] = &Command{Name: strings.Join(arg, " "), Help: list_help, Hand: func(cmd *Message, c *Context, key string, args ...string) (e error) { list := []string{} for _, v := range arg { if v == "__" { @@ -3225,6 +2591,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", msg := cmd.Sess("cli").Cmd("source", strings.Join(list, " ")) cmd.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") + return }} if list_name != "" { @@ -3232,15 +2599,16 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } m.Capi("list_count", 1) case "delete": - m.BackTrace(func(m *Message) bool { + c.BackTrace(m, func(m *Message) bool { delete(m.target.Commands, arg[0]) - return all + return !all }) } + return }}, "config": &Command{Name: "config [all] [export key..] [save|load file key...] [list|map arg...] [create map|list|string key name help] [delete key]", Help: "配置管理, export: 导出配置, save: 保存配置到文件, load: 从文件加载配置, create: 创建配置, delete: 删除配置", - Hand: func(m *Message, c *Context, key string, arg ...string) { + Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { if len(arg) > 2 && arg[2] == "list" { chain := strings.Split(arg[1], ".") chain = append(chain, "-2") @@ -3288,7 +2656,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", if action == "load" { f, e := os.Open(m.Sess("nfs").Cmd("path", which).Result(0)) if e != nil { - return + return e } defer f.Close() @@ -3298,7 +2666,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } - m.BackTrace(func(m *Message) bool { + c.BackTrace(m, func(m *Message) bool { for k, v := range m.target.Configs { switch action { case "export", "save": @@ -3335,7 +2703,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } m.target.Configs[arg[1]] = &Config{Name: arg[2], Value: value, Help: arg[3]} } - return all + return !all }) m.Sort("key", "str").Table() @@ -3363,10 +2731,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", msg := m.Spawn().Put("option", "_cache", value).Cmd("trans", "_cache") m.Copy(msg, "append").Copy(msg, "result") + return }}, "cache": &Command{Name: "cache [all] |key [value]|key = value|key name value help|delete key]", Help: "查看、读写、赋值、新建、删除缓存变量", - Hand: func(m *Message, c *Context, key string, arg ...string) { + Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { all := false if len(arg) > 0 && arg[0] == "all" { arg, all = arg[1:], true @@ -3374,13 +2743,13 @@ var Index = &Context{Name: "ctx", Help: "模块中心", switch len(arg) { case 0: - m.BackTrace(func(m *Message) bool { + c.BackTrace(m, func(m *Message) bool { for k, v := range m.target.Caches { m.Add("append", "key", k) m.Add("append", "value", m.Cap(k)) m.Add("append", "name", v.Name) } - return all + return !all }) m.Sort("key", "str").Table() return @@ -3393,12 +2762,13 @@ var Index = &Context{Name: "ctx", Help: "模块中心", case 3: m.Cap(arg[0], arg[0], arg[2], arg[0]) default: - m.Echo(m.Cap(arg[0], arg[1:]...)) + m.Echo(m.Cap(arg[0], arg[1:])) return } + return }}, - "trans": &Command{Name: "trans option [type|data|json] limit 10 [index...]", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) { + "trans": &Command{Name: "trans option [type|data|json] limit 10 [index...]", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { value, arg := m.Optionv(arg[0]), arg[1:] view := "data" @@ -3411,12 +2781,12 @@ var Index = &Context{Name: "ctx", Help: "模块中心", limit := m.Confi("page_limit") if len(arg) > 0 && arg[0] == "limit" { - limit, arg = Int(arg[1]), arg[2:] + limit, arg = kit.Int(arg[1]), arg[2:] } chain := strings.Join(arg, ".") if chain != "" { - value = Chain(m, value, chain) + value = kit.Chain(value, chain) } switch view { @@ -3446,7 +2816,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", b, e := json.MarshalIndent(value, "", " ") m.Assert(e) m.Echo(string(b)) - return + return nil } switch val := value.(type) { @@ -3543,10 +2913,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", b, _ := json.Marshal(val) m.Echo("%s", string(b)) } + return }}, "select": &Command{Name: "select key value field", Form: map[string]int{"parse": 2, "hide": 1, "fields": -1, "group": 1, "order": 2, "limit": 1, "offset": 1, "format": -1, "trans_map": -1, "vertical": 0}, - Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) { + Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { msg := m.Set("result").Spawn() // 解析 @@ -3560,7 +2931,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", var value interface{} json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value) if m.Meta["parse"][j+1] != "" { - value = Chain(m, value, m.Meta["parse"][j+1]) + value = kit.Chain(value, m.Meta["parse"][j+1]) } switch val := value.(type) { @@ -3583,7 +2954,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", var value interface{} json.Unmarshal([]byte(m.Meta[m.Meta["parse"][j]][i]), &value) if m.Meta["parse"][j+1] != "" { - value = Chain(m, value, m.Meta["parse"][j+1]) + value = kit.Chain(value, m.Meta["parse"][j+1]) } switch val := value.(type) { @@ -3629,7 +3000,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", // 选择列 if m.Option("fields") != "" { msg = m.Spawn() - msg.Copy(m, "append", strings.Split(strings.Join(m.Meta["fields"], " "), " ")...) + m.Hand = true + msg.Copy(m, strings.Split(strings.Join(m.Meta["fields"], " "), " ")...) + m.Hand = false m.Set("append").Copy(msg, "append") } @@ -3756,35 +3129,47 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } m.Set("result").Table() + return }}, }, } -func Start() { - Index.root = Index - Pulse.root = Pulse - - for _, m := range Pulse.Search("") { - m.target.root = Index - m.target.Begin(m) - } - - Pulse.Sess("ctx", Index) - for k, c := range Index.contexts { - Pulse.Sess(k, c) - } - Pulse.Cap("begin_time", time.Now().Format(Pulse.Conf("time_format"))) - - args := os.Args[1:] - if len(args) > 0 { - if strings.HasSuffix(args[0], ".log") { - Pulse.Sess("log", false).Conf("bench.log", args[0]) - args = args[1:] - } - } - - Pulse.Sess("yac", false).Cmd("init") - for _, v := range Pulse.Sess("cli", false).Cmd("source", args).Meta["result"] { - fmt.Printf("%v", v) - } +type CTX struct { +} + +func (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server { + s := new(CTX) + return s +} +func (ctx *CTX) Begin(m *Message, arg ...string) Server { + m.Sess(m.target.Name, m) + m.target.root = m.target + m.root = m + m.Cap("begin_time", m.Time()) + for _, msg := range m.Search("") { + msg.target.root = m.target + if msg.target == m.target { + continue + } + msg.target.Begin(msg, arg...) + m.Sess(msg.target.Name, msg) + } + return ctx +} +func (ctx *CTX) Start(m *Message, arg ...string) bool { + m.Cmd("cli.source", arg) + return false +} +func (ctx *CTX) Close(m *Message, arg ...string) bool { + return true +} + +func Start(args ...string) bool { + if len(args) == 0 { + args = append(args, os.Args[1:]...) + } + + if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) { + } + return false } diff --git a/src/contexts/gdb/gdb.go b/src/contexts/gdb/gdb.go index 5e9b42e1..3b512622 100644 --- a/src/contexts/gdb/gdb.go +++ b/src/contexts/gdb/gdb.go @@ -2,13 +2,62 @@ package gdb import ( "contexts/ctx" + "os" + "os/signal" + "syscall" + "toolkit" ) type GDB struct { + wait chan interface{} + goon chan os.Signal + *ctx.Context } -func (gdb *GDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ +func (gdb *GDB) Value(m *ctx.Message, arg ...interface{}) bool { + if value, ok := kit.Chain(gdb.Configs["debug"].Value, append(arg, "value")).(map[string]interface{}); ok { + if !kit.Right(value["enable"]) { + return false + } + + if kit.Right(value["source"]) && kit.Format(value["source"]) != m.Source().Name { + return false + } + + if kit.Right(value["target"]) && kit.Format(value["target"]) != m.Target().Name { + return false + } + + m.Log("error", "value %v %v", arg, kit.Formats(value)) + return true + } + return false +} +func (gdb *GDB) Wait(m *ctx.Message, arg ...interface{}) interface{} { + for i := len(arg); i > 0; i-- { + if gdb.Value(m, arg[:i]...) { + if result := kit.Chain(kit.Chain(gdb.Configs["debug"].Value, arg[:i]), []string{"value", "result"}); result != nil { + m.Log("error", "done %d %v", len(arg[:i]), arg) + return result + } + m.Log("error", "wait %d %v", len(arg[:i]), arg) + result := <-gdb.wait + m.Log("error", "done %d %v %v", len(arg[:i]), arg, result) + return result + } + } + return <-gdb.wait + + return nil +} +func (gdb *GDB) Goon(result interface{}, arg ...interface{}) { + m := gdb.Message() + m.Log("error", "goon %v %v", arg, result) + gdb.wait <- result +} + +func (gdb *GDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{} c.Configs = map[string]*ctx.Config{} @@ -16,19 +65,28 @@ func (gdb *GDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server s.Context = c return s } +func (gdb *GDB) Begin(m *ctx.Message, arg ...string) ctx.Server { + gdb.goon = make(chan os.Signal, 10) + gdb.wait = make(chan interface{}, 10) + m.Log("debug", "pid %d", os.Getpid()) + + signal.Notify(gdb.goon, syscall.Signal(19)) + go func() { + for { + select { + case sig := <-gdb.goon: + m.Log("error", "signal %v", sig) + gdb.Goon("hello", "cache", "read", "value") + } + } + }() -// }}} -func (gdb *GDB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ return gdb } - -// }}} -func (gdb *GDB) Start(m *ctx.Message, arg ...string) bool { // {{{ +func (gdb *GDB) Start(m *ctx.Message, arg ...string) bool { return false } - -// }}} -func (gdb *GDB) Close(m *ctx.Message, arg ...string) bool { // {{{ +func (gdb *GDB) Close(m *ctx.Message, arg ...string) bool { switch gdb.Context { case m.Target(): case m.Source(): @@ -37,8 +95,40 @@ func (gdb *GDB) Close(m *ctx.Message, arg ...string) bool { // {{{ } var Index = &ctx.Context{Name: "gdb", Help: "调试中心", - Caches: map[string]*ctx.Cache{}, - Configs: map[string]*ctx.Config{}, + Caches: map[string]*ctx.Cache{}, + Configs: map[string]*ctx.Config{ + "debug": &ctx.Config{Name: "debug", Value: map[string]interface{}{ + "value": map[string]interface{}{ + "enable": true, + }, + "command": map[string]interface{}{ + "value": map[string]interface{}{ + "enable": true, + }, + }, + "config": map[string]interface{}{ + "value": map[string]interface{}{ + "enable": true, + }, + }, + "cache": map[string]interface{}{ + "value": map[string]interface{}{ + "enable": true, + }, + "read": map[string]interface{}{ + "value": map[string]interface{}{ + "enable": true, + }, + "ncontext": map[string]interface{}{ + "value": map[string]interface{}{ + "enable": true, + "result": "hello", + }, + }, + }, + }, + }}, + }, Commands: map[string]*ctx.Command{}, } diff --git a/src/contexts/lex/lex.go b/src/contexts/lex/lex.go index c681ec63..60eadc8b 100644 --- a/src/contexts/lex/lex.go +++ b/src/contexts/lex/lex.go @@ -282,7 +282,7 @@ func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { lex.Configs["compact"] = &ctx.Config{Name: "紧凑模式", Value: "true", Help: "词法状态的共用"} if len(arg) > 0 { - if _, e := strconv.Atoi(arg[0]); m.Assert(e) { + if _, e := strconv.Atoi(arg[0]); e == nil { m.Cap("nlang", arg[0]) m.Cap("nline", arg[0]) } @@ -325,12 +325,13 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", "nhash": &ctx.Config{Name: "nhash", Value: "1", Help: "npage"}, }, Commands: map[string]*ctx.Command{ - "spawn": &ctx.Command{Name: "spawn", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "spawn": &ctx.Command{Name: "spawn", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*LEX); m.Assert(ok) { m.Start(fmt.Sprintf("matrix%d", m.Capi("nmat", 1)), "matrix") } + return }}, - "train": &ctx.Command{Name: "train seed [hash [page]", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "train": &ctx.Command{Name: "train seed [hash [page]", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { page := lex.index(m, "npage", m.Confx("npage", arg, 2)) hash := lex.index(m, "nhash", m.Confx("nhash", arg, 1)) @@ -342,15 +343,17 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", lex.seed = append(lex.seed, &Seed{page, hash, arg[0]}) m.Cap("stream", fmt.Sprintf("%d,%s,%s", m.Capi("nseed", 1), m.Cap("npage"), m.Cap("nhash"))) } + return }}, - "parse": &ctx.Command{Name: "parse line [page]", Help: "解析单词", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "parse": &ctx.Command{Name: "parse line [page]", Help: "解析单词", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { page := lex.index(m, "npage", m.Confx("npage", arg, 1)) hash, rest, word := lex.parse(m, page, []byte(arg[0])) m.Result(0, hash, string(rest), string(word)) } + return }}, - "show": &ctx.Command{Name: "show seed|page|hash|mat", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "show": &ctx.Command{Name: "show seed|page|hash|mat", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if lex, ok := m.Target().Server.(*LEX); m.Assert(ok) { if len(arg) == 0 { m.Append("seed", len(lex.seed)) @@ -430,6 +433,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", m.Table() } } + return }}, }, } diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go index 58d24508..b900f753 100644 --- a/src/contexts/log/log.go +++ b/src/contexts/log/log.go @@ -88,14 +88,15 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", "log_name": &ctx.Config{Name: "log_name", Value: "dump", Help: "日志屏蔽类型"}, }, Commands: map[string]*ctx.Command{ - "init": &ctx.Command{Name: "init file", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "init": &ctx.Command{Name: "init file", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if log, ok := m.Target().Server.(*LOG); ok { log.out = m.Sess("nfs").Cmd("open", m.Confx("bench.log", arg, 0)).Optionv("out").(*os.File) log.out.Truncate(0) fmt.Fprintln(log.out, "\n\n") } + return }}, - "log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if log, ok := m.Target().Server.(*LOG); m.Assert(ok) && log.out != nil { if m.Confs("silent", arg[0]) { return @@ -120,6 +121,7 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", log.out.WriteString(fmt.Sprintf("%s%s %s\n", date, action, cmd)) } } + return }}, }, } diff --git a/src/contexts/mdb/mdb.go b/src/contexts/mdb/mdb.go index 2d6e8c94..ae0db6aa 100644 --- a/src/contexts/mdb/mdb.go +++ b/src/contexts/mdb/mdb.go @@ -7,6 +7,7 @@ import ( "fmt" _ "github.com/go-sql-driver/mysql" "strings" + "toolkit" ) type MDB struct { @@ -78,7 +79,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", "temp_view": &ctx.Config{Name: "temp_view", Value: map[string]interface{}{}, Help: "缓存数据"}, }, Commands: map[string]*ctx.Command{ - "temp": &ctx.Command{Name: "temp [type [meta [data]]] [tid [node|ship|data] [chain... [select ...]]]", Form: map[string]int{"select": -1}, Help: "缓存数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "temp": &ctx.Command{Name: "temp [type [meta [data]]] [tid [node|ship|data] [chain... [select ...]]]", Form: map[string]int{"select": -1}, Help: "缓存数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 2 { // 添加数据 if temp := m.Confm("temp", arg[0]); temp == nil { h := m.Cmdx("aaa.hash", arg[0], arg[1]) @@ -189,7 +190,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", } } - arg, h := ctx.Slice(arg) + arg, h := kit.Slice(arg) if h != "" { if temp := m.Confm("temp", h); temp != nil { m.Echo(h) @@ -207,12 +208,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", } }) m.Sort("create_time", "time_r").Table().Cmd("select", m.Optionv("select")) + return }}, "open": &ctx.Command{Name: "open [database [username [password [address [protocol [driver]]]]]]", Help: "open打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型", Form: map[string]int{"dbname": 1, "dbhelp": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { dbname := fmt.Sprintf("db%d", m.Capi("nsource", 1)) dbhelp := "数据源" if m.Has("dbname") { @@ -222,8 +224,9 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", dbname = m.Option("dbhelp") } m.Start(dbname, dbhelp, arg...) + return }}, - "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 操作参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 操作参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil { which := make([]interface{}, 0, len(arg)) for _, v := range arg[1:] { @@ -240,8 +243,9 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", m.Log("info", "last(%s) nrow(%s)", m.Append("last", id), m.Append("nrow", n)) m.Echo("%d", n) } + return }}, - "query": &ctx.Command{Name: "query sql [arg]", Help: "查询数据库, sql: SQL语句, arg: 查询参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "query": &ctx.Command{Name: "query sql [arg]", Help: "查询数据库, sql: SQL语句, arg: 查询参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil { which := make([]interface{}, 0, len(arg)) for _, v := range arg[1:] { @@ -284,8 +288,9 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", m.Log("info", "rows(0) cols(0)") } } + return }}, - "db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil { if len(arg) == 0 { msg := m.Spawn().Cmd("query", "show databases") @@ -302,8 +307,9 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", m.Assert(m.Spawn().Cmd("exec", fmt.Sprintf("use %s", db))) m.Echo(m.Cap("database", db)) } + return }}, - "tab": &ctx.Command{Name: "tab[which [field]]", Help: "查看关系表信息,which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "tab": &ctx.Command{Name: "tab[which [field]]", Help: "查看关系表信息,which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*MDB); m.Assert(ok) { if len(arg) == 0 { msg := m.Spawn().Cmd("query", "show tables") @@ -326,12 +332,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", m.Copy(msg, "append") m.Table() } + return }}, "show": &ctx.Command{Name: "show table fields...", Help: "查询数据库, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段", Form: map[string]int{"like": 2, "eq": 2, "where": 1, "group": 1, "desc": 0, "order": 1, "limit": 1, "offset": 1, "other": -1, "extra_field": 2, "extra_fields": 1, "extra_format": 1, "trans_field": 1, "trans_map": 2}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*MDB); m.Assert(ok) { if len(arg) == 0 { msg := m.Spawn().Cmd("query", "show tables") @@ -456,15 +463,11 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", nrow := len(msg.Meta[msg.Meta["append"][0]]) m.Echo("data: %dx%d ", nrow, ncol) - m.Color(31, table).Echo(" %s %s %s %s %s %v\n", where, group, order, limit, offset, m.Meta["other"]) + m.Echo(table).Echo(" %s %s %s %s %s %v\n", where, group, order, limit, offset, m.Meta["other"]) m.Table(func(maps map[string]string, lists []string, line int) bool { for i, v := range lists { - if line == -1 { - m.Color(32, v) - } else { - m.Echo(v) - } + m.Echo(v) if i < len(lists)-1 { m.Echo(m.Conf("csv_col_sep")) } @@ -473,8 +476,9 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", return true }) } + return }}, - "set": &ctx.Command{Name: "set table [field value] where condition", Help: "查看或选择数据库信息", Form: map[string]int{"where": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "set": &ctx.Command{Name: "set table [field value] where condition", Help: "查看或选择数据库信息", Form: map[string]int{"where": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil { sql := []string{"update", arg[0], "set"} fields := []string{} @@ -490,6 +494,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", msg := m.Spawn().Cmd("show", arg[0], fields, "where", m.Option("where")) m.Copy(msg, "result").Copy(msg, "append") } + return }}, }, } diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index bfc6b063..769a0a85 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" "time" + "toolkit" "unicode" ) @@ -513,15 +514,15 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { case termbox.KeyCtrlI: if len(tab) == 0 { tabi = 0 - prefix := string(buf) - nfs.Message.BackTrace(func(m *ctx.Message) bool { - for k, _ := range m.Target().Commands { - if strings.HasPrefix(k, prefix) { - tab = append(tab, k[len(prefix):]) - } - } - return true - }, nfs.Optionv("ps_target").(*ctx.Context)) + // prefix := string(buf) + // nfs.Message.BackTrace(func(m *ctx.Message) bool { + // for k, _ := range m.Target().Commands { + // if strings.HasPrefix(k, prefix) { + // tab = append(tab, k[len(prefix):]) + // } + // } + // return true + // }, nfs.Optionv("ps_target").(*ctx.Context)) } if tabi >= 0 && tabi < len(tab) { @@ -844,7 +845,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "paths": &ctx.Config{Name: "paths", Value: []interface{}{"var", "usr", "etc", ""}, Help: "文件路径"}, }, Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{ m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message { sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件") @@ -857,9 +858,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", }) }, m.Meta["detail"]) } - + return }}, - "dial": &ctx.Command{Name: "dial args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "dial": &ctx.Command{Name: "dial args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message { sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件") @@ -873,16 +874,18 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", }, m.Meta["detail"]) } + return }}, - "send": &ctx.Command{Name: "send [file] args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "send": &ctx.Command{Name: "send [file] args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.io != nil { m.Remote = make(chan bool, 1) nfs.send <- m <-m.Remote } + return }}, - "scan": &ctx.Command{Name: "scan file name", Help: "扫描文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "scan": &ctx.Command{Name: "scan file name", Help: "扫描文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { help := fmt.Sprintf("scan %s", arg[0]) @@ -898,8 +901,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Start(m.Confx("nfs_name", arg, 1), help, key, p) } } + return }}, - "prompt": &ctx.Command{Name: "prompt arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "prompt": &ctx.Command{Name: "prompt arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { nfs.prompt() for _, v := range arg { @@ -907,8 +911,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Echo(v) } } + return }}, - "exec": &ctx.Command{Name: "exec cmd", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "exec": &ctx.Command{Name: "exec cmd", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { nfs.prompt() for _, v := range arg { @@ -923,30 +928,34 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } nfs.out.WriteString("\n") } + return }}, - "show": &ctx.Command{Name: "show arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "show": &ctx.Command{Name: "show arg", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { for _, v := range arg { nfs.out.WriteString(v) m.Echo(v) } } + return }}, - "open": &ctx.Command{Name: "open file name", Help: "打开文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "open": &ctx.Command{Name: "open file name", Help: "打开文件, file: 文件名, name: 模块名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { file := arg[0] if m.Has("io") { + } else if p, f, e := open(m, file, os.O_RDWR|os.O_CREATE); e == nil { m.Put("option", "in", f).Put("option", "out", f) file = p } else { - return + return nil } m.Start(m.Confx("nfs_name", arg, 1), fmt.Sprintf("file %s", file), "open", file) m.Echo(file) + return }}, - "read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil { n, e := strconv.Atoi(m.Confx("buf_size", arg, 0)) m.Assert(e) @@ -966,8 +975,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Cap("pos", "0") } } + return }}, - "write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { if len(arg) > 1 { m.Cap("pos", arg[1]) @@ -987,9 +997,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Echo(m.Cap("pos")) } + return }}, - "load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if p, f, e := open(m, arg[0]); m.Assert(e) { defer f.Close() @@ -1009,8 +1020,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Echo(string(buf[:l])) } } + return }}, - "save": &ctx.Command{Name: "save file string...", Help: "保存文件, file: 保存的文件, string: 保存的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "save": &ctx.Command{Name: "save file string...", Help: "保存文件, file: 保存的文件, string: 保存的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 1 && m.Has("data") { arg = append(arg, m.Option("data")) } @@ -1025,8 +1037,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Log("info", "save %s %d", p, n) } } + return }}, - "print": &ctx.Command{Name: "print file string...", Help: "输出文件, file: 输出的文件, string: 输出的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "print": &ctx.Command{Name: "print file string...", Help: "输出文件, file: 输出的文件, string: 输出的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if p, f, e := open(m, arg[0], os.O_WRONLY|os.O_CREATE|os.O_APPEND); m.Assert(e) { defer f.Close() @@ -1036,8 +1049,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Log("info", "print %s %d", p, n) } } + return }}, - "export": &ctx.Command{Name: "export filename", Help: "导出数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "export": &ctx.Command{Name: "export filename", Help: "导出数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { name := time.Now().Format(arg[0]) _, f, e := open(m, name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC) m.Assert(e) @@ -1083,8 +1097,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } } m.Set("append").Set("result").Add("append", "directory", name).Echo(name) + return }}, - "import": &ctx.Command{Name: "import filename [index]", Help: "导入数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "import": &ctx.Command{Name: "import filename [index]", Help: "导入数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { _, f, e := open(m, arg[0]) m.Assert(e) defer f.Close() @@ -1111,9 +1126,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } m.Table() } + return }}, - "pwd": &ctx.Command{Name: "pwd [all] | [[index] path] ", Help: "工作目录,all: 查看所有, index path: 设置路径, path: 设置当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "pwd": &ctx.Command{Name: "pwd [all] | [[index] path] ", Help: "工作目录,all: 查看所有, index path: 设置路径, path: 设置当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 0 && arg[0] == "all" { list := m.Confv("paths").([]interface{}) for i, v := range list { @@ -1139,8 +1155,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", wd, e := os.Getwd() m.Assert(e) m.Echo("%s", path.Join(wd, p)) + return }}, - "path": &ctx.Command{Name: "path file", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "path": &ctx.Command{Name: "path file", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { for _, v := range m.Confv("paths").([]interface{}) { p := path.Join(v.(string), arg[0]) if _, e := os.Stat(p); e == nil { @@ -1148,8 +1165,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", break } } + return }}, - "json": &ctx.Command{Name: "json [key value]...", Help: "生成格式化内容, key: 参数名, value: 参数值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "json": &ctx.Command{Name: "json [key value]...", Help: "生成格式化内容, key: 参数名, value: 参数值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 1 { var data interface{} json.Unmarshal([]byte(arg[0]), &data) @@ -1157,7 +1175,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", buf, e := json.MarshalIndent(data, "", " ") m.Assert(e) m.Echo(string(buf)) - return + return e } if len(arg) > 1 && arg[0] == "file" { @@ -1170,7 +1188,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", buf, e := json.MarshalIndent(data, "", " ") m.Assert(e) m.Echo(string(buf)) - return + return e } data := map[string]interface{}{} @@ -1190,20 +1208,22 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Assert(e) m.Echo(string(buf)) + return }}, - "genqr": &ctx.Command{Name: "genqr [qr_size size] filename string...", Help: "生成二维码图片, qr_size: 图片大小, filename: 文件名, string: 输出内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "genqr": &ctx.Command{Name: "genqr [qr_size size] filename string...", Help: "生成二维码图片, qr_size: 图片大小, filename: 文件名, string: 输出内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if size, e := strconv.Atoi(m.Confx("qr_size")); m.Assert(e) { p := path.Join(m.Confv("paths", 0).(string), arg[0]) qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, p) m.Log("info", "genqr %s", p) m.Append("directory", p) } + return }}, "dir": &ctx.Command{Name: "dir dir [dir_type both|file|dir] [dir_deep] fields...", Help: "查看目录, dir: 目录名, dir_type: 文件类型, dir_deep: 递归查询, fields: 查询字段", Form: map[string]int{"dir_reg": 1, "dir_type": 1, "dir_deep": 0, "dir_sort": 2}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { wd, e := os.Getwd() m.Assert(e) trip := len(wd) + 1 @@ -1222,12 +1242,12 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", d := path.Join(v.(string), dirs) if s, e := os.Stat(d); e == nil { if s.IsDir() { - dir(m, d, 0, ctx.Right(m.Has("dir_deep")), m.Confx("dir_type"), trip, rg, + dir(m, d, 0, kit.Right(m.Has("dir_deep")), m.Confx("dir_type"), trip, rg, strings.Split(m.Confx("dir_fields", strings.Join(arg[1:], " ")), " "), m.Conf("time_format")) } else { m.Append("directory", d) - return + return e } break } @@ -1243,12 +1263,13 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } else { m.Table() } + return }}, "git": &ctx.Command{ Name: "git branch|status|diff|log|info arg... [dir path]...", Help: "版本控制, branch: 分支管理, status: 查看状态, info: 查看分支与状态, dir: 指定路径", Form: map[string]int{"dir": 1, "git_info": 1, "git_log": 1, "git_log_form": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { arg = []string{"info"} } @@ -1373,12 +1394,13 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Find("web.code").Cmd("counter", "npush", 1) } - m.Log("info", "cmd: %s %v", "git", ctx.Trans("-C", p, c, args)) + m.Log("info", "cmd: %s %v", "git", kit.Trans("-C", p, c, args)) msg := m.Sess("cli").Cmd("system", "git", "-C", p, c, args) m.Copy(msg, "result").Copy(msg, "append") m.Echo("\n") } } + return }}, }, } diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index 8deb593e..273d3d94 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -43,7 +43,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", "domain.png": &ctx.Config{Name: "domain.png", Value: "var/domain.png", Help: "主机数量"}, }, Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message { sub.Start(fmt.Sprintf("host%d", m.Capi("nhost", 1)), "远程主机") sub.Spawn().Cmd("pwd", "") @@ -53,14 +53,16 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Cap("domain", m.Cap("hostname", m.Conf("hostname"))) } // m.Spawn(m.Target()).Cmd("save") + return }}, - "dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message { sub.Target().Start(sub) return sub }, m.Meta["detail"]) + return }}, - "send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { origin, domain := "", "" if len(arg) > 1 && arg[0] == "domain" { @@ -92,7 +94,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", match := false host := strings.SplitN(domain, ".", 2) - m.Travel(func(m *ctx.Message, i int) bool { + c.Travel(m, func(m *ctx.Message, i int) bool { if i == 0 { return true } @@ -113,8 +115,8 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return host[0] == "*" } - return true - }, c) + return false + }) if match { return @@ -133,8 +135,9 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", msg.Cmd("send", "domain", origin, arg) m.Copy(msg, "result").Copy(msg, "append") } + return }}, - "pwd": &ctx.Command{Name: "pwd [hostname]", Help: "主机域名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "pwd": &ctx.Command{Name: "pwd [hostname]", Help: "主机域名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Echo(m.Cap("domain")) return @@ -147,13 +150,13 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Cap("domain", msg.Result(1)) } else { hostname := arg[0] - m.Travel(func(m *ctx.Message, line int) bool { + c.Travel(m, func(m *ctx.Message, line int) bool { if hostname == m.Cap("hostname") { hostname += m.Cap("nhost") return false } - return true - }, c) + return false + }) m.Echo(m.Cap("hostname", hostname)) m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname")) } @@ -169,8 +172,9 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Spawn().Cmd("send", "pwd", arg[0]) } m.Echo(m.Cap("domain")) + return }}, - "hello": &ctx.Command{Name: "hello request", Help: "加密请求", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "hello": &ctx.Command{Name: "hello request", Help: "加密请求", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { aaa := m.Target().Message().Sess("aaa", false) for _, k := range m.Meta["seal"] { for i, v := range m.Meta[k] { @@ -198,12 +202,13 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", msg := m.Spawn().Copy(m, "option").Cmd(arg) m.Copy(msg, "result").Copy(msg, "append") + return }}, "shake": &ctx.Command{ Name: "shake [domain host] cmd... [seal option...][encrypt option...]", Help: "加密通信", Form: map[string]int{"seal": -1, "encrypt": -1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { if len(arg) == 0 { for k, v := range ssh.peer { @@ -250,13 +255,14 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", ssh.Message().Back(msg) m.Copy(msg, "result").Copy(msg, "append") } + return }}, - "save": &ctx.Command{Name: "save", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "save": &ctx.Command{Name: "save", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { json := m.Sess("nfs") json.Put("option", "data", map[string]string{"domain": m.Cap("domain")}) json.Cmd("json", m.Conf("domain.json")) m.Sess("nfs").Cmd("genqr", m.Conf("domain.png"), json.Result(0)) - + return }}, }, } diff --git a/src/contexts/tcp/tcp.go b/src/contexts/tcp/tcp.go index 0d3f2804..262b6d86 100644 --- a/src/contexts/tcp/tcp.go +++ b/src/contexts/tcp/tcp.go @@ -160,21 +160,25 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络中心", "protocol": &ctx.Config{Name: "protocol(tcp/tcp4/tcp6)", Value: "tcp4", Help: "网络协议"}, }, Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Start(fmt.Sprintf("pub%d", m.Capi("nlisten", 1)), "网络监听", m.Meta["detail"]...) + return }}, - "accept": &ctx.Command{Name: "accept address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "accept": &ctx.Command{Name: "accept address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Start(fmt.Sprintf("com%d", m.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...) + return }}, - "dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Start(fmt.Sprintf("com%d", m.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...) + return }}, - "send": &ctx.Command{Name: "send message", Help: "发送消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "send": &ctx.Command{Name: "send message", Help: "发送消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) { tcp.Write([]byte(arg[0])) } + return }}, - "recv": &ctx.Command{Name: "recv size", Help: "接收消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "recv": &ctx.Command{Name: "recv size", Help: "接收消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if tcp, ok := m.Target().Server.(*TCP); m.Assert(ok) { n, e := strconv.Atoi(arg[0]) m.Assert(e) @@ -183,8 +187,9 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络中心", n, _ = tcp.Read(buf) m.Echo(string(buf[:n])) } + return }}, - "ifconfig": &ctx.Command{Name: "ifconfig", Help: "网络配置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "ifconfig": &ctx.Command{Name: "ifconfig", Help: "网络配置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if ifs, e := net.Interfaces(); m.Assert(e) { for _, v := range ifs { if ips, e := v.Addrs(); m.Assert(e) { @@ -201,6 +206,7 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络中心", } m.Table() } + return }}, }, } diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index e64e3f71..6ae3e51f 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -307,7 +307,7 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { render := m.Target().Commands["/render"] proxy := m.Target().Commands["/proxy/"] - m.Travel(func(m *ctx.Message, i int) bool { + m.Target().Travel(m, func(m *ctx.Message, i int) bool { if h, ok := m.Target().Server.(MUX); ok && m.Cap("register") == "no" { m.Cap("register", "yes") @@ -338,7 +338,7 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { h.Handle("/", http.FileServer(http.Dir(m.Cap("directory")))) } } - return true + return false }) web.Caches["protocol"] = &ctx.Cache{Name: "protocol", Value: m.Confx("protocol", arg, 2), Help: "服务协议"} @@ -442,10 +442,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", }, Help: "工作流"}, }, Commands: map[string]*ctx.Command{ - "merge": &ctx.Command{Name: "merge", Help: "添加浏览器配置, address: 默认地址, output: 输出路径, editor: 编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "merge": &ctx.Command{Name: "merge", Help: "添加浏览器配置, address: 默认地址, output: 输出路径, editor: 编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Echo(merge(m, arg[0], arg[1:]...)) + return }}, - "client": &ctx.Command{Name: "client address [output [editor]]", Help: "添加浏览器配置, address: 默认地址, output: 输出路径, editor: 编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "client": &ctx.Command{Name: "client address [output [editor]]", Help: "添加浏览器配置, address: 默认地址, output: 输出路径, editor: 编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { uri, e := url.Parse(arg[0]) m.Assert(e) m.Conf("method", "method", "GET", "请求方法") @@ -463,8 +464,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", if m.Conf("editor", "editor", "vim", "文件编辑器"); len(arg) > 2 { m.Conf("editor", arg[2]) } + return }}, - "cookie": &ctx.Command{Name: "cookie [create]|[name [value]]", Help: "读写浏览器的Cookie, create: 创建cookiejar, name: 变量名, value: 变量值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "cookie": &ctx.Command{Name: "cookie [create]|[name [value]]", Help: "读写浏览器的Cookie, create: 创建cookiejar, name: 变量名, value: 变量值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch len(arg) { case 0: for k, v := range m.Confv("cookie").(map[string]interface{}) { @@ -488,11 +490,12 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Confv("cookie", arg[0], &http.Cookie{Name: arg[0], Value: arg[1]}) } } + return }}, "get": &ctx.Command{Name: "get [method GET|POST] url arg...", Help: "访问服务, method: 请求方法, url: 请求地址, arg: 请求参数", Form: map[string]int{"method": 1, "headers": 2, "content_type": 1, "body": 1, "path_value": 1, "body_response": 1, "parse": 1, "sub_parse": 3, "save": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { if m.Has("path_value") { values := []interface{}{} @@ -553,7 +556,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", res, e := web.Client.Do(req) if e != nil { m.Log("info", "get error %v", e) - return + return e } m.Assert(e) if m.Confs("logheaders") { @@ -581,7 +584,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", defer f.Close() m.Log("info", "save file %s %s", p, m.Sess("aaa").Cmd("hash", "file", p).Result(0)) m.Echo(p) - return + return e } ct := res.Header.Get("Content-Type") @@ -595,7 +598,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", if m.Has("parse") { msg := m.Spawn().Put("option", "data", result).Cmd("trans", "data", m.Option("parse")) m.Copy(msg, "append").Copy(msg, "result") - return + return e } b, _ := json.MarshalIndent(result, "", " ") result = string(b) @@ -660,7 +663,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", msg.Put("option", "response", result) msg.Cmd("trans", "response", m.Option("parse")) m.Copy(msg, "append").Copy(msg, "result") - return + return e } result = string(buf) default: @@ -670,7 +673,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", header.Add(k, v[0]) } io.Copy(w, res.Body) - return + return e } else { buf, e := ioutil.ReadAll(res.Body) m.Assert(e) @@ -682,10 +685,11 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } m.Echo("%v", result) } + return }}, "post": &ctx.Command{Name: "post [file fieldname filename]", Help: "post请求", Form: map[string]int{"file": 2, "content_type": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { msg := m.Spawn() parse := "_" if m.Has("file") { @@ -772,11 +776,12 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } msg.Cmd("get", "method", "POST", arg) m.Copy(msg, "result").Copy(msg, "append") + return }}, - "brow": &ctx.Command{Name: "brow url", Help: "浏览网页", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "brow": &ctx.Command{Name: "brow url", Help: "浏览网页", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Optionv("request").(*http.Request); ok { action := false - m.Travel(func(m *ctx.Message, i int) bool { + c.Travel(m, func(m *ctx.Message, i int) bool { for key, v := range m.Target().Commands { method, url := "", "" if strings.HasPrefix(v.Name, "get ") { @@ -816,12 +821,14 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", case "linux": m.Spawn().Cmd("open", url) } + return }}, - "serve": &ctx.Command{Name: "serve [directory [address [protocol [cert [key]]]]", Help: "启动服务, directory: 服务路径, address: 服务地址, protocol: 服务协议(https/http), cert: 服务证书, key: 服务密钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Set("detail", arg...).Target().Start(m) + "serve": &ctx.Command{Name: "serve [directory [address [protocol [cert [key]]]]", Help: "启动服务, directory: 服务路径, address: 服务地址, protocol: 服务协议(https/http), cert: 服务证书, key: 服务密钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Set("detail", arg).Target().Start(m) + return }}, - "route": &ctx.Command{Name: "route index content [help]", Help: "添加路由响应, index: 路由, context: 响应, help: 说明", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "route": &ctx.Command{Name: "route index content [help]", Help: "添加路由响应, index: 路由, context: 响应, help: 说明", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if mux, ok := m.Target().Server.(MUX); m.Assert(ok) { switch len(arg) { case 0: @@ -843,23 +850,26 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", if len(arg) > 2 { help = arg[2] } - hand := func(m *ctx.Message, c *ctx.Context, key string, a ...string) { + hand := func(m *ctx.Message, c *ctx.Context, key string, a ...string) (e error) { w := m.Optionv("response").(http.ResponseWriter) template.Must(template.New("temp").Parse(arg[1])).Execute(w, m) + return } if s, e := os.Stat(arg[1]); e == nil { if s.IsDir() { mux.Handle(arg[0]+"/", http.StripPrefix(arg[0], http.FileServer(http.Dir(arg[1])))) } else if strings.HasSuffix(arg[1], ".shy") { - hand = func(m *ctx.Message, c *ctx.Context, key string, a ...string) { + hand = func(m *ctx.Message, c *ctx.Context, key string, a ...string) (e error) { msg := m.Sess("cli").Cmd("source", arg[1]) m.Copy(msg, "result").Copy(msg, "append") + return } } else { - hand = func(m *ctx.Message, c *ctx.Context, key string, a ...string) { + hand = func(m *ctx.Message, c *ctx.Context, key string, a ...string) (e error) { w := m.Optionv("response").(http.ResponseWriter) template.Must(template.ParseGlob(arg[1])).Execute(w, m) + return } } } @@ -875,8 +885,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } } } + return }}, - "template": &ctx.Command{Name: "template [file [directory]]|[name [content]]", Help: "添加模板, content: 模板内容, directory: 模板目录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "template": &ctx.Command{Name: "template [file [directory]]|[name [content]]", Help: "添加模板, content: 模板内容, directory: 模板目录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { if len(arg) == 0 { for _, v := range web.Template.Templates() { @@ -908,8 +919,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } } } + return }}, - "componet": &ctx.Command{Name: "componet [group [order [arg...]]]", Help: "添加组件, group: 组件分组, arg...: 组件参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "componet": &ctx.Command{Name: "componet [group [order [arg...]]]", Help: "添加组件, group: 组件分组, arg...: 组件参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch len(arg) { case 0: for k, v := range m.Confv("componet").(map[string]interface{}) { @@ -954,8 +966,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", break } } + return }}, - "session": &ctx.Command{Name: "session [secrete]", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "session": &ctx.Command{Name: "session [secrete]", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { sessid := m.Option("sessid") if sessid == "" || !m.Cmds("aaa.sess", sessid) { if !m.Confs("sess_void") && !m.Options("username") { @@ -977,8 +990,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", // 用户角色 m.Cmdy("aaa.sess", m.Option("sessid"), "userrole") m.Log("info", "username: %v userrole: %v", m.Meta["username"], m.Meta["userrole"]) + return }}, - "bench": &ctx.Command{Name: "bench", Help: "任务列表", Form: map[string]int{"view": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "bench": &ctx.Command{Name: "bench", Help: "任务列表", Form: map[string]int{"view": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { default_com := "default bench" default_cmd := map[string]interface{}{} if len(arg) > 0 && arg[0] == "copy" { // 复制工作流 @@ -1070,9 +1084,10 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", // 查看工作流 msg := m.Spawn().Put("option", "_cache", bench).Cmd("trans", "_cache", arg[0]) m.Copy(msg, "append").Copy(msg, "result") + return }}, - "/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if m.Options("toolkit") { if kit, ok := m.Confv("toolkit", m.Option("toolkit")).(map[string]interface{}); ok { m.Sess("cli").Cmd(kit["cmd"], m.Option("argument")).CopyTo(m) @@ -1229,8 +1244,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", en.Encode(list) } } + return }}, - "/upload": &ctx.Command{Name: "/upload", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/upload": &ctx.Command{Name: "/upload", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { r := m.Optionv("request").(*http.Request) f, h, e := r.FormFile("upload") m.Assert(e) @@ -1244,20 +1260,23 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", io.Copy(o, f) m.Log("upload", "file: %s", p) m.Append("redirect", m.Option("referer")) + return }}, - "/download/": &ctx.Command{Name: "/download/", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/download/": &ctx.Command{Name: "/download/", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { r := m.Optionv("request").(*http.Request) w := m.Optionv("response").(http.ResponseWriter) p := m.Sess("nfs").Cmd("path", strings.TrimPrefix(m.Option("path"), "/download/")).Result(0) m.Log("info", "download %s %s", p, m.Sess("aaa").Cmd("hash", "file", p).Result(0)) http.ServeFile(w, r, p) + return }}, - "/proxy/": &ctx.Command{Name: "/proxy/", Help: "服务代理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/proxy/": &ctx.Command{Name: "/proxy/", Help: "服务代理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { msg := m.Spawn().Cmd("get", strings.TrimPrefix(key, "/proxy/"), arg) m.Copy(msg, "append").Copy(msg, "result") + return }}, - "spide": &ctx.Command{Name: "spide", Help: "spide", Form: map[string]int{"fields": 1, "limit": 1, "offset": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "spide": &ctx.Command{Name: "spide", Help: "spide", Form: map[string]int{"fields": 1, "limit": 1, "offset": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { for k, v := range m.Confv("spide").(map[string]interface{}) { val := v.(map[string]interface{}) @@ -1323,8 +1342,9 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Copy(msg, "append").Copy(msg, "result") m.Cmd("select", "limit", limit, "offset", offset, "fields", fields) + return }}, - "12306": &ctx.Command{Name: "12306", Help: "12306", Form: map[string]int{"fields": 1, "limit": 1, "offset": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "12306": &ctx.Command{Name: "12306", Help: "12306", Form: map[string]int{"fields": 1, "limit": 1, "offset": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { date := time.Now().Add(time.Hour * 24).Format("2006-01-02") if len(arg) > 0 { date, arg = arg[0], arg[1:] @@ -1350,6 +1370,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Add("append", "一等座", fields[31]) } m.Table() + return }}, }, } diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index 6b14c613..3f81be91 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -246,9 +246,9 @@ func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { return yac } - yac.Caches["ncell"] = &ctx.Cache{Name: "词法上限", Value: m.Confx("ncell", arg, 0), Help: "词法集合的最大数量"} - yac.Caches["nlang"] = &ctx.Cache{Name: "语法上限", Value: m.Confx("nlang", arg, 1), Help: "语法集合的最大数量"} - yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: m.Confx("nlang", arg, 1), Help: "状态机状态的数量"} + yac.Caches["ncell"] = &ctx.Cache{Name: "词法上限", Value: "128", Help: "词法集合的最大数量"} + yac.Caches["nlang"] = &ctx.Cache{Name: "语法上限", Value: "32", Help: "语法集合的最大数量"} + yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "32", Help: "状态机状态的数量"} yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"} yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"} yac.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "语法模板的数量"} @@ -323,7 +323,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", "label": &ctx.Config{Name: "嵌套标记", Value: "####################", Help: "嵌套层级日志的标记"}, }, Commands: map[string]*ctx.Command{ - "init": &ctx.Command{Name: "init", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "init": &ctx.Command{Name: "init", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Cmd("train", "void", "void", "[\t ]+") m.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") @@ -367,8 +367,9 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", m.Cmd("train", "exe", "exe", "$", "(", "cmd", ")") m.Cmd("train", "line", "line", "opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}") + return }}, - "train": &ctx.Command{Name: "train page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "train": &ctx.Command{Name: "train page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { page, ok := yac.page[arg[0]] if !ok { @@ -398,14 +399,16 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", yac.seed = append(yac.seed, &Seed{page, hash, arg[2:]}) m.Cap("stream", fmt.Sprintf("%d,%s,%s", m.Capi("nseed", 1), m.Cap("npage"), m.Cap("nhash"))) } + return }}, - "parse": &ctx.Command{Name: "parse page void word...", Help: "解析语句, page: 初始语法, void: 空白语法, word: 解析语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "parse": &ctx.Command{Name: "parse page void word...", Help: "解析语句, page: 初始语法, void: 空白语法, word: 解析语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { str, word, hash := yac.parse(m, m, m.Optioni("page", yac.page[arg[0]]), m.Optioni("void", yac.page[arg[1]]), arg[2], 1) m.Result(str, yac.hand[hash], word) } + return }}, - "scan": &ctx.Command{Name: "scan filename", Help: "解析文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "scan": &ctx.Command{Name: "scan filename", Help: "解析文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { m.Optioni("page", yac.page["line"]) m.Optioni("void", yac.page["void"]) @@ -415,8 +418,9 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", m.Start(fmt.Sprintf("parse%d", m.Capi("nparse", 1)), "parse") } } + return }}, - "show": &ctx.Command{Name: "show seed|page|hash|mat", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "show": &ctx.Command{Name: "show seed|page|hash|mat", Help: "查看信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { if len(arg) == 0 { m.Append("seed", len(yac.seed)) @@ -496,6 +500,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", m.Table() } } + return }}, }, } diff --git a/src/examples/code/code.go b/src/examples/code/code.go index 2c26e795..da37469f 100644 --- a/src/examples/code/code.go +++ b/src/examples/code/code.go @@ -208,7 +208,7 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", }, Help: "组件列表"}, }, Commands: map[string]*ctx.Command{ - "/counter": &ctx.Command{Name: "/counter", Help: "/counter", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/counter": &ctx.Command{Name: "/counter", Help: "/counter", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 0 { m.Option("name", arg[0]) } @@ -225,11 +225,13 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", } m.Log("info", "%v: %v", m.Option("name"), m.Confv("counter", m.Option("name"), fmt.Sprintf("%d", count))) m.Echo("%d", count) + return }}, - "counter": &ctx.Command{Name: "counter name count", Help: "counter", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "counter": &ctx.Command{Name: "counter name count", Help: "counter", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 1 { m.Copy(m.Spawn().Cmd("get", m.Conf("counter_service"), "name", arg[0], "count", arg[1]), "result") } + return }}, }, } diff --git a/src/examples/wiki/wiki.go b/src/examples/wiki/wiki.go index 3a2d3fb2..276726ed 100644 --- a/src/examples/wiki/wiki.go +++ b/src/examples/wiki/wiki.go @@ -48,7 +48,7 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", }, Help: "组件列表"}, }, Commands: map[string]*ctx.Command{ - "wiki_list": &ctx.Command{Name: "wiki_list sort_field sort_order", Help: "wiki_list", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "wiki_list": &ctx.Command{Name: "wiki_list sort_field sort_order", Help: "wiki_list", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { sort_field, sort_order := "h2", "int_r" if len(arg) > 0 { sort_field, arg = arg[0], arg[1:] @@ -108,8 +108,9 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", } return true }) + return }}, - "wiki_body": &ctx.Command{Name: "wiki_body", Help: "wiki_body", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "wiki_body": &ctx.Command{Name: "wiki_body", Help: "wiki_body", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { which := path.Join(m.Conf("wiki_dir"), m.Confx("wiki_favor", arg, 0)) if ls, e := ioutil.ReadFile(which); e == nil { @@ -124,9 +125,10 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", ls = markdown.ToHTML(ls, nil, nil) m.Echo(string(ls)) } + return }}, - "/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 0 { m.Option("dir", arg[0]) } @@ -193,8 +195,9 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", yac.Meta = nil } } + return }}, - "/wiki_body": &ctx.Command{Name: "/wiki_body", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/wiki_body": &ctx.Command{Name: "/wiki_body", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { which := path.Join(m.Conf("wiki_dir"), m.Confx("which")) st, _ := os.Stat(which) if ls, e := ioutil.ReadFile(which); e == nil { @@ -242,7 +245,7 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", m.Add("append", "body", string(ls)) m.Add("append", "code", "") } - return + return e } if m.Options("query") { @@ -270,8 +273,9 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", msg := m.Spawn().Cmd("/wiki_list") m.Copy(msg, "append").Copy(msg, "option") + return }}, - "/wiki_list": &ctx.Command{Name: "/wiki_list", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/wiki_list": &ctx.Command{Name: "/wiki_list", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { ls, e := ioutil.ReadDir(path.Join(m.Conf("wiki_dir"), m.Option("which"))) m.Option("dir", m.Option("which")) if e != nil { @@ -305,17 +309,19 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", m.Option("time_format", "2006-01-02 15:04:05") m.Sort("time", "time_r") } + return }}, - "/wiki/": &ctx.Command{Name: "/wiki", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/wiki/": &ctx.Command{Name: "/wiki", Help: "维基", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Option("which", strings.TrimPrefix(key, "/wiki/")) if f, e := os.Stat(path.Join(m.Conf("wiki_dir"), m.Option("which"))); e == nil && !f.IsDir() && (strings.HasSuffix(m.Option("which"), ".json") || strings.HasSuffix(m.Option("which"), ".js") || strings.HasSuffix(m.Option("which"), ".css")) { m.Append("directory", path.Join(m.Conf("wiki_dir"), m.Option("which"))) - return + return e } m.Append("template", "wiki") + return }}, - "/wx/": &ctx.Command{Name: "/wx/", Help: "微信", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "/wx/": &ctx.Command{Name: "/wx/", Help: "微信", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if !m.Sess("aaa").Cmd("wx").Results(0) { return } @@ -428,6 +434,7 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", b, e = xml.Marshal(echo) m.Echo(string(b)) } + return }}, }, } diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index 286e5272..f3203fff 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -1,13 +1,443 @@ package kit import ( + "crypto/md5" + "encoding/hex" + "encoding/json" "fmt" + "strconv" + "strings" + "io/ioutil" - // "log" + "math/rand" "os" "path" + "time" ) +func Errorf(str string, args ...interface{}) { + if len(args) == 0 { + fmt.Fprintf(os.Stderr, "%s\n", str) + return + } + fmt.Fprintf(os.Stderr, str, args...) +} + +func Int(arg ...interface{}) int { + result := 0 + for _, v := range arg { + switch val := v.(type) { + case int: + result += val + case bool: + if val { + result += 1 + } + case string: + if i, e := strconv.Atoi(val); e == nil { + result += i + } + case time.Time: + result += int(val.Unix()) + default: + } + } + 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 + break + } + result = result || true + case error: + result = result || false + 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 uint, uint8, uint16, uint32, uint64: + result = append(result, fmt.Sprintf("%d", val)) + case int, int8, int16, int32, int64: + result = append(result, fmt.Sprintf("%d", val)) + case bool: + result = append(result, fmt.Sprintf("%t", val)) + case string: + result = append(result, val) + case []string: + result = append(result, val...) + case float64: + result = append(result, fmt.Sprintf("%d", int(val))) + case time.Time: + result = append(result, fmt.Sprintf("%d", val.Format("2006-01-02 15:03:04"))) + 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 { + if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n+1 { + return fmt.Sprintf(result[0], result[1:n+1]) + strings.Join(result[n+1:], "") + } else if len(result) == n+1 { + return fmt.Sprintf(result[0], result[1:]) + } + } + 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)) + } + } + } + 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 []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{}: + ls = append(ls, Format(val...)) + default: + ls = append(ls, Format(val)) + } + } + return ls +} +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 arg != "" { + return arg + } + 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) + + var next interface{} + switch value := data.(type) { + case nil: + if j == len(keys)-1 { + next = args[i+1] + } + + if i == len(args)-1 { + return nil + } + + 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] // 修改数据 + } + 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 { + data, index = append([]interface{}{next}, value...), 0 + } else if index == -2 { + data, index = append(value, next), len(value) + } else if j == len(keys)-1 { + value[index] = next + } + next = 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 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", + "01-02 15:04", + } { + if t, e := time.ParseInLocation(v, arg[0], time.Local); e == nil { + return Int(t) + } + } + return 0 +} +func Hash(arg ...interface{}) (string, []string) { + meta := Trans(arg...) + for i, v := range meta { + meta[i] = Action(v) + } + + h := md5.Sum([]byte(strings.Join(meta, ""))) + return hex.EncodeToString(h[:]), meta +} + +func Action(cmd string, arg ...interface{}) string { + switch cmd { + case "time": + return Format(time.Now()) + case "rand": + return Format(rand.Int()) + case "uniq": + return Format(time.Now(), rand.Int()) + default: + if len(arg) > 0 { + return Format(arg...) + } + } + return cmd +} +func Check(e error) bool { + if e != nil { + panic(e) + } + return true +} func FmtSize(size uint64) string { if size > 1<<30 { return fmt.Sprintf("%d.%dG", size>>30, (size>>20)%1024*100/1024) @@ -23,7 +453,6 @@ func FmtSize(size uint64) string { return fmt.Sprintf("%dB", size) } - func FmtNano(nano int64) string { if nano > 1000000000 { return fmt.Sprintf("%d.%ds", nano/1000000000, nano/100000000%100) @@ -39,14 +468,6 @@ func FmtNano(nano int64) string { return fmt.Sprintf("%dns", nano) } - -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)