diff --git a/etc/common.shy b/etc/common.shy index 30c0e6f6..4d34dbc0 100644 --- a/etc/common.shy +++ b/etc/common.shy @@ -1,11 +1,11 @@ ~aaa role root user shy shaoying -~mdb - note model favor spirit spirit relate relate - note model money expend expend amount amount - note model state active active elapse elapse - note model event action action target target - note model proxy ctx text cmd text - note model share stuff stuff right right - +# ~mdb +# note model favor spirit spirit relate relate +# note model money expend expend amount amount +# note model state active active elapse elapse +# note model event action action target target +# note model proxy ctx text cmd text +# note model share stuff stuff right right +# diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go index 4a086078..c0d02314 100644 --- a/src/contexts/aaa/aaa.go +++ b/src/contexts/aaa/aaa.go @@ -1,7 +1,6 @@ package aaa import ( - "gopkg.in/gomail.v2" "contexts/ctx" "crypto" "crypto/aes" @@ -16,6 +15,7 @@ import ( "encoding/json" "encoding/pem" "fmt" + "gopkg.in/gomail.v2" "io/ioutil" "math/big" "math/rand" @@ -36,7 +36,7 @@ type AAA struct { } func Auto(m *ctx.Message, arg ...string) { - msg := m.Spawn().Add("option", "auto_cmd", "").Cmd("auth", arg) + msg := m.Spawn().Add("option", "bio.cmd", "").Cmd("auth", arg) msg.Table(func(line int, maps map[string]string) { m.Add("append", "value", maps["key"]) m.Add("append", "name", fmt.Sprintf("%s: %s", maps["type"], maps["meta"])) @@ -130,10 +130,10 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", "expire": &ctx.Config{Name: "expire(s)", Value: "72000", Help: "会话超时"}, "email": &ctx.Config{Name: "email", Value: map[string]interface{}{ - "self": "shylinux@163.com", - "smtp": "smtp.163.com", - "port": "25", - }, Help: "会话超时"}, + "self": "shylinux@163.com", + "smtp": "smtp.163.com", + "port": "25", + }, Help: "会话超时"}, }, Commands: map[string]*ctx.Command{ "_init": &ctx.Command{Name: "_init", Help: "数字摘要", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -723,7 +723,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", msg.SetHeader("From", m.Conf("email", "self")) msg.SetHeader("To", arg[0]) msg.SetHeader("Subject", arg[1]) - msg.SetBody("text/html", strings.Join(arg[2:], "")) + msg.SetBody("text/html", strings.Join(arg[2:], "")) d := gomail.NewDialer(m.Conf("email", "smtp"), kit.Int(m.Conf("email", "port")), m.Conf("email", "self"), m.Conf("email", "code")) if e := d.DialAndSend(msg); e != nil { m.Echo("%v", e) @@ -832,8 +832,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心", // 生成证书 template := x509.Certificate{ - SerialNumber: big.NewInt(1), - IsCA: true, + SerialNumber: big.NewInt(1), + IsCA: true, BasicConstraintsValid: true, KeyUsage: x509.KeyUsageCertSign, Subject: pkix.Name{CommonName: kit.Format(common)}, diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 022535d9..18e18d68 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -16,24 +16,13 @@ import ( "fmt" "os" "plugin" - "regexp" "runtime" "strconv" "strings" "time" ) -type Frame struct { - key string - run bool - pos int - index int - list []string -} type CLI struct { - label map[string]string - stack []*Frame - *time.Timer Context *ctx.Context } @@ -51,51 +40,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: "命令解析"}, - } - return &CLI{Context: c} } func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { return cli } func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { - m.Cap("stream", m.Sess("yac").Call(func(cmd *ctx.Message) *ctx.Message { - if !m.Caps("parse") { - switch cmd.Detail(0) { - case "if": - cmd.Set("detail", "if", "false") - case "else": - case "end": - case "for": - default: - cmd.Hand = true - return nil - } - } - - if cmd.Cmd(); cmd.Has("return") { - m.Options("scan_end", true) - m.Target().Close(m) - } - - v := cmd.Optionv("ps_target") - if v != nil { - m.Optionv("ps_target", v) - } - return nil - }, "scan", arg).Target().Name) - - return false + return true } func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { - switch cli.Context { - case m.Target(): - case m.Source(): - } - return true + return false } var Index = &ctx.Context{Name: "cli", Help: "管理中心", @@ -605,52 +559,6 @@ func main() { } return }}, - "source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if len(arg) == 0 { - m.Cmdy("dir", "", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$") - return - } - - // 解析脚本文件 - if p := m.Cmdx("nfs.path", arg[0]); p != "" && strings.Contains(p, ".") { - arg[0] = p - switch path.Ext(p) { - case "": - case ".shy": - m.Option("scan_end", "false") - m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...) - m.Wait() - default: - m.Cmdy("system", m.Conf("system", []string{"script", strings.TrimPrefix(path.Ext(p), ".")}), arg) - } - m.Append("directory", "") - return - } - - // 解析终端命令 - if arg[0] == "stdio" { - m.Option("scan_end", "false") - m.Start("shy", "shell", "stdio", "engine") - m.Wait() - return - } - - text := strings.Join(arg, " ") - if !strings.HasPrefix(text, "sess") && m.Options("remote") { - text = m.Current(text) - } - - // 解析代码片段 - m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message { - switch msg.Cmd().Detail(0) { - case "cmd": - m.Set("append").Copy(msg, "append") - m.Set("result").Copy(msg, "result") - } - return nil - }, "parse", "line", "void", text) - 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) (e error) { if d, e := time.ParseDuration(arg[0]); m.Assert(e) { m.Log("info", "sleep %v", d) @@ -866,7 +774,7 @@ func main() { m.Echo("quit") case "1": - if m.Option("cli.modal") != "action" { + if m.Option("bio.modal") != "action" { m.Cmd("cli.source", m.Conf("system", "script.exit")) m.Echo("restart") } @@ -1289,16 +1197,16 @@ var version = struct { detail = append(detail, arg...) // 目标切换 - target := m.Optionv("ps_target") + target := m.Optionv("bio.ctx") if detail[0] != "context" { - defer func() { m.Optionv("ps_target", target) }() + defer func() { m.Optionv("bio.ctx", target) }() } // 解析脚本 msg := m for k, v := range m.Confv("system", "script").(map[string]interface{}) { if strings.HasSuffix(detail[0], "."+k) { - msg = m.Spawn(m.Optionv("ps_target")) + msg = m.Spawn(m.Optionv("bio.ctx")) detail[0] = m.Cmdx("nfs.path", detail[0]) detail = append([]string{v.(string)}, detail...) break @@ -1319,7 +1227,7 @@ var version = struct { } detail[0] = routes[len(routes)-1] } else { - msg = m.Spawn(m.Optionv("ps_target")) + msg = m.Spawn(m.Optionv("bio.ctx")) } } msg.Copy(m, "option").Copy(m, "append") @@ -1378,7 +1286,7 @@ var version = struct { if msg.Set("detail", args).Cmd(); !msg.Hand { msg.Cmd("system", args) } - if msg.Appends("ps_target1") { + if msg.Appends("bio.ctx1") { target = msg.Target() } @@ -1413,251 +1321,11 @@ var version = struct { } // 返回结果 - m.Optionv("ps_target", msg.Target()) + m.Optionv("bio.ctx", 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) { - 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) (e error) { - 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]) - } - 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) { - result := "false" - switch len(arg) { - case 0: - result = "" - case 1: - result = arg[0] - case 2: - switch arg[0] { - case "-z": - if arg[1] == "" { - result = "true" - } - case "-n": - if arg[1] != "" { - result = "true" - } - - case "-e": - if _, e := os.Stat(arg[1]); e == nil { - result = "true" - } - case "-f": - if info, e := os.Stat(arg[1]); e == nil && !info.IsDir() { - result = "true" - } - case "-d": - if info, e := os.Stat(arg[1]); e == nil && info.IsDir() { - result = "true" - } - case "+": - result = arg[1] - case "-": - result = arg[1] - if i, e := strconv.Atoi(arg[1]); e == nil { - result = fmt.Sprintf("%d", -i) - } - } - case 3: - v1, e1 := strconv.Atoi(arg[0]) - v2, e2 := strconv.Atoi(arg[2]) - switch arg[1] { - case ":=": - if !m.Target().Has(arg[0]) { - result = m.Cap(arg[0], arg[0], arg[2], "临时变量") - } - case "=": - result = m.Cap(arg[0], arg[2]) - case "+=": - if i, e := strconv.Atoi(m.Cap(arg[0])); e == nil && e2 == nil { - result = m.Cap(arg[0], fmt.Sprintf("%d", v2+i)) - } else { - result = m.Cap(arg[0], m.Cap(arg[0])+arg[2]) - } - case "+": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%d", v1+v2) - } else { - result = arg[0] + arg[2] - } - case "-": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%d", v1-v2) - } else { - result = strings.Replace(arg[0], arg[1], "", -1) - } - case "*": - result = arg[0] - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%d", v1*v2) - } - case "/": - result = arg[0] - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%d", v1/v2) - } - case "%": - result = arg[0] - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%d", v1%v2) - } - - case "<": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%t", v1 < v2) - } else { - result = fmt.Sprintf("%t", arg[0] < arg[2]) - } - case "<=": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%t", v1 <= v2) - } else { - result = fmt.Sprintf("%t", arg[0] <= arg[2]) - } - case ">": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%t", v1 > v2) - } else { - result = fmt.Sprintf("%t", arg[0] > arg[2]) - } - case ">=": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%t", v1 >= v2) - } else { - result = fmt.Sprintf("%t", arg[0] >= arg[2]) - } - case "==": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%t", v1 == v2) - } else { - result = fmt.Sprintf("%t", arg[0] == arg[2]) - } - case "!=": - if e1 == nil && e2 == nil { - result = fmt.Sprintf("%t", v1 != v2) - } else { - result = fmt.Sprintf("%t", arg[0] != arg[2]) - } - - case "~": - if m, e := regexp.MatchString(arg[2], arg[0]); m && e == nil { - result = "true" - } - case "!~": - if m, e := regexp.MatchString(arg[2], arg[0]); !m || e != nil { - result = "true" - } - } - } - m.Echo(result) - - return - }}, - "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++ { - key := arg[i] - for i += 3; i < len(arg); i++ { - if arg[i] == "]" { - break - } - msg.Add("append", key, arg[i]) - } - } - m.Echo("%d", msg.Code()) - return - } - - pre := map[string]int{ - "=": 1, - "+": 2, "-": 2, - "*": 3, "/": 3, "%": 3, - } - num := []string{arg[0]} - op := []string{} - - for i := 1; i < len(arg); i += 2 { - if len(op) > 0 && pre[op[len(op)-1]] >= pre[arg[i]] { - num[len(op)-1] = m.Spawn().Cmd("val", num[len(op)-1], op[len(op)-1], num[len(op)]).Get("result") - num = num[:len(num)-1] - op = op[:len(op)-1] - } - - num = append(num, arg[i+1]) - op = append(op, arg[i]) - } - - for i := len(op) - 1; i >= 0; i-- { - num[i] = m.Spawn().Cmd("val", num[i], op[i], num[i+1]).Get("result") - } - - 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) (e error) { - switch arg[2] { - case "=": - m.Cap(arg[1], arg[3]) - case "<-": - 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) (e error) { - if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 { - switch arg[2] { - case "=": - m.Cap(arg[1], arg[3]) - case "<-": - m.Cap(arg[1], m.Cap("last_msg")) - } - } - 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) (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) (e error) { - m.Add("append", "return", arg[1:]) - return - }}, - "arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - m.Set("result", m.Optionv("arguments")) - return - }}, "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] { @@ -1702,125 +1370,6 @@ var version = struct { m.Table() return }}, - - "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) (e error) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { - if pos, ok := cli.label[arg[1]]; ok { - 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) (e error) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { - 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) (e error) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { - if !m.Caps("parse") { - m.Caps("parse", true) - } else { - if len(cli.stack) == 1 { - m.Caps("parse", false) - } else { - frame := cli.stack[len(cli.stack)-2] - m.Caps("parse", !frame.run) - } - } - } - return - }}, - "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) - return - } - - if cli.stack = cli.stack[:len(cli.stack)-1]; m.Capi("level", -1) > 0 { - m.Caps("parse", cli.stack[len(cli.stack)-1].run) - } else { - 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) (e error) { - if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { - run := m.Caps("parse") - defer func() { m.Caps("parse", run) }() - - msg := m - if run { - if arg[1] == "index" { - if code, e := strconv.Atoi(arg[2]); m.Assert(e) { - msg = m.Target().Message().Tree(code) - run = run && msg != nil && msg.Meta != nil - switch len(arg) { - case 4: - run = run && len(msg.Meta) > 0 - case 5: - run = run && len(msg.Meta[arg[3]]) > 0 - } - } - } else { - run = run && kit.Right(arg[len(arg)-1]) - } - - if len(cli.stack) > 0 { - if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.pos == m.Optioni("file_pos") { - if arg[1] == "index" { - frame.index++ - if run = run && len(frame.list) > frame.index; run { - if len(arg) == 5 { - arg[3] = arg[4] - } - m.Cap(arg[3], frame.list[frame.index]) - } - } - frame.run = run - return - } - } - } - - cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run, index: 0}) - if m.Capi("level", 1); run && arg[1] == "index" { - frame := cli.stack[len(cli.stack)-1] - switch len(arg) { - case 4: - frame.list = []string{} - for k, _ := range msg.Meta { - frame.list = append(frame.list, k) - } - case 5: - frame.list = msg.Meta[arg[3]] - arg[3] = arg[4] - } - m.Cap(arg[3], arg[3], frame.list[0], "临时变量") - } - } - return - }}, }, } diff --git a/src/contexts/cli/version.go b/src/contexts/cli/version.go index 500d7325..6d5c774c 100644 --- a/src/contexts/cli/version.go +++ b/src/contexts/cli/version.go @@ -4,5 +4,5 @@ var version = struct { host string self int }{ - "2019-07-20 15:41:22", "mac", 229, + "2019-07-20 17:10:58", "mac", 232, } diff --git a/src/contexts/ctx/core.go b/src/contexts/ctx/core.go index b6f18168..6d4b9a6f 100644 --- a/src/contexts/ctx/core.go +++ b/src/contexts/ctx/core.go @@ -36,7 +36,7 @@ func (c *Context) Plugin(s *Context, args []string) string { m := &Message{code: 0, time: time.Now(), source: s, target: s, Meta: map[string][]string{}} kit.DisableLog = true m.Option("log.disable", true) - m.Option("cli.modal", "action") + m.Option("bio.modal", "action") if len(args) == 0 { m.Echo("%s: %s\n\n", s.Name, s.Help) @@ -57,9 +57,9 @@ func (c *Context) Plugin(s *Context, args []string) string { } m.Cmd(args) } - for _, v := range m.Meta["result"] { - m.Show(v) - } + for _, v := range m.Meta["result"] { + m.Show(v) + } return "" } func (c *Context) Spawn(m *Message, name string, help string) *Context { @@ -235,7 +235,7 @@ func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) } func (m *Message) Gos(msg *Message, hand ...func(msg *Message)) *Message { go func() { - msg.Option("routine", m.Capi("ngo", 1)) + msg.Option("ctx.routine", m.Capi("ngo", 1)) m.TryCatch(msg, true, hand...) }() return m diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 7eddaee3..0835ea21 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -22,10 +22,15 @@ func (ctx *CTX) Spawn(m *Message, c *Context, arg ...string) Server { return s } func (ctx *CTX) Begin(m *Message, arg ...string) Server { + m.Option("ctx.routine", 0) m.Option("log.disable", true) + m.Option("ctx.chain", "aaa", "ssh", "cli", "nfs") + m.Option("page.limit", 10) m.Option("page.offset", 0) - m.Option("routine", 0) + m.Optionv("ctx.form", map[string]int{ + "page.limit": 1, "page.offset": 1, + }) m.root = m m.Sess(m.target.Name, m) @@ -39,19 +44,20 @@ func (ctx *CTX) Begin(m *Message, arg ...string) Server { return ctx } func (ctx *CTX) Start(m *Message, arg ...string) bool { - m.Cmd("ctx._init") - if m.Optionv("ps_target", Index); len(arg) == 0 { - m.Option("cli.modal", "active") + if m.Optionv("bio.ctx", Index); len(arg) == 0 { + m.Option("bio.modal", "active") m.Option("log.disable", false) - m.Cap("stream", "shy") + m.Cap("stream", "stdio") m.Cmd("log._init") - m.Cmd("yac._init") m.Cmd("gdb._init") - m.Cmd("cli.source", m.Conf("system", "script.init")).Cmd("cli.source", "stdio").Cmd("cli.source", m.Conf("system", "script.exit")) + + m.Cmd("ctx._init") + m.Cmd("nfs.source", m.Conf("system", "script.init")).Cmd("nfs.source", "stdio").Cmd("nfs.source", m.Conf("system", "script.exit")) } else { - m.Option("cli.modal", "action") - // m.Cmd("yac._init") - for _, v := range m.Spawn().Cmd(arg).Meta["result"] { + m.Option("bio.modal", "action") + + m.Cmd("ctx._init") + for _, v := range m.Sess("cli").Cmd(arg).Meta["result"] { fmt.Printf("%s", v) } } @@ -103,7 +109,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, }, Commands: map[string]*Command{ "_init": &Command{Name: "_init", Help: "启动", Hand: func(m *Message, c *Context, key string, arg ...string) (e error) { - for _, x := range []string{"lex", "cli", "nfs", "aaa", "ssh", "web"} { + for _, x := range []string{"lex", "cli", "yac", "nfs", "aaa", "ssh", "web"} { + kit.Log("error", "%v", x) m.Cmd(x + "._init") } return @@ -735,7 +742,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, "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 { + if ms := m.Find(m.Cap("bio.ctx")); ms != nil { msg = ms } @@ -816,7 +823,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, keys[k] = true m.Add("append", "key", k) m.Add("append", "len", len(msg.Meta[k])) - m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k])) + if _, ok := msg.Data[k]; ok { + m.Add("append", "value", kit.Format(msg.Data[k])) + } else { + m.Add("append", "value", kit.Format(msg.Meta[k])) + } continue } @@ -1420,7 +1431,7 @@ func Start(args ...string) bool { args = args[1:] } if len(args) > 0 && args[0] == "daemon" { - Pulse.Options("cli.modal", "daemon") + Pulse.Options("bio.modal", "daemon") Pulse.Options("daemon", true) args = args[1:] } diff --git a/src/contexts/ctx/what.go b/src/contexts/ctx/misc.go similarity index 98% rename from src/contexts/ctx/what.go rename to src/contexts/ctx/misc.go index ce58d8aa..3c318394 100644 --- a/src/contexts/ctx/what.go +++ b/src/contexts/ctx/misc.go @@ -129,7 +129,7 @@ func (m *Message) Format(arg ...interface{}) string { case "code": meta = append(meta, kit.Format(m.code)) case "ship": - meta = append(meta, fmt.Sprintf("%s:%d(%s->%s)", m.Option("routine"), m.code, m.source.Name, m.target.Name)) + meta = append(meta, fmt.Sprintf("%s:%d(%s->%s)", m.Option("ctx.routine"), m.code, m.source.Name, m.target.Name)) case "source": target := m.target m.target = m.source @@ -535,7 +535,7 @@ func (m *Message) Log(action string, str string, arg ...interface{}) *Message { func (m *Message) Show(str string, args ...interface{}) *Message { res := fmt.Sprintf(str, args...) - if m.Option("cli.modal") == "action" { + if m.Option("bio.modal") == "action" { fmt.Printf(res) } else if kit.STDIO != nil { kit.STDIO.Show(res) @@ -631,7 +631,7 @@ func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context } context := []*Context{m.target} - for _, v := range []string{"aaa", "ssh", "cli", "nfs"} { + for _, v := range kit.Trans(m.Optionv("ctx.chain")) { if msg := m.Sess(v, false); msg != nil && msg.target != nil { context = append(context, msg.target) } diff --git a/src/contexts/ctx/type.go b/src/contexts/ctx/type.go index 797626ff..eb021228 100644 --- a/src/contexts/ctx/type.go +++ b/src/contexts/ctx/type.go @@ -281,6 +281,97 @@ func (m *Message) Results(arg ...interface{}) bool { return kit.Right(m.Result(arg...)) } +func (m *Message) Form(x *Command, arg []string) []string { + for _, form := range []map[string]int{m.Optionv("ctx.form").(map[string]int), x.Form} { + + if args := []string{}; form != nil { + for i := 0; i < len(arg); i++ { + if n, ok := form[arg[i]]; ok { + if n < 0 { + n += len(arg) - i + } + for j := i + 1; j <= i+n && j < len(arg); j++ { + if _, ok := form[arg[j]]; ok { + n = j - i - 1 + } + } + if i+1+n > len(arg) { + m.Add("option", arg[i], arg[i+1:]) + } else { + m.Add("option", arg[i], arg[i+1:i+1+n]) + } + i += n + } else { + args = append(args, arg[i]) + } + } + arg = args + } + } + + return arg +} +func (m *Message) Push(str string, arg ...interface{}) *Message { + return m.Add("append", str, arg...) +} +func (m *Message) Sort(key string, arg ...string) *Message { + cmp := "str" + if len(arg) > 0 { + cmp = arg[0] + } + + number := map[int]int{} + table := []map[string]string{} + m.Table(func(index int, line map[string]string) { + table = append(table, line) + switch cmp { + case "int": + number[index] = kit.Int(line[key]) + case "int_r": + number[index] = -kit.Int(line[key]) + case "time": + number[index] = kit.Time(line[key]) + case "time_r": + number[index] = -kit.Time(line[key]) + } + }) + + for i := 0; i < len(table)-1; i++ { + for j := i + 1; j < len(table); j++ { + result := false + switch cmp { + case "str": + if table[i][key] > table[j][key] { + result = true + } + case "str_r": + if table[i][key] < table[j][key] { + result = true + } + default: + if number[i] > number[j] { + result = true + } + } + + if result { + table[i], table[j] = table[j], table[i] + number[i], number[j] = number[j], number[i] + } + } + } + + for _, k := range m.Meta["append"] { + delete(m.Meta, k) + } + + for _, v := range table { + for _, k := range m.Meta["append"] { + m.Add("append", k, v[k]) + } + } + return m +} func (m *Message) Table(cbs ...interface{}) *Message { if len(m.Meta["append"]) == 0 { return m @@ -376,63 +467,11 @@ func (m *Message) Table(cbs ...interface{}) *Message { return m } -func (m *Message) Sort(key string, arg ...string) *Message { - cmp := "str" +func (m *Message) Echo(str string, arg ...interface{}) *Message { if len(arg) > 0 { - cmp = arg[0] + return m.Add("result", fmt.Sprintf(str, arg...)) } - - number := map[int]int{} - table := []map[string]string{} - m.Table(func(index int, line map[string]string) { - table = append(table, line) - switch cmp { - case "int": - number[index] = kit.Int(line[key]) - case "int_r": - number[index] = -kit.Int(line[key]) - case "time": - number[index] = kit.Time(line[key]) - case "time_r": - number[index] = -kit.Time(line[key]) - } - }) - - for i := 0; i < len(table)-1; i++ { - for j := i + 1; j < len(table); j++ { - result := false - switch cmp { - case "str": - if table[i][key] > table[j][key] { - result = true - } - case "str_r": - if table[i][key] < table[j][key] { - result = true - } - default: - if number[i] > number[j] { - result = true - } - } - - if result { - table[i], table[j] = table[j], table[i] - number[i], number[j] = number[j], number[i] - } - } - } - - for _, k := range m.Meta["append"] { - delete(m.Meta, k) - } - - for _, v := range table { - for _, k := range m.Meta["append"] { - m.Add("append", k, v[k]) - } - } - return m + return m.Add("result", str) } func (m *Message) Copy(msg *Message, arg ...string) *Message { if msg == nil || m == msg { @@ -487,15 +526,6 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message { return m } -func (m *Message) Push(str string, arg ...interface{}) *Message { - return m.Add("append", str, arg...) -} -func (m *Message) Echo(str string, arg ...interface{}) *Message { - if len(arg) > 0 { - return m.Add("result", fmt.Sprintf(str, arg...)) - } - return m.Add("result", str) -} func (m *Message) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message { if head != nil && len(head) > 0 { @@ -571,43 +601,19 @@ func (m *Message) Cmd(args ...interface{}) *Message { if x, ok := c.Commands[key]; ok && x.Hand != nil { msg.TryCatch(msg, true, func(msg *Message) { msg.Log("cmd", "%s %s %v %v", c.Name, key, arg, msg.Meta["option"]) - - for _, form := range []map[string]int{map[string]int{"page.limit": 1, "page.offset": 1}, x.Form} { - - if args := []string{}; form != nil { - for i := 0; i < len(arg); i++ { - if n, ok := form[arg[i]]; ok { - if n < 0 { - n += len(arg) - i - } - for j := i + 1; j <= i+n && j < len(arg); j++ { - if _, ok := form[arg[j]]; ok { - n = j - i - 1 - } - } - if i+1+n > len(arg) { - msg.Add("option", arg[i], arg[i+1:]) - } else { - msg.Add("option", arg[i], arg[i+1:i+1+n]) - } - i += n - } else { - args = append(args, arg[i]) - } - } - arg = args - } - } + msg.Hand = true + x.Hand(msg, c, key, msg.Form(x, arg)...) + msg.Log("cmd", "%s %s %v %v", c.Name, key, len(msg.Meta["result"]), msg.Meta["append"]) + return target := msg.target msg.target = s - msg.Hand = true switch v := msg.Gdb("command", key, arg).(type) { case string: msg.Echo(v) case nil: - if msg.Options("auto_cmd") { + if msg.Options("bio.cmd") { if x.Auto != nil { x.Auto(msg, c, key, arg...) } diff --git a/src/contexts/lex/lex.go b/src/contexts/lex/lex.go index c72c7bdf..67342f3f 100644 --- a/src/contexts/lex/lex.go +++ b/src/contexts/lex/lex.go @@ -22,12 +22,13 @@ type State struct { next int hash int } + type LEX struct { - seed []*Seed - hash map[string]int - hashs map[int]string - pages map[int]string - page map[string]int + seed []*Seed + hash map[string]int + word map[int]string + hand map[int]string + page map[string]int char map[byte][]byte state map[State]*State @@ -36,10 +37,16 @@ type LEX struct { *ctx.Context } +func (lex *LEX) charset(c byte) []byte { + if cs, ok := lex.char[c]; ok { + return cs + } + return []byte{c} +} func (lex *LEX) index(m *ctx.Message, hash string, h string) int { - which, names := lex.hash, lex.hashs + which, names := lex.hash, lex.word if hash == "npage" { - which, names = lex.page, lex.pages + which, names = lex.page, lex.hand } if x, e := strconv.Atoi(h); e == nil { @@ -60,12 +67,6 @@ func (lex *LEX) index(m *ctx.Message, hash string, h string) int { m.Assert(hash != "npage" || m.Capi("npage") < m.Confi("meta", "nlang"), "语法集合超过上限") return which[h] } -func (lex *LEX) charset(c byte) []byte { - if cs, ok := lex.char[c]; ok { - return cs - } - return []byte{c} -} func (lex *LEX) train(m *ctx.Message, page int, hash int, seed []byte) int { m.Log("debug", "%s %s page: %v hash: %v seed: %v", "train", "lex", page, hash, string(seed)) @@ -288,8 +289,8 @@ func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { lex.page = map[string]int{"nil": 0} lex.hash = map[string]int{"nil": 0} - lex.hashs = map[int]string{0: "nil"} - lex.pages = map[int]string{0: "nil"} + lex.word = map[int]string{0: "nil"} + lex.hand = map[int]string{0: "nil"} lex.char = map[byte][]byte{ 't': []byte{'\t'}, @@ -376,7 +377,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", } m.Push("word", string(word)) - m.Push("hash", lex.hashs[hash]) + m.Push("hash", lex.word[hash]) m.Push("rest", string(rest)) input = rest } @@ -387,40 +388,34 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", "show": &ctx.Command{Name: "show seed|page|hash|mat|node", 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)) - m.Append("page", len(lex.page)) - m.Append("hash", len(lex.hash)) - m.Append("nmat", len(lex.mat)) - m.Append("node", len(lex.state)) + m.Push("seed", len(lex.seed)) + m.Push("page", len(lex.page)) + m.Push("hash", len(lex.hash)) + m.Push("nmat", len(lex.mat)) + m.Push("node", len(lex.state)) m.Table() return } switch arg[0] { case "seed": for _, v := range lex.seed { - m.Push("page", fmt.Sprintf("%s", lex.pages[v.page])) - m.Push("word", fmt.Sprintf("%s", strings.Replace(strings.Replace(v.word, "\n", "\\n", -1), "\t", "\\t", -1))) - m.Push("hash", fmt.Sprintf("%s", lex.hashs[v.hash])) + m.Push("page", lex.hand[v.page]) + m.Push("word", strings.Replace(strings.Replace(v.word, "\n", "\\n", -1), "\t", "\\t", -1)) + m.Push("hash", lex.word[v.hash]) } m.Sort("page", "int").Table() case "page": for k, v := range lex.page { - if k == "nil" { - continue - } m.Push("page", k) - m.Push("code", fmt.Sprintf("%d", v)) + m.Push("code", v) } m.Sort("code", "int").Table() case "hash": for k, v := range lex.hash { - if k == "nil" { - continue - } m.Push("hash", k) - m.Push("code", fmt.Sprintf("%d", v)) + m.Push("code", v) } m.Sort("code", "int").Table() @@ -435,7 +430,7 @@ var Index = &ctx.Context{Name: "lex", Help: "词法中心", case "mat": for i, v := range lex.mat { if i <= m.Capi("npage") { - m.Push("index", lex.pages[i]) + m.Push("index", lex.hand[i]) } else if i < m.Confi("meta", "nlang") { continue } else { diff --git a/src/contexts/mdb/mdb.go b/src/contexts/mdb/mdb.go index bae3731c..b692a018 100644 --- a/src/contexts/mdb/mdb.go +++ b/src/contexts/mdb/mdb.go @@ -57,7 +57,7 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { var Index = &ctx.Context{Name: "mdb", Help: "数据中心", Caches: map[string]*ctx.Cache{ "nsource": &ctx.Cache{Name: "nsource", Value: "0", Help: "已打开数据库的数量"}, - "redis": &ctx.Cache{Name: "redis", Value: "", Help: "服务地址"}, + "redis": &ctx.Cache{Name: "redis", Value: "", Help: "服务地址"}, }, Configs: map[string]*ctx.Config{ "database": &ctx.Config{Name: "database", Value: "demo", Help: "默认数据库"}, @@ -138,7 +138,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", break } if mdb.conn.Err() != nil { - mdb.conn, e = redis.Dial("tcp", m.Cap("redis"), redis.DialKeepAlive(time.Second*10)) + mdb.conn, e = redis.Dial("tcp", m.Cap("redis"), redis.DialKeepAlive(time.Second*10)) } args := []interface{}{} for _, v := range arg[1:] { @@ -156,13 +156,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", } m.Table() default: - str := kit.Format(res) - var data interface{} - if json.Unmarshal([]byte(str), &data) == nil { - m.Echo(kit.Formats(data)) - } else { - m.Echo(str) - } + str := kit.Format(res) + var data interface{} + if json.Unmarshal([]byte(str), &data) == nil { + m.Echo(kit.Formats(data)) + } else { + m.Echo(str) + } } } } @@ -265,7 +265,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", "db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库", Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool { if len(arg) == 0 { - m.Put("option", "auto_cmd", "").Spawn().Cmd("query", "show databases").Table(func(line map[string]string) { + m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show databases").Table(func(line map[string]string) { for _, v := range line { m.Auto(v, "", "") } @@ -287,13 +287,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool { switch len(arg) { case 0: - m.Put("option", "auto_cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) { + m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) { for _, v := range line { m.Auto(v, "", "") } }) case 1: - m.Put("option", "auto_cmd", "").Spawn().Cmd("query", fmt.Sprintf("desc %s", arg[0])).Table(func(line map[string]string) { + m.Put("option", "bio.cmd", "").Spawn().Cmd("query", fmt.Sprintf("desc %s", arg[0])).Table(func(line map[string]string) { m.Auto(line["Field"], line["Type"], line["Default"]) }) } @@ -314,7 +314,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", Form: map[string]int{"where": 1, "eq": 2, "like": 2, "in": 2, "begin": 2, "group": 1, "order": 1, "desc": 0, "limit": 1, "offset": 1, "other": -1}, Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool { if len(arg) == 0 { - m.Put("option", "auto_cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) { + m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) { for _, v := range line { m.Auto(v, "", "") } diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 0ea5d9a1..830536e2 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -191,11 +191,10 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { rest := make([]rune, 0, 1024) back := make([]rune, 0, 1024) - m.Optionv("auto_target", m.Optionv("ps_target")) - m.Option("auto_cmd", "") - m.Options("show_shadow", m.Confs("show_shadow")) + m.Option("bio.cmd", "") + m.Options("bio.shadow", m.Confs("show_shadow")) - defer func() { m.Option("auto_cmd", "") }() + defer func() { m.Option("bio.cmd", "") }() frame, table, index, pick := map[string]interface{}{}, []map[string]string{}, 0, 0 if change, f, t, i := nfs.Auto(what, ":", 0); change { @@ -358,13 +357,13 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { case termbox.KeyCtrlG: case termbox.KeyCtrlX: - m.Options("show_shadow", !m.Options("show_shadow")) + m.Options("bio.shadow", !m.Options("bio.shadow")) case termbox.KeyCtrlS: case termbox.KeyCtrlZ: case termbox.KeyTab: - m.Options("show_shadow", true) + m.Options("bio.shadow", true) // if index > len(what) { // nfs.shadow("", table, frame) // } else { @@ -380,7 +379,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { case termbox.KeySpace: what = append(what, ' ') nfs.prompt(what).shadow(rest) - if !m.Options("show_shadow") { + if !m.Options("bio.shadow") { break } @@ -402,7 +401,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { default: what = append(what, ev.Ch) nfs.prompt(what).shadow(rest) - if !m.Options("show_shadow") { + if !m.Options("bio.shadow") { break } @@ -428,9 +427,10 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { return } func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame map[string]interface{}, table []map[string]string, nindex int) { + return m := nfs.Context.Message() - auto_target := m.Optionv("auto_target").(*ctx.Context) + auto_target := m.Optionv("bio.ctx").(*ctx.Context) auto_cmd := "" auto_arg := []string{} @@ -439,14 +439,14 @@ func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame switch m.Conf("term", "help_state") { case "context": auto_target = auto_target.Sub(m.Option("auto_key")) - m.Optionv("auto_target", auto_target) + m.Optionv("bio.ctx", auto_target) trigger = ":" case "command": m.Option("arg_index", index) - auto_cmd = m.Option("auto_cmd", m.Option("auto_key")) + auto_cmd = m.Option("bio.cmd", m.Option("auto_key")) trigger = "=" case "argument": - auto_cmd = m.Option("auto_cmd") + auto_cmd = m.Option("bio.cmd") auto_arg = strings.Split(strings.TrimSpace(string(what[m.Optioni("arg_index"):])), " ") trigger = "=" } @@ -720,7 +720,7 @@ func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS } func (nfs *NFS) prompt(arg ...interface{}) *NFS { m := nfs.Context.Message() - target, _ := m.Optionv("ps_target").(*ctx.Context) + target, _ := m.Optionv("bio.ctx").(*ctx.Context) if target == nil { target = nfs.Context } @@ -783,10 +783,10 @@ func (nfs *NFS) shadow(args ...interface{}) *NFS { return nfs } -func (nfs *NFS) printf(arg ...interface{}) *NFS { +func (nfs *NFS) print(arg ...string) *NFS { m := nfs.Context.Message() - line := strings.TrimRight(kit.Format(arg...), "\n") + line := strings.TrimRight(strings.Join(arg, ""), "\n") m.Log("debug", "noutput %s", m.Cap("noutput", m.Capi("noutput")+1)) m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) @@ -900,16 +900,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { } if len(arg) > 0 && arg[0] == "scan" { - // 终端用户 - m.Cmd("aaa.role", "root", "user", m.Option("username", m.Conf("runtime", "boot.username"))) - - // 创建会话 - m.Option("sessid", m.Cmdx("aaa.user", "session", "select")) - - // 创建空间 - m.Option("bench", m.Cmdx("aaa.sess", "bench", "select")) - - // 默认配置 m.Cap("stream", arg[1]) nfs.Caches["ninput"] = &ctx.Cache{Value: "0"} nfs.Caches["noutput"] = &ctx.Cache{Value: "0"} @@ -919,20 +909,28 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { nfs.Configs["prompt"] = &ctx.Config{Value: ""} // 终端控制 - if nfs.in = m.Optionv("in").(*os.File); m.Has("out") { - if nfs.out = m.Optionv("out").(*os.File); m.Conf("runtime", "host.GOOS") != "windows" && !m.Options("daemon") { - kit.STDIO = nfs - nfs.Term(m, "init") - m.Conf("term", "use", true) + if nfs.in = m.Optionv("bio.in").(*os.File); m.Has("bio.out") { + if nfs.out = m.Optionv("bio.out").(*os.File); m.Conf("runtime", "host.GOOS") != "windows" && !m.Options("daemon") { + m.Conf("term", "use", nfs.Term(m, "init") != nil) defer nfs.Term(m, "exit") - } - if what := make(chan bool); m.Options("daemon") { - <-what + kit.STDIO = nfs + + } else if m.Options("daemon") { + return true } } + // 终端用户 + m.Cmd("aaa.role", "root", "user", m.Option("username", m.Conf("runtime", "boot.username"))) + m.Option("sessid", m.Cmdx("aaa.user", "session", "select")) + m.Optionv("bio.ctx", m.Target()) + stack := kit.Stack{} + stack.Push(m.Option("stack.key", "source"), m.Options("stack.run", true), m.Optioni("stack.pos", 0)) + line, bio := "", bufio.NewScanner(nfs) - for nfs.prompt(); !m.Options("scan_end"); nfs.prompt() { + for nfs.prompt(); ; nfs.prompt() { + + // 读取数据 for bio.Scan() { if text := bio.Text(); text == "" { continue @@ -944,31 +942,66 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { } } if line == "" { - line = "return" + break } - m.Log("debug", "%s %d %d [%s]", "input", m.Capi("ninput", 1), len(line), line) m.Confv("input", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) + // 解析数据 for i := m.Capi("ninput") - 1; i < m.Capi("ninput"); i++ { line = m.Conf("input", []interface{}{i, "line"}) - msg := m.Backs(m.Spawn(m.Source()).Set( - "detail", line).Set( - "option", "file_pos", i).Set( - "option", "username", m.Conf("runtime", "boot.username"))) + // 结束语句 + if strings.TrimSpace(line) == "end" { + m.Log("stack", " pop %v", stack.Peek().String("/")) + if stack.Pop(); m.Options("stack.run") && m.Option("stack.key") == "for" { + i = m.Optioni("stack.pos") - 1 + } + frame := stack.Peek() + m.Options("stack.run", frame.Run) + m.Option("stack.key", frame.Key) + continue + } - nfs.printf(m.Conf("prompt"), line) - nfs.printf(msg.Meta["result"]) + // 跳过语句 + if !stack.Peek().Run { + m.Log("stack", "skip %v", line) + continue + } - if msg.Appends("file_pos0") { - i = int(msg.Appendi("file_pos0")) - 1 - msg.Append("file_pos0", "") + // 执行语句 + msg := m.Cmd("yac.parse", line+"\n").Set("option", "bio.pos", i) + nfs.print(m.Conf("prompt"), line) + nfs.print(msg.Meta["result"]...) + + // 切换模块 + if v := msg.Optionv("bio.ctx"); v != nil { + m.Optionv("bio.ctx", v) + } + + // 压栈语句 + if msg.Appends("stack.key") { + stack.Push(m.Option("stack.key", msg.Append("stack.key")), m.Options("stack.run", msg.Appends("stack.run")), m.Optioni("stack.pos", i)) + m.Log("stack", "push %v", stack.Peek().String("\\")) + msg.Append("stack.key", "") + } + + // 跳转语句 + if msg.Appends("bio.pos0") { + i = int(msg.Appendi("bio.pos0")) - 1 + msg.Append("bio.pos0", "") + } + + // 结束脚本 + if msg.Appends("bio.end") { + m.Copy(msg, "append") + m.Copy(msg, "result") + break } } line = "" } - return false + return true } m.Cap("stream", m.Option("ms_source")) @@ -1775,7 +1808,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } m.Start(fmt.Sprintf("file%d", m.Capi("nfile")), fmt.Sprintf("file %s", arg[0]), "open", arg[0]) - m.Append("ps_target1", m.Cap("module")) + m.Append("bio.ctx1", m.Cap("module")) m.Echo(m.Cap("module")) return }}, @@ -1819,19 +1852,9 @@ 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) { - 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%d", m.Capi("nfile", 1)), help, key, p) - } - } - 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) + nfs.print(arg...) } return }}, @@ -1850,8 +1873,8 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "action": &ctx.Command{Name: "action 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) { msg := m.Cmd("cli.source", arg) - nfs.printf(msg.Conf("prompt"), arg, "\n") - nfs.printf(msg.Meta["result"]) + // nfs.print(msg.Conf("prompt"), arg, "\n") + nfs.print(msg.Meta["result"]...) } return }}, @@ -1876,6 +1899,103 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, + + "source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { + m.Optionv("bio.args", arg) + if help := fmt.Sprintf("scan %s", arg[0]); arg[0] == "stdio" { + m.Put("option", "bio.in", os.Stdin).Put("option", "bio.out", os.Stdout).Start(arg[0], help, "scan", arg[0]) + m.Wait() + + } else if p, f, e := open(m, arg[0]); e == nil { + m.Put("option", "bio.in", f).Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), help, "scan", p) + m.Wait() + + } else { + + } + } + return + if len(arg) == 0 { + m.Cmdy("dir", "", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$") + return + } + + m.Cap("stream", m.Sess("yac").Call(func(cmd *ctx.Message) *ctx.Message { + if !m.Caps("parse") { + switch cmd.Detail(0) { + case "if": + cmd.Set("detail", "if", "false") + case "else": + case "end": + case "for": + default: + cmd.Hand = true + return nil + } + } + + if cmd.Cmd(); cmd.Has("return") { + m.Options("scan_end", true) + m.Target().Close(m) + } + + v := cmd.Optionv("bio.ctx") + if v != nil { + m.Optionv("bio.ctx", v) + } + return nil + }, "scan", arg).Target().Name) + + // 解析脚本文件 + if p := m.Cmdx("nfs.path", arg[0]); p != "" && strings.Contains(p, ".") { + arg[0] = p + switch path.Ext(p) { + case "": + case ".shy": + m.Option("scan_end", "false") + m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...) + m.Wait() + default: + m.Cmdy("system", m.Conf("system", []string{"script", strings.TrimPrefix(path.Ext(p), ".")}), arg) + } + m.Append("directory", "") + return + } + + // 解析终端命令 + if arg[0] == "stdio" { + m.Option("scan_end", "false") + m.Start("shy", "shell", "stdio", "engine") + m.Wait() + return + } + + text := strings.Join(arg, " ") + if !strings.HasPrefix(text, "sess") && m.Options("remote") { + text = m.Current(text) + } + + // 解析代码片段 + m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message { + switch msg.Cmd().Detail(0) { + case "cmd": + m.Set("append").Copy(msg, "append") + m.Set("result").Copy(msg, "result") + } + return nil + }, "parse", "line", "void", text) + return + }}, + "arguments": &ctx.Command{Name: "arguments", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + args := kit.Trans(m.Optionv("bio.args")) + if len(arg) == 0 { + m.Set("result", args) + } else { + m.Echo(kit.Select("", args, kit.Int(arg[0]))) + } + return + }}, }, } diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index ae05b6dc..32591ac9 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -3,8 +3,11 @@ package yac import ( "contexts/ctx" "fmt" + "os" + "regexp" "strconv" "strings" + "toolkit" ) type Seed struct { @@ -12,26 +15,28 @@ type Seed struct { hash int word []string } -type State struct { - next int - star int - hash int -} type Point struct { s int c byte } +type State struct { + star int + next int + hash int +} type YAC struct { seed []*Seed page map[string]int word map[int]string - hash map[string]int hand map[int]string + hash map[string]int - mat []map[byte]*State state map[State]*State + mat []map[byte]*State lex *ctx.Message + + label map[string]string *ctx.Context } @@ -41,6 +46,21 @@ func (yac *YAC) name(page int) string { } return fmt.Sprintf("yac%d", page) } +func (yac *YAC) index(m *ctx.Message, hash string, h string) int { + which, names := yac.page, yac.word + if hash == "nhash" { + which, names = yac.hash, yac.hand + } + + if x, ok := which[h]; ok { + return x + } + + which[h] = m.Capi(hash, 1) + names[which[h]] = h + m.Assert(hash != "npage" || m.Capi("npage") < m.Confi("meta", "nlang"), "语法集合超过上限") + return which[h] +} func (yac *YAC) train(m *ctx.Message, page, hash int, word []string, level int) (int, []*Point, []*Point) { m.Log("debug", "%s %s\\%d page: %v hash: %v word: %v", "train", strings.Repeat("#", level), level, page, hash, word) @@ -127,7 +147,7 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string, level int) } } for _, s := range ss { - if s < m.Confi("info", "nlang") || s >= len(yac.mat) { + if s < m.Confi("meta", "nlang") || s >= len(yac.mat) { continue } void := true @@ -171,168 +191,179 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string, level int) m.Log("debug", "%s %s/%d word: %d point: %d end: %d", "train", strings.Repeat("#", level), level, len(word), len(points), len(ends)) return len(word), points, ends } -func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line string, level int) (string, []string, int) { +func (yac *YAC) parse(m *ctx.Message, msg *ctx.Message, page int, void int, line string, level int) (string, []string, int) { m.Log("debug", "%s %s\\%d %s(%d): %s", "parse", strings.Repeat("#", level), level, yac.name(page), page, line) - hash, word := 0, []string{} + lex, hash, word := yac.lex, 0, []string{} for star, s := 0, page; s != 0 && len(line) > 0; { //解析空白 - lex := yac.lex.Spawn() - if lex.Cmd("parse", line, yac.name(void)); lex.Result(0) == "-1" { + if lex = yac.lex.Spawn().Cmd("parse", line, yac.name(void)); lex.Result(0) == "-1" { break } - //解析单词 line = lex.Result(1) - lex = yac.lex.Spawn() - if lex.Cmd("parse", line, yac.name(s)); lex.Result(0) == "-1" { + + //解析单词 + if lex = yac.lex.Spawn().Cmd("parse", line, yac.name(s)); lex.Result(0) == "-1" { break } - //解析状态 result := append([]string{}, lex.Meta["result"]...) - i, _ := strconv.Atoi(result[0]) - c := byte(i) - state := yac.mat[s][c] - if state != nil { //全局语法检查 + + //解析状态 + state := yac.mat[s][byte(kit.Int(result[0]))] + + //全局语法检查 + if state != nil { if key := yac.lex.Spawn().Cmd("parse", line, "key"); key.Resulti(0) == 0 || len(key.Result(2)) <= len(result[2]) { line, word = result[1], append(word, result[2]) } else { state = nil } } - if state == nil { //嵌套语法递归解析 - for i := 0; i < m.Confi("info", "ncell"); i++ { - if x := yac.mat[s][byte(i)]; i < m.Confi("info", "nlang") && x != nil { - if l, w, _ := yac.parse(m, out, i, void, line, level+1); l != line { - line, word = l, append(word, w...) - state = x + //嵌套语法递归解析 + if state == nil { + for i := 0; i < m.Confi("meta", "ncell"); i++ { + if x := yac.mat[s][byte(i)]; i < m.Confi("meta", "nlang") && x != nil { + if l, w, _ := yac.parse(m, msg, i, void, line, level+1); l != line { + line, word, state = l, append(word, w...), x break } } } } - if state == nil { //语法切换 + + //语法切换 + if state == nil { s, star = star, 0 - continue - } - if s, star, hash = state.next, state.star, state.hash; s == 0 { //状态切换 + } else if s, star, hash = state.next, state.star, state.hash; s == 0 { s, star = star, 0 } } if hash == 0 { word = word[:0] + } 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 { //命令替换 - word = msg.Meta["result"] + cmd := msg.Spawn(m.Optionv("bio.ctx")) + if cmd.Cmd(yac.hand[hash], word); cmd.Hand { + word = cmd.Meta["result"] + } + if v := cmd.Optionv("bio.ctx"); v != nil { + m.Optionv("bio.ctx", v) } } - m.Log("debug", "%s %s/%d %s(%d): %v", "parse", strings.Repeat("#", level), level, yac.name(page), page, word) + m.Log("debug", "%s %s/%d %s(%d): %v", "parse", strings.Repeat("#", level), level, yac.hand[hash], hash, word) return line, word, hash } func (yac *YAC) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { - if len(arg) > 0 && arg[0] == "scan" { - return yac - } - return &YAC{Context: c} } func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { + yac.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "语法模板的数量"} + yac.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "语法集合的数量"} + yac.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "语句类型的数量"} + + yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: m.Conf("meta", "nlang"), Help: "状态机状态的数量"} + yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"} + yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"} + + yac.Caches["level"] = &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"} + yac.Caches["parse"] = &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"} + + yac.page = map[string]int{"nil": 0} + yac.word = map[int]string{0: "nil"} + yac.hash = map[string]int{"nil": 0} + yac.hand = map[int]string{0: "nil"} + + yac.state = map[State]*State{} + yac.mat = make([]map[byte]*State, m.Capi("nline")) return yac } func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) { - if len(arg) > 0 && arg[0] == "scan" { - m.Cap("stream", arg[1]) - m.Sess("nfs").Call(func(input *ctx.Message) *ctx.Message { - _, word, _ := yac.parse(m, input, m.Optioni("page"), m.Optioni("void"), input.Detail(0)+"\n", 1) - input.Result(0, word) - return nil - }, "scan", arg[1:]) - return false - } return true } func (yac *YAC) Close(m *ctx.Message, arg ...string) bool { - return true + return false } var Index = &ctx.Context{Name: "yac", Help: "语法中心", Caches: map[string]*ctx.Cache{ - "nparse": &ctx.Cache{Name: "nparse", Value: "0", Help: "解析器数量"}, + "nshy": &ctx.Cache{Name: "nshy", Value: "0", Help: "引擎数量"}, }, Configs: map[string]*ctx.Config{ + "nline": &ctx.Config{Name: "nline", Value: "line", Help: "默认页"}, + "nvoid": &ctx.Config{Name: "nvoid", Value: "void", Help: "默认值"}, + "meta": &ctx.Config{Name: "meta", Value: map[string]interface{}{ + "ncell": 128, "nlang": 64, "compact": true, + "name": "shy%d", "help": "engine", + }, Help: "初始参数"}, "seed": &ctx.Config{Name: "seed", Value: []interface{}{ map[string]interface{}{"page": "void", "hash": "void", "word": []interface{}{"[\t ]+"}}, - map[string]interface{}{"page": "key", "hash": "key", "word": []interface{}{"[A-Za-z_][A-Za-z_0-9]*"}}, map[string]interface{}{"page": "num", "hash": "num", "word": []interface{}{"mul{", "0", "-?[1-9][0-9]*", "0[0-9]+", "0x[0-9]+", "}"}}, + map[string]interface{}{"page": "key", "hash": "key", "word": []interface{}{"[A-Za-z_][A-Za-z_0-9]*"}}, map[string]interface{}{"page": "str", "hash": "str", "word": []interface{}{"mul{", "\"[^\"]*\"", "'[^']*'", "}"}}, - map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"mul{", "$", "@", "}", "key"}}, + map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"mul{", "$", "@", "}", "opt{", "key", "}"}}, - map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-z", "-n", "}"}}, - map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-e", "-f", "-d", "}"}}, map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-", "+", "}"}}, - map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", ":=", "=", "+=", "}"}}, map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "+", "-", "*", "/", "%", "}"}}, map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "<", "<=", ">", ">=", "==", "!=", "}"}}, - map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "~", "!~", "}"}}, - map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "mul{", "num", "key", "str", "exe", "}"}}, map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"val", "rep{", "op2", "val", "}"}}, - map[string]interface{}{"page": "map", "hash": "map", "word": []interface{}{"key", ":", "\\[", "rep{", "key", "}", "\\]"}}, - map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"\\{", "rep{", "map", "}", "\\}"}}, - map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "(", "exp", ")"}}, - - map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "opt{", "=", "exp", "}"}}, map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "opt{", "=", "exp", "}"}}, - map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-"}}, - map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-", "opt{", "exe", "}"}}, - map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "<-", "opt{", "exe", "}"}}, - - map[string]interface{}{"page": "stm", "hash": "if", "word": []interface{}{"if", "exp"}}, - map[string]interface{}{"page": "stm", "hash": "else", "word": []interface{}{"else"}}, - map[string]interface{}{"page": "stm", "hash": "end", "word": []interface{}{"end"}}, - map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "opt{", "exp", ";", "}", "exp"}}, - map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "index", "exp", "opt{", "exp", "}", "exp"}}, - map[string]interface{}{"page": "stm", "hash": "label", "word": []interface{}{"label", "exp"}}, - map[string]interface{}{"page": "stm", "hash": "goto", "word": []interface{}{"goto", "exp", "opt{", "exp", "}", "exp"}}, - - map[string]interface{}{"page": "stm", "hash": "expr", "word": []interface{}{"expr", "rep{", "exp", "}"}}, + map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "opt{", "=", "exp", "}"}}, map[string]interface{}{"page": "stm", "hash": "return", "word": []interface{}{"return", "rep{", "exp", "}"}}, - map[string]interface{}{"page": "word", "hash": "word", "word": []interface{}{"mul{", "~", "!", "=", "\\?\\?", "\\?", "<", ">$", ">@", ">", "\\|", "%", "exe", "str", "[a-zA-Z0-9_/\\-.:*%]+", "}"}}, + map[string]interface{}{"page": "word", "hash": "word", "word": []interface{}{"mul{", "~", "!", "\\?", "\\?\\?", "exe", "str", "[\\-a-zA-Z0-9_:/.]+", "=", "<", ">$", ">@", ">", "\\|", "%", "}"}}, map[string]interface{}{"page": "cmd", "hash": "cmd", "word": []interface{}{"rep{", "word", "}"}}, - map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"$", "(", "cmd", ")"}}, + map[string]interface{}{"page": "com", "hash": "com", "word": []interface{}{"mul{", ";", "#[^\n]*\n?", "\n", "}"}}, + map[string]interface{}{"page": "line", "hash": "line", "word": []interface{}{"opt{", "mul{", "stm", "cmd", "}", "}", "com"}}, + + map[string]interface{}{"page": "exe", "hash": "exe", "word": []interface{}{"$", "(", "cmd", ")"}}, + map[string]interface{}{"page": "stm", "hash": "if", "word": []interface{}{"if", "exp"}}, + map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "rep{", "exp", "}"}}, + /* + + map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-z", "-n", "}"}}, + map[string]interface{}{"page": "op1", "hash": "op1", "word": []interface{}{"mul{", "-e", "-f", "-d", "}"}}, + map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", ":=", "=", "+=", "}"}}, + map[string]interface{}{"page": "op2", "hash": "op2", "word": []interface{}{"mul{", "~", "!~", "}"}}, + + map[string]interface{}{"page": "exp", "hash": "exp", "word": []interface{}{"\\{", "rep{", "map", "}", "\\}"}}, + map[string]interface{}{"page": "val", "hash": "val", "word": []interface{}{"opt{", "op1", "}", "(", "exp", ")"}}, + + map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-"}}, + map[string]interface{}{"page": "stm", "hash": "var", "word": []interface{}{"var", "key", "<-", "opt{", "exe", "}"}}, + map[string]interface{}{"page": "stm", "hash": "let", "word": []interface{}{"let", "key", "<-", "opt{", "exe", "}"}}, + + map[string]interface{}{"page": "stm", "hash": "else", "word": []interface{}{"else"}}, + map[string]interface{}{"page": "stm", "hash": "end", "word": []interface{}{"end"}}, + map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "opt{", "exp", ";", "}", "exp"}}, + map[string]interface{}{"page": "stm", "hash": "for", "word": []interface{}{"for", "index", "exp", "opt{", "exp", "}", "exp"}}, + map[string]interface{}{"page": "stm", "hash": "label", "word": []interface{}{"label", "exp"}}, + map[string]interface{}{"page": "stm", "hash": "goto", "word": []interface{}{"goto", "exp", "opt{", "exp", "}", "exp"}}, + + map[string]interface{}{"page": "stm", "hash": "expr", "word": []interface{}{"expr", "rep{", "exp", "}"}}, + map[string]interface{}{"page": "stm", "hash": "return", "word": []interface{}{"return", "rep{", "exp", "}"}}, + + */ - 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}, + "void": map[string]interface{}{"disable": true}, + "num": map[string]interface{}{"disable": true}, + "key": map[string]interface{}{"disable": true}, + "op1": map[string]interface{}{"disable": true}, + "op2": map[string]interface{}{"disable": true}, "word": map[string]interface{}{"disable": true}, + "line": 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) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { - yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "64", 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: "语法模板的数量"} - yac.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "0", Help: "语法集合的数量"} - yac.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "0", Help: "语句类型的数量"} - - yac.page = map[string]int{"nil": 0} - yac.word = map[int]string{0: "nil"} - yac.hash = map[string]int{"nil": 0} - yac.hand = map[int]string{0: "nil"} - - yac.mat = make([]map[byte]*State, m.Confi("info", "nlang")) - yac.state = map[State]*State{} - + yac.lex = m.Cmd("lex.spawn") m.Confm("seed", func(line int, seed map[string]interface{}) { m.Spawn().Cmd("train", seed["page"], seed["hash"], seed["word"]) }) @@ -341,70 +372,40 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", }}, "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 { - page = m.Capi("npage", 1) - yac.page[arg[0]] = page - yac.word[page] = arg[0] - m.Assert(page < m.Confi("info", "nlang"), "语法集合过多") - + page := yac.index(m, "npage", arg[0]) + hash := yac.index(m, "nhash", arg[1]) + if yac.mat[page] == nil { yac.mat[page] = map[byte]*State{} - for i := 0; i < m.Confi("info", "nlang"); i++ { + for i := 0; i < m.Confi("meta", "nlang"); i++ { yac.mat[page][byte(i)] = nil } } - - hash, ok := yac.hash[arg[1]] - if !ok { - hash = m.Capi("nhash", 1) - yac.hash[arg[1]] = hash - yac.hand[hash] = arg[1] - } - - if yac.lex == nil { - yac.lex = m.Cmd("lex.spawn") - } - yac.train(m, page, hash, arg[2:], 1) + 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"))) + m.Cap("stream", fmt.Sprintf("%d,%s,%s", m.Cap("nseed", len(yac.seed)), + m.Cap("npage"), m.Cap("nhash", len(yac.hash)-1))) } 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) (e error) { + "parse": &ctx.Command{Name: "parse line", 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) { - 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 modulename", 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"]) + m.Optioni("yac.page", yac.page[m.Conf("nline")]) + m.Optioni("yac.void", yac.page[m.Conf("nvoid")]) - name := "" - if len(arg) > 1 { - name = arg[1] - } else { - name = fmt.Sprintf("parse%d", m.Capi("nparse", 1)) - } - - if len(arg) > 0 { - m.Start(name, "parse", key, arg[0]) - } else { - m.Start(name, "parse") - } + _, word, _ := yac.parse(m, m, m.Optioni("yac.page"), m.Optioni("yac.void"), arg[0], 1) + m.Result(word) } return }}, "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)) - m.Append("page", len(yac.page)) - m.Append("hash", len(yac.hash)) - m.Append("node", len(yac.state)) + m.Push("seed", len(yac.seed)) + m.Push("page", len(yac.page)) + m.Push("hash", len(yac.hash)) + m.Push("nmat", len(yac.mat)) + m.Push("node", len(yac.state)) m.Table() return } @@ -412,32 +413,51 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", switch arg[0] { case "seed": for _, v := range yac.seed { - m.Add("append", "page", fmt.Sprintf("%d", v.page)) - m.Add("append", "hash", fmt.Sprintf("%d", v.hash)) - m.Add("append", "word", fmt.Sprintf("%s", strings.Replace(strings.Replace(strings.Join(v.word, " "), "\n", "\\n", -1), "\t", "\\t", -1))) + m.Push("page", yac.hand[v.page]) + m.Push("word", strings.Replace(strings.Replace(fmt.Sprint(v.word), "\n", "\\n", -1), "\t", "\\t", -1)) + m.Push("hash", yac.word[v.hash]) } - m.Table() + m.Sort("page", "int").Table() + case "page": for k, v := range yac.page { m.Add("append", "page", k) - m.Add("append", "code", fmt.Sprintf("%d", v)) + m.Add("append", "code", v) } m.Sort("code", "int").Table() + case "hash": for k, v := range yac.hash { m.Add("append", "hash", k) - m.Add("append", "code", fmt.Sprintf("%d", v)) + m.Add("append", "code", v) m.Add("append", "hand", yac.hand[v]) } m.Sort("code", "int").Table() + + case "node": + for _, v := range yac.state { + m.Push("star", v.star) + m.Push("next", v.next) + m.Push("hash", v.hash) + } + m.Table() + case "mat": - for _, v := range yac.mat { - for j := byte(0); j < byte(m.Confi("info", "ncell")); j++ { - s := v[j] - if s == nil { - m.Add("append", fmt.Sprintf("%d", j), "") + for i, v := range yac.mat { + if i <= m.Capi("npage") { + m.Push("index", yac.hand[i]) + } else if i < m.Confi("meta", "nlang") { + continue + } else { + m.Push("index", i) + } + + for j := byte(0); j < byte(m.Confi("meta", "ncell")); j++ { + c := fmt.Sprintf("%d", j) + if s := v[j]; s == nil { + m.Push(c, "") } else { - m.Add("append", fmt.Sprintf("%d", j), fmt.Sprintf("%d,%d,%d", s.star, s.next, s.hash)) + m.Push(c, fmt.Sprintf("%d,%d,%d", s.star, s.next, s.hash)) } } } @@ -480,6 +500,352 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", } return }}, + + "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) (e error) { + switch len(arg) { + case 1: + m.Echo(arg[0]) + case 2: + msg := m.Spawn(m.Optionv("bio.ctx")) + 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]) + } + 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) { + result := "false" + switch len(arg) { + case 0: + result = "" + case 1: + result = arg[0] + case 2: + switch arg[0] { + case "-z": + if arg[1] == "" { + result = "true" + } + case "-n": + if arg[1] != "" { + result = "true" + } + + case "-e": + if _, e := os.Stat(arg[1]); e == nil { + result = "true" + } + case "-f": + if info, e := os.Stat(arg[1]); e == nil && !info.IsDir() { + result = "true" + } + case "-d": + if info, e := os.Stat(arg[1]); e == nil && info.IsDir() { + result = "true" + } + case "+": + result = arg[1] + case "-": + result = arg[1] + if i, e := strconv.Atoi(arg[1]); e == nil { + result = fmt.Sprintf("%d", -i) + } + } + case 3: + v1, e1 := strconv.Atoi(arg[0]) + v2, e2 := strconv.Atoi(arg[2]) + switch arg[1] { + case ":=": + if !m.Target().Has(arg[0]) { + result = m.Cap(arg[0], arg[0], arg[2], "临时变量") + } + case "=": + result = m.Cap(arg[0], arg[2]) + case "+=": + if i, e := strconv.Atoi(m.Cap(arg[0])); e == nil && e2 == nil { + result = m.Cap(arg[0], fmt.Sprintf("%d", v2+i)) + } else { + result = m.Cap(arg[0], m.Cap(arg[0])+arg[2]) + } + case "+": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%d", v1+v2) + } else { + result = arg[0] + arg[2] + } + case "-": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%d", v1-v2) + } else { + result = strings.Replace(arg[0], arg[1], "", -1) + } + case "*": + result = arg[0] + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%d", v1*v2) + } + case "/": + result = arg[0] + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%d", v1/v2) + } + case "%": + result = arg[0] + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%d", v1%v2) + } + + case "<": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%t", v1 < v2) + } else { + result = fmt.Sprintf("%t", arg[0] < arg[2]) + } + case "<=": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%t", v1 <= v2) + } else { + result = fmt.Sprintf("%t", arg[0] <= arg[2]) + } + case ">": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%t", v1 > v2) + } else { + result = fmt.Sprintf("%t", arg[0] > arg[2]) + } + case ">=": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%t", v1 >= v2) + } else { + result = fmt.Sprintf("%t", arg[0] >= arg[2]) + } + case "==": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%t", v1 == v2) + } else { + result = fmt.Sprintf("%t", arg[0] == arg[2]) + } + case "!=": + if e1 == nil && e2 == nil { + result = fmt.Sprintf("%t", v1 != v2) + } else { + result = fmt.Sprintf("%t", arg[0] != arg[2]) + } + + case "~": + if m, e := regexp.MatchString(arg[2], arg[0]); m && e == nil { + result = "true" + } + case "!~": + if m, e := regexp.MatchString(arg[2], arg[0]); !m || e != nil { + result = "true" + } + } + } + m.Echo(result) + + return + }}, + "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++ { + key := arg[i] + for i += 3; i < len(arg); i++ { + if arg[i] == "]" { + break + } + msg.Add("append", key, arg[i]) + } + } + m.Echo("%d", msg.Code()) + return + } + + pre := map[string]int{ + "=": -1, + "+": 2, "-": 2, + "*": 3, "/": 3, "%": 3, + } + num, op := []string{arg[0]}, []string{} + + for i := 1; i < len(arg); i += 2 { + if len(op) > 0 && pre[op[len(op)-1]] >= pre[arg[i]] { + num[len(op)-1] = m.Cmdx("yac.val", num[len(op)-1], op[len(op)-1], num[len(op)]) + num, op = num[:len(num)-1], op[:len(op)-1] + } + num, op = append(num, arg[i+1]), append(op, arg[i]) + } + + for i := len(op) - 1; i >= 0; i-- { + num[i] = m.Cmdx("yac.val", num[i], op[i], num[i+1]) + } + + m.Echo("%s", num[0]) + return + }}, + "let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + switch arg[2] { + case "=": + m.Cap(arg[1], arg[3]) + m.Log("stack", " set %v = %v", arg[1], arg[3]) + case "<-": + 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) (e error) { + if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 { + switch arg[2] { + case "=": + m.Cap(arg[1], arg[3]) + case "<-": + m.Cap(arg[1], m.Cap("last_msg")) + } + } + m.Echo(m.Cap(arg[1])) + return + }}, + "return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Appends("bio.end", true) + m.Result(arg[1:]) + return + }}, + "com": &ctx.Command{Name: "com", Help: "解析注释", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + return + }}, + + "if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Push("stack.key", arg[0]) + m.Push("stack.run", m.Options("stack.run") && kit.Right(arg[1])) + 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) (e error) { + m.Push("stack.key", arg[0]) + m.Push("stack.run", m.Options("stack.run") && kit.Right(arg[1])) + + /* + if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) { + run := m.Caps("parse") + defer func() { m.Caps("parse", run) }() + + msg := m + if run { + if arg[1] == "index" { + if code, e := strconv.Atoi(arg[2]); m.Assert(e) { + msg = m.Target().Message().Tree(code) + run = run && msg != nil && msg.Meta != nil + switch len(arg) { + case 4: + run = run && len(msg.Meta) > 0 + case 5: + run = run && len(msg.Meta[arg[3]]) > 0 + } + } + } else { + run = run && kit.Right(arg[len(arg)-1]) + } + + if len(cli.stack) > 0 { + if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.pos == m.Optioni("file_pos") { + if arg[1] == "index" { + frame.index++ + if run = run && len(frame.list) > frame.index; run { + if len(arg) == 5 { + arg[3] = arg[4] + } + m.Cap(arg[3], frame.list[frame.index]) + } + } + frame.run = run + return + } + } + } + + cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run, index: 0}) + if m.Capi("level", 1); run && arg[1] == "index" { + frame := cli.stack[len(cli.stack)-1] + switch len(arg) { + case 4: + frame.list = []string{} + for k, _ := range msg.Meta { + frame.list = append(frame.list, k) + } + case 5: + frame.list = msg.Meta[arg[3]] + arg[3] = arg[4] + } + m.Cap(arg[3], arg[3], frame.list[0], "临时变量") + } + } + */ + return + }}, + + "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 + }}, + "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.(*YAC); 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) (e error) { + if cli, ok := m.Target().Server.(*YAC); m.Assert(ok) { + if pos, ok := cli.label[arg[1]]; ok { + if !kit.Right(arg[len(arg)-1]) { + return + } + m.Append("file_pos0", pos) + } + } + return + }}, + "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.(*YAC); m.Assert(ok) { + if !m.Caps("parse") { + m.Caps("parse", true) + } else { + if len(cli.stack) == 1 { + m.Caps("parse", false) + } else { + frame := cli.stack[len(cli.stack)-2] + m.Caps("parse", !frame.run) + } + } + } + */ + return + }}, }, } diff --git a/src/toolkit/what.go b/src/toolkit/misc.go similarity index 100% rename from src/toolkit/what.go rename to src/toolkit/misc.go diff --git a/src/toolkit/stmt.go b/src/toolkit/stmt.go new file mode 100644 index 00000000..3e972e3e --- /dev/null +++ b/src/toolkit/stmt.go @@ -0,0 +1,35 @@ +package kit + +import ( + "fmt" + "strings" +) + +type Frame struct { + Key string + Run bool + Pos int + deep int + // list []string +} + +func (f *Frame) String(meta string) string { + return fmt.Sprintf("%s%s%d %s %t", strings.Repeat("#", f.deep), meta, f.deep, f.Key, f.Run) +} + +type Stack struct { + fs []*Frame +} + +func (s *Stack) Pop() *Frame { + f := s.fs[len(s.fs)-1] + s.fs = s.fs[:len(s.fs)-1] + return f +} +func (s *Stack) Push(key string, run bool, pos int) *Frame { + s.fs = append(s.fs, &Frame{key, run, pos, len(s.fs)}) + return s.fs[len(s.fs)-1] +} +func (s *Stack) Peek() *Frame { + return s.fs[len(s.fs)-1] +} diff --git a/src/toolkit/type.go b/src/toolkit/type.go index 049f2987..b5f3933f 100644 --- a/src/toolkit/type.go +++ b/src/toolkit/type.go @@ -116,18 +116,6 @@ func Format(arg ...interface{}) string { result = append(result, string(val)) case []rune: result = append(result, string(val)) - case []string: - result = append(result, val...) - // case []interface{}: - // - // result = append(result, "[") - // for i, value := range val { - // result = append(result, Format(value)) - // if i < len(val)-1 { - // result = append(result, ",") - // } - // } - // result = append(result, "]") case time.Time: result = append(result, fmt.Sprintf("%s", val.Format("2006-01-02 15:03:04"))) case *os.File: @@ -210,7 +198,7 @@ func Trans(arg ...interface{}) []string { } case []interface{}: for _, v := range val { - ls = append(ls, Format(v)) + ls = append(ls, Trans(v)...) } default: ls = append(ls, Format(val))