diff --git a/base/log/log.go b/base/log/log.go index 285b1b17..5fa4a5c4 100644 --- a/base/log/log.go +++ b/base/log/log.go @@ -120,8 +120,8 @@ var Index = &ice.Context{Name: "log", Help: "日志模块", // 日志文件 if f, p, e := kit.Create(kit.Format(value["path"])); m.Assert(e) { m.Cap(ice.CTX_STREAM, path.Base(p)) - m.Log("create", "%s: %s", key, p) value["file"] = bufio.NewWriter(f) + m.Log_CREATE(kit.MDB_FILE, p) } }) } diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index a9f5f2f6..263cd9c5 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -4,17 +4,18 @@ import ( "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/toolkits" + "github.com/shylinux/toolkits/task" "encoding/csv" "encoding/json" "os" "sort" - "strings" ) func _list_import(m *ice.Message, prefix, key, file string) { f, e := os.Open(file) m.Assert(e) + defer m.Cmdy(web.STORY, web.CATCH, CSV, file) defer f.Close() r := csv.NewReader(f) @@ -43,10 +44,10 @@ func _list_import(m *ice.Message, prefix, key, file string) { m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count) } func _list_export(m *ice.Message, prefix, key, file string) { - f, p, e := kit.Create(kit.Keys(file, "csv")) + f, p, e := kit.Create(kit.Keys(file, CSV)) m.Assert(e) + defer m.Cmdy(web.STORY, web.CATCH, CSV, p) defer f.Close() - defer m.Cmdy(web.STORY, "catch", "csv", p) w := csv.NewWriter(f) defer w.Flush() @@ -73,54 +74,101 @@ func _list_export(m *ice.Message, prefix, key, file string) { }) m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_COUNT, count) } +func _list_select(m *ice.Message, prefix, key, limit, offend, field, value string) { + m.Option("cache.limit", limit) + m.Option("cache.offend", offend) + m.Grows(prefix, key, field, value, func(index int, value map[string]interface{}) { + m.Push("", value) + }) +} +func _list_search(m *ice.Message, prefix, key, field, value string) { + list := []interface{}{} + files := map[string]bool{} + m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, value map[string]interface{}) { + kit.Fetch(kit.Value(value, "meta.record"), func(index int, value map[string]interface{}) { + file := value["file"].(string) + if _, ok := files[file]; ok { + list = append(list, file) + } else { + files[file] = true + } + }) + }) + defer m.Cost("search") + + task.Sync(list, func(task *task.Task, lock *task.Lock) error { + kit.CSV(kit.Format(task.Arg), 100000, func(index int, line map[string]string, head []string) { + if line[field] != value { + return + } + + defer lock.WLock()() + m.Push("", line) + }) + return nil + }) +} + +func _hash_search(m *ice.Message, prefix, key, field, value string) { + m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, val map[string]interface{}) { + if field != "" && value != val[field] { + return + } + m.Push(key, value) + }) +} func _hash_import(m *ice.Message, prefix, key, file string) { f, e := os.Open(file) m.Assert(e) + defer m.Cmdy(web.STORY, web.CATCH, JSON, file) defer f.Close() - defer m.Log_IMPORT(kit.MDB_FILE, file) - - data := map[string]interface{}{} + list := map[string]interface{}{} de := json.NewDecoder(f) - de.Decode(&data) + de.Decode(&list) - for k, v := range data { - m.Log_MODIFY(kit.MDB_KEY, kit.Keys(prefix, key, kit.MDB_HASH), "k", k, "v", v) - m.Conf(prefix, kit.Keys(key, k), v) + count := 0 + for _, data := range list { + // 导入数据 + m.Rich(prefix, key, data) + count++ } + m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count) } func _hash_export(m *ice.Message, prefix, key, file string) { - f, p, e := kit.Create(kit.Keys(file, "json")) + f, p, e := kit.Create(kit.Keys(file, JSON)) m.Assert(e) + defer m.Cmdy(web.STORY, web.CATCH, JSON, p) defer f.Close() - defer m.Cmdy(web.STORY, "catch", "json", p) en := json.NewEncoder(f) en.SetIndent("", " ") - en.Encode(m.Confv(prefix, kit.Keys(key, kit.MDB_HASH))) + en.Encode(m.Confv(prefix, kit.Keys(key, HASH))) m.Log_EXPORT(kit.MDB_FILE, p) } func _dict_import(m *ice.Message, prefix, key, file string) { f, e := os.Open(file) m.Assert(e) + m.Cmdy(web.STORY, web.CATCH, JSON, file) defer f.Close() - defer m.Log_IMPORT(kit.MDB_FILE, file) - data := map[string]interface{}{} de := json.NewDecoder(f) de.Decode(&data) + count := 0 for k, v := range data { m.Log_MODIFY(kit.MDB_KEY, kit.Keys(prefix, key), "k", k, "v", v) m.Conf(prefix, kit.Keys(key, k), v) + count++ } + m.Log_EXPORT(kit.MDB_FILE, file, kit.MDB_COUNT, count) } func _dict_export(m *ice.Message, prefix, key, file string) { - f, p, e := kit.Create(kit.Keys(file, "json")) + f, p, e := kit.Create(kit.Keys(file, JSON)) m.Assert(e) + defer m.Cmdy(web.STORY, web.CATCH, JSON, p) defer f.Close() - defer m.Cmdy(web.STORY, "catch", "json", p) en := json.NewEncoder(f) en.SetIndent("", " ") @@ -128,72 +176,66 @@ func _dict_export(m *ice.Message, prefix, key, file string) { m.Log_EXPORT(kit.MDB_FILE, p) } -const IMPORT = "import" -const EXPORT = "export" +const ( + CSV = "csv" + JSON = "json" +) +const ( + DICT = "dict" + META = "meta" + HASH = "hash" + LIST = "list" +) +const ( + IMPORT = "import" + EXPORT = "export" + SELECT = "select" + SEARCH = "search" +) var Index = &ice.Context{Name: "mdb", Help: "数据模块", Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, - kit.MDB_IMPORT: {Name: "import conf key type file", Help: "导入数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + + IMPORT: {Name: "import conf key type file", Help: "导入数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[2] { - case kit.MDB_LIST: + case LIST: _list_import(m, arg[0], arg[1], arg[3]) - case kit.MDB_HASH: + case HASH: _hash_import(m, arg[0], arg[1], arg[3]) - case kit.MDB_DICT: + case DICT: _dict_import(m, arg[0], arg[1], arg[3]) } }}, - kit.MDB_EXPORT: {Name: "export conf key type [name]", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + EXPORT: {Name: "export conf key type [name]", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch file := kit.Select(kit.Select(arg[0], arg[0]+":"+arg[1], arg[1] != ""), arg, 3); arg[2] { - case kit.MDB_LIST: + case LIST: _list_export(m, arg[0], arg[1], file) - case kit.MDB_HASH: + case HASH: _hash_export(m, arg[0], arg[1], file) - case kit.MDB_DICT: + case DICT: _dict_export(m, arg[0], arg[1], file) } }}, - "update": {Name: "update config table index key value", Help: "修改数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - meta := m.Confm(arg[0], arg[1]+".meta") - index := kit.Int(arg[2]) - kit.Int(meta["offset"]) - 1 - - data := m.Confm(arg[0], arg[1]+".list."+kit.Format(index)) - for i := 3; i < len(arg)-1; i += 2 { - kit.Value(data, arg[i], arg[i+1]) - } - }}, - "select": {Name: "select config table index offend limit match value", Help: "修改数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 3 { - meta := m.Confm(arg[0], arg[1]+".meta") - index := kit.Int(arg[2]) - kit.Int(meta["offset"]) - 1 - - data := m.Confm(arg[0], arg[1]+".list."+kit.Format(index)) - m.Push(arg[2], data) - } else { - m.Option("cache.offend", kit.Select("0", arg, 3)) - m.Option("cache.limit", kit.Select("10", arg, 4)) - fields := strings.Split(arg[7], " ") - m.Grows(arg[0], arg[1], kit.Select("", arg, 5), kit.Select("", arg, 6), func(index int, value map[string]interface{}) { - m.Push("id", value, fields) - }) - } - }}, - - ice.MDB_DELETE: {Name: "delete conf key type", Help: "删除", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + SELECT: {Name: "select conf key type [limit [offend [key value]]]", Help: "数据查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[2] { - case kit.MDB_DICT: - m.Log(ice.LOG_DELETE, "%s: %s", arg[1], m.Conf(arg[0], arg[1])) - m.Echo("%s", m.Conf(arg[0], arg[1])) - m.Conf(arg[0], arg[1], "") - case kit.MDB_META: - case kit.MDB_LIST: - case kit.MDB_HASH: + case LIST: + _list_select(m, arg[0], arg[1], kit.Select("10", arg, 3), kit.Select("0", arg, 4), kit.Select("", arg, 5), kit.Select("", arg, 6)) + } + }}, + SEARCH: {Name: "search conf key type key value", Help: "数据查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + switch arg[2] { + case LIST: + _list_search(m, arg[0], arg[1], arg[3], arg[4]) + case HASH: + _hash_search(m, arg[0], arg[1], arg[3], arg[4]) } }}, }, } -func init() { ice.Index.Register(Index, nil, IMPORT, EXPORT) } +func init() { + ice.Index.Register(Index, nil, IMPORT, EXPORT, SELECT, SEARCH) +} diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index 7a84fb1a..ae4cb8fa 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -2,6 +2,8 @@ package nfs import ( ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/web" kit "github.com/shylinux/toolkits" "bufio" @@ -18,8 +20,7 @@ import ( ) const ( - FILE = "file" - TRASH = "trash" + FILE = "file" ) func _file_list(m *ice.Message, root string, name string, level int, deep bool, dir_type string, dir_reg *regexp.Regexp, fields []string) { @@ -141,12 +142,12 @@ func _file_list(m *ice.Message, root string, name string, level int, deep bool, } } func _file_show(m *ice.Message, name string) { - if f, e := os.OpenFile(name, os.O_RDONLY, 0777); m.Assert(e) { + if f, e := os.OpenFile(name, os.O_RDONLY, 0640); m.Assert(e) { defer f.Close() if s, e := f.Stat(); m.Assert(e) { buf := make([]byte, s.Size()) if n, e := f.Read(buf); m.Assert(e) { - m.Log_IMPORT("file", name, "size", n) + m.Log_IMPORT(kit.MDB_FILE, name, kit.MDB_SIZE, n) m.Echo(string(buf[:n])) } } @@ -157,7 +158,7 @@ func _file_save(m *ice.Message, name string, text ...string) { defer f.Close() for _, v := range text { if n, e := f.WriteString(v); m.Assert(e) { - m.Log_EXPORT("file", p, "size", n) + m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, n) } } m.Echo(p) @@ -170,7 +171,7 @@ func _file_copy(m *ice.Message, name string, from ...string) { if s, e := os.Open(v); !m.Warn(e != nil, "%s", e) { defer s.Close() if n, e := io.Copy(f, s); !m.Warn(e != nil, "%s", e) { - m.Log_IMPORT("file", p, "size", n) + m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, n) } } } @@ -178,14 +179,14 @@ func _file_copy(m *ice.Message, name string, from ...string) { } func _file_link(m *ice.Message, name string, from string) { m.Cmd("nfs.trash", name) - os.MkdirAll(path.Dir(name), 0777) + os.MkdirAll(path.Dir(name), 0760) os.Link(from, name) } func _file_trash(m *ice.Message, name string, from ...string) { if s, e := os.Stat(name); e == nil { if s.IsDir() { name := path.Base(name) + ".tar.gz" - m.Cmd(ice.CLI_SYSTEM, "tar", "zcf", name, name) + m.Cmd(cli.SYSTEM, "tar", "zcf", name, name) } if f, e := os.Open(name); m.Assert(e) { @@ -196,36 +197,41 @@ func _file_trash(m *ice.Message, name string, from ...string) { os.MkdirAll(path.Dir(p), 0777) os.Rename(name, p) - m.Cmd(ice.WEB_FAVOR, "trash", "bin", name, p) + m.Cmd(web.FAVOR, "trash", "bin", name, p) } } } -func FileSave(m *ice.Message, file string, text ...string) { - _file_save(m, file, text...) -} +const ( + DIR = "dir" + CAT = "cat" + SAVE = "save" + COPY = "copy" + LINK = "link" + TRASH = "trash" +) var Index = &ice.Context{Name: "nfs", Help: "存储模块", Configs: map[string]*ice.Config{ TRASH: {Name: "trash", Help: "删除", Value: kit.Data("path", "var/trash")}, }, Commands: map[string]*ice.Command{ - "dir": {Name: "dir path field...", Help: "目录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + DIR: {Name: "dir path field...", Help: "目录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { rg, _ := regexp.Compile(m.Option("dir_reg")) _file_list(m, kit.Select("./", m.Option("dir_root")), kit.Select("", arg, 0), 0, m.Options("dir_deep"), kit.Select("both", m.Option("dir_type")), rg, strings.Split(kit.Select("time size line path", strings.Join(arg[1:], " ")), " ")) }}, - "cat": {Name: "cat file", Help: "查看", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + CAT: {Name: "cat file", Help: "查看", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { _file_show(m, arg[0]) }}, - "save": {Name: "save file text...", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + SAVE: {Name: "save file text...", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { _file_save(m, arg[0], arg[1:]...) }}, - "copy": {Name: "copy file from...", Help: "复制", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + COPY: {Name: "copy file from...", Help: "复制", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { _file_copy(m, arg[0], arg[1:]...) }}, - "link": {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + LINK: {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { _file_link(m, arg[0], arg[1]) }}, diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go index bc7b77ac..76aa8b01 100644 --- a/base/ssh/ssh.go +++ b/base/ssh/ssh.go @@ -3,6 +3,8 @@ package ssh import ( "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/aaa" + "github.com/shylinux/icebergs/base/cli" + "github.com/shylinux/icebergs/base/web" "github.com/shylinux/toolkits" "bufio" @@ -17,15 +19,20 @@ import ( ) type Frame struct { - in io.ReadCloser - out io.Writer - + source string target *ice.Context - exit bool + stdout io.Writer + + count int + ps1 []string + ps2 []string + + exit bool } func Render(msg *ice.Message, cmd string, args ...interface{}) { - msg.Log(ice.LOG_EXPORT, "%s: %v", cmd, args) + defer func() { msg.Log_EXPORT(kit.MDB_RENDER, cmd, kit.MDB_TEXT, args) }() + switch arg := kit.Simple(args...); cmd { case ice.RENDER_OUTPUT: @@ -49,6 +56,7 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) { if res == "" { res = msg.Table().Result() } + args = append(args, "length:", len(res)) // 输出结果 if fmt.Fprintf(msg.O, res); !strings.HasSuffix(res, "\n") { @@ -58,60 +66,125 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) { msg.Append(ice.MSG_OUTPUT, ice.RENDER_OUTPUT) } -func (f *Frame) prompt(m *ice.Message) *Frame { - if f.out == os.Stdout { - fmt.Fprintf(f.out, "\r") - for _, v := range kit.Simple(m.Optionv(ice.MSG_PROMPT)) { - switch v { - case "count": - fmt.Fprintf(f.out, "%d", kit.Int(m.Conf("history", "meta.count"))+1) - case "time": - fmt.Fprintf(f.out, time.Now().Format("15:04:05")) - case "target": - fmt.Fprintf(f.out, f.target.Name) - default: - fmt.Fprintf(f.out, v) - } +func (f *Frame) history(m *ice.Message, line string) string { + favor := m.Conf(SOURCE, kit.Keys(kit.MDB_META, web.FAVOR)) + if strings.HasPrefix(strings.TrimSpace(line), "!!") { + if len(line) == 2 { + line = m.Cmd(web.FAVOR, favor).Append(kit.MDB_TEXT) } + } else if strings.HasPrefix(strings.TrimSpace(line), "!") { + if len(line) == 1 { + // 历史记录 + msg := m.Cmd(web.FAVOR, favor) + msg.Sort(kit.MDB_ID) + msg.Appendv(ice.MSG_APPEND, kit.MDB_TIME, kit.MDB_ID, kit.MDB_TEXT) + f.printf(m, msg.Table().Result()) + return "" + } + if i, e := strconv.Atoi(line[1:]); e == nil { + // 历史命令 + line = kit.Format(kit.Value(m.Cmd(web.FAVOR, favor, i).Optionv("value"), kit.MDB_TEXT)) + } else { + f.printf(m, m.Cmd("history", "search", line[1:]).Table().Result()) + return "" + } + } else if strings.TrimSpace(line) != "" && f.source == STDIO { + // 记录历史 + m.Cmd(web.FAVOR, favor, "cmd", f.source, line) } - return f + return line } func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame { if len(arg) > 0 { - fmt.Fprintf(f.out, res, arg...) + fmt.Fprintf(f.stdout, res, arg...) } else { - fmt.Fprint(f.out, res) + fmt.Fprint(f.stdout, res) } - // if !strings.HasSuffix(res, "\n") { - // fmt.Fprint(f.out, "\n") - // } return f } -func (f *Frame) parse(m *ice.Message, line string) *Frame { - for _, one := range kit.Split(line, ";", ";", ";") { - ls := kit.Split(one) - m.Log(ice.LOG_IMPORT, "stdin: %d %v", len(ls), ls) +func (f *Frame) prompt(m *ice.Message, list ...string) *Frame { + if f.stdout != os.Stdout { + return f + } + if len(list) == 0 { + list = append(list, f.ps1...) + } - if len(ls) == 1 && ls[0] == "~" { - // 模块列表 - ls = []string{"context"} - } else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") { - // 切换模块 - target := ls[0][1:] - if ls = ls[1:]; len(target) == 0 && len(ls) > 0 { - target, ls = ls[0], ls[1:] - } - if target == "~" { - target = "" - } - m.Spawn(f.target).Search(target+".", func(p *ice.Context, s *ice.Context, key string) { - m.Info("choice: %s", s.Name) - f.target = s - }) + fmt.Fprintf(f.stdout, "\r") + for _, v := range list { + switch v { + case "count": + fmt.Fprintf(f.stdout, "%d", kit.Int(m.Conf("history", "meta.count"))+1) + case "time": + fmt.Fprintf(f.stdout, time.Now().Format("15:04:05")) + case "target": + fmt.Fprintf(f.stdout, f.target.Name) + default: + fmt.Fprintf(f.stdout, v) } - if len(ls) == 0 { - continue + } + return f +} +func (f *Frame) option(m *ice.Message, ls []string) []string { + // 解析选项 + ln := []string{} + m.Option("cache.limit", 10) + for i := 0; i < len(ls); i++ { + if ls[i] == "--" { + ln = append(ln, ls[i+1:]...) + break + } else if strings.HasPrefix(ls[i], "-") { + for j := i; j < len(ls); j++ { + if j == len(ls)-1 || strings.HasPrefix(ls[j+1], "-") { + if i == j { + m.Option(ls[i][1:], "true") + } else { + m.Option(ls[i][1:], ls[i+1:j+1]) + } + i = j + break + } + } + } else { + ln = append(ln, ls[i]) } + } + return ln +} +func (f *Frame) change(m *ice.Message, ls []string) []string { + if len(ls) == 1 && ls[0] == "~" { + // 模块列表 + ls = []string{"context"} + } else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") { + // 切换模块 + target := ls[0][1:] + if ls = ls[1:]; len(target) == 0 && len(ls) > 0 { + target, ls = ls[0], ls[1:] + } + if target == "~" { + target = "" + } + m.Spawn(f.target).Search(target+".", func(p *ice.Context, s *ice.Context, key string) { + m.Info("choice: %s", s.Name) + f.target = s + }) + } + return ls +} +func (f *Frame) alias(m *ice.Message, ls []string) []string { + // 命令替换 + if alias, ok := m.Optionv(ice.MSG_ALIAS).(map[string]interface{}); ok { + if a := kit.Simple(alias[ls[0]]); len(a) > 0 { + ls = append(append([]string{}, a...), ls[1:]...) + } + } + return ls +} +func (f *Frame) parse(m *ice.Message, line string) string { + for _, one := range kit.Split(line, ";", ";", ";") { + m.Log_IMPORT("stdin", one, "length", len(one)) + + ls := kit.Split(one) if m.Option("scan_mode") == "scan" { f.printf(m, ls[0]) f.printf(m, "`") @@ -121,104 +194,47 @@ func (f *Frame) parse(m *ice.Message, line string) *Frame { continue } - // 命令替换 - if alias, ok := m.Optionv(ice.MSG_ALIAS).(map[string]interface{}); ok { - if a := kit.Simple(alias[ls[0]]); len(a) > 0 { - ls = append(append([]string{}, a...), ls[1:]...) - } - } - - // 解析选项 - ln := []string{} + // 解析引擎 msg := m.Spawns(f.target) - msg.Option("cache.limit", 10) - for i := 0; i < len(ls); i++ { - if ls[i] == "--" { - ln = append(ln, ls[i+1:]...) - break - } else if strings.HasPrefix(ls[i], "-") { - for j := i; j < len(ls); j++ { - if j == len(ls)-1 || strings.HasPrefix(ls[j+1], "-") { - if i == j { - msg.Option(ls[i][1:], "true") - } else { - msg.Option(ls[i][1:], ls[i+1:j+1]) - } - i = j - break - } - } - } else { - ln = append(ln, ls[i]) - } - } - - if ln[0] == "qrcode" { - msg.Option(ice.MSG_OUTPUT, ice.RENDER_QRCODE) - ln = ln[1:] - } msg.Option("_cmd", one) + ls = f.alias(msg, ls) + ls = f.change(msg, ls) + ls = f.option(msg, ls) + if len(ls) == 0 { + continue + } // 执行命令 - msg.Cmdy(ln[0], ln[1:]) + msg.Cmdy(ls[0], ls[1:]) // 渲染引擎 _args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{}) Render(msg, msg.Option(ice.MSG_OUTPUT), _args...) - } - return f + return "" } +func (f *Frame) scan(m *ice.Message, file, line string, r io.Reader) *Frame { + f.ps1 = kit.Simple(m.Confv("prompt", "meta.PS1")) + f.ps2 = kit.Simple(m.Confv("prompt", "meta.PS2")) + ps := f.ps1 -func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { - return &Frame{} -} -func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { - return f -} -func (f *Frame) Start(m *ice.Message, arg ...string) bool { - m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) - f.target = m.Source() - aaa.UserRoot(m) - - switch kit.Select("stdio", arg, 0) { - case "stdio": - // 解析终端 - f.in, f.out = os.Stdin, os.Stdout - m.Cap(ice.CTX_STREAM, "stdio") - f.target = m.Target() - default: - if s, e := os.Open(arg[0]); m.Warn(e != nil, "%s", e) { - // 打开失败 - return true - } else { - // 解析脚本 - defer s.Close() - if f.in, f.out = s, os.Stdout; m.Optionv(ice.MSG_STDOUT) != nil { - f.out = m.Optionv(ice.MSG_STDOUT).(io.Writer) - } - m.Cap(ice.CTX_STREAM, arg[0]) - } - } - m.I, m.O = f.in, f.out - - line := "" - bio := bufio.NewScanner(f.in) - for f.prompt(m); bio.Scan() && !f.exit; f.prompt(m) { + m.I, m.O = r, f.stdout + bio := bufio.NewScanner(r) + for f.prompt(m, ps...); bio.Scan() && !f.exit; f.prompt(m, ps...) { if len(bio.Text()) == 0 { // 空行 continue } if strings.HasSuffix(bio.Text(), "\\") { // 续行 - m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS2")) line += bio.Text()[:len(bio.Text())-1] + ps = f.ps2 continue } if line += bio.Text(); strings.Count(line, "`")%2 == 1 { // 多行 - m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS2")) line += "\n" + ps = f.ps2 continue } if strings.HasPrefix(strings.TrimSpace(line), "#") { @@ -226,127 +242,127 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { line = "" continue } - - if strings.HasPrefix(strings.TrimSpace(line), "!") { - if len(line) == 1 { - // 历史记录 - f.printf(m, m.Cmd("history").Table().Result()) - line = "" - continue - } - if i, e := strconv.Atoi(line[1:]); e == nil { - // 历史命令 - m.Grows("history", nil, "id", kit.Format(i), func(index int, value map[string]interface{}) { - line = kit.Format(value["line"]) - }) - } else { - f.printf(m, m.Cmd("history", "search", line[1:]).Table().Result()) - line = "" - continue - } - } else { - // 记录历史 - m.Grow("history", nil, kit.Dict("line", line)) + if line = f.history(m, line); line == "" { + // 历史命令 + continue } - - // 清空格式 - if m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")); f.out == os.Stdout { + if ps = f.ps1; f.stdout == os.Stdout { + // 清空格式 f.printf(m, "\033[0m") } - if m.Cap(ice.CTX_STREAM) == "stdio" { - m.Cmd(ice.WEB_FAVOR, "cmd.history", "cmd", kit.Select("stdio", arg, 0), line) - } - - // 解析命令 - f.parse(m, line) - m.Cost("stdin: %v", line) - line = "" + line = f.parse(m, line) } + return f +} + +func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { + return f +} +func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server { + return &Frame{} +} +func (f *Frame) Start(m *ice.Message, arg ...string) bool { + var r io.Reader + switch kit.Select(STDIO, arg, 0) { + case STDIO: + // 终端交互 + f.source = STDIO + r, f.stdout = os.Stdin, os.Stdout + m.Cap(ice.CTX_STREAM, STDIO) + f.target = m.Target() + aaa.UserRoot(m) + default: + + if s, e := os.Open(arg[0]); !m.Warn(e != nil, "%s", e) { + defer s.Close() + + buf := bytes.NewBuffer(make([]byte, 0, 4096)) + defer m.Echo(buf.String()) + + // 脚本解析 + f.source = arg[0] + r, f.stdout = s, buf + m.Cap(ice.CTX_STREAM, arg[0]) + f.target = m.Source() + break + } + return true + } + + f.scan(m, kit.Select(STDIO, arg, 0), "", r) return true } func (f *Frame) Close(m *ice.Message, arg ...string) bool { return true } +const ( + SOURCE = "source" + TARGET = "target" + PROMPT = "prompt" + QRCODE = "qrcode" + RETURN = "return" + REMOTE = "remote" +) +const ( + STDIO = "stdio" +) + var Index = &ice.Context{Name: "ssh", Help: "终端模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "history": {Name: "history", Help: "history", Value: kit.Data("limit", "200", "least", "100")}, - "prompt": {Name: "prompt", Help: "prompt", Value: kit.Data( + SOURCE: {Name: "prompt", Help: "命令提示", Value: kit.Data( + web.FAVOR, "cmd.history", + )}, + PROMPT: {Name: "prompt", Help: "命令提示", Value: kit.Data( "PS1", []interface{}{"\033[33;44m", "count", "[", "time", "]", "\033[5m", "target", "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"}, "PS2", []interface{}{"count", " ", "target", "> "}, )}, - - "super": {Name: "super", Help: "super", Value: kit.Data()}, + REMOTE: {Name: "remote", Help: "远程连接", Value: kit.Data()}, }, Commands: map[string]*ice.Command{ - ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Load() - }}, + ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Save("history") - - if f, ok := m.Target().Server().(*Frame); ok { - // 关闭终端 - f.in.Close() + if _, ok := m.Target().Server().(*Frame); ok { m.Done() } }}, - "history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) { - m.Push("", value, []string{"id", "time", "line"}) - }) - return - } - - switch arg[0] { - case "search": - m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) { - if strings.Contains(kit.Format(value["line"]), arg[1]) { - m.Push("", value, []string{"id", "time", "line"}) - } - }) - default: - m.Grows("history", nil, "id", arg[0], func(index int, value map[string]interface{}) { - m.Push("", value, []string{"id", "time", "line"}) - }) - } + SOURCE: {Name: "source file", Help: "脚本解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[0], arg[0:]...) }}, - "return": {Name: "return", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")) + TARGET: {Name: "target name", Help: "当前模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + m.Search(arg[0], func(p *ice.Context, s *ice.Context, key string) { + f := m.Target().Server().(*Frame) + f.target = s + f.prompt(m) + }) + }}, + PROMPT: {Name: "prompt arg...", Help: "命令提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + f := m.Target().Server().(*Frame) + f.ps1 = arg + f.prompt(m) + }}, + QRCODE: {Name: "qrcode arg...", Help: "命令提示", Action: map[string]*ice.Action{ + "json": {Name: "json [key val]...", Help: "json", Hand: func(m *ice.Message, arg ...string) { + val := map[string]interface{}{} + for i := 0; i < len(arg)-1; i += 2 { + kit.Value(val, arg[i], arg[i+1]) + } + f := m.Target().Server().(*Frame) + f.printf(m, m.Cmdx(cli.PYTHON, "qrcode", kit.Format(val))) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + f := m.Target().Server().(*Frame) + f.printf(m, m.Cmdx(cli.PYTHON, "qrcode", strings.Join(arg, ""))) + }}, + RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { f := m.Target().Server().(*Frame) f.exit = true }}, - "target": {Name: "target", Help: "目标", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - f := m.Target().Server().(*Frame) - m.Search(arg[0], func(p *ice.Context, s *ice.Context, key string) { - f.target = s - }) - f.prompt(m) - }}, - "source": {Name: "source file", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - buf := bytes.NewBuffer(make([]byte, 0, 4096)) - m.Optionv(ice.MSG_STDOUT, buf) - m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[0], arg[0:]...) - m.Echo(buf.String()) - }}, - "show": {Name: "show", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - f, e := os.Open("usr/local/what/hi.shy") - m.Assert(e) - - bio := bufio.NewScanner(f) - for bio.Scan() { - ls := kit.Split(bio.Text()) - m.Echo("%d: %v\n", len(ls), ls) - m.Info("%v", ls) - } - }}, - - "super": {Name: "super user remote port local", Help: "上位机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - key := m.Rich("super", nil, kit.Dict( + REMOTE: {Name: "remote user remote port local", Help: "远程连接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + key := m.Rich(REMOTE, nil, kit.Dict( "user", arg[0], "remote", arg[1], "port", arg[2], "local", arg[3], )) m.Echo(key) @@ -354,17 +370,13 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块", m.Gos(m, func(m *ice.Message) { for { - m.Cmd(ice.CLI_SYSTEM, "ssh", "-CNR", kit.Format("%s:%s:22", arg[2], arg[3]), kit.Format("%s@%s", arg[0], arg[1])) + m.Cmd(cli.SYSTEM, "ssh", "-CNR", kit.Format("%s:%s:22", arg[2], kit.Select("localhost", arg, 3)), + kit.Format("%s@%s", arg[0], arg[1])) m.Info("reconnect after 10s") time.Sleep(time.Second * 10) } }) }}, - - "what": {Name: "what", Help: "上位机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - ls := kit.Split("window:=auto", " ", ":=") - m.Echo("%v %v", len(ls), ls) - }}, }, } diff --git a/base/web/story.go b/base/web/story.go index b30eeabb..fc221cfb 100644 --- a/base/web/story.go +++ b/base/web/story.go @@ -384,6 +384,9 @@ func StoryAdd(m *ice.Message, mime string, name string, text string, arg ...stri } const STORY = "story" +const ( + CATCH = "catch" +) func init() { Index.Merge(&ice.Context{ diff --git a/core/wiki/draw.go b/core/wiki/draw.go index c4aaea4b..9b4ccb71 100644 --- a/core/wiki/draw.go +++ b/core/wiki/draw.go @@ -2,7 +2,6 @@ package wiki import ( "github.com/shylinux/icebergs" - "github.com/shylinux/icebergs/base/nfs" "github.com/shylinux/toolkits" "path" @@ -36,7 +35,7 @@ func init() { "display", "/plugin/local/wiki/draw.js", ), Action: map[string]*ice.Action{ "save": {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, arg ...string) { - nfs.FileSave(m, path.Join(m.Conf(DRAW, "meta.path"), kit.Select("hi.svg", arg, 0)), kit.Select(m.Option("content"), arg, 1)) + m.Cmd("nfs.save", path.Join(m.Conf(DRAW, "meta.path"), kit.Select("hi.svg", arg, 0)), kit.Select(m.Option("content"), arg, 1)) }}, "run": {Name: "show path text", Help: "运行", Hand: func(m *ice.Message, arg ...string) { _draw_show(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...) diff --git a/data.go b/data.go index 5897e3d9..adf12d7b 100644 --- a/data.go +++ b/data.go @@ -342,7 +342,7 @@ func (m *Message) Grows(key string, chain interface{}, match string, value strin order := 0 if begin < current { // 读取文件 - m.Log(LOG_INFO, "%s.%v read %v-%v from %v-%v", key, chain, begin, end, current, current+len(list)) + // m.Log(LOG_INFO, "%s.%v read %v-%v from %v-%v", key, chain, begin, end, current, current+len(list)) store, _ := meta["record"].([]interface{}) for s := len(store) - 1; s > -1; s-- { item, _ := store[s].(map[string]interface{}) diff --git a/exec.go b/exec.go index 4cb644f1..94c6f125 100644 --- a/exec.go +++ b/exec.go @@ -9,6 +9,7 @@ import ( "time" kit "github.com/shylinux/toolkits" + "github.com/shylinux/toolkits/task" ) func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message { @@ -112,6 +113,10 @@ func (m *Message) Back(res *Message) *Message { return m } func (m *Message) Gos(msg *Message, cb func(*Message)) *Message { - go func() { msg.TryCatch(msg, true, func(msg *Message) { cb(msg) }) }() + task.Put(nil, func(task *task.Task) error { + msg.Optionv("_task", task) + msg.TryCatch(msg, true, func(msg *Message) { cb(msg) }) + return nil + }) return m } diff --git a/base.go b/init.go similarity index 100% rename from base.go rename to init.go diff --git a/meta.go b/meta.go index ddc04bd4..396ec19c 100644 --- a/meta.go +++ b/meta.go @@ -52,6 +52,11 @@ func (m *Message) Set(key string, arg ...string) *Message { } func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Message { switch value := value.(type) { + case map[string]string: + for k, v := range value { + m.Push(k, v) + } + return m case map[string]interface{}: if key == "detail" { // 格式转换 @@ -452,6 +457,10 @@ func (m *Message) Append(key string, arg ...interface{}) string { return kit.Select("", m.Appendv(key, arg...), 0) } func (m *Message) Appendv(key string, arg ...interface{}) []string { + if key == MSG_APPEND { + m.meta[MSG_APPEND] = kit.Simple(arg) + return m.meta[key] + } if key == "_index" { max := 0 for _, k := range m.meta[MSG_APPEND] { diff --git a/misc/alpha/alpha.go b/misc/alpha/alpha.go index 9e45b322..c0f05bbd 100644 --- a/misc/alpha/alpha.go +++ b/misc/alpha/alpha.go @@ -47,7 +47,7 @@ func _alpha_find2(m *ice.Message, method, word string) { } var mu sync.Mutex - task.Sync(args, func(task *task.Task) error { + task.Sync(args, func(task *task.Task, lock *task.Lock) error { info := task.Arg.(os.FileInfo) file := path.Join(p, info.Name()) kit.CSV(file, 100000, func(index int, value map[string]string, head []string) { diff --git a/misc/input/input.go b/misc/input/input.go index 873ab1dc..520e5cf1 100644 --- a/misc/input/input.go +++ b/misc/input/input.go @@ -90,7 +90,7 @@ func _input_find2(m *ice.Message, method, word, limit string) { defer m.Cost("some") var mu sync.Mutex - task.Sync(list, func(task *task.Task) error { + task.Sync(list, func(task *task.Task, lock *task.Lock) error { kit.CSV(kit.Format(task.Arg), 100000, func(index int, value map[string]string, head []string) { if value["code"] != word { return @@ -181,7 +181,7 @@ var Index = &ice.Context{Name: "input", Help: "输入法", Configs: map[string]*ice.Config{ INPUT: {Name: "input", Help: "输入法", Value: kit.Data( "repos", "wubi-dict", "local", "person", - kit.MDB_STORE, "var/data/input", kit.MDB_FSIZE, "200000", + kit.MDB_STORE, "usr/export/input", kit.MDB_FSIZE, "200000", kit.MDB_LIMIT, "5000", kit.MDB_LEAST, "1000", kit.MDB_SHORT, "zone", )}, diff --git a/type.go b/type.go index c499f91b..aebc1e6e 100644 --- a/type.go +++ b/type.go @@ -78,6 +78,9 @@ func (c *Context) Cap(key string, arg ...interface{}) string { return c.Caches[key].Value } func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Message { + if cmd == nil { + return m + } m.meta[MSG_DETAIL] = kit.Simple(key, arg) m.Hand = true @@ -100,7 +103,7 @@ func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Mess } } } - if len(arg) > 0 { + if len(arg) > 0 && cmd.Action != nil { if h, ok := cmd.Action[arg[0]]; ok { m.Log(LOG_CMDS, "%s.%s %d %v %s", c.Name, key, len(arg), arg, kit.FileLine(h.Hand, 3)) h.Hand(m, arg[1:]...) @@ -499,7 +502,9 @@ func (m *Message) Search(key interface{}, cb interface{}) *Message { // 查找模块 p := m.target.root - if strings.Contains(key, ":") { + if ctx, ok := names[key].(*Context); ok { + p = ctx + } else if strings.Contains(key, ":") { } else if key == "." { if m.target.context != nil { @@ -597,14 +602,10 @@ func (m *Message) Cmd(arg ...interface{}) *Message { return m } - if ctx, ok := names[list[0]].(*Context); ok { - m.Hand = true - return ctx.Run(m.Spawns(ctx), ctx.Commands[list[0]], list[0], list[1:]...) - } - m.Search(list[0], func(p *Context, c *Context, key string, cmd *Command) { - m = p.Run(m.Spawns(c), cmd, key, list[1:]...) - m.Hand = true + m.TryCatch(m.Spawns(c), true, func(msg *Message) { + m = p.Run(msg, cmd, key, list[1:]...) + }) }) if m.Warn(m.Hand == false, "not found %v", list) {