From dc791f251904f3c03478af46f0cc6e4f0650ef71 Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 7 Jan 2019 15:21:56 +0800 Subject: [PATCH] some --- src/contexts/cli/cli.go | 563 +++++++++----------- src/contexts/ctx/ctx.go | 1093 ++++++++++++++++++++------------------- src/contexts/gdb/gdb.go | 3 +- src/contexts/log/log.go | 4 +- src/contexts/nfs/nfs.go | 370 ++++++------- src/contexts/yac/yac.go | 7 +- src/toolkit/kit.go | 6 + 7 files changed, 984 insertions(+), 1062 deletions(-) diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 86cf6172..99556277 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -27,13 +27,11 @@ type Frame struct { list []string } type CLI struct { - alias map[string][]string - label map[string]string - target *ctx.Context - stack []*Frame + label map[string]string + stack []*Frame *time.Timer - *ctx.Context + Context *ctx.Context } func (cli *CLI) schedule(m *ctx.Message) string { @@ -50,74 +48,16 @@ func (cli *CLI) schedule(m *ctx.Message) string { func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{ - "level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"}, - "parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"}, - "last_msg": &ctx.Cache{Name: "last_msg", Value: "0", Help: "前一条消息"}, - "ps_count": &ctx.Cache{Name: "ps_count", Value: "0", Help: "命令计数"}, - "ps_target": &ctx.Cache{Name: "ps_target", Value: c.Name, Help: "当前模块", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { - if len(arg) > 0 { - if cli, ok := m.Target().Server.(*CLI); ok { - if msg := m.Find(arg[0]); msg != nil { - cli.target = msg.Target() - return arg[0] - } - } - } - return x.Value - }}, - } - c.Configs = map[string]*ctx.Config{ - "ps_time": &ctx.Config{Name: "ps_time", Value: "[15:04:05]", Help: "当前时间", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 { - return arg[0] - } - return time.Now().Format(x.Value.(string)) - - }}, - "ps_end": &ctx.Config{Name: "ps_end", Value: "> ", Help: "命令行提示符结尾"}, - "prompt": &ctx.Config{Name: "prompt(ps_count/ps_time/ps_target/ps_end/...)", Value: "ps_count ps_time ps_target ps_end", Help: "命令行提示符, 以空格分隔, 依次显示缓存或配置信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { - if len(arg) > 0 { - return arg[0] - } - - ps := make([]string, 0, 3) - for _, v := range strings.Split(x.Value.(string), " ") { - if m.Conf(v) != "" { - ps = append(ps, m.Conf(v)) - } else { - ps = append(ps, m.Cap(v)) - } - } - return strings.Join(ps, "") - - }}, + "level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"}, + "parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"}, } - s := new(CLI) - s.Context = c - s.target = c - s.alias = map[string][]string{ - "~": []string{"context"}, - "!": []string{"message"}, - ":": []string{"command"}, - "::": []string{"command", "list"}, - - "pwd": []string{"nfs.pwd"}, - "path": []string{"nfs.path"}, - "dir": []string{"nfs.dir"}, - "git": []string{"nfs.git"}, - "brow": []string{"web.brow"}, - } - - return s + return &CLI{Context: c} } func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { - cli.target = m.Target() return cli } func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { - m.Optionv("ps_target", cli.target) - m.Option("prompt", m.Conf("prompt")) m.Cap("stream", m.Spawn(m.Sess("yac", false).Target()).Call(func(cmd *ctx.Message) *ctx.Message { if !m.Caps("parse") { switch cmd.Detail(0) { @@ -132,12 +72,14 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { } } - if m.Option("prompt", cmd.Cmd().Conf("prompt")); cmd.Has("return") { - kit.Log("error", "waht ?????") + if cmd.Cmd(); cmd.Has("return") { m.Options("scan_end", true) m.Target().Close(m) } - m.Optionv("ps_target", cli.target) + + m.Optionv("ps_target", cmd.Optionv("ps_target")) + m.Set("append").Copy(cmd, "append") + m.Set("result").Copy(cmd, "result") return nil }, "scan", arg).Target().Name) @@ -148,8 +90,6 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { case m.Target(): case m.Source(): } - msg := cli.Message() - msg.Append("last_target", msg.Cap("ps_target")) return true } @@ -160,13 +100,24 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", Configs: map[string]*ctx.Config{ "init_shy": &ctx.Config{Name: "init_shy", Value: "etc/init.shy", Help: "启动脚本"}, "exit_shy": &ctx.Config{Name: "exit_shy", Value: "etc/exit.shy", Help: "启动脚本"}, - - "time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"}, - "time_close": &ctx.Config{Name: "time_close(open/close)", Value: "open", Help: "时间区间"}, - "cmd_script": &ctx.Config{Name: "cmd_script", Value: map[string]interface{}{ "sh": "bash", "shy": "source", "py": "python", }, Help: "系统命令超时"}, + "alias": &ctx.Config{Name: "alias", Value: map[string]interface{}{ + "~": []string{"context"}, + "!": []string{"message"}, + ":": []string{"command"}, + "::": []string{"command", "list"}, + + "pwd": []string{"nfs.pwd"}, + "path": []string{"nfs.path"}, + "dir": []string{"nfs.dir"}, + "git": []string{"nfs.git"}, + "brow": []string{"web.brow"}, + }, Help: "启动脚本"}, + + "time_unit": &ctx.Config{Name: "time_unit", Value: "1000", Help: "时间倍数"}, + "time_close": &ctx.Config{Name: "time_close(open/close)", Value: "open", Help: "时间区间"}, "source_list": &ctx.Config{Name: "source_list", Value: []interface{}{}, Help: "系统命令超时"}, "system_env": &ctx.Config{Name: "system_env", Value: map[string]interface{}{}, Help: "系统命令超时"}, @@ -184,198 +135,187 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", "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) (e error) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { - switch len(arg) { - case 0: - for k, v := range cli.alias { - m.Echo("%s: %v\n", k, v) + switch len(arg) { + case 0: + m.Cmdy("ctx.config", "alias") + case 1: + m.Cmdy("ctx.config", "alias", arg[0]) + default: + switch arg[0] { + case "delete": + alias := m.Confm("alias") + m.Echo("delete: %s %v\n", arg[1], alias[arg[1]]) + delete(alias, arg[1]) + case "import": + msg := m.Find(arg[1], false) + if msg == nil { + msg = m.Find(arg[1], true) + } + if msg == nil { + m.Echo("%s not exist", arg[1]) + return + } + + module := msg.Cap("module") + for k, _ := range msg.Target().Commands { + if len(k) > 0 && k[0] == '/' { + continue + } + + if len(arg) == 2 { + m.Confv("alias", k, []string{module + "." + k}) + m.Log("info", "import %s.%s", module, k) + continue + } + + if key := k; k == arg[2] { + if len(arg) > 3 { + key = arg[3] + } + m.Confv("alias", key, []string{module + "." + k}) + m.Log("info", "import %s.%s as %s", module, k, key) + break + } } - case 1: - m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]]) default: - switch arg[0] { - case "delete": - m.Echo("delete: %s %v\n", arg[1], cli.alias[arg[1]]) - delete(cli.alias, arg[1]) - case "import": - msg := m.Find(arg[1], false) - if msg == nil { - msg = m.Find(arg[1], true) - } - if msg == nil { - m.Echo("%s not exist", arg[1]) - return - } - m.Log("info", "import %s", arg[1]) - module := msg.Cap("module") - for k, _ := range msg.Target().Commands { - if len(k) > 0 && k[0] == '/' { - continue - } - if len(arg) == 2 { - cli.alias[k] = []string{module + "." + k} - continue - } - if key := k; k == arg[2] { - if len(arg) > 3 { - key = arg[3] - } - cli.alias[key] = []string{module + "." + k} - break - } - } - default: - cli.alias[arg[0]] = arg[1:] - m.Echo("%s: %v\n", arg[0], cli.alias[arg[0]]) - m.Log("info", "%s: %v", arg[0], cli.alias[arg[0]]) - } + m.Confv("alias", arg[0], arg[1:]) + m.Log("info", "%s: %v", arg[0], arg[1:]) } } return }}, - "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 { - detail = append(detail, a...) - detail = append(detail, arg[1:]...) + "cmd": &ctx.Command{Name: "cmd word", Help: "解析命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + // 解析别名 + detail := []string{} + if alias, ok := m.Confv("alias", arg[0]).([]string); ok { + detail, arg = append(detail, alias...), arg[1:] + } + detail = append(detail, arg...) + + // 目标切换 + if detail[0] != "context" { + target := m.Optionv("ps_target") + defer func() { m.Optionv("ps_target", target) }() + } + + // 解析脚本 + msg := m + for k, v := range m.Confv("cmd_script").(map[string]interface{}) { + if strings.HasSuffix(detail[0], "."+k) { + msg = m.Spawn(m.Optionv("ps_target")) + detail[0] = m.Cmdx("nfs.path", detail[0]) + detail = append([]string{v.(string)}, detail...) + break + } + } + + // 解析路由 + if msg == m { + if routes := strings.Split(detail[0], "."); len(routes) > 1 { + route := strings.Join(routes[:len(routes)-1], ".") + if msg = m.Find(route, false); msg == nil { + msg = m.Find(route, true) + } + + if msg == nil { + m.Echo("%s not exist", route) + return + } + detail[0] = routes[len(routes)-1] } else { - detail = append(detail, arg...) + msg = m.Spawn(m.Optionv("ps_target")) } + } + msg.Copy(m, "option").Copy(m, "append") - if detail[0] != "context" { - target := m.Cap("ps_target") - defer func() { - m.Cap("ps_target", target) - }() - } - - msg := m - for k, v := range m.Confv("cmd_script").(map[string]interface{}) { - if strings.HasSuffix(detail[0], "."+k) { - detail[0] = m.Sess("nfs").Cmd("path", detail[0]).Result(0) - detail = append([]string{v.(string)}, detail...) - msg = m.Spawn(cli.target) + // 解析命令 + args, rest := []string{}, []string{} + exports := []map[string]string{} + exec, execexec := true, false + for i := 0; i < len(detail); i++ { + switch detail[i] { + case "?": + if !kit.Right(detail[i+1]) { + return + } + i++ + case "??": + exec = false + execexec = execexec || kit.Right(detail[i+1]) + i++ + case "<": + m.Cmdy("nfs.import", detail[i+1]) + i++ + case ">": + exports = append(exports, map[string]string{"file": detail[i+1]}) + i++ + case ">$": + if i == len(detail)-2 { + exports = append(exports, map[string]string{"cache": detail[i+1], "index": "result"}) + i += 1 break } - } - - if msg == m { - if routes := strings.Split(detail[0], "."); len(routes) > 1 { - route := strings.Join(routes[:len(routes)-1], ".") - if msg = m.Find(route, false); msg == nil { - msg = m.Find(route, true) - } - - if msg == nil { - m.Echo("%s not exist", route) - return - } - detail[0] = routes[len(routes)-1] - } else { - msg = m.Spawn(cli.target) + exports = append(exports, map[string]string{"cache": detail[i+1], "index": detail[i+2]}) + i += 2 + case ">@": + if i == len(detail)-2 { + exports = append(exports, map[string]string{"config": detail[i+1], "index": "result"}) + i += 1 + break } + exports = append(exports, map[string]string{"config": detail[i+1], "index": detail[i+2]}) + i += 2 + case "|": + detail, rest = detail[:i], detail[i+1:] + case "%": + rest = append(rest, "select") + detail, rest = detail[:i], append(rest, detail[i+1:]...) + default: + args = append(args, detail[i]) } - msg.Copy(m, "append") - msg.Copy(m, "option") - - args := []string{} - rest := []string{} - exec := true - execexec := false - exports := []map[string]string{} - for i := 0; i < len(detail); i++ { - switch detail[i] { - case "?": - if !kit.Right(detail[i+1]) { - return - } - i++ - case "??": - exec = false - execexec = execexec || kit.Right(detail[i+1]) - i++ - case "<": - pipe := m.Sess("nfs").Cmd("import", detail[i+1]) - msg.Copy(pipe, "append") - i++ - case ">": - exports = append(exports, map[string]string{"file": detail[i+1]}) - i++ - case ">$": - if i == len(detail)-2 { - exports = append(exports, map[string]string{"cache": detail[i+1], "index": "result"}) - i += 1 - break - } - exports = append(exports, map[string]string{"cache": detail[i+1], "index": detail[i+2]}) - i += 2 - case ">@": - if i == len(detail)-2 { - exports = append(exports, map[string]string{"config": detail[i+1], "index": "result"}) - i += 1 - break - } - exports = append(exports, map[string]string{"config": detail[i+1], "index": detail[i+2]}) - i += 2 - case "|": - detail, rest = detail[:i], detail[i+1:] - case "%": - rest = append(rest, "select") - detail, rest = detail[:i], append(rest, detail[i+1:]...) - default: - args = append(args, detail[i]) - } - } - - if !exec && !execexec { - return - } - - detail = args - msg.Set("detail", detail) - - if msg.Cmd(); msg.Hand { - m.Cap("ps_target", msg.Cap("module")) - } else { - msg.Copy(m, "target").Copy(m, "result").Detail(-1, "system") - msg.Cmd() - } - - for _, v := range exports { - if v["file"] != "" { - m.Sess("nfs").Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"]) - } - if v["cache"] != "" { - if v["index"] == "result" { - m.Cap(v["cache"], strings.Join(msg.Meta["result"], "")) - } else { - m.Cap(v["cache"], msg.Append(v["index"])) - } - } - if v["config"] != "" { - if v["index"] == "result" { - m.Conf(v["config"], strings.Join(msg.Meta["result"], "")) - } else { - m.Conf(v["config"], msg.Append(v["index"])) - } - } - } - - if len(rest) > 0 { - pipe := m.Spawn().Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("cmd", rest) - - msg.Set("result").Set("append") - msg.Copy(pipe, "result").Copy(pipe, "append") - } - - m.Target().Message().Set("result").Set("append").Copy(msg, "result").Copy(msg, "append") - m.Set("append").Copy(msg, "append") - m.Set("result").Copy(msg, "result") - - // m.Capi("last_msg", 0, msg.Code()) - // m.Capi("ps_count", 1) } + if !exec && !execexec { + return + } + + // 执行命令 + if msg.Set("detail", args).Cmd(); !msg.Hand { + msg.Cmd("system", args) + } + + // 管道命令 + if len(rest) > 0 { + pipe := m.Spawn().Copy(msg, "option") + pipe.Copy(msg, "append").Copy(msg, "result").Cmd("cmd", rest) + msg.Set("append").Copy(pipe, "append") + msg.Set("result").Copy(pipe, "result") + } + + // 导出结果 + for _, v := range exports { + if v["file"] != "" { + m.Sess("nfs").Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"]) + } + if v["cache"] != "" { + if v["index"] == "result" { + m.Cap(v["cache"], strings.Join(msg.Meta["result"], "")) + } else { + m.Cap(v["cache"], msg.Append(v["index"])) + } + } + if v["config"] != "" { + if v["index"] == "result" { + m.Conf(v["config"], strings.Join(msg.Meta["result"], "")) + } else { + m.Conf(v["config"], msg.Append(v["index"])) + } + } + } + + // 返回结果 + m.Optionv("ps_target", msg.Target()) + m.Set("append").Copy(msg, "append") + m.Set("result").Copy(msg, "result") return }}, "str": &ctx.Command{Name: "str word", Help: "解析字符串", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -383,33 +323,30 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", return }}, "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: - m.Echo(arg[0]) - case 2: - msg := m.Spawn(cli.target) - switch arg[0] { - case "$": - m.Echo(msg.Cap(arg[1])) - case "@": - value := msg.Option(arg[1]) - if value == "" { - value = msg.Conf(arg[1]) - } + switch len(arg) { + case 1: + m.Echo(arg[0]) + case 2: + msg := m.Spawn(m.Optionv("ps_target")) + switch arg[0] { + case "$": + m.Echo(msg.Cap(arg[1])) + case "@": + value := msg.Option(arg[1]) + if value == "" { + value = msg.Conf(arg[1]) + } - m.Echo(value) - default: - m.Echo(arg[0]).Echo(arg[1]) - } + m.Echo(value) default: - switch arg[0] { - case "$", "@": - m.Result(0, arg[2:len(arg)-1]) - } + m.Echo(arg[0]).Echo(arg[1]) } - return - } //}}} + default: + switch arg[0] { + case "$", "@": + m.Result(0, arg[2:len(arg)-1]) + } + } return }}, "val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -614,10 +551,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", return }}, "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 }}, @@ -630,6 +563,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", if (len(arg) == 0 || arg[0] == "stdio") && m.Target().Name == "cli" { // 启动终端 m.Cmd("yac.init") + m.Optionv("ps_target", m.Target()) if m.Start("shy", "shell", "stdio"); m.Cmds("nfs.path", m.Confx("init_shy", arg, 1)) { // msg := m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("init_shy")) @@ -682,10 +616,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", return }}, "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") - } + m.Set("result", m.Optionv("arguments")) return }}, "run": &ctx.Command{Name: "run", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -803,45 +734,37 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { wait := make(chan bool, 1) go func() { - if m.Has("cmd_error") { - if out, e := cmd.CombinedOutput(); e != nil { - m.Echo("error: ").Echo("%s\n", e) - m.Echo("%s\n", string(out)) - } else { - m.Echo(string(out)) - } - } else { - if out, e := cmd.Output(); e != nil { - if e == exec.ErrNotFound { - m.Echo("error: ").Echo("not found\n") - } else { - m.Echo("error: ").Echo("%s\n", e) - m.Echo("%s\n", string(out)) - } - } else { - switch m.Option("cmd_parse") { - case "json": - var data interface{} - if json.Unmarshal(out, &data) == nil { - msg := m.Spawn().Put("option", "data", data).Cmd("trans", "data", "") - m.Copy(msg, "append").Copy(msg, "result") - } else { - m.Echo(string(out)) - } - case "csv": - data, e := csv.NewReader(bytes.NewReader(out)).ReadAll() - m.Assert(e) - for i := 1; i < len(data); i++ { - for j := 0; j < len(data[i]); j++ { - m.Add("append", data[0][j], data[i][j]) - } - } - m.Table() - default: + out := bytes.NewBuffer(make([]byte, 1024)) + err := bytes.NewBuffer(make([]byte, 1024)) + cmd.Stdout = out + cmd.Stderr = err + + if e := cmd.Run(); e == nil { + m.Echo("error: ").Echo("%s", e).Echo(string(err)) + } else { + + switch m.Option("cmd_parse") { + case "json": + var data interface{} + if json.Unmarshal(out, &data) == nil { + msg := m.Spawn().Put("option", "data", data).Cmd("trans", "data", "") + m.Copy(msg, "append").Copy(msg, "result") + } else { m.Echo(string(out)) } + case "csv": + data, e := csv.NewReader(bytes.NewReader(out)).ReadAll() + m.Assert(e) + for i := 1; i < len(data); i++ { + for j := 0; j < len(data[i]); j++ { + m.Add("append", data[0][j], data[i][j]) + } + } + m.Table() + default: + m.Echo(string(out)) } } wait <- true diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index ffba1e69..b486429a 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -402,13 +402,24 @@ func (m *Message) Format(arg ...string) string { meta = append(meta, fmt.Sprintf("%v", m.Meta["result"])) case "full": meta = append(meta, fmt.Sprintf("%s\n", m.Format("time", "ship"))) - meta = append(meta, fmt.Sprintf("detail: %s\n", m.Format("detail"))) - meta = append(meta, fmt.Sprintf("option: %s\n", m.Format("option"))) - for k, v := range m.Meta { - meta = append(meta, fmt.Sprintf(" %s: %v\n", k, v)) + meta = append(meta, fmt.Sprintf("detail: %d %v\n", len(m.Meta["detail"]), m.Meta["detail"])) + meta = append(meta, fmt.Sprintf("option: %d %v\n", len(m.Meta["option"]), m.Meta["option"])) + for _, k := range m.Meta["option"] { + if v, ok := m.Data[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v))) + } else if v, ok := m.Meta[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + } } - meta = append(meta, fmt.Sprintf("append: %s\n", m.Format("append"))) - meta = append(meta, fmt.Sprintf("result: %s\n", m.Format("result"))) + meta = append(meta, fmt.Sprintf("append: %d %v\n", len(m.Meta["append"]), m.Meta["append"])) + for _, k := range m.Meta["append"] { + if v, ok := m.Data[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v))) + } else if v, ok := m.Meta[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + } + } + meta = append(meta, fmt.Sprintf("result: %d %v\n", len(m.Meta["result"]), m.Meta["result"])) } } return strings.Join(meta, " ") @@ -786,6 +797,7 @@ func (m *Message) Table(cbs ...func(maps map[string]string, list []string, line if len(m.Meta[k]) > depth { depth = len(m.Meta[k]) } + width[k] = len(k) for _, v := range m.Meta[k] { if len(v) > width[k] { width[k] = len(v) @@ -1062,9 +1074,9 @@ func (m *Message) Back(msg *Message) *Message { } if msg.Hand { - m.Log("cb", "%d %v %v", msg.code, msg.Meta["result"], msg.Meta["append"]) + m.Log("cbs", msg.Format("ship", "result", "append")) } else { - m.Log("cb", "%d %v %v", msg.code, msg.Meta["detail"], msg.Meta["option"]) + m.Log("cbs", msg.Format("ship", "detail", "option")) } if sub := m.callback(msg); sub != nil && m.message != nil && m.message != m { @@ -1073,6 +1085,10 @@ func (m *Message) Back(msg *Message) *Message { return m } +func (m *Message) Backs(msg *Message) *Message { + m.Back(msg) + return msg +} func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg ...interface{}) *Message { if !sync { return m.Call(cb, arg...) @@ -1119,11 +1135,13 @@ func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) case io.EOF: case nil: default: + m.Log("stack", "%s", msg.Format("full")) + m.Log("stack", "%s\n%s\n", e, string(debug.Stack())) + 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) } } @@ -1382,532 +1400,9 @@ func (m *Message) Cap(key string, arg ...interface{}) string { return cache.Value } -var CGI = template.FuncMap{ - "meta": func(arg ...interface{}) string { - //meta meta [key [index]] - if len(arg) == 0 { - return "" - } - - up := "" - - list := []string{} - switch data := arg[0].(type) { - case map[string][]string: - if len(arg) == 1 { - list = append(list, fmt.Sprintf("detail: %s\n", data["detail"])) - list = append(list, fmt.Sprintf("option: %s\n", data["option"])) - list = append(list, fmt.Sprintf("result: %s\n", data["result"])) - list = append(list, fmt.Sprintf("append: %s\n", data["append"])) - break - } - if key, ok := arg[1].(string); ok { - if list, ok = data[key]; ok { - arg = arg[1:] - } else { - return up - } - } else { - return fmt.Sprintf("%v", data) - } - case []string: - list = data - default: - if data == nil { - return "" - } - return fmt.Sprintf("%v", data) - } - - if len(arg) == 1 { - return strings.Join(list, "") - } - - index, ok := arg[1].(int) - if !ok { - return strings.Join(list, "") - } - - if index >= len(list) { - return "" - } - return list[index] - }, - "sess": func(arg ...interface{}) string { - if len(arg) == 0 { - return "" - } - - if m, ok := arg[0].(*Message); ok { - if len(arg) == 1 { - return fmt.Sprintf("%v", m) - } - - switch which := arg[1].(type) { - case string: - m.Sess(which, arg[2:]...) - return "" - } - } - return "" - }, - - "ctx": func(arg ...interface{}) string { - if len(arg) == 0 { - return "" - } - if m, ok := arg[0].(*Message); ok { - if len(arg) == 1 { - return fmt.Sprintf("%v", m) - } - - switch which := arg[1].(type) { - case string: - switch which { - case "name": - return fmt.Sprintf("%s", m.target.Name) - case "help": - return fmt.Sprintf("%s", m.target.Help) - case "context": - return fmt.Sprintf("%s", m.target.context.Name) - case "contexts": - ctx := []string{} - for _, v := range m.target.contexts { - ctx = append(ctx, fmt.Sprintf("%d", v.Name)) - } - return strings.Join(ctx, " ") - case "time": - return m.time.Format("2006-01-02 15:04:05") - case "source": - return m.source.Name - case "target": - return m.target.Name - case "message": - return fmt.Sprintf("%d", m.message.code) - case "messages": - case "sessions": - msg := []string{} - for k, _ := range m.Sessions { - msg = append(msg, fmt.Sprintf("%s", k)) - } - return strings.Join(msg, " ") - } - case int: - } - } - return "" - }, - "msg": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - if m, ok := arg[0].(*Message); ok { - if len(arg) == 1 { - return fmt.Sprintf("%v", m.Format()) - } - - switch which := arg[1].(type) { - case string: - switch which { - case "spawn": - return m.Spawn() - case "code": - return m.code - case "time": - return m.time.Format("2006-01-02 15:04:05") - case "source": - return m.source.Name - case "target": - return m.target.Name - case "message": - return m.message - case "messages": - return m.messages - case "sessions": - return m.Sessions - default: - return m.Sess(which) - } - case int: - ms := []*Message{m} - for i := 0; i < len(ms); i++ { - if ms[i].code == which { - return ms[i] - } - ms = append(ms, ms[i].messages...) - } - } - } - return "" - }, - - "cap": func(arg ...interface{}) string { - if len(arg) == 0 { - return "" - } - - if m, ok := arg[0].(*Message); ok { - if len(arg) == 1 { - return fmt.Sprintf("%v", m) - } - - switch which := arg[1].(type) { - case string: - if len(arg) == 2 { - return m.Cap(which) - } - - switch value := arg[2].(type) { - case string: - return m.Cap(which, value) - case int: - return fmt.Sprintf("%d", m.Capi(which, value)) - case bool: - return fmt.Sprintf("%t", m.Caps(which, value)) - default: - return m.Cap(which, fmt.Sprintf("%v", arg[2])) - } - } - } - return "" - }, - "conf": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - if m, ok := arg[0].(*Message); ok { - if len(arg) == 1 { - list := []string{} - for k, _ := range m.target.Configs { - list = append(list, k) - } - return list - } - - switch which := arg[1].(type) { - case string: - if len(arg) == 2 { - return m.Confv(which) - } - return m.Confv(which, arg[2:]...) - } - } - return "" - }, - "cmd": func(arg ...interface{}) string { - if len(arg) == 0 { - return "" - } - - return strings.Join(Pulse.Sess("cli").Cmd(arg).Meta["result"], "") - }, - - "detail": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - switch m := arg[0].(type) { - case *Message: - if len(arg) == 1 { - return m.Meta["detail"] - } - - index := 0 - switch value := arg[1].(type) { - case int: - index = value - case string: - i, e := strconv.Atoi(value) - m.Assert(e) - index = i - } - - if len(arg) == 2 { - return m.Detail(index) - } - - return m.Detail(index, arg[2]) - case map[string][]string: - return strings.Join(m["detail"], "") - case []string: - return strings.Join(m, "") - default: - return m - } - return "" - }, - "option": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - switch m := arg[0].(type) { - case *Message: - if len(arg) == 1 { - return m.Meta["option"] - } - - switch value := arg[1].(type) { - case int: - if 0 <= value && value < len(m.Meta["option"]) { - return m.Meta["option"][value] - } - case string: - if len(arg) == 2 { - return m.Optionv(value) - } - - switch val := arg[2].(type) { - case int: - if 0 <= val && val < len(m.Meta[value]) { - return m.Meta[value][val] - } - } - } - case map[string][]string: - if len(arg) == 1 { - return strings.Join(m["option"], "") - } - switch value := arg[1].(type) { - case string: - return strings.Join(m[value], "") - } - case []string: - return strings.Join(m, "") - default: - return m - } - return "" - }, - "result": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - switch m := arg[0].(type) { - case *Message: - if len(arg) == 1 { - return m.Meta["result"] - } - - index := 0 - switch value := arg[1].(type) { - case int: - index = value - case string: - i, e := strconv.Atoi(value) - m.Assert(e) - index = i - } - - if len(arg) == 2 { - return m.Result(index) - } - - return m.Result(index, arg[2]) - case map[string][]string: - return strings.Join(m["result"], "") - case []string: - return strings.Join(m, "") - default: - return m - } - return "" - }, - "append": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - switch m := arg[0].(type) { - case *Message: - if len(arg) == 1 { - return m.Meta["append"] - } - - switch value := arg[1].(type) { - case int: - if 0 <= value && value < len(m.Meta["append"]) { - return m.Meta["append"][value] - } - case string: - if len(arg) == 2 { - return m.Meta[value] - } - - switch val := arg[2].(type) { - case int: - if 0 <= val && val < len(m.Meta[value]) { - return m.Meta[value][val] - } - } - } - case map[string][]string: - if len(arg) == 1 { - return strings.Join(m["append"], "") - } - switch value := arg[1].(type) { - case string: - return strings.Join(m[value], "") - } - case []string: - return strings.Join(m, "") - default: - return m - } - return "" - }, - "table": func(arg ...interface{}) []interface{} { - if len(arg) == 0 { - return []interface{}{} - } - - switch m := arg[0].(type) { - case *Message: - if len(m.Meta["append"]) == 0 { - return []interface{}{} - } - if len(arg) == 1 { - data := []interface{}{} - nrow := len(m.Meta[m.Meta["append"][0]]) - for i := 0; i < nrow; i++ { - line := map[string]string{} - for _, k := range m.Meta["append"] { - line[k] = m.Meta[k][i] - if len(m.Meta[k]) != i { - continue - } - } - data = append(data, line) - } - - return data - } - case map[string][]string: - if len(arg) == 1 { - data := []interface{}{} - nrow := len(m[m["append"][0]]) - - for i := 0; i < nrow; i++ { - line := map[string]string{} - for _, k := range m["append"] { - line[k] = m[k][i] - } - data = append(data, line) - } - - return data - } - } - return []interface{}{} - }, - - "list": func(arg interface{}) interface{} { - n := 0 - switch v := arg.(type) { - case string: - i, e := strconv.Atoi(v) - if e == nil { - n = i - } - case int: - n = v - } - - list := make([]int, n) - for i := 1; i <= n; i++ { - list[i-1] = i - } - return list - }, - "slice": func(list interface{}, arg ...interface{}) interface{} { - switch l := list.(type) { - case string: - if len(arg) == 0 { - return l - } - if len(arg) == 1 { - return l[arg[0].(int):] - } - if len(arg) == 2 { - return l[arg[0].(int):arg[1].(int)] - } - } - - return "" - }, - - "work": func(m *Message, arg ...interface{}) interface{} { - switch len(arg) { - case 0: - list := map[string]map[string]interface{}{} - m.Confm("auth", []string{m.Option("sessid"), "ship"}, func(key string, ship map[string]interface{}) { - if ship["type"] == "bench" { - if work := m.Confm("auth", key); work != nil { - list[key] = work - } - } - }) - return list - } - return nil - }, - - "unescape": func(str string) interface{} { - return template.HTML(str) - }, - "json": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - b, _ := json.MarshalIndent(arg[0], "", " ") - return string(b) - }, - "so": func(arg ...interface{}) interface{} { - if len(arg) == 0 { - return "" - } - - cli := Pulse.Sess("cli") - cmd := strings.Join(kit.Trans(arg), " ") - cli.Cmd("source", cmd) - - result := []string{} - if len(cli.Meta["append"]) > 0 { - result = append(result, "") - result = append(result, "") - cli.Table(func(maps map[string]string, list []string, line int) bool { - if line == -1 { - result = append(result, "") - for _, v := range list { - result = append(result, "") - } - result = append(result, "") - return true - } - result = append(result, "") - for _, v := range list { - result = append(result, "") - } - result = append(result, "") - return true - }) - result = append(result, "
", cmd, "
", v, "
", v, "
") - } else { - result = append(result, "
")
-			result = append(result, fmt.Sprintf("%s", cli.Find("shy", false).Conf("prompt")), cmd, "\n")
-			result = append(result, cli.Meta["result"]...)
-			result = append(result, "
") - } - - return template.HTML(strings.Join(result, "")) - }, +type CTX struct { } -var Pulse = &Message{code: 0, time: time.Now(), source: Index, target: Index, Meta: map[string][]string{}} + var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, Caches: map[string]*Cache{ "begin_time": &Cache{Name: "begin_time", Value: "", Help: "启动时间"}, @@ -2457,7 +1952,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, case "switch": m.target = msg.target case "list": - m.Target().Travel(msg, func(msg *Message, n int) bool { + msg.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) @@ -2468,7 +1963,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, m.Add("append", "status", msg.Cap("status")) m.Add("append", "stream", msg.Cap("stream")) m.Add("append", "help", msg.target.Help) - return true + return false }) case "spawn": msg.target.Spawn(msg, arg[0], arg[1]).Begin(msg, arg[2:]...) @@ -3155,8 +2650,530 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, }}, }, } +var CGI = template.FuncMap{ + "meta": func(arg ...interface{}) string { + //meta meta [key [index]] + if len(arg) == 0 { + return "" + } -type CTX struct { + up := "" + + list := []string{} + switch data := arg[0].(type) { + case map[string][]string: + if len(arg) == 1 { + list = append(list, fmt.Sprintf("detail: %s\n", data["detail"])) + list = append(list, fmt.Sprintf("option: %s\n", data["option"])) + list = append(list, fmt.Sprintf("result: %s\n", data["result"])) + list = append(list, fmt.Sprintf("append: %s\n", data["append"])) + break + } + if key, ok := arg[1].(string); ok { + if list, ok = data[key]; ok { + arg = arg[1:] + } else { + return up + } + } else { + return fmt.Sprintf("%v", data) + } + case []string: + list = data + default: + if data == nil { + return "" + } + return fmt.Sprintf("%v", data) + } + + if len(arg) == 1 { + return strings.Join(list, "") + } + + index, ok := arg[1].(int) + if !ok { + return strings.Join(list, "") + } + + if index >= len(list) { + return "" + } + return list[index] + }, + "sess": func(arg ...interface{}) string { + if len(arg) == 0 { + return "" + } + + if m, ok := arg[0].(*Message); ok { + if len(arg) == 1 { + return fmt.Sprintf("%v", m) + } + + switch which := arg[1].(type) { + case string: + m.Sess(which, arg[2:]...) + return "" + } + } + return "" + }, + + "ctx": func(arg ...interface{}) string { + if len(arg) == 0 { + return "" + } + if m, ok := arg[0].(*Message); ok { + if len(arg) == 1 { + return fmt.Sprintf("%v", m) + } + + switch which := arg[1].(type) { + case string: + switch which { + case "name": + return fmt.Sprintf("%s", m.target.Name) + case "help": + return fmt.Sprintf("%s", m.target.Help) + case "context": + return fmt.Sprintf("%s", m.target.context.Name) + case "contexts": + ctx := []string{} + for _, v := range m.target.contexts { + ctx = append(ctx, fmt.Sprintf("%d", v.Name)) + } + return strings.Join(ctx, " ") + case "time": + return m.time.Format("2006-01-02 15:04:05") + case "source": + return m.source.Name + case "target": + return m.target.Name + case "message": + return fmt.Sprintf("%d", m.message.code) + case "messages": + case "sessions": + msg := []string{} + for k, _ := range m.Sessions { + msg = append(msg, fmt.Sprintf("%s", k)) + } + return strings.Join(msg, " ") + } + case int: + } + } + return "" + }, + "msg": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + if m, ok := arg[0].(*Message); ok { + if len(arg) == 1 { + return fmt.Sprintf("%v", m.Format()) + } + + switch which := arg[1].(type) { + case string: + switch which { + case "spawn": + return m.Spawn() + case "code": + return m.code + case "time": + return m.time.Format("2006-01-02 15:04:05") + case "source": + return m.source.Name + case "target": + return m.target.Name + case "message": + return m.message + case "messages": + return m.messages + case "sessions": + return m.Sessions + default: + return m.Sess(which) + } + case int: + ms := []*Message{m} + for i := 0; i < len(ms); i++ { + if ms[i].code == which { + return ms[i] + } + ms = append(ms, ms[i].messages...) + } + } + } + return "" + }, + + "cap": func(arg ...interface{}) string { + if len(arg) == 0 { + return "" + } + + if m, ok := arg[0].(*Message); ok { + if len(arg) == 1 { + return fmt.Sprintf("%v", m) + } + + switch which := arg[1].(type) { + case string: + if len(arg) == 2 { + return m.Cap(which) + } + + switch value := arg[2].(type) { + case string: + return m.Cap(which, value) + case int: + return fmt.Sprintf("%d", m.Capi(which, value)) + case bool: + return fmt.Sprintf("%t", m.Caps(which, value)) + default: + return m.Cap(which, fmt.Sprintf("%v", arg[2])) + } + } + } + return "" + }, + "conf": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + if m, ok := arg[0].(*Message); ok { + if len(arg) == 1 { + list := []string{} + for k, _ := range m.target.Configs { + list = append(list, k) + } + return list + } + + switch which := arg[1].(type) { + case string: + if len(arg) == 2 { + return m.Confv(which) + } + return m.Confv(which, arg[2:]...) + } + } + return "" + }, + "cmd": func(arg ...interface{}) string { + if len(arg) == 0 { + return "" + } + + return strings.Join(Pulse.Sess("cli").Cmd(arg).Meta["result"], "") + }, + + "detail": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + switch m := arg[0].(type) { + case *Message: + if len(arg) == 1 { + return m.Meta["detail"] + } + + index := 0 + switch value := arg[1].(type) { + case int: + index = value + case string: + i, e := strconv.Atoi(value) + m.Assert(e) + index = i + } + + if len(arg) == 2 { + return m.Detail(index) + } + + return m.Detail(index, arg[2]) + case map[string][]string: + return strings.Join(m["detail"], "") + case []string: + return strings.Join(m, "") + default: + return m + } + return "" + }, + "option": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + switch m := arg[0].(type) { + case *Message: + if len(arg) == 1 { + return m.Meta["option"] + } + + switch value := arg[1].(type) { + case int: + if 0 <= value && value < len(m.Meta["option"]) { + return m.Meta["option"][value] + } + case string: + if len(arg) == 2 { + return m.Optionv(value) + } + + switch val := arg[2].(type) { + case int: + if 0 <= val && val < len(m.Meta[value]) { + return m.Meta[value][val] + } + } + } + case map[string][]string: + if len(arg) == 1 { + return strings.Join(m["option"], "") + } + switch value := arg[1].(type) { + case string: + return strings.Join(m[value], "") + } + case []string: + return strings.Join(m, "") + default: + return m + } + return "" + }, + "result": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + switch m := arg[0].(type) { + case *Message: + if len(arg) == 1 { + return m.Meta["result"] + } + + index := 0 + switch value := arg[1].(type) { + case int: + index = value + case string: + i, e := strconv.Atoi(value) + m.Assert(e) + index = i + } + + if len(arg) == 2 { + return m.Result(index) + } + + return m.Result(index, arg[2]) + case map[string][]string: + return strings.Join(m["result"], "") + case []string: + return strings.Join(m, "") + default: + return m + } + return "" + }, + "append": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + switch m := arg[0].(type) { + case *Message: + if len(arg) == 1 { + return m.Meta["append"] + } + + switch value := arg[1].(type) { + case int: + if 0 <= value && value < len(m.Meta["append"]) { + return m.Meta["append"][value] + } + case string: + if len(arg) == 2 { + return m.Meta[value] + } + + switch val := arg[2].(type) { + case int: + if 0 <= val && val < len(m.Meta[value]) { + return m.Meta[value][val] + } + } + } + case map[string][]string: + if len(arg) == 1 { + return strings.Join(m["append"], "") + } + switch value := arg[1].(type) { + case string: + return strings.Join(m[value], "") + } + case []string: + return strings.Join(m, "") + default: + return m + } + return "" + }, + "table": func(arg ...interface{}) []interface{} { + if len(arg) == 0 { + return []interface{}{} + } + + switch m := arg[0].(type) { + case *Message: + if len(m.Meta["append"]) == 0 { + return []interface{}{} + } + if len(arg) == 1 { + data := []interface{}{} + nrow := len(m.Meta[m.Meta["append"][0]]) + for i := 0; i < nrow; i++ { + line := map[string]string{} + for _, k := range m.Meta["append"] { + line[k] = m.Meta[k][i] + if len(m.Meta[k]) != i { + continue + } + } + data = append(data, line) + } + + return data + } + case map[string][]string: + if len(arg) == 1 { + data := []interface{}{} + nrow := len(m[m["append"][0]]) + + for i := 0; i < nrow; i++ { + line := map[string]string{} + for _, k := range m["append"] { + line[k] = m[k][i] + } + data = append(data, line) + } + + return data + } + } + return []interface{}{} + }, + + "list": func(arg interface{}) interface{} { + n := 0 + switch v := arg.(type) { + case string: + i, e := strconv.Atoi(v) + if e == nil { + n = i + } + case int: + n = v + } + + list := make([]int, n) + for i := 1; i <= n; i++ { + list[i-1] = i + } + return list + }, + "slice": func(list interface{}, arg ...interface{}) interface{} { + switch l := list.(type) { + case string: + if len(arg) == 0 { + return l + } + if len(arg) == 1 { + return l[arg[0].(int):] + } + if len(arg) == 2 { + return l[arg[0].(int):arg[1].(int)] + } + } + + return "" + }, + + "work": func(m *Message, arg ...interface{}) interface{} { + switch len(arg) { + case 0: + list := map[string]map[string]interface{}{} + m.Confm("auth", []string{m.Option("sessid"), "ship"}, func(key string, ship map[string]interface{}) { + if ship["type"] == "bench" { + if work := m.Confm("auth", key); work != nil { + list[key] = work + } + } + }) + return list + } + return nil + }, + + "unescape": func(str string) interface{} { + return template.HTML(str) + }, + "json": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + b, _ := json.MarshalIndent(arg[0], "", " ") + return string(b) + }, + "so": func(arg ...interface{}) interface{} { + if len(arg) == 0 { + return "" + } + + cli := Pulse.Sess("cli") + cmd := strings.Join(kit.Trans(arg), " ") + cli.Cmd("source", cmd) + + result := []string{} + if len(cli.Meta["append"]) > 0 { + result = append(result, "") + result = append(result, "") + cli.Table(func(maps map[string]string, list []string, line int) bool { + if line == -1 { + result = append(result, "") + for _, v := range list { + result = append(result, "") + } + result = append(result, "") + return true + } + result = append(result, "") + for _, v := range list { + result = append(result, "") + } + result = append(result, "") + return true + }) + result = append(result, "
", cmd, "
", v, "
", v, "
") + } else { + result = append(result, "
")
+			result = append(result, fmt.Sprintf("%s", cli.Find("shy", false).Conf("prompt")), cmd, "\n")
+			result = append(result, cli.Meta["result"]...)
+			result = append(result, "
") + } + + return template.HTML(strings.Join(result, "")) + }, } func (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server { @@ -3189,6 +3206,8 @@ func (ctx *CTX) Close(m *Message, arg ...string) bool { return true } +var Pulse = &Message{code: 0, time: time.Now(), source: Index, target: Index, Meta: map[string][]string{}} + func Start(args ...string) bool { if len(args) == 0 { args = append(args, os.Args[1:]...) diff --git a/src/contexts/gdb/gdb.go b/src/contexts/gdb/gdb.go index 8a8a8488..0a10816e 100644 --- a/src/contexts/gdb/gdb.go +++ b/src/contexts/gdb/gdb.go @@ -2,12 +2,13 @@ package gdb import ( "contexts/ctx" + "toolkit" + "fmt" "io/ioutil" "os" "os/signal" "syscall" - "toolkit" ) type GDB struct { diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go index bbed4645..a8fe9a94 100644 --- a/src/contexts/log/log.go +++ b/src/contexts/log/log.go @@ -89,13 +89,15 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", Configs: map[string]*ctx.Config{ "output": &ctx.Config{Name: "output", Value: map[string]interface{}{ "error": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "trace": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, + "debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, + "bench": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}}}, "begin": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, "start": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, "cmd": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}, "lex": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, }, - "debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, }, Help: "日志输出配置"}, }, Commands: map[string]*ctx.Command{ diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 6ab5b4f5..5a49c1bd 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -239,40 +239,6 @@ func (nfs *NFS) print(str string) bool { return true } -func (nfs *NFS) prompt(arg ...string) string { - nfs.out.WriteString("> ") - return "> " - - ps := nfs.Option("prompt") - if nfs.Caps("windows") { - nfs.color(ps) - return ps - } - line, rest := "", "" - if len(arg) > 0 { - line = arg[0] - } - if len(arg) > 1 { - rest = arg[1] - } - - if !nfs.Caps("windows") && len(nfs.pages) > 0 && nfs.width > 0 { - for i := (len(nfs.pages[len(nfs.pages)-1]) - 1) / (nfs.width); i > 0; i-- { - nfs.escape("2K").escape("A") - } - nfs.escape("2K").escape("G").escape("?25h") - } - - if len(nfs.pages) > 0 { - nfs.pages = nfs.pages[:len(nfs.pages)-1] - } - nfs.pages = append(nfs.pages, ps+line+rest+"\n") - - if nfs.color(ps, nfs.Confi("pscolor")).color(line).color(rest); len(rest) > 0 { - nfs.escape("%dD", len(rest)) - } - return ps -} func (nfs *NFS) zone(buf []string, top, height int) (row, col int) { row, col = len(buf)-1, 0 for i := nfs.Capi("cursor_pos"); i > top-1; { @@ -558,6 +524,54 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { return } +func (nfs *NFS) prompt(arg ...string) string { + m := nfs.Context.Message() + target := m.Optionv("ps_target").(*ctx.Context) + nfs.out.WriteString(fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name)) + return "> " + + ps := nfs.Option("prompt") + if nfs.Caps("windows") { + nfs.color(ps) + return ps + } + line, rest := "", "" + if len(arg) > 0 { + line = arg[0] + } + if len(arg) > 1 { + rest = arg[1] + } + + if !nfs.Caps("windows") && len(nfs.pages) > 0 && nfs.width > 0 { + for i := (len(nfs.pages[len(nfs.pages)-1]) - 1) / (nfs.width); i > 0; i-- { + nfs.escape("2K").escape("A") + } + nfs.escape("2K").escape("G").escape("?25h") + } + + if len(nfs.pages) > 0 { + nfs.pages = nfs.pages[:len(nfs.pages)-1] + } + nfs.pages = append(nfs.pages, ps+line+rest+"\n") + + if nfs.color(ps, nfs.Confi("pscolor")).color(line).color(rest); len(rest) > 0 { + nfs.escape("%dD", len(rest)) + } + return ps +} +func (nfs *NFS) printf(arg ...interface{}) *NFS { + for _, v := range arg { + if nfs.io != nil { + fmt.Fprint(nfs.io, kit.Format(v)) + } else if nfs.out != nil { + nfs.out.WriteString(kit.Format(v)) + } + } + + return nfs +} + func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") { c.Caches = map[string]*ctx.Cache{ @@ -591,7 +605,22 @@ func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { return nfs } func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { + + if len(arg) > 0 && (arg[0] == "open" || arg[0] == "append") { + nfs.out = m.Optionv("out").(*os.File) + nfs.in = m.Optionv("in").(*os.File) + m.Cap("stream", arg[1]) + + if s, e := nfs.in.Stat(); m.Assert(e) { + if m.Capi("size", int(s.Size())); arg[0] == "append" { + m.Capi("pos", int(s.Size())) + } + } + return false + } + if len(arg) > 0 && arg[0] == "scan" { + m.Cap("stream", arg[1]) nfs.Caches["ninput"] = &ctx.Cache{Value: "0"} nfs.Caches["noutput"] = &ctx.Cache{Value: "0"} nfs.Configs["input"] = &ctx.Config{Value: []interface{}{}} @@ -609,30 +638,38 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { } line = strings.TrimSuffix(line, "\\") } - m.Confv("input", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) m.Log("debug", "%s %d %d [%s]", "input", m.Capi("ninput", 1), len(line), line) for i := m.Capi("ninput") - 1; i < m.Capi("ninput"); i++ { line = m.Conf("input", []interface{}{i, "line"}) - msg := m.Spawn(m.Source()).Set("detail", line).Set("option", "file_pos", i) - m.Back(msg) + msg := m.Backs(m.Spawn(m.Source()).Set("detail", line).Set("option", "file_pos", i)) lines := strings.Split(strings.Join(msg.Meta["result"], ""), "\n") - for _, line := range lines { - if line != "" { - m.Log("debug", "%s %d %d [%s]", "output", m.Capi("noutput", 1), len(line), line) - m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) - nfs.print(line) - nfs.print("\n") + for j := len(lines) - 1; j > 0; j-- { + if strings.TrimSpace(lines[j]) != "" { + break } + lines = lines[:j] + } + for _, line := range lines { + m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) + m.Log("debug", "%s %d %d [%s]", "output", m.Capi("noutput", 1), len(line), line) + nfs.printf(line).printf("\n") + } + + if msg.Appends("file_pos0") { + i = msg.Appendi("file_pos0") - 1 + msg.Append("file_pos0", "") } } - line = "" } + if !m.Options("scan_end") { + m.Backs(m.Spawn(m.Source()).Set("detail", "return")) + } return true } @@ -649,12 +686,13 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // nfs.Configs["statusfgcolor"] = &ctx.Config{Name: "statusfgcolor", Value: "1", Help: "pscolor"} // nfs.Configs["statusbgcolor"] = &ctx.Config{Name: "statusbgcolor", Value: "2", Help: "pscolor"} // - nfs.in = m.Optionv("in").(*os.File) - bio := bufio.NewScanner(nfs) - s, e := nfs.in.Stat() - m.Assert(e) - m.Capi("size", int(s.Size())) + // nfs.in = m.Optionv("in").(*os.File) + // bio := bufio.NewScanner(nfs) + // + // s, e := nfs.in.Stat() + // m.Assert(e) + // m.Capi("size", int(s.Size())) if m.Cap("stream", arg[1]) == "stdio" { nfs.out = m.Optionv("out").(*os.File) @@ -689,61 +727,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // } // } } - - line := "" - for nfs.prompt(); !m.Options("scan_end") && bio.Scan(); nfs.prompt() { - kit.Log("error", "stdio read %v", "text") - text := bio.Text() - m.Capi("nread", len(text)+1) - kit.Log("error", "stdio read %v", text) - continue - - if line += text; len(text) > 0 && text[len(text)-1] == '\\' { - line = line[:len(line)-1] - continue - } - m.Capi("nline", 1) - m.Confv("history", -2, line) - history := m.Confv("history").([]interface{}) - - for i := len(history) - 1; i < len(history); i++ { - line = history[i].(string) - - msg := m.Spawn(m.Source()).Set("detail", line) - msg.Option("file_pos", i) - m.Back(msg) - - for _, v := range msg.Meta["result"] { - m.Capi("nwrite", len(v)) - nfs.print(v) - } - if msg.Append("file_pos0") != "" { - i = msg.Appendi("file_pos0") - 1 - msg.Append("file_pos0", "") - } - } - line = "" - } - - kit.Log("error", "stdio read %v", line) - if !m.Options("scan_end") { - msg := m.Spawn(m.Source()).Set("detail", "return") - m.Back(msg) - } - return true - } - - if len(arg) > 0 && (arg[0] == "open" || arg[0] == "append") { - nfs.out = m.Optionv("out").(*os.File) - nfs.in = m.Optionv("in").(*os.File) - s, e := nfs.in.Stat() - m.Assert(e) - m.Capi("size", int(s.Size())) - m.Cap("stream", arg[1]) - if arg[0] == "append" { - m.Capi("pos", int(s.Size())) - } - return false } m.Cap("stream", m.Option("stream")) @@ -864,7 +847,7 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { var FileNotExist = errors.New("file not exist") var Index = &ctx.Context{Name: "nfs", Help: "存储中心", Caches: map[string]*ctx.Cache{ - "nfile": &ctx.Cache{Name: "nfile", Value: "-1", Help: "已经打开的文件数量"}, + "nfile": &ctx.Cache{Name: "nfile", Value: "0", Help: "已经打开的文件数量"}, }, Configs: map[string]*ctx.Config{ "term_simple": &ctx.Config{Name: "term_simple", Value: "false", Help: "二维码的默认大小"}, @@ -902,6 +885,86 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "paths": &ctx.Config{Name: "paths", Value: []interface{}{"var", "usr", "etc", ""}, Help: "文件路径"}, }, Commands: map[string]*ctx.Command{ + "open": &ctx.Command{Name: "open file", Help: "打开文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if m.Has("io") { + } else if p, f, e := open(m, arg[0], os.O_RDWR|os.O_CREATE); e == nil { + m.Put("option", "in", f).Put("option", "out", f) + arg[0] = p + } else { + return nil + } + + m.Start(fmt.Sprintf("file%d", m.Capi("nfile")), fmt.Sprintf("file %s", arg[0]), "open", arg[0]) + m.Echo(arg[0]) + 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) (e error) { + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil { + if len(arg) > 1 { + m.Cap("pos", arg[1]) + } + + buf := make([]byte, kit.Int(m.Confx("buf_size", arg, 0))) + if n, e := nfs.in.ReadAt(buf, int64(m.Capi("pos"))); e == io.EOF || m.Assert(e) { + m.Capi("nread", n) + if m.Capi("pos", n); n == 0 { + m.Cap("pos", "0") + } + } + m.Echo(string(buf)) + } + return + }}, + "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]) + } + + if len(arg[0]) == 0 { + m.Assert(nfs.out.Truncate(int64(m.Capi("pos")))) + m.Cap("size", m.Cap("pos")) + m.Cap("pos", "0") + } else { + n, e := nfs.out.WriteAt([]byte(arg[0]), int64(m.Capi("pos"))) + if m.Capi("nwrite", n); m.Assert(e) && m.Capi("pos", n) > m.Capi("size") { + m.Cap("size", m.Cap("pos")) + } + nfs.out.Sync() + } + + m.Echo(m.Cap("pos")) + } + return + }}, + + "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) { + if help := fmt.Sprintf("scan %s", arg[0]); arg[0] == "stdio" { + m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout).Start(arg[0], help, key, arg[0]) + } else if p, f, e := open(m, arg[0]); m.Assert(e) { + m.Put("option", "in", f).Start(fmt.Sprintf("file%s", m.Capi("nfile")), help, key, p) + } + } + return + }}, + "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 { + nfs.printf(v) + m.Echo(v) + } + } + return + }}, + "printf": &ctx.Command{Name: "printf 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.printf(arg) + } + return + }}, + "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 { @@ -942,34 +1005,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", return }}, - "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]) - - if arg[0] == "stdio" { - m.Optionv("in", os.Stdin) - m.Optionv("out", os.Stdout) - m.Start(arg[0], help, key, arg[0]) - return - } - - if p, f, e := open(m, arg[0]); m.Assert(e) { - m.Optionv("in", f) - 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) (e error) { - if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { - nfs.prompt() - for _, v := range arg { - nfs.out.WriteString(v) - m.Echo(v) - } - } - return - }}, "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() @@ -987,75 +1022,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, - "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) (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 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) (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) - - if len(arg) > 1 { - m.Cap("pos", arg[1]) - } - - buf := make([]byte, n) - if n, e = nfs.in.ReadAt(buf, int64(m.Capi("pos"))); e != io.EOF { - m.Assert(e) - } - m.Capi("nread", n) - m.Echo(string(buf)) - - if m.Capi("pos", n); n == 0 { - 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) (e error) { - if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { - if len(arg) > 1 { - m.Cap("pos", arg[1]) - } - - if len(arg[0]) == 0 { - m.Assert(nfs.out.Truncate(int64(m.Capi("pos")))) - m.Cap("size", m.Cap("pos")) - m.Cap("pos", "0") - } else { - n, e := nfs.out.WriteAt([]byte(arg[0]), int64(m.Capi("pos"))) - if m.Capi("nwrite", n); m.Assert(e) && m.Capi("pos", n) > m.Capi("size") { - m.Cap("size", m.Cap("pos")) - } - nfs.out.Sync() - } - - 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) (e error) { if p, f, e := open(m, arg[0]); m.Assert(e) { diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index 92fdf753..707fd3aa 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -218,9 +218,10 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line s, star = star, 0 } } + if hash == 0 { word = word[:0] - } else if out != nil { //执行命令 + } else if !m.Confs("exec", []string{yac.hand[hash], "disable"}) { //执行命令 msg := out.Spawn(m.Source()).Add("detail", yac.hand[hash], word) if m.Back(msg); msg.Hand { //命令替换 m.Assert(!msg.Has("return")) @@ -316,6 +317,10 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", map[string]interface{}{"page": "line", "hash": "line", "word": []interface{}{"opt{", "mul{", "stm", "cmd", "}", "}", "mul{", ";", "\n", "#[^\n]*\n", "}"}}, }, Help: "语法集合的最大数量"}, "info": &ctx.Config{Name: "info", Value: map[string]interface{}{"ncell": 128, "nlang": 64}, Help: "嵌套层级日志的标记"}, + "exec": &ctx.Config{Name: "info", Value: map[string]interface{}{ + "line": map[string]interface{}{"disable": true}, + "word": map[string]interface{}{"disable": true}, + }, 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) (e error) { diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index 2c33ef38..3f1308f5 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -94,6 +94,12 @@ func Format(arg ...interface{}) string { result = append(result, val...) case float64: result = append(result, fmt.Sprintf("%d", int(val))) + case *os.File: + if s, e := val.Stat(); e == nil { + result = append(result, fmt.Sprintf("%T [name: %s]", v, s.Name())) + } else { + result = append(result, fmt.Sprintf("%T", v)) + } case time.Time: result = append(result, fmt.Sprintf("%d", val.Format("2006-01-02 15:03:04"))) // case error: