From 002b42b68ee7f6e692ba927897764b81477fa5e8 Mon Sep 17 00:00:00 2001 From: shaoying Date: Tue, 23 Jul 2019 21:49:04 +0800 Subject: [PATCH] opt nfs --- src/contexts/cli/cli.go | 26 +- src/contexts/cli/version.go | 2 +- src/contexts/ctx/misc.go | 2 +- src/contexts/nfs/nfs.go | 1061 +++++------------------------------ src/contexts/nfs/term.go | 640 +++++++++++++++++++++ src/contexts/ssh/ssh.go | 2 +- src/toolkit/core.go | 15 + usr/librarys/example.css | 4 +- 8 files changed, 826 insertions(+), 926 deletions(-) create mode 100644 src/contexts/nfs/term.go diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 7face312..c5d3967f 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -29,7 +29,7 @@ type CLI struct { func (cli *CLI) schedule(m *ctx.Message) string { first, timer := "", int64(1<<50) - for k, v := range m.Confv("timer").(map[string]interface{}) { + for k, v := range m.Confv("timer", "list").(map[string]interface{}) { val := v.(map[string]interface{}) if val["action_time"].(int64) < timer && !val["done"].(bool) { first, timer = k, val["action_time"].(int64) @@ -331,6 +331,9 @@ func main() { for i := 0; i < len(m.Meta["cmd_env"])-1; i += 2 { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", m.Meta["cmd_env"][i], m.Parse(m.Meta["cmd_env"][i+1]))) } + for _, k := range []string{"PATH", "HOME"} { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, os.Getenv(k))) + } if len(cmd.Env) > 0 { m.Log("info", "env %v", cmd.Env) } @@ -617,10 +620,10 @@ func main() { break } - if timer := m.Confm("timer", "list", m.Conf("timer", "next")); timer != nil && !kit.Right(timer["stop"]) { + if timer := m.Confm("timer", []string{"list", m.Conf("timer", "next")}); timer != nil && !kit.Right(timer["stop"]) { m.Log("info", "timer %s %v", m.Conf("timer", "next"), timer["cmd"]) - msg := m.Sess("cli").Cmd("source", timer["cmd"]) + msg := m.Cmd("nfs.source", timer["cmd"]) timer["result"] = msg.Meta["result"] timer["msg"] = msg.Code() @@ -834,16 +837,23 @@ func main() { m.Cmdy("nfs.dir", m.Conf("publish", "path"), "dir_reg", "bench") case "self": - env := []string{} + env := []string{ + "cmd_env", "GOTMPDIR", path.Join(wd, m.Conf("compile", "tmp")), + "cmd_env", "GOCACHE", path.Join(wd, m.Conf("compile", "tmp")), + } m.Confm("compile", "env", func(index int, key string) { env = append(env, "cmd_env", key, kit.Select(os.Getenv(key), m.Option(key))) }) m.Cmd("cli.version", "create") - if m.Cmdy("cli.system", env, "go", "install", path.Join(m.Conf("runtime", "boot.ctx_home"), m.Conf("compile", "bench"))); m.Result(0) == "" { + os.MkdirAll(m.Conf("compile", "tmp"), 0777) + + p, q := path.Join(m.Conf("runtime", "boot.ctx_home"), m.Conf("compile", "bench")), path.Join(kit.Select(os.Getenv("GOBIN"), ""), "bench") + if m.Cmdy("cli.system", env, "go", "build", "-o", q, p); m.Result(0) == "" { m.Cmdy("cli.quit", 1) - m.Append("host", version.host) - m.Append("self", version.self) + m.Append("time", m.Time()) + m.Append("hash", kit.Hashs(q)[:8]) + m.Append("bin", q) m.Table() } @@ -1008,7 +1018,7 @@ func main() { m.Add("append", "time", m.Time()) m.Add("append", "file", file) - m.Add("append", "hash", kit.Hashs(file)) + m.Add("append", "hash", kit.Hashs(file)[:8]) if strings.HasSuffix(link, ".tar.gz") { m.Cmd("cli.system", "tar", "-xvf", file, "-C", path.Dir(file)) diff --git a/src/contexts/cli/version.go b/src/contexts/cli/version.go index 8f90a4e6..98732704 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-23 08:08:38", "com.mac_1", 209, + "2019-07-23 21:26:44", "ZYB-20190522USI", 232, } diff --git a/src/contexts/ctx/misc.go b/src/contexts/ctx/misc.go index 3c318394..3c7302c3 100644 --- a/src/contexts/ctx/misc.go +++ b/src/contexts/ctx/misc.go @@ -192,7 +192,7 @@ func (m *Message) Format(arg ...interface{}) string { } case "stack": pc := make([]uintptr, 100) - pc = pc[:runtime.Callers(6, pc)] + pc = pc[:runtime.Callers(0, pc)] frames := runtime.CallersFrames(pc) for { diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 6d235851..b88c51f1 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -3,7 +3,6 @@ package nfs import ( "contexts/ctx" "crypto/md5" - "math/rand" "toolkit" "crypto/sha1" @@ -149,8 +148,8 @@ func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, tri } func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) { if !path.IsAbs(name) { - paths := m.Confv("paths").([]interface{}) - for _, v := range paths { + pwd := m.Confv("pwd").([]interface{}) + for _, v := range pwd { p := path.Join(v.(string), name) if len(arg) > 0 { name = p @@ -177,634 +176,6 @@ func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) { return name, f, e } -func (nfs *NFS) Read(p []byte) (n int, err error) { - m := nfs.Context.Message() - if !m.Caps("termbox") { - return nfs.in.Read(p) - } - - m.TryCatch(m, true, func(m *ctx.Message) { - scroll_count := 0 - scroll_lines := m.Confi("term", "scroll_lines") - which := m.Capi("ninput") - what := make([]rune, 0, 1024) - rest := make([]rune, 0, 1024) - back := make([]rune, 0, 1024) - - m.Option("bio.cmd", "") - m.Options("bio.shadow", m.Confs("show_shadow")) - - 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 { - frame, table, index, pick = f, t, i, 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: - if m.Confs("term", "mouse.resize") { - nfs.Term(m, "window", ev.MouseX, ev.MouseY) - nfs.prompt(what).shadow(rest) - } - - case termbox.MouseMiddle: - case termbox.MouseRight: - if m.Confs("term", "mouse.resize") { - 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 = append(what[:0], []rune(v)...), rest[:0] - 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 = append(what[:0], []rune(v)...), rest[:0] - 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: - m.Confi("term", "begin_row", m.Capi("noutput")) - m.Confi("term", "begin_col", 0) - nfs.Term(m, "clear", "all").Term(m, "flush") - nfs.prompt(what).shadow(rest) - - case termbox.KeyCtrlT: - m.Option("scroll", true) - nfs.Term(m, "scroll", scroll_lines).Term(m, "flush") - m.Option("scroll", false) - case termbox.KeyCtrlO: - m.Option("scroll", true) - nfs.Term(m, "scroll", -scroll_lines).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: - m.Options("bio.shadow", !m.Options("bio.shadow")) - case termbox.KeyCtrlS: - - case termbox.KeyCtrlZ: - - case termbox.KeyTab: - m.Options("bio.shadow", true) - // 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 !m.Options("bio.shadow") { - break - } - - 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 - } - - if nfs.shadow(what[index:], table, frame); len(table) > 0 { - rest = append(rest[:0], []rune(table[0][kit.Format(frame["field"])])...) - nfs.prompt(what).shadow(rest) - nfs.shadow(what[index:], table, frame) - } - } - - default: - what = append(what, ev.Ch) - nfs.prompt(what).shadow(rest) - if !m.Options("bio.shadow") { - break - } - - if change, f, t, i := nfs.Auto(what, kit.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) { - return - m := nfs.Context.Message() - - auto_target := m.Optionv("bio.ctx").(*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("bio.ctx", auto_target) - trigger = ":" - case "command": - m.Option("arg_index", index) - auto_cmd = m.Option("bio.cmd", m.Option("auto_key")) - trigger = "=" - case "argument": - auto_cmd = m.Option("bio.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(line int, maps map[string]string) { - 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) - }) - 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) - - switch action { - case "init": - defer func() { - if e := recover(); e != nil { - m.Log("warn", "term init %s", e) - } - }() - termbox.Init() - termbox.SetInputMode(termbox.InputEsc) - termbox.SetInputMode(termbox.InputMouse) - m.Cap("termbox", "true") - } - - width, height := termbox.Size() - msg.Conf("term", "width", width) - msg.Conf("term", "height", height) - - left := msg.Confi("term", "left") - top := msg.Confi("term", "top") - right := msg.Confi("term", "right") - bottom := msg.Confi("term", "bottom") - - x := m.Confi("term", "cursor_x") - y := m.Confi("term", "cursor_y") - bg := termbox.Attribute(msg.Confi("term", "bgcolor")) - fg := termbox.Attribute(msg.Confi("term", "fgcolor")) - - begin_row := m.Confi("term", "begin_row") - begin_col := m.Confi("term", "begin_col") - - switch action { - case "init": - m.Conf("term", "left", 0) - m.Conf("term", "top", 0) - m.Conf("term", "right", width) - m.Conf("term", "bottom", height) - - case "exit": - m.Cap("termbox", "false") - termbox.Close() - - case "window": - if len(args) > 1 { - msg.Conf("term", "left", args[0]) - msg.Conf("term", "top", args[1]) - } - if len(args) > 3 { - msg.Conf("term", "right", args[2]) - msg.Conf("term", "bottom", args[3]) - } else { - msg.Conf("term", "right", width) - msg.Conf("term", "bottom", height) - } - - case "resize": - if len(args) > 1 { - msg.Conf("term", "right", args[0]) - msg.Conf("term", "bottom", args[1]) - right = msg.Confi("term", "right") - bottom = msg.Confi("term", "bottom") - } else { - msg.Conf("term", "right", right) - msg.Conf("term", "bottom", bottom) - } - - fallthrough - case "clear": - if len(args) == 0 { - top = m.Confi("term", "prompt_y") - } else if kit.Format(args[0]) == "all" { - // nothing - } - - for x := left; x < right; x++ { - for y := top; y < bottom; y++ { - termbox.SetCell(x, y, ' ', fg, bg) - } - } - m.Conf("term", "cursor_x", left) - m.Conf("term", "cursor_y", top) - termbox.SetCursor(left, top) - - case "cursor": - m.Conf("term", "cursor_x", kit.Format(args[0])) - m.Conf("term", "cursor_y", kit.Format(args[1])) - termbox.SetCursor(m.Confi("term", "cursor_x"), m.Confi("term", "cursor_y")) - - case "flush": - termbox.Flush() - - case "scroll": - n := 1 - if len(args) > 0 { - n = kit.Int(args[0]) - } - m.Options("on_scroll", true) - - // 向下滚动 - for i := begin_row; n > 0 && i < m.Capi("noutput"); i++ { - line := []rune(m.Conf("output", []interface{}{i, "line"})) - - for j, l := begin_col, left; n > 0; j, l = j+1, l+1 { - if j >= len(line)-1 { - begin_row, begin_col = i+1, 0 - n-- - break - } else if line[j] == '\n' { - begin_row, begin_col = i, j+1 - n-- - } else if l >= right-1 && m.Confs("term", "wrap") { - begin_row, begin_col = i, j - n-- - } - } - } - - // 向上滚动 - for i := begin_row; n < 0 && i >= 0; i-- { - line := []rune(m.Conf("output", []interface{}{i, "line"})) - if begin_col == 0 { - i-- - line = []rune(m.Conf("output", []interface{}{i, "line"})) - begin_col = len(line) - } - - for j, l := begin_col-1, right-1; n < 0; j, l = j-1, l-1 { - if j <= 0 { - begin_row, begin_col = i, 0 - n++ - break - } else if line[j-1] == '\n' { - begin_row, begin_col = i, j - n++ - } else if l < left && m.Confs("term", "wrap") { - begin_row, begin_col = i, j - n++ - } - } - } - - m.Conf("term", "begin_row", begin_row) - m.Conf("term", "begin_col", begin_col) - - fallthrough - case "refresh": - - nfs.Term(m, "clear", "all") - for i := begin_row; i < m.Capi("noutput"); i++ { - if line := m.Conf("output", []interface{}{i, "line"}); begin_col < len(line) { - nfs.Term(m, "print", line[begin_col:]) - } - begin_col = 0 - } - // nfs.Term(m, "print", "\n") - // nfs.Term(m, "print", m.Conf("prompt")) - m.Options("on_scroll", false) - - case "print": - list := kit.Format(args...) - n := strings.Count(list, "\n") + y - bottom - - for _, v := range list { - if x < right { - if termbox.SetCell(x, y, v, fg, bg); v > 255 { - x++ - } - } - - if x++; v == '\n' || (x >= right && m.Confs("term", "wrap")) { - x, y = left, y+1 - if y >= bottom { - if m.Options("on_scroll") { - break - } - if n%bottom > 0 { - - nfs.Term(m, "scroll", n%bottom+1) - n -= n % bottom - x = m.Confi("term", "cursor_x") - y = m.Confi("term", "cursor_y") - - } else if n > 0 { - - nfs.Term(m, "scroll", bottom) - n -= bottom - x = m.Confi("term", "cursor_x") - y = m.Confi("term", "cursor_y") - - } - } - } - - if x < right { - m.Conf("term", "cursor_x", x) - m.Conf("term", "cursor_y", y) - termbox.SetCursor(x, y) - } - } - - if m.Options("on_scroll") { - x = 0 - y = y + 1 - m.Conf("term", "cursor_x", x) - m.Conf("term", "cursor_y", y) - termbox.SetCursor(x, y) - } - - case "color": - 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) - - case "shadow": - x := m.Confi("term", "cursor_x") - y := m.Confi("term", "cursor_y") - nfs.Term(m, "color", args...) - nfs.Term(m, "cursor", x, y).Term(m, "flush") - } - return nfs -} -func (nfs *NFS) prompt(arg ...interface{}) *NFS { - m := nfs.Context.Message() - target, _ := m.Optionv("bio.ctx").(*ctx.Context) - if target == nil { - target = nfs.Context - } - - line := fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name) - m.Conf("prompt", line) - - line += kit.Format(arg...) - if m.Caps("termbox") { - m.Conf("term", "prompt_y", m.Conf("term", "cursor_y")) - nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush") - } else if nfs.out != nil { - nfs.out.WriteString(line) - } - return nfs -} -func (nfs *NFS) shadow(args ...interface{}) *NFS { - 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: - 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)) - - 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++ - if i > 10 { - break - } - } - } - frame["lines"] = i - } - } - - } - - return nfs -} -func (nfs *NFS) print(arg ...string) *NFS { - m := nfs.Context.Message() - - 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}) - - 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) - nfs.out.WriteString("\n") - } - return nfs -} -func (nfs *NFS) Show(arg ...interface{}) bool { - nfs.prompt(arg...) - return true -} - func (nfs *NFS) Recv(line string) (field string, value string) { m := nfs.Context.Message() @@ -876,9 +247,7 @@ func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server c.Configs = map[string]*ctx.Config{} } - s := new(NFS) - s.Context = c - return s + return &NFS{Context: c} } func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { @@ -1066,23 +435,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { return true } func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { - switch nfs.Context { - case m.Target(): - if nfs.in != nil { - m.Log("info", "close in %s", m.Cap("stream")) - nfs.in.Close() - nfs.in = nil - } - if nfs.out != nil { - m.Log("info", "close out %s", m.Cap("stream")) - nfs.out.Close() - nfs.out = nil - } - case m.Source(): - } - if nfs.Name == "stdio" { - return false - } return true } @@ -1166,10 +518,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", }, }, Help: "读取文件的缓存区的大小"}, - "buf_size": &ctx.Config{Name: "buf_size", Value: "81920", Help: "读取文件的缓存区的大小"}, - "dir_type": &ctx.Config{Name: "dir_type(file/dir/both/all)", Value: "both", Help: "dir命令输出的文件类型, file: 只输出普通文件, dir: 只输出目录文件, 否则输出所有文件"}, - "dir_fields": &ctx.Config{Name: "dir_fields(time/type/name/size/line/hash)", Value: "time size line filename", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"}, - + "buf_size": &ctx.Config{Name: "buf_size", Value: "81920", Help: "读取文件的缓存区的大小"}, "grep": &ctx.Config{Name: "grep", Value: map[string]interface{}{ "list": []interface{}{}, }, Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"}, @@ -1187,12 +536,18 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "pretty": "--pretty=format:%h %ad %an %s", }, }, Help: "命令集合"}, - "paths": &ctx.Config{Name: "paths", Value: []interface{}{"var", "usr", "etc", "bin", ""}, Help: "文件路径"}, + "dir_fields": &ctx.Config{Name: "dir_fields(time/type/name/size/line/hash)", Value: "time size line filename", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"}, + "dir_type": &ctx.Config{Name: "dir_type(file/dir/both/all)", Value: "both", Help: "dir命令输出的文件类型, file: 只输出普通文件, dir: 只输出目录文件, 否则输出所有文件"}, + "dir": &ctx.Config{Name: "dir", Value: map[string]interface{}{ + "temp": "var/tmp/file", + "trash": "var/tmp/trash", + }, Help: ""}, + "pwd": &ctx.Config{Name: "pwd", Value: []interface{}{"var", "usr", "bin", "etc", ""}, 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) { - m.Conf("paths", -2, m.Conf("runtime", "boot.ctx_home")) - m.Conf("paths", -2, m.Conf("runtime", "boot.ctx_root")) + m.Conf("pwd", -2, m.Conf("runtime", "boot.ctx_home")) + m.Conf("pwd", -2, m.Conf("runtime", "boot.ctx_root")) return }}, "_exit": &ctx.Command{Name: "_init", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -1201,9 +556,24 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, - "pwd": &ctx.Command{Name: "pwd [all] | [[index] path] ", Help: "工作目录,all: 查看所有, index path: 设置路径, path: 设置当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "path": &ctx.Command{Name: "path filename", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if len(arg) == 0 { + return + } + + m.Confm("pwd", 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 + }}, + "pwd": &ctx.Command{Name: "pwd [all] | [[index] path] ", Help: "当前目录,all: 查看所有, index path: 设置路径, path: 设置当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 0 && arg[0] == "all" { - m.Cmdy("nfs.config", "paths") + m.Cmdy("nfs.config", "pwd") return } @@ -1212,11 +582,11 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", index, arg = kit.Int(arg[0]), arg[1:] } for i, v := range arg { - m.Log("info", "paths %s %s", index+i, v) - m.Confv("paths", index+i, v) + m.Log("info", "pwd %s %s", index+i, v) + m.Confv("pwd", index+i, v) } - if p := m.Conf("paths", index); path.IsAbs(p) { + if p := m.Conf("pwd", index); path.IsAbs(p) { m.Echo("%s", p) } else if wd, e := os.Getwd(); m.Assert(e) { m.Echo("%s", path.Join(wd, p)) @@ -1283,7 +653,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", rg, e := regexp.Compile(m.Option("dir_reg")) - m.Confm("paths", func(index int, value string) bool { + m.Confm("pwd", func(index int, value string) bool { // p := path.Join(value, m.Option("dir_root"), arg[0]) p := path.Join(value, arg[0]) if s, e := os.Stat(p); e == nil { @@ -1414,6 +784,50 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, + + "temp": &ctx.Command{Name: "temp data", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if f, p, e := kit.Create(path.Join(m.Conf("dir", "temp"), kit.Hashs("uniq"))); m.Assert(e) { + defer f.Close() + + for _, v := range arg { + f.WriteString(v) + } + m.Echo(p) + } + return + }}, + "hash": &ctx.Command{Name: "hash file", Help: "文件哈希", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + p := m.Append("name", m.Cmdx("nfs.path", arg[0])) + if s, e := os.Stat(p); e == nil && !s.IsDir() { + m.Append("size", s.Size()) + if f, e := os.Open(p); e == nil { + defer f.Close() + + md := md5.New() + io.Copy(md, f) + h := md.Sum(nil) + m.Echo(hex.EncodeToString(h[:])) + } + } + return + }}, + "copy": &ctx.Command{Name: "copy to from", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if to, p, e := kit.Create(arg[0]); m.Assert(e) { + defer to.Close() + + for _, from := range arg[1:] { + if f, e := os.Open(m.Cmdx("nfs.path", from)); e == nil { + defer f.Close() + + if n, e := io.Copy(to, f); m.Assert(e) { + m.Log("info", "copy %d to %s from %s", n, p, from) + } + } + } + m.Echo(p) + } + return + }}, "grep": &ctx.Command{Name: "grep", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { hold := false if len(arg) > 0 { @@ -1492,120 +906,13 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", m.Table() return }}, - - "draw": &ctx.Command{Name: "draw", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if len(arg) == 0 { - m.Cmdy("nfs.dir", "src", "filename", "line", "size", "dir_deep", "dir_type", "file", "dir_sort", "line", "int_r") - return - } - if arg[0] == "git" { - m.Cmdy("nfs.git", "sum") - return - } - - m.Append("text", m.Time()) - m.Append("style", map[int]string{ - 0: "black", - 1: "red", - 2: "green", - 3: "yellow", - 4: "blue", - 5: "purple", - 6: "cyan", - 7: "white", - }[rand.Intn(8)]) - switch arg[2] { - case "drawText": - x, y := rand.Intn(400), rand.Intn(300) - m.Append("ps", kit.Format([]interface{}{ - map[string]int{"x": x, "y": y}, - map[string]int{"x": x + 200, "y": y}, - })) - case "drawRect": - x, y, l := rand.Intn(400), rand.Intn(300), rand.Intn(100) - m.Append("ps", kit.Format([]interface{}{ - map[string]int{"x": x, "y": y}, - map[string]int{"x": x + l + l, "y": y + l}, - })) - case "drawCircle": - x, y, l := rand.Intn(400), rand.Intn(300), rand.Intn(100) - m.Append("ps", kit.Format([]interface{}{ - map[string]int{"x": x, "y": y}, - map[string]int{"x": x + l, "y": y}, - })) - } - return - }}, - - "hash": &ctx.Command{Name: "hash filename", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - dir, name := path.Split(arg[0]) - m.Append("dir", dir) - m.Append("name", name) - m.Append("type", strings.TrimPrefix(path.Ext(arg[0]), ".")) - if s, e := os.Stat(arg[0]); e == nil && !s.IsDir() { - m.Append("size", s.Size()) - if f, e := os.Open(arg[0]); e == nil { - defer f.Close() - md := md5.New() - io.Copy(md, f) - h := md.Sum(nil) - m.Echo(hex.EncodeToString(h[:])) - } - } - return - }}, - "path": &ctx.Command{Name: "path filename", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if len(arg) == 0 { - return - } - - 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 - }}, - "copy": &ctx.Command{Name: "copy to from", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - dir, _ := path.Split(arg[0]) - m.Assert(os.MkdirAll(dir, 0777)) - - to, e := os.Create(arg[0]) - m.Assert(e) - defer to.Close() - - for _, from := range arg[1:] { - f, e := os.Open(from) - if e != nil { - continue - } - defer f.Close() - - n, e := io.Copy(to, f) - m.Assert(e) - m.Log("info", "copy %d from %s to %s", n, from, arg[0]) - } - m.Echo(arg[0]) - return - }}, - "temp": &ctx.Command{Name: "temp data", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - h, _ := kit.Hash("uniq") - name := fmt.Sprintf("var/tmp/file/%s", h) - - m.Assert(os.MkdirAll("var/tmp/file/", 0777)) - f, e := os.Create(name) - m.Assert(e) - defer f.Close() - f.Write([]byte(arg[0])) - - m.Echo(name) - return - }}, "trash": &ctx.Command{Name: "trash file", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - os.Remove(arg[0]) + if len(arg) == 0 { + m.Cmdy("nfs.dir", m.Conf("dir", "trash")) + return + } + m.Assert(os.Mkdir(m.Conf("dir", "trash"), 0777)) + m.Assert(os.Rename(arg[0], path.Join(m.Conf("dir", "trash"), arg[0]))) return }}, @@ -1613,15 +920,15 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", if p, f, e := open(m, arg[0]); e == nil { defer f.Close() - pos := kit.Int(kit.Select("0", arg, 2)) size := kit.Int(m.Confx("buf_size", arg, 1)) if size == -1 { - s, e := f.Stat() - m.Assert(e) - size = int(s.Size()) + if s, e := f.Stat(); m.Assert(e) { + size = int(s.Size()) + } } buf := make([]byte, size) + pos := kit.Int(kit.Select("0", arg, 2)) if l, e := f.ReadAt(buf, int64(pos)); e == io.EOF || m.Assert(e) { m.Log("info", "load %s %d %d", p, l, pos) m.Echo(string(buf[:l])) @@ -1634,20 +941,15 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", arg = append(arg, m.Option("data")) } - dir := path.Dir(arg[0]) - if _, e = os.Stat(dir); e != nil { - m.Assert(os.MkdirAll(dir, 0777)) - } - - if f, e := os.Create(arg[0]); m.Assert(e) { + if f, p, e := kit.Create(arg[0]); m.Assert(e) { defer f.Close() + for _, v := range arg[1:] { - n, e := fmt.Fprint(f, v) - m.Assert(e) - m.Log("info", "save %s %d", arg[0], n) + if n, e := f.WriteString(v); m.Assert(e) { + m.Log("info", "save %s %d", p, n) + } } - m.Append("directory", arg[0]) - m.Echo(arg[0]) + m.Echo(p) } return }}, @@ -1665,27 +967,26 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", switch { case strings.HasSuffix(arg[0], ".json"): var data interface{} - de := json.NewDecoder(f) - de.Decode(&data) - + json.NewDecoder(f).Decode(&data) m.Put("option", "filedata", data).Cmdy("ctx.trans", "filedata", arg[1:]).CopyTo(m) + case strings.HasSuffix(arg[0], ".csv"): r := csv.NewReader(f) + if l, e := r.Read(); m.Assert(e) { + m.Meta["append"] = l - l, e := r.Read() - m.Assert(e) - m.Meta["append"] = l - - for l, e = r.Read(); e != nil; l, e = r.Read() { - for i, v := range l { - m.Add("append", m.Meta["append"][i], v) + for l, e = r.Read(); e == nil; l, e = r.Read() { + for i, v := range l { + m.Add("append", m.Meta["append"][i], v) + } } } m.Table() + default: - b, e := ioutil.ReadAll(f) - m.Assert(e) - m.Echo(string(b)) + if b, e := ioutil.ReadAll(f); m.Assert(e) { + m.Echo(string(b)) + } } return }}, @@ -1695,7 +996,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", tp, arg = true, arg[1:] } - p, f, e := open(m, kit.Select(arg[0], m.Format(arg[0]), tp), os.O_WRONLY|os.O_CREATE|os.O_TRUNC) + f, p, e := kit.Create(kit.Select(arg[0], m.Format(arg[0]), tp)) m.Assert(e) defer f.Close() @@ -1723,6 +1024,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", en := json.NewEncoder(f) en.SetIndent("", " ") en.Encode(data) + case strings.HasSuffix(arg[0], ".csv"): fields := m.Meta["append"] if m.Options("fields") { @@ -1750,14 +1052,16 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } w.Flush() } + case strings.HasSuffix(arg[0], ".png"): if data == nil { - data = kit.Format(arg[1:]) + data = strings.Join(arg[1:], "") + } + + if qr, e := qrcode.New(kit.Format(data), qrcode.Medium); m.Assert(e) { + m.Assert(qr.Write(256, f)) } - qr, e := qrcode.New(kit.Format(data), qrcode.Medium) - m.Assert(e) - m.Assert(qr.Write(256, f)) default: f.WriteString(kit.Format(m.Meta["result"])) } @@ -1769,9 +1073,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", "json": &ctx.Command{Name: "json str", Help: "导入数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { var data interface{} m.Assert(json.Unmarshal([]byte(arg[0]), &data)) - b, e := json.MarshalIndent(data, "", " ") - m.Assert(e) - m.Echo(string(b)) + if b, e := json.MarshalIndent(data, "", " "); m.Assert(e) { + m.Echo(string(b)) + } return }}, @@ -1856,6 +1160,36 @@ 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 len(arg) == 0 { + m.Cmdy("dir", "src", "time", "line", "path", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$") + return + } + + 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 { + m.Cmdy("yac.parse", strings.Join(arg, " ")+"\n") + } + 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 + }}, + "remote": &ctx.Command{Name: "remote listen|dial args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{ m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message { @@ -1876,108 +1210,9 @@ 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 - }}, }, } func init() { - nfs := &NFS{} - nfs.Context = Index - ctx.Index.Register(Index, nfs) + ctx.Index.Register(Index, &NFS{Context: Index}) } diff --git a/src/contexts/nfs/term.go b/src/contexts/nfs/term.go new file mode 100644 index 00000000..a2789c5f --- /dev/null +++ b/src/contexts/nfs/term.go @@ -0,0 +1,640 @@ +package nfs + +import ( + "contexts/ctx" + "toolkit" + + "fmt" + "strings" + + "github.com/nsf/termbox-go" + "time" +) + +func (nfs *NFS) Read(p []byte) (n int, err error) { + m := nfs.Context.Message() + if !m.Caps("termbox") { + return nfs.in.Read(p) + } + + m.TryCatch(m, true, func(m *ctx.Message) { + scroll_count := 0 + scroll_lines := m.Confi("term", "scroll_lines") + which := m.Capi("ninput") + what := make([]rune, 0, 1024) + rest := make([]rune, 0, 1024) + back := make([]rune, 0, 1024) + + m.Option("bio.cmd", "") + m.Options("bio.shadow", m.Confs("show_shadow")) + + 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 { + frame, table, index, pick = f, t, i, 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: + if m.Confs("term", "mouse.resize") { + nfs.Term(m, "window", ev.MouseX, ev.MouseY) + nfs.prompt(what).shadow(rest) + } + + case termbox.MouseMiddle: + case termbox.MouseRight: + if m.Confs("term", "mouse.resize") { + 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 = append(what[:0], []rune(v)...), rest[:0] + 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 = append(what[:0], []rune(v)...), rest[:0] + 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: + m.Confi("term", "begin_row", m.Capi("noutput")) + m.Confi("term", "begin_col", 0) + nfs.Term(m, "clear", "all").Term(m, "flush") + nfs.prompt(what).shadow(rest) + + case termbox.KeyCtrlT: + m.Option("scroll", true) + nfs.Term(m, "scroll", scroll_lines).Term(m, "flush") + m.Option("scroll", false) + case termbox.KeyCtrlO: + m.Option("scroll", true) + nfs.Term(m, "scroll", -scroll_lines).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: + m.Options("bio.shadow", !m.Options("bio.shadow")) + case termbox.KeyCtrlS: + + case termbox.KeyCtrlZ: + + case termbox.KeyTab: + m.Options("bio.shadow", true) + // 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 !m.Options("bio.shadow") { + break + } + + 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 + } + + if nfs.shadow(what[index:], table, frame); len(table) > 0 { + rest = append(rest[:0], []rune(table[0][kit.Format(frame["field"])])...) + nfs.prompt(what).shadow(rest) + nfs.shadow(what[index:], table, frame) + } + } + + default: + what = append(what, ev.Ch) + nfs.prompt(what).shadow(rest) + if !m.Options("bio.shadow") { + break + } + + if change, f, t, i := nfs.Auto(what, kit.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) { + return + m := nfs.Context.Message() + + auto_target := m.Optionv("bio.ctx").(*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("bio.ctx", auto_target) + trigger = ":" + case "command": + m.Option("arg_index", index) + auto_cmd = m.Option("bio.cmd", m.Option("auto_key")) + trigger = "=" + case "argument": + auto_cmd = m.Option("bio.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(line int, maps map[string]string) { + 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) + }) + 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) + + switch action { + case "init": + defer func() { + if e := recover(); e != nil { + m.Log("warn", "term init %s", e) + } + }() + termbox.Init() + termbox.SetInputMode(termbox.InputEsc) + termbox.SetInputMode(termbox.InputMouse) + m.Cap("termbox", "true") + } + + width, height := termbox.Size() + msg.Conf("term", "width", width) + msg.Conf("term", "height", height) + + left := msg.Confi("term", "left") + top := msg.Confi("term", "top") + right := msg.Confi("term", "right") + bottom := msg.Confi("term", "bottom") + + x := m.Confi("term", "cursor_x") + y := m.Confi("term", "cursor_y") + bg := termbox.Attribute(msg.Confi("term", "bgcolor")) + fg := termbox.Attribute(msg.Confi("term", "fgcolor")) + + begin_row := m.Confi("term", "begin_row") + begin_col := m.Confi("term", "begin_col") + + switch action { + case "init": + m.Conf("term", "left", 0) + m.Conf("term", "top", 0) + m.Conf("term", "right", width) + m.Conf("term", "bottom", height) + + case "exit": + m.Cap("termbox", "false") + termbox.Close() + + case "window": + if len(args) > 1 { + msg.Conf("term", "left", args[0]) + msg.Conf("term", "top", args[1]) + } + if len(args) > 3 { + msg.Conf("term", "right", args[2]) + msg.Conf("term", "bottom", args[3]) + } else { + msg.Conf("term", "right", width) + msg.Conf("term", "bottom", height) + } + + case "resize": + if len(args) > 1 { + msg.Conf("term", "right", args[0]) + msg.Conf("term", "bottom", args[1]) + right = msg.Confi("term", "right") + bottom = msg.Confi("term", "bottom") + } else { + msg.Conf("term", "right", right) + msg.Conf("term", "bottom", bottom) + } + + fallthrough + case "clear": + if len(args) == 0 { + top = m.Confi("term", "prompt_y") + } else if kit.Format(args[0]) == "all" { + // nothing + } + + for x := left; x < right; x++ { + for y := top; y < bottom; y++ { + termbox.SetCell(x, y, ' ', fg, bg) + } + } + m.Conf("term", "cursor_x", left) + m.Conf("term", "cursor_y", top) + termbox.SetCursor(left, top) + + case "cursor": + m.Conf("term", "cursor_x", kit.Format(args[0])) + m.Conf("term", "cursor_y", kit.Format(args[1])) + termbox.SetCursor(m.Confi("term", "cursor_x"), m.Confi("term", "cursor_y")) + + case "flush": + termbox.Flush() + + case "scroll": + n := 1 + if len(args) > 0 { + n = kit.Int(args[0]) + } + m.Options("on_scroll", true) + + // 向下滚动 + for i := begin_row; n > 0 && i < m.Capi("noutput"); i++ { + line := []rune(m.Conf("output", []interface{}{i, "line"})) + + for j, l := begin_col, left; n > 0; j, l = j+1, l+1 { + if j >= len(line)-1 { + begin_row, begin_col = i+1, 0 + n-- + break + } else if line[j] == '\n' { + begin_row, begin_col = i, j+1 + n-- + } else if l >= right-1 && m.Confs("term", "wrap") { + begin_row, begin_col = i, j + n-- + } + } + } + + // 向上滚动 + for i := begin_row; n < 0 && i >= 0; i-- { + line := []rune(m.Conf("output", []interface{}{i, "line"})) + if begin_col == 0 { + i-- + line = []rune(m.Conf("output", []interface{}{i, "line"})) + begin_col = len(line) + } + + for j, l := begin_col-1, right-1; n < 0; j, l = j-1, l-1 { + if j <= 0 { + begin_row, begin_col = i, 0 + n++ + break + } else if line[j-1] == '\n' { + begin_row, begin_col = i, j + n++ + } else if l < left && m.Confs("term", "wrap") { + begin_row, begin_col = i, j + n++ + } + } + } + + m.Conf("term", "begin_row", begin_row) + m.Conf("term", "begin_col", begin_col) + + fallthrough + case "refresh": + + nfs.Term(m, "clear", "all") + for i := begin_row; i < m.Capi("noutput"); i++ { + if line := m.Conf("output", []interface{}{i, "line"}); begin_col < len(line) { + nfs.Term(m, "print", line[begin_col:]) + } + begin_col = 0 + } + // nfs.Term(m, "print", "\n") + // nfs.Term(m, "print", m.Conf("prompt")) + m.Options("on_scroll", false) + + case "print": + list := kit.Format(args...) + n := strings.Count(list, "\n") + y - bottom + + for _, v := range list { + if x < right { + if termbox.SetCell(x, y, v, fg, bg); v > 255 { + x++ + } + } + + if x++; v == '\n' || (x >= right && m.Confs("term", "wrap")) { + x, y = left, y+1 + if y >= bottom { + if m.Options("on_scroll") { + break + } + if n%bottom > 0 { + + nfs.Term(m, "scroll", n%bottom+1) + n -= n % bottom + x = m.Confi("term", "cursor_x") + y = m.Confi("term", "cursor_y") + + } else if n > 0 { + + nfs.Term(m, "scroll", bottom) + n -= bottom + x = m.Confi("term", "cursor_x") + y = m.Confi("term", "cursor_y") + + } + } + } + + if x < right { + m.Conf("term", "cursor_x", x) + m.Conf("term", "cursor_y", y) + termbox.SetCursor(x, y) + } + } + + if m.Options("on_scroll") { + x = 0 + y = y + 1 + m.Conf("term", "cursor_x", x) + m.Conf("term", "cursor_y", y) + termbox.SetCursor(x, y) + } + + case "color": + 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) + + case "shadow": + x := m.Confi("term", "cursor_x") + y := m.Confi("term", "cursor_y") + nfs.Term(m, "color", args...) + nfs.Term(m, "cursor", x, y).Term(m, "flush") + } + return nfs +} +func (nfs *NFS) prompt(arg ...interface{}) *NFS { + m := nfs.Context.Message() + target, _ := m.Optionv("bio.ctx").(*ctx.Context) + if target == nil { + target = nfs.Context + } + + line := fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name) + m.Conf("prompt", line) + + line += kit.Format(arg...) + if m.Caps("termbox") { + m.Conf("term", "prompt_y", m.Conf("term", "cursor_y")) + nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush") + } else if nfs.out != nil { + nfs.out.WriteString(line) + } + return nfs +} +func (nfs *NFS) shadow(args ...interface{}) *NFS { + 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: + 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)) + + 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++ + if i > 10 { + break + } + } + } + frame["lines"] = i + } + } + + } + + return nfs +} +func (nfs *NFS) print(arg ...string) *NFS { + m := nfs.Context.Message() + + 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}) + + 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) + nfs.out.WriteString("\n") + } + return nfs +} +func (nfs *NFS) Show(arg ...interface{}) bool { + nfs.prompt(arg...) + return true +} diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index 78ae007f..9822cbd7 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -608,7 +608,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", case "_redial": // 断线重连 if !m.Caps("stream") { - m.Cmdx("remote", "dial", arg[1:]) + m.Cmdx("ssh.remote", "dial", arg[1:]) } case "dial": // 连接主机 diff --git a/src/toolkit/core.go b/src/toolkit/core.go index 4b0d40da..4e42c519 100644 --- a/src/toolkit/core.go +++ b/src/toolkit/core.go @@ -7,6 +7,7 @@ import ( "io" "math/rand" "os" + "path" "strconv" "strings" "time" @@ -14,6 +15,10 @@ import ( var DisableLog = false +func Pwd() string { + wd, _ := os.Getwd() + return wd +} func Env(key string) { os.Getenv(key) } @@ -296,3 +301,13 @@ func View(args []string, conf map[string]interface{}) []string { } return keys } + +func Create(p string) (*os.File, string, error) { + if dir, _ := path.Split(p); dir != "" { + if e := os.MkdirAll(dir, 0777); e != nil { + return nil, p, e + } + } + f, e := os.Create(p) + return f, p, e +} diff --git a/usr/librarys/example.css b/usr/librarys/example.css index c67da088..fe0d384d 100644 --- a/usr/librarys/example.css +++ b/usr/librarys/example.css @@ -24,7 +24,7 @@ fieldset>form.option div.hide { display:none; } fieldset>form.option div input.args { - width:100px; + width:80px; } fieldset>form.option div.cmd input.args { color:white; @@ -35,7 +35,7 @@ fieldset>form.option div.clear { clear:both; } fieldset>form.option div.long input.args { - width:320px; + width:240px; } fieldset>form.option label { margin-right:6px;