diff --git a/etc/init.shy b/etc/init.shy index 74533cc8..2ffa6955 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,4 +1,5 @@ -~cli config debug on +~file1 + history load hi.cmd return scan_file etc/demo.shy echo "who" diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 2b1cdcef..0b9aad99 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -51,6 +51,7 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server if len(arg) > 0 { s.target = c } + s.target = cli.target return s } @@ -280,6 +281,10 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{ return nil }, "parse", arg[1]) m.Cap("stream", yac.Target().Name) + + if arg[1] == "stdio" { + m.Spawn().Cmd("scan_file", "etc/init.shy") + } return false } @@ -844,7 +849,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", }}, "return": &ctx.Command{Name: "return result...", Help: "结束脚本, rusult: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if _, ok := m.Target().Server.(*CLI); m.Assert(ok) && !m.Caps("skip") { // {{{ - m.Add("append", "return", arg[1:]...) + m.Add("append", "return", arg[1:]) } // }}} }}, "if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { @@ -930,11 +935,17 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Echo("%s", strings.Join(arg, "")) }}, "scan_file": &ctx.Command{ - Name: "scan_file filename [cli_name [cli_help]]", + Name: "scan_file filename [async [cli_name [cli_help]]", Help: "解析脚本, filename: 文件名, cli_name: 模块名, cli_help: 模块帮助", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Start(m.Confx("cli_name", arg, 1), m.Confx("cli_help", arg, 2), key, arg[0]) - <-m.Target().Exit + if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { + m.Start(m.Confx("cli_name", arg, 2), m.Confx("cli_help", arg, 3), key, arg[0]) + if len(arg) > 1 && arg[1] != "async" { + <-m.Target().Exit + sub := m.Target().Server.(*CLI) + cli.target = sub.target + } + } }}, }, Index: map[string]*ctx.Context{ diff --git a/src/contexts/ctx.go b/src/contexts/ctx.go index 72d34a8b..c2b6004b 100644 --- a/src/contexts/ctx.go +++ b/src/contexts/ctx.go @@ -107,7 +107,11 @@ func (c *Context) Spawn(m *Message, name string, help string) *Context { // {{{ } // }}} -func (c *Context) Begin(m *Message) *Context { // {{{ +func (c *Context) Begin(m *Message, arg ...string) *Context { // {{{ + if len(arg) > 0 { + m.Meta["detail"] = arg + } + c.Caches["status"] = &Cache{Name: "服务状态(begin/start/close)", Value: "begin", Help: "服务状态,begin:初始完成,start:正在运行,close:未在运行"} c.Caches["stream"] = &Cache{Name: "服务数据", Value: "", Help: "服务数据"} @@ -145,7 +149,11 @@ func (c *Context) Begin(m *Message) *Context { // {{{ } // }}} -func (c *Context) Start(m *Message) bool { // {{{ +func (c *Context) Start(m *Message, arg ...string) bool { // {{{ + if len(arg) > 0 { + m.Meta["detail"] = arg + } + m.Hand = true if m != c.Requests[0] { @@ -998,7 +1006,29 @@ func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg // }}} -func (m *Message) Add(meta string, key string, value ...string) *Message { // {{{ +func (m *Message) Trans(arg ...interface{}) []string { + ls := []string{} + for _, v := range arg { + value := "" + switch val := v.(type) { + case []string: + ls = append(ls, val...) + continue + case string: + value = val + case bool: + value = fmt.Sprintf("%t", val) + case int, int8, int16, int32, int64: + value = fmt.Sprintf("%d", val) + default: + value = fmt.Sprintf("%v", val) + } + ls = append(ls, value) + } + return ls +} + +func (m *Message) Add(meta string, key string, value ...interface{}) *Message { // {{{ if m.Meta == nil { m.Meta = make(map[string][]string) } @@ -1009,13 +1039,13 @@ func (m *Message) Add(meta string, key string, value ...string) *Message { // {{ switch meta { case "detail", "result": m.Meta[meta] = append(m.Meta[meta], key) - m.Meta[meta] = append(m.Meta[meta], value...) + m.Meta[meta] = append(m.Meta[meta], m.Trans(value...)...) case "option", "append": if _, ok := m.Meta[key]; !ok { m.Meta[key] = make([]string, 0, 3) } - m.Meta[key] = append(m.Meta[key], value...) + m.Meta[key] = append(m.Meta[key], m.Trans(value...)...) for _, v := range m.Meta[meta] { if v == key { @@ -1055,7 +1085,7 @@ func (m *Message) Set(meta string, arg ...string) *Message { // {{{ } if len(arg) > 0 { - m.Add(meta, arg[0], arg[1:]...) + m.Add(meta, arg[0], arg[1:]) } return m @@ -1148,7 +1178,7 @@ func (m *Message) Copy(msg *Message, meta string, arg ...string) *Message { // { for _, k := range arg { if v, ok := msg.Meta[k]; ok { - m.Set(meta, k).Add(meta, k, v...) + m.Set(meta, k).Add(meta, k, v) } if v, ok := msg.Data[k]; ok { m.Put(meta, k, v) @@ -1160,11 +1190,12 @@ func (m *Message) Copy(msg *Message, meta string, arg ...string) *Message { // { } // }}} -func (m *Message) Table(cb func(map[string]string, []string, int) bool) *Message { // {{{ +func (m *Message) Table(cb func(maps map[string]string, list []string, line int) (goon bool)) *Message { // {{{ if len(m.Meta["append"]) == 0 { return m } + //计算列宽 width := make(map[string]int, len(m.Meta[m.Meta["append"][0]])) for _, k := range m.Meta["append"] { title := k @@ -1182,6 +1213,7 @@ func (m *Message) Table(cb func(map[string]string, []string, int) bool) *Message } } + //输出字段名 row := map[string]string{} wor := []string{} for _, k := range m.Meta["append"] { @@ -1202,6 +1234,7 @@ func (m *Message) Table(cb func(map[string]string, []string, int) bool) *Message wor := []string{} for _, k := range m.Meta["append"] { data := m.Meta[k][i] + //解析extra字段 if m.Options("extras") && k == "extra" { var extra interface{} json.Unmarshal([]byte(data), &extra) @@ -1569,7 +1602,6 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{ for _, c := range []*Context{m.target, m.target.master, m.target.Owner, m.source, m.source.master, m.source.Owner} { for s := c; s != nil; s = s.context { - if x, ok := s.Commands[key]; ok && x.Hand != nil && c.Check(m, "commands", key) { m.TryCatch(m, true, func(m *Message) { m.Log("cmd", s, "%d %s %v %v", len(m.target.Historys), key, arg, m.Meta["option"]) @@ -1602,7 +1634,7 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{ // continue // } // - m.Add("option", arg[i], arg[i+1:i+1+n]...) + m.Add("option", arg[i], arg[i+1:i+1+n]) i += n } arg = m.Meta["args"] @@ -2414,7 +2446,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", for i, v := range msg.messages { if !all { switch v.target.Name { - case "log", "yac": + case "log", "yac", "lex": continue } } @@ -3373,6 +3405,6 @@ func Start(args ...string) { Pulse.Options("terminal_color", true) Pulse.Sesss("log", "log").Conf("bench.log", Pulse.Conf("bench.log")) - Pulse.Find("cli").Cmd("scan_file", "etc/init.shy") - Pulse.Find("cli").Cmd("scan_file", "stdio") + cli := Pulse.Find("cli").Cmd("scan_file", "stdio", "async") + <-cli.target.Exit } diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go index 8c52817c..957d46b6 100644 --- a/src/contexts/log/log.go +++ b/src/contexts/log/log.go @@ -14,7 +14,7 @@ import ( // {{{ type LOG struct { module map[string]map[string]bool - slient map[string]bool + silent map[string]bool color map[string]int *Log.Logger @@ -33,10 +33,6 @@ func (log *LOG) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server // }}} func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ - if log.Context == Index { - Pulse = m - } - log.Context.Master(nil) log.Message = m log.Configs["flag_date"] = &ctx.Config{Name: "输出日期", Value: "true", Help: "模块日志输出消息日期"} @@ -50,7 +46,7 @@ func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ if len(arg) > 0 { if m.Sess("nfs") == nil { os.Create(arg[0]) - m.Sess("nfs", "nfs").Cmd("open", arg[0]) + m.Sess("nfs", "nfs").Cmd("open", arg[0], "", "日志文件") } return arg[0] } @@ -82,12 +78,12 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{}, Commands: map[string]*ctx.Command{ - "slient": &ctx.Command{Name: "slient [[module] level state]", Help: "查看或设置日志开关, module: 模块名, level: 日志类型, state(true/false): 是否打印日志", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "silent": &ctx.Command{Name: "silent [[module] level state]", Help: "查看或设置日志开关, module: 模块名, level: 日志类型, state(true/false): 是否打印日志", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { // {{{ switch len(arg) { case 2: if len(arg) > 1 { - log.slient[arg[0]] = ctx.Right(arg[1]) + log.silent[arg[0]] = ctx.Right(arg[1]) } case 3: if log.module[arg[0]] == nil { @@ -96,7 +92,7 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", log.module[arg[0]][arg[1]] = ctx.Right(arg[2]) } - for k, v := range log.slient { + for k, v := range log.silent { m.Echo("%s: %t\n", k, v) } for k, v := range log.module { @@ -121,7 +117,7 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", }}, "log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { // {{{ - if s, ok := log.slient[arg[0]]; ok && s == true { + if s, ok := log.silent[arg[0]]; ok && s == true { return } @@ -216,7 +212,7 @@ func init() { "close": 36, "debug": 0, } - log.slient = map[string]bool{ + log.silent = map[string]bool{ // "lock": true, } log.module = map[string]map[string]bool{ diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 00904a32..87415aad 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -9,9 +9,11 @@ import ( // {{{ "bufio" "fmt" "io" + "io/ioutil" "net/url" "os" "os/exec" + "path" "strconv" "strings" "time" @@ -21,17 +23,17 @@ import ( // {{{ // }}} type NFS struct { + in *os.File + out *os.File + history []string + io io.ReadWriteCloser *bufio.Reader *bufio.Writer send map[int]*ctx.Message target *ctx.Context - in *os.File - out *os.File - cli *ctx.Message - buf []string pages []string width, height int @@ -40,6 +42,71 @@ type NFS struct { *ctx.Context } +func dir(m *ctx.Message, name string, level int) { + back, e := os.Getwd() + m.Assert(e) + os.Chdir(name) + defer os.Chdir(back) + + if fs, e := ioutil.ReadDir("."); m.Assert(e) { + for _, f := range fs { + if f.Name()[0] == '.' { + continue + } + + if f.IsDir() { + if m.Has("dirs") { + m.Optioni("dirs", m.Optioni("dirs")+1) + } + } else { + if m.Has("files") { + m.Optioni("files", m.Optioni("files")+1) + } + } + + if m.Has("sizes") { + m.Optioni("sizes", m.Optioni("sizes")+int(f.Size())) + } + + line := 0 + if m.Has("lines") { + if !f.IsDir() { + f, e := os.Open(path.Join(back, name, f.Name())) + m.Assert(e) + defer f.Close() + bio := bufio.NewScanner(f) + for bio.Scan() { + bio.Text() + line++ + } + m.Optioni("lines", m.Optioni("lines")+line) + } + } + + filename := "" + if m.Confx("dir_name") == "name" { + filename = strings.Repeat(" ", level) + f.Name() + } else { + filename = path.Join(back, name, f.Name()) + } + + if !(m.Confx("dir_type") == "file" && f.IsDir() || + m.Confx("dir_type") == "dir" && !f.IsDir()) { + m.Add("append", "filename", filename) + m.Add("append", "dir", f.IsDir()) + m.Add("append", "size", f.Size()) + m.Log("fuck", nil, "why %s %d", f.Name(), f.Size()) + m.Add("append", "line", line) + m.Add("append", "time", f.ModTime().Format("2006-01-02 15:04:05")) + } + + if f.IsDir() { + dir(m, f.Name(), level+1) + } + } + } +} + func (nfs *NFS) insert(rest []rune, letters []rune) []rune { // {{{ n := len(rest) l := len(letters) @@ -207,7 +274,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { // {{{ back := buf - his := len(nfs.buf) + his := len(nfs.history) tab := []string{} tabi := 0 @@ -238,21 +305,21 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { // {{{ return case termbox.KeyCtrlP: - for i := 0; i < len(nfs.buf); i++ { - his = (his + len(nfs.buf) - 1) % len(nfs.buf) - if strings.HasPrefix(nfs.buf[his], string(buf)) { + for i := 0; i < len(nfs.history); i++ { + his = (his + len(nfs.history) - 1) % len(nfs.history) + if strings.HasPrefix(nfs.history[his], string(buf)) { rest = rest[:0] - rest = append(rest, []rune(nfs.buf[his][len(buf):])...) + rest = append(rest, []rune(nfs.history[his][len(buf):])...) break } } case termbox.KeyCtrlN: - for i := 0; i < len(nfs.buf); i++ { - his = (his + len(nfs.buf) + 1) % len(nfs.buf) - if strings.HasPrefix(nfs.buf[his], string(buf)) { + for i := 0; i < len(nfs.history); i++ { + his = (his + len(nfs.history) + 1) % len(nfs.history) + if strings.HasPrefix(nfs.history[his], string(buf)) { rest = rest[:0] - rest = append(rest, []rune(nfs.buf[his][len(buf):])...) + rest = append(rest, []rune(nfs.history[his][len(buf):])...) break } } @@ -388,13 +455,19 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { // {{{ // }}} func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ - if len(arg) > 0 && arg[0] == "scan_file" { + if len(arg) > 0 && arg[0] == "scan" { nfs.Message = m c.Caches = map[string]*ctx.Cache{ "nread": &ctx.Cache{Name: "nread", Value: "0", Help: "nread"}, "nwrite": &ctx.Cache{Name: "nwrite", Value: "0", Help: "nwrite"}, } c.Configs = map[string]*ctx.Config{} + } else if len(arg) > 0 && arg[0] == "open" { + c.Caches = map[string]*ctx.Cache{ + "pos": &ctx.Cache{Name: "pos", Value: "0", Help: "pos"}, + "size": &ctx.Cache{Name: "size", Value: "0", Help: "size"}, + } + c.Configs = map[string]*ctx.Config{} } else { c.Caches = map[string]*ctx.Cache{ "pos": &ctx.Cache{Name: "读写位置", Value: "0", Help: "读写位置"}, @@ -429,31 +502,34 @@ func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server // }}} func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ nfs.Message = m - nfs.Context.Master(nil) - if nfs.Context == Index { - Pulse = m - } return nfs } // }}} func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ - if len(arg) > 0 && arg[0] == "scan_file" { + if len(arg) > 0 && arg[0] == "scan" { nfs.Message = m nfs.in = m.Optionv("in").(*os.File) bio := bufio.NewScanner(nfs) - if m.Options("stdout", m.Cap("stream", arg[1]) == "stdio") { + if m.Cap("stream", arg[1]) == "stdio" { termbox.Init() defer termbox.Close() nfs.out = m.Optionv("out").(*os.File) } + line := "" for nfs.prompt(); bio.Scan(); nfs.prompt() { text := bio.Text() m.Capi("nread", len(text)) - msg := m.Spawn(m.Source()).Set("detail", text) + if line += text; len(text) > 0 && text[len(text)-1] == '\\' { + line = line[:len(line)-1] + continue + } + nfs.history = append(nfs.history, line) + + msg := m.Spawn(m.Source()).Set("detail", line) if m.Back(msg); m.Options("scan_end") { break } @@ -462,10 +538,21 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ m.Capi("nwrite", len(v)) nfs.print(v) } + line = "" } return true } + if len(arg) > 0 && arg[0] == "open" { + nfs.in = m.Optionv("in").(*os.File) + s, e := nfs.in.Stat() + m.Assert(e) + m.Capi("size", int(s.Size())) + nfs.out = m.Optionv("out").(*os.File) + m.Cap("stream", arg[1]) + return false + } + m.Target().Sessions["nfs"] = m m.Sessions["nfs"] = m @@ -596,95 +683,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ return true } - if in, ok := m.Data["in"]; ok { - nfs.in = in.(*os.File) - } - if out, ok := m.Data["out"]; ok { - nfs.out = out.(*os.File) - } - if len(arg) > 1 { - if m.Cap("stream", arg[1]); arg[0] == "open" { - return false - } - } - - // cli := m.Reply() - cli := m.Sesss("cli") - nfs.cli = cli - yac := m.Sesss("yac", cli.Conf("yac")) - bio := bufio.NewScanner(nfs) - - if m.Cap("stream") == "stdio" { - termbox.Init() - defer termbox.Close() - } - - nfs.Context.Master(nil) - pos := 0 - - if buf, ok := m.Data["buf"]; ok { - nfs.buf = buf.([]string) - m.Capi("nline", len(nfs.buf)) - goto out - } - - nfs.pages = append(nfs.pages, nfs.cli.Conf("PS1")) - nfs.prompt() - - for rest, text := "", ""; pos < m.Capi("nline") || bio.Scan(); { - if pos == m.Capi("nline") { - if text = bio.Text(); len(text) > 0 && text[len(text)-1] == '\\' { - rest += text[:len(text)-1] - continue - } - - if text, rest = rest+text, ""; len(text) == 0 && len(nfs.buf) > 0 && nfs.in == os.Stdin { - pos-- - } else { - nfs.buf = append(nfs.buf, text) - m.Capi("nline", 1) - } - } - - for ; pos < m.Capi("nline"); pos++ { - - for text = nfs.buf[pos] + "\n"; text != ""; { - - if true { - m.Result(0, 0, len(text)) - m.Put("append", fmt.Sprintf("%d", len(text)), text) - m.Back(m) - } else { - line := m.Spawn(yac.Target()) - line.Optioni("pos", pos) - line.Options("stdio", true) - line.Put("option", "cli", cli.Target()) - text = line.Cmd("parse", "line", "void", text).Get("result") - cli.Target(line.Data["cli"].(*ctx.Context)) - if line.Has("return") { - goto out - } - if line.Has("back") { - pos = line.Appendi("back") - } - if result := strings.TrimRight(strings.Join(line.Meta["result"][1:len(line.Meta["result"])-1], ""), "\n"); len(result) > 0 { - nfs.print("%s", result+"\n") - } - } - - } - } - - nfs.pages = append(nfs.pages, fmt.Sprintf("\033[32m%s\033[m", nfs.cli.Conf("PS1"))) - nfs.prompt() - } - -out: - if len(arg) > 1 { - cli.Cmd("end") - } else { - m.Cap("status", "stop") - } return false } @@ -696,6 +694,14 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { // {{{ nfs.in.Close() nfs.in = nil } + if nfs.out != nil { + nfs.out.Close() + nfs.out = nil + } + if nfs.io != nil { + nfs.io.Close() + nfs.io = nil + } case m.Source(): m.Source().Close(m.Spawn(m.Source())) } @@ -707,57 +713,341 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { // {{{ // }}} -var Pulse *ctx.Message var Index = &ctx.Context{Name: "nfs", Help: "存储中心", Caches: map[string]*ctx.Cache{ - "nfile": &ctx.Cache{Name: "nfile", Value: "0", Help: "已经打开的文件数量"}, + "nfile": &ctx.Cache{Name: "nfile", Value: "-1", Help: "已经打开的文件数量"}, }, Configs: map[string]*ctx.Config{ - "size": &ctx.Config{Name: "size", Value: "1024", Help: "读取文件的默认大小值"}, "color": &ctx.Config{Name: "color", Value: "9", Help: "读取文件的默认大小值"}, "backcolor": &ctx.Config{Name: "backcolor", Value: "9", Help: "读取文件的默认大小值"}, "pscolor": &ctx.Config{Name: "pscolor", Value: "2", Help: "读取文件的默认大小值"}, "statuscolor": &ctx.Config{Name: "statuspscolor", Value: "1", Help: "读取文件的默认大小值"}, "statusbackcolor": &ctx.Config{Name: "statusbackcolor", Value: "2", Help: "读取文件的默认大小值"}, - "nfs_name": &ctx.Config{Name: "nfs_name", Value: "file", Help: "默认模块命名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { + "name": &ctx.Config{Name: "name", Value: "file", Help: "默认模块命名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { if len(arg) > 0 { // {{{ return arg[0] } return fmt.Sprintf("%s%d", x.Value, m.Capi("nfile", 1)) // }}} }}, - "nfs_help": &ctx.Config{Name: "nfs_help", Value: "file", Help: "默认模块帮助"}, - "buffer_size": &ctx.Config{Name: "buffer_size", Value: "1024", Help: "缓存区大小"}, + "help": &ctx.Config{Name: "help", Value: "file", Help: "默认模块帮助"}, + "buf_size": &ctx.Config{Name: "buf_size", Value: "1024", Help: "读取文件的默认大小值"}, + "qr_size": &ctx.Config{Name: "qr_size", Value: "256", Help: "读取文件的默认大小值"}, + "dir_name": &ctx.Config{Name: "dir_name", Value: "name", Help: "读取文件的默认大小值"}, + "dir_info": &ctx.Config{Name: "dir_info", Value: "info", Help: "读取文件的默认大小值"}, + "dir_type": &ctx.Config{Name: "dir_type", Value: "type", Help: "读取文件的默认大小值"}, + "sort_field": &ctx.Config{Name: "sort_field", Value: "line", Help: "读取文件的默认大小值"}, + "sort_type": &ctx.Config{Name: "sort_type", Value: "int", Help: "读取文件的默认大小值"}, + "git_status": &ctx.Config{Name: "git_status", Value: "-sb", Help: "读取文件的默认大小值"}, + "git_path": &ctx.Config{Name: "git_path", Value: ".", Help: "读取文件的默认大小值"}, }, Commands: map[string]*ctx.Command{ - "scan_file": &ctx.Command{ - Name: "scan_file filename [nfs_name [nfs_help]]", - Help: "扫描文件, filename: 文件名, nfs_name: 模块名, nfs_help: 模块帮助", + "scan": &ctx.Command{ + Name: "scan filename [name [help]]", + Help: "扫描文件, filename: 文件名, name: 模块名, help: 模块帮助", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { // {{{ if arg[0] == "stdio" { - m.Put("option", "in", os.Stdin) - m.Put("option", "out", os.Stdout) - } else { - f, e := os.Open(arg[0]) - m.Assert(e) - m.Put("option", "in", f) + m.Optionv("in", os.Stdin) + m.Optionv("out", os.Stdout) + } else if f, e := os.Open(arg[0]); m.Assert(e) { + m.Optionv("in", f) } - m.Start(m.Confx("nfs_name", arg, 1), m.Confx("nfs_help", arg, 2), key, arg[0]) + m.Start(m.Confx("name", arg, 1), m.Confx("help", arg, 2), key, arg[0]) } // }}} }}, - "buffer": &ctx.Command{Name: "buffer [index string]", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.buf != nil { // {{{ - for i, v := range nfs.buf { - m.Echo("%d: %s\n", i, v) + "history": &ctx.Command{Name: "history [save|load filename [lines [pos]]] [find|search string]", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) { // {{{ + if len(arg) == 0 { + for i, v := range nfs.history { + m.Echo("%d: %s\n", i, v) + } + return + } + switch arg[0] { + case "load": + f, e := os.Open(arg[1]) + m.Assert(e) + defer f.Close() + + pos, lines := 0, -1 + if len(arg) > 3 { + i, e := strconv.Atoi(arg[3]) + m.Assert(e) + pos = i + + } + if len(arg) > 2 { + i, e := strconv.Atoi(arg[2]) + m.Assert(e) + lines = i + } + + bio := bufio.NewScanner(f) + for i := 0; bio.Scan(); i++ { + if i < pos { + continue + } + if lines != -1 && (i-pos) >= lines { + break + } + nfs.history = append(nfs.history, bio.Text()) + } + case "save": + f, e := os.Create(arg[1]) + m.Assert(e) + defer f.Close() + + pos, lines := 0, -1 + if len(arg) > 3 { + i, e := strconv.Atoi(arg[3]) + m.Assert(e) + pos = i + + } + if len(arg) > 2 { + i, e := strconv.Atoi(arg[2]) + m.Assert(e) + lines = i + } + + for i, v := range nfs.history { + if i < pos { + continue + } + if lines != -1 && (i-pos) >= lines { + break + } + fmt.Fprintln(f, v) + } + case "find": + for i, v := range nfs.history { + if strings.HasPrefix(v, arg[1]) { + m.Echo("%d: %s\n", i, v) + } + } + case "search": + default: + if i, e := strconv.Atoi(arg[0]); e == nil && i < len(nfs.history) { + m.Echo(nfs.history[i]) + } } } // }}} }}, + "open": &ctx.Command{ + Name: "open filename [name [help]]", + Help: "打开文件, filename: 文件名, name: 模块名, help: 模块帮助", + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if m.Has("io") { // {{{ + } else if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE, os.ModePerm); m.Assert(e) { + m.Put("option", "in", f).Put("option", "out", f) + } + m.Start(m.Confx("name", arg, 1), m.Confx("help", arg, 2), "open", arg[0]) + m.Echo(m.Target().Name) + // }}} + }}, + "read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + 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.Echo(string(buf)) + + if m.Capi("pos", n); n == 0 { + m.Cap("pos", "0") + } + } // }}} + }}, + "write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + 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.Assert(e) && m.Capi("pos", n) > m.Capi("size") { + m.Cap("size", m.Cap("pos")) + } + nfs.out.Sync() + } + + m.Echo(m.Cap("pos")) + } // }}} + }}, + "load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if f, e := os.Open(arg[0]); m.Assert(e) { // {{{ + defer f.Close() + + pos := 0 + if len(arg) > 2 { + i, e := strconv.Atoi(arg[2]) + m.Assert(e) + pos = i + } + + s, e := strconv.Atoi(m.Confx("buf_size", arg, 1)) + m.Assert(e) + buf := make([]byte, s) + + if l, e := f.ReadAt(buf, int64(pos)); e == io.EOF || m.Assert(e) { + m.Log("info", nil, "read %d", l) + m.Echo(string(buf[:l])) + } + } // }}} + }}, + "save": &ctx.Command{Name: "save file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if f, e := os.Create(arg[0]); m.Assert(e) { // {{{ + defer f.Close() + + for _, v := range arg[1:] { + fmt.Fprint(f, v) + } + } // }}} + }}, + "print": &ctx.Command{Name: "print file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if f, e := os.OpenFile(arg[0], os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); m.Assert(e) { // {{{ + defer f.Close() + + for _, v := range arg[1:] { + fmt.Fprint(f, v) + } + fmt.Fprint(f, "\n") + } // }}} + }}, + "genqr": &ctx.Command{Name: "genqr [qr_size size] file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if size, e := strconv.Atoi(m.Confx("qr_size")); m.Assert(e) { // {{{ + qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, arg[0]) + } // }}} + }}, + "json": &ctx.Command{Name: "json [key value]...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + data := map[string]interface{}{} // {{{ + for _, k := range m.Meta["option"] { + if v, ok := m.Data[k]; ok { + data[k] = v + continue + } + data[k] = m.Meta[k] + } + + for i := 1; i < len(arg)-1; i += 2 { + data[arg[i]] = arg[i+1] + } + + buf, e := json.Marshal(data) + m.Assert(e) + m.Echo(string(buf)) + // }}} + }}, + "pwd": &ctx.Command{Name: "pwd", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + wd, e := os.Getwd() // {{{ + m.Assert(e) + m.Echo(wd) // }}} + }}, + "dir": &ctx.Command{ + Name: "dir dir [dir_info info] [dir_name name|path|full] [dir_type file|dir] [sort_field name] [sort_type type]", + Help: "查看目录, dir: 目录名, dir_info: 显示统计信息, dir_name: 文件名类型, dir_type: 文件类型, sort_field: 排序字段, sort_type: 排序类型", + Form: map[string]int{"dir_info": 1, "dir_name": 1, "dir_type": 1, "sort_field": 1, "sort_type": 1}, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + d := "." // {{{ + if len(arg) > 0 { + d = arg[0] + } + trip := 0 + if m.Confx("dir_name") == "path" { + wd, e := os.Getwd() + m.Assert(e) + trip = len(wd) + 1 + } + + if m.Confx("dir_info") == "info" { + m.Option("sizes", 0) + m.Option("lines", 0) + m.Option("files", 0) + m.Option("dirs", 0) + } + dir(m, d, 0) + m.Sort(m.Confx("sort_field"), m.Confx("sort_type")) + m.Table(func(maps map[string]string, list []string, line int) bool { + for i, v := range list { + key := m.Meta["append"][i] + switch key { + case "filename": + if trip > 0 { + v = v[trip:] + } + case "dir": + continue + } + m.Echo("%s\t", v) + } + m.Echo("\n") + return true + }) + if m.Confx("dir_info") == "info" { + m.Echo("sizes: %s\n", m.Option("sizes")) + m.Echo("lines: %s\n", m.Option("lines")) + m.Echo("files: %s\n", m.Option("files")) + m.Echo("dirs: %s\n", m.Option("dirs")) + } + // }}} + }}, + "git": &ctx.Command{ + Name: "git cmd", + Help: "写入文件, string: 写入内容, pos: 写入位置", + Form: map[string]int{"git_path": 1}, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + cmds := []string{arg[0]} // {{{ + if arg[0] == "info" { + cmds = []string{"branch", "status"} + } + wd, e := os.Getwd() + m.Assert(e) + if !m.Has("git_path") { + m.Option("git_path", m.Conf("git_path")) + } + for _, p := range m.Meta["git_path"] { + if !path.IsAbs(p) { + p = path.Join(wd, p) + } + for _, c := range cmds { + args := []string{} + switch c { + case "status": + args = append(args, m.Confx("git_status", arg, 1)) + default: + args = append(args, arg[1:]...) + } + + m.Log("fuck", nil, "cmd %p", m.Trans("-C", p, c, args)) + cmd := exec.Command("git", m.Trans("-C", p, c, args)...) + if out, e := cmd.CombinedOutput(); e != nil { + m.Echo("error: ") + m.Echo("%s\n", e) + } else { + m.Echo(string(out)) + } + } + } // }}} + }}, + "copy": &ctx.Command{Name: "copy name [begin [end]]", Help: "复制文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && len(nfs.buf) > 0 { // {{{ - begin, end := 0, len(nfs.buf) + if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && len(nfs.history) > 0 { // {{{ + begin, end := 0, len(nfs.history) if len(arg) > 1 { i, e := strconv.Atoi(arg[1]) m.Assert(e) @@ -768,24 +1058,10 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Assert(e) end = i } - m.Put("option", "buf", nfs.buf[begin:end]) + m.Put("option", "buf", nfs.history[begin:end]) m.Start(arg[0], "扫描文件", key) } // }}} }}, - "scan": &ctx.Command{Name: "scan file", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if arg[0] == "stdio" { // {{{ - m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout).Start("stdio", "扫描文件", m.Meta["detail"]...) - } else if f, e := os.Open(arg[0]); m.Assert(e) { - m.Put("option", "in", f).Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "扫描文件", m.Meta["detail"]...) - } - // }}} - }}, - "print": &ctx.Command{Name: "print str", Help: "扫描文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { // {{{ - fmt.Fprintf(nfs.out, "%s\n", arg[0]) - } - // }}} - }}, "listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{ @@ -793,7 +1069,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", sub := com.Spawn(m.Target()) sub.Put("option", "target", m.Source()) sub.Put("option", "io", com.Data["io"]) - sub.Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "打开文件") + sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "打开文件") return sub }, m.Meta["detail"]) } @@ -805,7 +1081,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", sub := com.Spawn(m.Target()) sub.Put("option", "target", m.Source()) sub.Put("option", "io", com.Data["io"]) - sub.Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "打开文件") + sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "打开文件") return sub }, m.Meta["detail"]) } @@ -916,132 +1192,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", nfs.Writer.Flush() } // }}} }}, - "open": &ctx.Command{Name: "open file", Help: "打开文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if m.Has("io") { // {{{ - m.Put("option", "io", m.Data["io"]) - m.Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "打开文件", m.Meta["detail"]...) - m.Echo(m.Target().Name) - } else if f, e := os.OpenFile(arg[0], os.O_RDWR|os.O_CREATE, os.ModePerm); e == nil { - m.Put("option", "in", f).Put("option", "out", f) - m.Start(fmt.Sprintf("file%d", Pulse.Capi("nfile", 1)), "打开文件", m.Meta["detail"]...) - m.Echo(m.Target().Name) - } // }}} - }}, - "read": &ctx.Command{Name: "read [size [pos]]", Help: "读取文件, size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.in != nil { // {{{ - var e error - n := m.Confi("size") - if len(arg) > 0 { - n, e = strconv.Atoi(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.Echo(string(buf)) - - if m.Capi("pos", n); m.Capi("pos") == m.Capi("size") { - m.Cap("pos", "0") - } - } // }}} - }}, - "write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - 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.Assert(e) && m.Capi("pos", n) > m.Capi("size") { - m.Cap("size", m.Cap("pos")) - } - nfs.out.Sync() - } - - m.Echo(m.Cap("pos")) - } // }}} - }}, - "load": &ctx.Command{Name: "load file [size]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if f, e := os.Open(arg[0]); m.Assert(e) { // {{{ - defer f.Close() - - m.Meta = nil - size := 1024 - if len(arg) > 1 { - if s, e := strconv.Atoi(arg[1]); m.Assert(e) { - size = s - } - } - buf := make([]byte, size) - - if l, e := f.Read(buf); m.Assert(e) { - m.Log("info", nil, "read %d", l) - m.Echo(string(buf[:l])) - } - } // }}} - }}, - "save": &ctx.Command{Name: "save file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if f, e := os.Create(arg[0]); m.Assert(e) { // {{{ - defer f.Close() - - fmt.Fprint(f, strings.Join(arg[1:], "")) - } // }}} - }}, - "append": &ctx.Command{Name: "append file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if f, e := os.OpenFile(arg[0], os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); m.Assert(e) { // {{{ - defer f.Close() - fmt.Fprint(f, strings.Join(arg[1:], "")) - } // }}} - }}, - "genqr": &ctx.Command{Name: "genqr [size] file string...", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - size := 256 // {{{ - if len(arg) > 2 { - if s, e := strconv.Atoi(arg[0]); e == nil { - arg = arg[1:] - size = s - } - } - qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, arg[0]) // }}} - }}, - "json": &ctx.Command{Name: "json file", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - buf, e := json.Marshal(m.Data["data"]) // {{{ - m.Assert(e) - - f, e := os.Create(arg[0]) - m.Assert(e) - f.Write(buf) - f.Close() - - m.Echo(string(buf)) - // }}} - }}, - - "pwd": &ctx.Command{Name: "pwd", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - wd, e := os.Getwd() // {{{ - m.Assert(e) - m.Echo(wd) // }}} - }}, - "git": &ctx.Command{Name: "git", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - cmd := exec.Command("git", arg...) // {{{ - if out, e := cmd.CombinedOutput(); e != nil { - m.Echo("error: ") - m.Echo("%s\n", e) - } else { - m.Echo(string(out)) - } - // }}} - }}, }, Index: map[string]*ctx.Context{ "void": &ctx.Context{Name: "void", diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index ad3d6e0c..38a5b7f1 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -96,7 +96,7 @@ func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.C msg.Option("referer", r.Header.Get("Referer")) for k, v := range r.Form { - msg.Add("option", k, v...) + msg.Add("option", k, v) } for _, v := range r.Cookies() { msg.Option(v.Name, v.Value) @@ -537,7 +537,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", value := []string{} json.Unmarshal([]byte(m.Option("value")), &value) if len(value) > 0 { - msg.Add("detail", value[0], value[1:]...) + msg.Add("detail", value[0], value[1:]) } } @@ -569,7 +569,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", value := []string{} json.Unmarshal([]byte(m.Option("value")), &value) if len(value) > 0 { - msg.Add("detail", value[0], value[1:]...) + msg.Add("detail", value[0], value[1:]) } } diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index 52454126..68671414 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -186,7 +186,7 @@ func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Po // }}} func (yac *YAC) parse(m *ctx.Message, page int, void int, line string, level int) (string, []string) { // {{{ - m.Log("debug", nil, "%s\\%d %s(%d): %s", m.Conf("label")[0:level], level, yac.name(page), page, line) + // m.Log("debug", nil, "%s\\%d %s(%d): %s", m.Conf("label")[0:level], level, yac.name(page), page, line) hash, word := 0, []string{} for star, s := 0, page; s != 0 && len(line) > 0; { @@ -239,15 +239,15 @@ func (yac *YAC) parse(m *ctx.Message, page int, void int, line string, level int if hash == 0 { word = word[:0] - } else { - msg := m.Spawn(m.Source()).Add("detail", yac.hand[hash], word...) - if m.Back(msg); msg.Hand { + } else { //执行命令 + msg := m.Spawn(m.Source()).Add("detail", yac.hand[hash], word) + if m.Back(msg); msg.Hand { //命令替换 m.Assert(!msg.Has("return")) word = msg.Meta["result"] } } - m.Log("debug", nil, "%s/%d %s(%d): %v", m.Conf("label")[0:level], level, yac.name(page), page, word) + // m.Log("debug", nil, "%s/%d %s(%d): %v", m.Conf("label")[0:level], level, yac.name(page), page, word) return line, word } @@ -276,17 +276,16 @@ func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ return yac } - yac.Caches["ncell"] = &ctx.Cache{Name: "词法上限", Value: "128", Help: "词法集合的最大数量"} - yac.Caches["nlang"] = &ctx.Cache{Name: "语法上限", Value: "32", Help: "语法集合的最大数量"} + yac.Caches["ncell"] = &ctx.Cache{Name: "词法上限", Value: m.Confx("ncell", arg, 0), Help: "词法集合的最大数量"} + yac.Caches["nlang"] = &ctx.Cache{Name: "语法上限", Value: m.Confx("nlang", arg, 1), Help: "语法集合的最大数量"} + yac.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: m.Confx("nlang", arg, 1), Help: "状态机状态的数量"} + yac.Caches["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.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "32", Help: "状态机状态的数量"} - yac.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "状态机连接的逻辑数量"} - yac.Caches["nreal"] = &ctx.Cache{Name: "实点数量", Value: "0", Help: "状态机连接的存储数量"} - yac.page = map[string]int{"nil": 0} yac.word = map[int]string{0: "nil"} yac.hash = map[string]int{"nil": 0} @@ -308,36 +307,36 @@ func (yac *YAC) Start(m *ctx.Message, arg ...string) bool { // {{{ data := make(chan string, 1) next := make(chan bool, 1) - //加载文件 m.Options("scan_end", false) + defer func() { + if e := recover(); e != nil { + m.Option("scan_end", true) + next <- true + } + }() + + //加载文件 nfs := m.Find("nfs").Call(func(buf *ctx.Message) *ctx.Message { out = buf data <- buf.Detail(0) + "; " <-next return nil - }, "scan_file", arg[1]) + }, "scan", arg[1], "", "扫描文件") - go func() { - defer func() { - m.Target().Close(m.Spawn()) - if e := recover(); e != nil { - m.Option("scan_end", true) - next <- true - } - }() + m.Find("log").Cmd("silent", yac.Context.Name, "debug", true) - //解析循环 - for m.Cap("stream", nfs.Target().Name); !m.Options("scan_end"); next <- true { - _, word := yac.parse(m, m.Optioni("page"), m.Optioni("void"), <-data, 1) - if len(word) > 0 { - word = word[:len(word)-1] - if last := len(word) - 1; last > 0 && len(word[last]) > 0 && word[last][len(word[last])-1] != '\n' { - word = append(word, "\n") - } + //解析循环 + for m.Cap("stream", nfs.Target().Name); !m.Options("scan_end"); next <- true { + _, word := yac.parse(m, m.Optioni("page"), m.Optioni("void"), <-data, 1) + if len(word) > 0 { + word = word[:len(word)-1] + if last := len(word) - 1; last >= 0 && len(word[last]) > 0 && word[last][len(word[last])-1] != '\n' { + word = append(word, "\n") } - out.Result(0, word) } - }() + out.Result(0, word) + } + return true } return false @@ -359,6 +358,8 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", "nparse": &ctx.Cache{Name: "nparse", Value: "0", Help: "解析器数量"}, }, Configs: map[string]*ctx.Config{ + "ncell": &ctx.Config{Name: "词法上限", Value: "128", Help: "词法集合的最大数量"}, + "nlang": &ctx.Config{Name: "语法上限", Value: "32", Help: "语法集合的最大数量"}, "name": &ctx.Config{Name: "name", Value: "parse", Help: "模块名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { if len(arg) > 0 { // {{{ return arg[0] @@ -372,6 +373,39 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", "label": &ctx.Config{Name: "嵌套标记", Value: "####################", Help: "嵌套层级日志的标记"}, }, Commands: map[string]*ctx.Command{ + "init": &ctx.Command{Name: "init [ncell [nlang]]", Help: "初始化语法矩阵", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if _, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{ + s := new(YAC) + s.Context = m.Target() + m.Target().Server = s + m.Target().Begin(m, arg...) + } + // }}} + }}, + "info": &ctx.Command{Name: "info", Help: "查看语法矩阵", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{ + for i, v := range yac.seed { + m.Echo("seed: %d %v\n", i, v) + } + for i, v := range yac.page { + m.Echo("page: %s %d\n", i, v) + } + for i, v := range yac.hash { + m.Echo("hash: %s %d\n", i, v) + } + for i, v := range yac.state { + m.Echo("node: %v %v\n", i, v) + } + for i, v := range yac.mat { + for k, v := range v { + if v != nil { + m.Echo("node: %s(%d,%d): %v\n", yac.name(i), i, k, v) + } + } + } + } + // }}} + }}, "train": &ctx.Command{Name: "train page hash word...", Help: "添加语法规则, page: 语法集合, hash: 语句类型, word: 语法模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{ page, ok := yac.page[arg[0]] @@ -409,30 +443,6 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", } // }}} }}, - "info": &ctx.Command{Name: "info", Help: "显示缓存", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { // {{{ - for i, v := range yac.seed { - m.Echo("seed: %d %v\n", i, v) - } - for i, v := range yac.page { - m.Echo("page: %s %d\n", i, v) - } - for i, v := range yac.hash { - m.Echo("hash: %s %d\n", i, v) - } - for i, v := range yac.state { - m.Echo("node: %v %v\n", i, v) - } - for i, v := range yac.mat { - for k, v := range v { - if v != nil { - m.Echo("node: %s(%d,%d): %v\n", yac.name(i), i, k, v) - } - } - } - } - // }}} - }}, "parse": &ctx.Command{ Name: "parse filename [name [help]] [line line] [void void]", Help: "解析文件, filename: name:模块名, help:模块帮助, 文件名, line: 默认语法, void: 默认空白",