From 7deb5c46e6eb841b4c9943b66da38ef2d19bdb73 Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 14 Jan 2019 02:17:49 +0800 Subject: [PATCH] nfs.Auto --- etc/init.shy | 2 + src/contexts/ctx/ctx.go | 39 ++- src/contexts/nfs/nfs.go | 728 ++++++++++++++++++++++++---------------- src/toolkit/kit.go | 20 +- 4 files changed, 500 insertions(+), 289 deletions(-) diff --git a/etc/init.shy b/etc/init.shy index c3a948b4..1a63f04c 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,2 +1,4 @@ ~ssh remote listen :9090 + +~stdio diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 0b4b2e33..fda6372f 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -34,6 +34,7 @@ type Command struct { Form map[string]int Name string Help interface{} + Auto func(m *Message, c *Context, key string, arg ...string) (ok bool) Hand func(m *Message, c *Context, key string, arg ...string) (e error) } type Server interface { @@ -274,6 +275,9 @@ func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Cont m.target = target return target } +func (c *Context) Sub(key string) *Context { + return c.contexts[key] +} type LOGGER interface { Log(*Message, string, string, ...interface{}) @@ -1344,7 +1348,11 @@ func (m *Message) Cmd(args ...interface{}) *Message { case string: m.Echo(v) case nil: - x.Hand(m, c, key, arg...) + if m.Options("auto_cmd") { + x.Auto(m, c, key, arg...) + } else { + x.Hand(m, c, key, arg...) + } } if m.target == s { m.target = target @@ -1676,6 +1684,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, m.Echo("%s: %s\n%s\n", k, v.Name, v.Help) } for k, v := range v.Form { + m.Add("append", "arg", k) + m.Add("append", "len", v) m.Echo(" option: %s(%d)\n", k, v) } return @@ -2065,10 +2075,31 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, msg = msg.Sess("cli").Cmd("cmd", arg) } msg.CopyTo(m) + case "switch": m.target = msg.target + case "list": + cs := []*Context{} + if msg.target.Name != "ctx" { + cs = append(cs, msg.target.context) + } msg.Target().Travel(msg, func(msg *Message, n int) bool { + cs = append(cs, msg.target) + return false + }) + + for _, v := range cs { + if msg.target = v; v == nil { + m.Add("append", "name", "") + m.Add("append", "ctx", "") + m.Add("append", "msg", "") + m.Add("append", "status", "") + m.Add("append", "stream", "") + m.Add("append", "help", "") + continue + } + m.Add("append", "name", msg.target.Name) if msg.target.context != nil { m.Add("append", "ctx", msg.target.context.Name) @@ -2079,14 +2110,16 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, m.Add("append", "status", msg.Cap("status")) m.Add("append", "stream", msg.Cap("stream")) m.Add("append", "help", msg.target.Help) - return false - }) + } + case "spawn": msg.target.Spawn(msg, arg[0], arg[1]).Begin(msg, arg[2:]...) m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") + case "start": msg.target.Start(msg, arg...) m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") + case "close": msg := m.Spawn() m.target = msg.target.context diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index be382597..356827fc 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -154,7 +154,319 @@ func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) { f, e := os.OpenFile(name, flag, 0660) return name, f, e } +func Format(args ...interface{}) string { + result := []string{} + for _, arg := range args { + switch arg := arg.(type) { + case rune: + result = append(result, string(arg)) + case termbox.Key: + switch arg { + } + } + } + return strings.Join(result, "") +} + +func (nfs *NFS) Read(p []byte) (n int, err error) { + m := nfs.Context.Message() + if !m.Caps("termbox") { + return nfs.in.Read(p) + } + + scroll_count := 0 + which := m.Capi("ninput") + what := make([]rune, 0, 1024) + rest := make([]rune, 0, 1024) + back := make([]rune, 0, 1024) + + m.Optionv("auto_target", m.Optionv("ps_target")) + m.Option("auto_cmd", "") + defer func() { m.Option("auto_cmd", "") }() + + frame, table, index, pick := map[string]interface{}{}, []map[string]string{}, 0, 0 + if change, f, t, i := nfs.Auto(what, ":", 0); change { + frame, table, index, pick = f, t, i, 0 + } + + m.TryCatch(m, true, func(m *ctx.Message) { + for { + switch ev := termbox.PollEvent(); ev.Type { + case termbox.EventInterrupt: + case termbox.EventResize: + nfs.Term(m, "resize") + case termbox.EventMouse: + switch ev.Key { + case termbox.MouseLeft: + nfs.Term(m, "window", ev.MouseX, ev.MouseY) + nfs.prompt(what).shadow(rest) + case termbox.MouseMiddle: + case termbox.MouseRight: + nfs.Term(m, "resize", ev.MouseX, ev.MouseY) + case termbox.MouseRelease: + case termbox.MouseWheelUp: + if scroll_count++; scroll_count > m.Confi("term", "scroll_count") { + nfs.Term(m, "scroll", -1).Term(m, "flush") + scroll_count = 0 + } + case termbox.MouseWheelDown: + if scroll_count++; scroll_count > m.Confi("term", "scroll_count") { + nfs.Term(m, "scroll", 1).Term(m, "flush") + scroll_count = 0 + } + } + case termbox.EventError: + case termbox.EventNone: + case termbox.EventRaw: + case termbox.EventKey: + + switch ev.Key { + case termbox.KeyCtrlP: + if which--; which < 0 { + which = m.Capi("ninput") - 1 + } + if v := m.Conf("input", []interface{}{which, "line"}); v != "" { + what, rest := what[:0], rest[:0] + what = append(what, []rune(v)...) + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlN: + if which++; which >= m.Capi("ninput") { + which = 0 + } + if v := m.Conf("input", []interface{}{which, "line"}); v != "" { + what, rest := what[:0], rest[:0] + what = append(what, []rune(v)...) + nfs.prompt(what).shadow(rest) + } + + case termbox.KeyCtrlA: + if len(what) > 0 { + what, rest = append(what, rest...), rest[:0] + rest, what = append(rest, what...), what[:0] + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlF: + if len(rest) > 0 { + pos := len(what) + 1 + what, rest = append(what, rest...), rest[:0] + rest, what = append(rest, what[pos:]...), what[:pos] + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlB: + if len(what) > 0 { + pos := len(what) - 1 + what, rest = append(what, rest...), rest[:0] + rest, what = append(rest, what[pos:]...), what[:pos] + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlE: + if len(rest) > 0 { + what, rest = append(what, rest...), rest[:0] + nfs.prompt(what).shadow(rest) + } + + case termbox.KeyCtrlU: + back = back[:0] + back, what = append(back, what...), what[:0] + nfs.prompt(what).shadow(rest) + case termbox.KeyCtrlD: // termbox.KeyBackspace + if len(rest) > 0 { + pos := len(what) + what, rest = append(what, rest[1:]...), rest[:0] + rest, what = append(rest, what[pos:]...), what[:pos] + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlH: // termbox.KeyBackspace + if len(what) > 0 { + what = what[:len(what)-1] + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlK: + back = back[:0] + back, rest = append(back, rest...), rest[:0] + nfs.prompt(what).shadow(rest) + + case termbox.KeyCtrlW: + if len(what) > 0 { + pos := len(what) - 1 + for space := what[pos] == ' '; pos >= 0; pos-- { + if (space && what[pos] != ' ') || (!space && what[pos] == ' ') { + break + } + } + back = back[:0] + back, what = append(back, what[pos+1:]...), what[:pos+1] + nfs.prompt(what).shadow(rest) + } + case termbox.KeyCtrlY: + what = append(what, back...) + nfs.prompt(what).shadow(rest) + + case termbox.KeyCtrlR: + nfs.Term(m, "refresh").Term(m, "flush") + nfs.prompt(what).shadow(rest) + case termbox.KeyCtrlL: + nfs.Term(m, "clear", "all").Term(m, "flush") + nfs.prompt(what).shadow(rest) + + case termbox.KeyCtrlO: + m.Option("scroll", true) + nfs.Term(m, "scroll", 1).Term(m, "flush") + m.Option("scroll", false) + case termbox.KeyCtrlT: + m.Option("scroll", true) + nfs.Term(m, "scroll", -1).Term(m, "flush") + m.Option("scroll", false) + + case termbox.KeyCtrlJ, termbox.KeyEnter: + what = append(what, '\n') + n = copy(p, []byte(string(what))) + return + case termbox.KeyCtrlQ, termbox.KeyCtrlC: + nfs.Term(m, "exit") + n = copy(p, []byte("return\n")) + return + + case termbox.KeyCtrlV: + + for i := -1; i < 8; i++ { + nfs.Term(m, "color", i, m.Confi("term", "rest_fg"), fmt.Sprintf("\nhello bg %d", i)) + } + + for i := -1; i < 8; i++ { + nfs.Term(m, "color", m.Confi("term", "rest_bg"), i, fmt.Sprintf("\nhello fg %d", i)) + } + nfs.Term(m, "flush") + + case termbox.KeyCtrlG: + case termbox.KeyCtrlX: + case termbox.KeyCtrlS: + + case termbox.KeyCtrlZ: + + case termbox.KeyTab: + if index > len(what) { + nfs.shadow("", table, frame) + } else { + if lines := kit.Int(frame["lines"]); lines > 0 { + pick = (pick + 1) % lines + } + nfs.shadow(what[index:], table, frame, pick) + rest = append(rest[:0], []rune(kit.Format(frame["pick"]))[len(what)-index:]...) + nfs.prompt(what).shadow(rest) + nfs.shadow(what[index:], table, frame, pick) + } + + case termbox.KeySpace: + what = append(what, ' ') + nfs.prompt(what).shadow(rest) + + if index > len(what) { + nfs.shadow("", table, frame) + } else { + m.Option("auto_key", strings.TrimSpace(string(what[index:]))) + if change, f, t, i := nfs.Auto(what, " ", len(what)); change { + frame, table, index, pick = f, t, i, 0 + } + + nfs.shadow(what[index:], table, frame) + } + + default: + what = append(what, ev.Ch) + nfs.prompt(what).shadow(rest) + + if change, f, t, i := nfs.Auto(what, Format(ev.Ch), len(what)); change { + frame, table, index, pick = f, t, i, 0 + } + + if index > len(what) { + nfs.shadow("", table, frame) + } else { + nfs.shadow(what[index:], table, frame, pick) + if pos, word := len(what)-index, kit.Format(frame["pick"]); len(table) > 0 && pos < len(word) { + rest = append(rest[:0], []rune(word)[pos:]...) + } else { + } + nfs.prompt(what).shadow(rest) + nfs.shadow(what[index:], table, frame, pick) + } + } + } + } + }) + return +} +func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame map[string]interface{}, table []map[string]string, nindex int) { + m := nfs.Context.Message() + + auto_target := m.Optionv("auto_target").(*ctx.Context) + auto_cmd := "" + auto_arg := []string{} + + switch trigger { + case " ": + switch m.Conf("term", "help_state") { + case "context": + auto_target = auto_target.Sub(m.Option("auto_key")) + m.Optionv("auto_target", auto_target) + trigger = ":" + case "command": + m.Option("arg_index", index+1) + auto_cmd = m.Option("auto_cmd", m.Option("auto_key")) + trigger = "=" + case "argument": + auto_cmd = m.Option("auto_cmd") + auto_arg = strings.Split(strings.TrimSpace(string(what[m.Optioni("arg_index"):])), " ") + trigger = "=" + } + } + + auto := m.Confm("auto", trigger) + if auto == nil { + return false, nil, nil, 0 + } + + cmd := []interface{}{kit.Select(kit.Format(auto["cmd"]), auto_cmd)} + if len(auto_arg) == 0 { + auto_arg = kit.Trans(auto["arg"]) + } + for _, v := range auto_arg { + cmd = append(cmd, m.Parse(v)) + } + + table = []map[string]string{} + m.Spawn(auto_target).Cmd(cmd...).Table(func(maps map[string]string, list []string, line int) bool { + if line >= 0 { + fields := []interface{}{} + for _, v := range auto["fields"].([]interface{}) { + fields = append(fields, maps[kit.Format(v)]) + } + maps["format"] = fmt.Sprintf(kit.Format(auto["format"]), fields...) + table = append(table, maps) + } + return true + }) + m.Conf("term", []interface{}{"help_table", auto["table"]}, table) + + frame = map[string]interface{}{ + "color": auto["color"], + "table": auto["table"], + "field": auto["field"], + } + + if m.Conf("term", []interface{}{"help_index"}, index); index == 0 { + m.Conf("term", "help_stack", []interface{}{frame}) + } else { + m.Conf("term", []interface{}{"help_stack", -2}, frame) + } + + m.Conf("term", "help_next_auto", auto["next_auto"]) + m.Conf("term", "help_state", auto["state"]) + return true, frame, table, index +} func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS { m := nfs.Context.Message() m.Log("debug", "%s %v", action, args) @@ -337,8 +649,8 @@ func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS } } case "color": - msg.Conf("term", "bgcolor", kit.Int(args[0])) - msg.Conf("term", "fgcolor", kit.Int(args[1])) + msg.Conf("term", "bgcolor", kit.Int(args[0])+1) + msg.Conf("term", "fgcolor", kit.Int(args[1])+1) nfs.Term(m, "print", args[2:]...) msg.Conf("term", "fgcolor", fg) msg.Conf("term", "bgcolor", bg) @@ -350,240 +662,6 @@ func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS } return nfs } -func (nfs *NFS) Read(p []byte) (n int, err error) { - m := nfs.Context.Message() - if !m.Caps("termbox") { - return nfs.in.Read(p) - } - - what := make([]rune, 0, 1024) - which := m.Capi("ninput") - scroll_count := 0 - - help := []map[string]interface{}{} - index := 0 - color := 0 - - for { - switch ev := termbox.PollEvent(); ev.Type { - case termbox.EventInterrupt: - case termbox.EventResize: - nfs.Term(m, "resize") - case termbox.EventMouse: - switch ev.Key { - case termbox.MouseLeft: - nfs.Term(m, "window", ev.MouseX, ev.MouseY) - nfs.prompt() - case termbox.MouseMiddle: - case termbox.MouseRight: - nfs.Term(m, "resize", ev.MouseX, ev.MouseY) - case termbox.MouseRelease: - case termbox.MouseWheelUp: - if scroll_count++; scroll_count > m.Confi("term", "scroll_count") { - nfs.Term(m, "scroll", -1).Term(m, "flush") - scroll_count = 0 - } - case termbox.MouseWheelDown: - if scroll_count++; scroll_count > m.Confi("term", "scroll_count") { - nfs.Term(m, "scroll", 1).Term(m, "flush") - scroll_count = 0 - } - } - case termbox.EventError: - case termbox.EventNone: - case termbox.EventRaw: - case termbox.EventKey: - switch ev.Key { - case termbox.KeyCtrlP: - if which--; which < 0 { - which = m.Capi("ninput") - 1 - } - if v := m.Conf("input", []interface{}{which, "line"}); v != "" { - what = []rune(v) - m.Log("debug", "what %v %v", which, what) - nfs.prompt(what) - } - case termbox.KeyCtrlN: - if which++; which >= m.Capi("ninput") { - which = 0 - } - if v := m.Conf("input", []interface{}{which, "line"}); v != "" { - what = []rune(v) - m.Log("debug", "what %v %v", which, what) - nfs.prompt(what) - } - - case termbox.KeyCtrlH: // termbox.KeyBackspace - if len(what) > 0 { - what = what[:len(what)-1] - } else { - } - if len(what) < index { - index = 0 - } - - nfs.prompt(what) - nfs.shadow(what[index:], help, color) - - case termbox.KeyCtrlU: - what = what[:0] - nfs.prompt(what) - - color = 3 - index := 0 - help = help[:0] - ps_target := m.Optionv("ps_target").(*ctx.Context) - for k, v := range ps_target.Commands { - help = append(help, map[string]interface{}{ - "key": k, - "value": "", - "name": v.Name, - "help": v.Help, - }) - } - nfs.shadow(what[index:], help, color) - - case termbox.KeyCtrlL: - nfs.Term(m, "clear", "all").Term(m, "flush") - nfs.prompt(what) - if len(what) < index { - index = 0 - } - nfs.shadow(what[index:], help, color) - - case termbox.KeyCtrlJ, termbox.KeyEnter: - what = append(what, '\n') - n = copy(p, []byte(string(what))) - return - - case termbox.KeyCtrlC: - nfs.Term(m, "exit") - n = copy(p, []byte("return\n")) - return - - case termbox.KeyCtrlE: - m.Option("scroll", true) - nfs.Term(m, "scroll", 1).Term(m, "flush") - m.Option("scroll", false) - case termbox.KeyCtrlY: - m.Option("scroll", true) - nfs.Term(m, "scroll", -1).Term(m, "flush") - m.Option("scroll", false) - - case termbox.KeyTab: - what = append(what, '\t') - nfs.prompt(what) - case termbox.KeySpace: - what = append(what, ' ') - nfs.prompt(what) - nfs.shadow(what[:index], help) - - default: - switch ev.Ch { - case '~': - what = append(what, '~') - index = len(what) - color = 2 - nfs.prompt(what) - - help = help[:0] - ps_target := m.Optionv("ps_target").(*ctx.Context) - if ps_target.Context() != nil { - help = append(help, map[string]interface{}{ - "key": ps_target.Context().Name, - "value": ps_target.Context().Name, - "name": ps_target.Context().Help, - "help": ps_target.Context().Help, - }) - } - ps_target.Travel(m, func(m *ctx.Message, n int) bool { - help = append(help, map[string]interface{}{ - "key": m.Target().Name, - "value": m.Target().Name, - "name": m.Target().Help, - "help": m.Target().Help, - }) - return false - }) - nfs.shadow(what[index:], help, color) - - case '@': - what = append(what, '@') - index = len(what) - color = 4 - nfs.prompt(what) - - help = help[:0] - ps_target := m.Optionv("ps_target").(*ctx.Context) - for k, v := range ps_target.Configs { - help = append(help, map[string]interface{}{ - "key": k, - "value": v.Value, - "name": v.Name, - "help": v.Help, - }) - } - - nfs.shadow(what[index:], help, color) - - case '$': - what = append(what, '$') - index = len(what) - color = 7 - nfs.prompt(what) - - help = help[:0] - ps_target := m.Optionv("ps_target").(*ctx.Context) - for k, v := range ps_target.Caches { - help = append(help, map[string]interface{}{ - "key": k, - "value": v.Value, - "name": v.Name, - "help": v.Help, - }) - } - nfs.shadow(what[index:], help, color) - - default: - what = append(what, ev.Ch) - nfs.prompt(what) - - if len(help) == 0 { - index = 0 - color = 3 - ps_target := m.Optionv("ps_target").(*ctx.Context) - for k, v := range ps_target.Commands { - help = append(help, map[string]interface{}{ - "key": k, - "value": "", - "name": v.Name, - "help": v.Help, - }) - } - } - - nfs.shadow(what[index:], help, color) - } - } - } - } -} -func (nfs *NFS) printf(arg ...interface{}) *NFS { - m := nfs.Context.Message() - - line := strings.TrimRight(kit.Format(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}) - - if m.Caps("termbox") { - nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush") - m.Conf("term", "prompt_y", m.Confi("term", "cursor_y")+1) - m.Conf("term", "cursor_y", m.Confi("term", "cursor_y")+1) - } else { - nfs.out.WriteString(line) - } - return nfs -} func (nfs *NFS) prompt(arg ...interface{}) *NFS { m := nfs.Context.Message() target, _ := m.Optionv("ps_target").(*ctx.Context) @@ -604,59 +682,65 @@ func (nfs *NFS) prompt(arg ...interface{}) *NFS { return nfs } func (nfs *NFS) shadow(args ...interface{}) *NFS { - m := nfs.Context.Message() - - x := m.Confi("term", "cursor_x") - y := m.Confi("term", "cursor_y") - - defer func() { nfs.Term(m, "cursor", x, y).Term(m, "flush") }() - if len(args) == 0 { return nfs } + m := nfs.Context.Message() + x := m.Confi("term", "cursor_x") + y := m.Confi("term", "cursor_y") + defer func() { nfs.Term(m, "cursor", x, y).Term(m, "flush") }() + switch arg := args[0].(type) { case []rune: - cmd := strings.Split(string(arg), " ") + if len(args) == 1 { + nfs.Term(m, "color", m.Confi("term", "rest_bg"), m.Confi("term", "rest_fg"), string(arg)) + } else { + cmd := strings.Split(string(arg), " ") + switch table := args[1].(type) { + case []map[string]string: + frame := args[2].(map[string]interface{}) + field := kit.Format(frame["field"]) + fg := kit.Int(frame["color"]) + pick := kit.Int(kit.Select("0", args, 3)) - help := []string{} - fg := 2 - if len(args) > 2 { - fg = kit.Int(args[2]) - } - - if len(args) > 1 { - switch list := args[1].(type) { - case []map[string]interface{}: - for _, v := range list { - if strings.Contains(v["key"].(string), cmd[0]) { - help = append(help, fmt.Sprintf("%s(%s): %s", v["key"], v["value"], v["name"])) + i := 0 + for _, line := range table { + if strings.Contains(kit.Format(line[field]), cmd[0]) { + if i == pick { + frame["pick"] = line[field] + nfs.Term(m, "color", m.Confi("term", "pick_bg"), m.Confi("term", "pick_fg"), "\n", kit.Format(line["format"])) + } else { + nfs.Term(m, "color", 0, fg, "\n", kit.Format(line["format"])) + } + i++ } } + frame["lines"] = i } } - nfs.Term(m, "color", 1, fg, "\n", strings.Join(help, "\n")) } return nfs } - -func (nfs *NFS) Send(meta string, arg ...interface{}) *NFS { +func (nfs *NFS) printf(arg ...interface{}) *NFS { m := nfs.Context.Message() - line := "\n" - if meta != "" { - line = fmt.Sprintf("%s: %s\n", url.QueryEscape(meta), url.QueryEscape(kit.Format(arg[0]))) + line := strings.TrimRight(kit.Format(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}) + + if m.Caps("termbox") { + nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush") + m.Conf("term", "prompt_y", m.Confi("term", "cursor_y")+1) + m.Conf("term", "cursor_y", m.Confi("term", "cursor_y")+1) + } else { + nfs.out.WriteString(line) } - - n, e := fmt.Fprint(nfs.io, line) - m.Assert(e) - m.Capi("nwrite", n) - m.Log("send", "%d [%s]", len(line), line) - return nfs } + func (nfs *NFS) Recv(line string) (field string, value string) { m := nfs.Context.Message() @@ -677,6 +761,21 @@ func (nfs *NFS) Recv(line string) (field string, value string) { m.Assert(e) return } +func (nfs *NFS) Send(meta string, arg ...interface{}) *NFS { + m := nfs.Context.Message() + + line := "\n" + if meta != "" { + line = fmt.Sprintf("%s: %s\n", url.QueryEscape(meta), url.QueryEscape(kit.Format(arg[0]))) + } + + n, e := fmt.Fprint(nfs.io, line) + m.Assert(e) + m.Capi("nwrite", n) + m.Log("send", "%d [%s]", len(line), line) + + return nfs +} func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") { @@ -877,15 +976,70 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "width": 80, "height": "24", "left": 0, "top": 0, "right": 80, "bottom": 24, - "cursor_x": 0, "cursor_y": 0, "fgcolor": 0, "bgcolor": 0, + "cursor_x": 0, "cursor_y": 0, "fgcolor": -1, "bgcolor": -1, "prompt": "", "wrap": "false", "scroll_count": "5", "begin_row": 0, "begin_col": 0, "shadow": "hello", - "help": "nice", - "list": "to", + + "rest_fg": "0", + "rest_bg": "7", + "pick_fg": "0", + "pick_bg": "7", + "pick": "", + + "help_index": 0, + "help_state": "command", + "help_next_auto": "=", + "help_stack": []interface{}{}, + "help_table": map[string]interface{}{}, }, Help: "二维码的默认大小"}, + "auto": &ctx.Config{Name: "auto", Value: map[string]interface{}{ + "!": map[string]interface{}{ + "state": "message", + "next_auto": ":", + "color": 2, "cmd": "message", + "table": "message", "field": "code", + "format": "%s(%s) %s->%s %s %s", "fields": []interface{}{"code", "time", "source", "target", "details", "options"}, + }, + "~": map[string]interface{}{ + "state": "context", "next_auto": ":", + "color": 2, "cmd": "context", + "table": "context", "field": "name", + "format": "%s(%s) %s %s", "fields": []interface{}{"name", "status", "stream", "help"}, + }, + "": map[string]interface{}{ + "state": "command", "next_auto": "=", + "color": 3, "cmd": "command", + "table": "command", "field": "key", + "format": "%s %s", "fields": []interface{}{"key", "name"}, + }, + ":": map[string]interface{}{ + "state": "command", "next_auto": "=", + "color": 3, "cmd": "command", + "table": "command", "field": "key", + "format": "%s %s", "fields": []interface{}{"key", "name"}, + }, + "=": map[string]interface{}{ + "cmd": "help", + "format": "%s %s %s ", "fields": []interface{}{"value", "name", "help"}, + "color": 3, "table": "command", "field": "value", + "state": "argument", "next_auto": "=", + }, + "@": map[string]interface{}{ + "state": "config", "next_auto": "@", + "color": 4, "cmd": "config", + "table": "config", "field": "key", + "format": "%s(%s) %s", "fields": []interface{}{"key", "value", "name"}, + }, + "$": map[string]interface{}{ + "state": "cache", "next_auto": "$", + "color": 7, "cmd": "cache", + "table": "cache", "field": "key", + "format": "%s(%s) %s", "fields": []interface{}{"key", "value", "name"}, + }, + }, Help: "读取文件的缓存区的大小"}, "buf_size": &ctx.Config{Name: "buf_size", Value: "1024", Help: "读取文件的缓存区的大小"}, "dir_type": &ctx.Config{Name: "dir_type(file/dir/all)", Value: "all", Help: "dir命令输出的文件类型, file: 只输出普通文件, dir: 只输出目录文件, 否则输出所有文件"}, @@ -1031,17 +1185,29 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", return }}, - "path": &ctx.Command{Name: "path file", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - m.Confm("paths", func(index int, value string) bool { - p := path.Join(value, arg[0]) - if _, e := os.Stat(p); e == nil { - m.Echo(p) - return true + "path": &ctx.Command{Name: "path filename", Help: "查找文件路径", + Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (ok bool) { + if len(arg) == 0 { + m.Add("append", "value", "") + m.Add("append", "name", "filename") + m.Add("append", "help", "文件名") + return false } - return false - }) - return - }}, + m.Add("append", "value", "") + m.Add("append", "name", "no more arg") + return true + }, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Confm("paths", func(index int, value string) bool { + p := path.Join(value, arg[0]) + if _, e := os.Stat(p); e == nil { + m.Echo(p) + return true + } + return false + }) + return + }}, "load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if p, f, e := open(m, arg[0]); m.Assert(e) { defer f.Close() diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index 18b9bb46..a63aa00e 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -133,12 +133,13 @@ func Formats(arg ...interface{}) string { result := []string{} for _, v := range arg { switch val := v.(type) { - case []interface{}: - for _, v := range val { - result = append(result, Format(v)) - } + // case []interface{}: + // for _, v := range val { + // result = append(result, Format(v)) + // } default: - if b, e := json.MarshalIndent(val, "", " "); e == nil { + if b, e := json.MarshalIndent(val, " ", " "); e == nil { + Log("fuck", "what %v", b) result = append(result, string(b)) } } @@ -155,6 +156,7 @@ func Trans(arg ...interface{}) []string { // } else { // ls = append(ls, val.Meta["detail"]...) // } + case nil: case []float64: for _, v := range val { ls = append(ls, fmt.Sprintf("%d", int(v))) @@ -294,6 +296,14 @@ func Select(value string, args ...interface{}) string { if arg != "" { return arg } + case []interface{}: + index := 0 + if len(args) > 1 { + index = Int(args[1]) + } + if index < len(arg) && Format(arg[index]) != "" { + return Format(arg[index]) + } case []string: index := 0 if len(args) > 1 {