diff --git a/base.go b/base.go index 008fc7dc..788160cd 100644 --- a/base.go +++ b/base.go @@ -58,11 +58,6 @@ var Index = &Context{Name: "ice", Help: "冰山模块", "row_sep": "\n", "compact": "false", }}, - "cache": {Name: "数据缓存", Value: map[string]interface{}{ - "store": "var/data", - "limit": "30", - "least": "10", - }}, "help": {Value: map[string]interface{}{ "index": []interface{}{ "^_^ 欢迎使用冰山框架 ^_^", @@ -77,9 +72,9 @@ var Index = &Context{Name: "ice", Help: "冰山模块", }, Commands: map[string]*Command{ ICE_INIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { - m.Travel(func(p *Context, s *Context) { - if _, ok := s.Commands[ICE_INIT]; ok && p != nil { - m.Spawns(s).Runs(ICE_INIT, ICE_INIT, arg...) + m.Travel(func(p *Context, c *Context) { + if cmd, ok := c.Commands[ICE_INIT]; ok && p != nil { + c.Run(m.Spawns(c), cmd, ICE_INIT, arg...) } }) }}, @@ -98,10 +93,10 @@ var Index = &Context{Name: "ice", Help: "冰山模块", m.root.Cmd(ICE_EXIT) }}, ICE_EXIT: {Hand: func(m *Message, c *Context, cmd string, arg ...string) { - m.root.Travel(func(p *Context, s *Context) { - if _, ok := s.Commands[ICE_EXIT]; ok && p != nil { - m.TryCatch(m.Spawns(s), true, func(msg *Message) { - msg.Runs(ICE_EXIT, ICE_EXIT, arg...) + m.root.Travel(func(p *Context, c *Context) { + if cmd, ok := c.Commands[ICE_EXIT]; ok && p != nil { + m.TryCatch(m.Spawns(c), true, func(msg *Message) { + c.Run(msg, cmd, ICE_EXIT, arg...) }) } }) diff --git a/base/cli/cli.go b/base/cli/cli.go index d28e3584..d95541ac 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -25,7 +25,7 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块", }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd("ctx.config", "load", "var/conf/cli.json") + m.Cmd(ice.CTX_CONFIG, "load", "var/conf/cli.json") m.Conf("runtime", "host.GOARCH", runtime.GOARCH) m.Conf("runtime", "host.GOOS", runtime.GOOS) @@ -46,7 +46,7 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块", m.Log("info", "runtime %v", kit.Formats(m.Confv("runtime"))) }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd("ctx.config", "save", "var/conf/cli.json", "cli.runtime") + m.Cmd(ice.CTX_CONFIG, "save", "var/conf/cli.json", "cli.runtime") }}, "runtime": {Name: "runtime", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }}, diff --git a/base/ctx/ctx.go b/base/ctx/ctx.go index 2b10a511..6075876b 100644 --- a/base/ctx/ctx.go +++ b/base/ctx/ctx.go @@ -6,12 +6,15 @@ import ( "encoding/json" "os" + "path" "sort" ) var Index = &ice.Context{Name: "ctx", Help: "元始模块", - Caches: map[string]*ice.Cache{}, - Configs: map[string]*ice.Config{}, + Caches: map[string]*ice.Cache{}, + Configs: map[string]*ice.Config{ + ice.CTX_CONFIG: {Name: "config", Help: "配置", Value: ice.Data("path", "var/conf")}, + }, Commands: map[string]*ice.Command{ "context": {Name: "context", Help: "模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.Pulse.Travel(func(p *ice.Context, s *ice.Context) { @@ -53,26 +56,34 @@ var Index = &ice.Context{Name: "ctx", Help: "元始模块", return } - m.Search(arg[0]+"."+arg[1], func(p *ice.Context, s *ice.Context, key string) { - if i, ok := s.Commands[key]; ok { - if len(arg) == 2 { - m.Push("name", i.Name) - m.Push("help", i.Help) - m.Push("meta", kit.Format(i.Meta)) - m.Push("list", kit.Format(i.List)) + m.Search(arg[0]+"."+arg[1], func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) { + if len(arg) == 2 { + m.Push("name", cmd.Name) + m.Push("help", cmd.Help) + m.Push("meta", kit.Format(cmd.Meta)) + m.Push("list", kit.Format(cmd.List)) + } else { + if cmd.Meta != nil && kit.Format(cmd.Meta["remote"]) == "true" && m.Option("you") != "" { + m.Copy(m.Spawns(s).Cmd("web.space", m.Option("you"), "ctx.command", arg[0], arg[1], "run", arg[3:])) } else { - if i.Meta != nil && kit.Format(i.Meta["remote"]) == "true" && m.Option("you") != "" { - m.Copy(m.Spawns(s).Cmd("web.space", m.Option("you"), "ctx.command", arg[0], arg[1], "run", arg[3:])) - } else { - m.Copy(m.Spawns(s).Runs(key, key, arg[3:]...)) - } + m.Copy(s.Run(m.Spawns(s), cmd, key, arg[3:]...)) } } }) }}, - "config": {Name: "config", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ice.CTX_CONFIG: {Name: "config", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Travel(func(p *ice.Context, s *ice.Context, key string, conf *ice.Config) { + m.Push("key", key) + m.Push("name", conf.Name) + m.Push("value", kit.Format(conf.Value)) + }) + return + } + switch arg[0] { case "save": + arg[1] = path.Join(m.Conf(ice.CTX_CONFIG, ice.Meta("path")), arg[1]) if f, p, e := kit.Create(arg[1]); m.Assert(e) { data := map[string]interface{}{} for _, k := range arg[2:] { @@ -86,6 +97,7 @@ var Index = &ice.Context{Name: "ctx", Help: "元始模块", m.Echo(p) } case "load": + arg[1] = path.Join(m.Conf(ice.CTX_CONFIG, ice.Meta("path")), arg[1]) if f, e := os.Open(arg[1]); e == nil { data := map[string]interface{}{} json.NewDecoder(f).Decode(&data) @@ -97,6 +109,8 @@ var Index = &ice.Context{Name: "ctx", Help: "元始模块", }) } } + default: + m.Echo(m.Conf(arg[0])) } }}, }, diff --git a/base/nfs/nfs.go b/base/nfs/nfs.go index 22cdbd0b..8934d358 100644 --- a/base/nfs/nfs.go +++ b/base/nfs/nfs.go @@ -136,6 +136,17 @@ var Index = &ice.Context{Name: "nfs", Help: "文件模块", dir(m, arg[0], arg[1], 0, false, "both", rg, strings.Split(kit.Select("time size line path", arg, 2), " "), ice.ICE_TIME) }}, + "save": {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if f, p, e := kit.Create(arg[0]); m.Assert(e) { + defer f.Close() + for _, v := range arg[1:] { + if n, e := f.WriteString(v); m.Assert(e) { + m.Log("info", "save %v %v", n, p) + m.Echo(p) + } + } + } + }}, }, } diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go index e507ac94..32652300 100644 --- a/base/ssh/ssh.go +++ b/base/ssh/ssh.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "os" + "strings" ) type Frame struct { @@ -47,6 +48,9 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { } fmt.Fprintf(f.out, res) + if !strings.HasSuffix(res, "\n") { + fmt.Fprintf(f.out, "\n") + } fmt.Fprintf(f.out, m.Time(prompt, count, target.Name)) count++ } diff --git a/base/web/web.go b/base/web/web.go index d1436a28..1a6dab18 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -36,7 +36,6 @@ func Cookie(msg *ice.Message, sessid string) string { http.SetCookie(w, &http.Cookie{Name: ice.WEB_SESS, Value: sessid, Path: "/", Expires: expire}) return sessid } - func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool { if msg.Options(ice.WEB_SESS) { sub := msg.Cmd("aaa.sess", "check", msg.Option(ice.WEB_SESS)) @@ -44,7 +43,7 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request msg.Option("username", sub.Append("username"))) } - msg.Runs("_login", msg.Option("url"), kit.Simple(msg.Optionv("cmds"))...) + msg.Target().Runs(msg, msg.Option("url"), ice.WEB_LOGIN, kit.Simple(msg.Optionv("cmds"))...) return true } func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) bool { @@ -108,16 +107,13 @@ func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) bool { return false } func (web *Frame) HandleCGI(m *ice.Message, alias map[string]interface{}, which string) *template.Template { - cgi := template.FuncMap{ - "result": func(msg *ice.Message) string { - return msg.Result() - }, - } + cgi := template.FuncMap{} tmpl := template.New(ice.WEB_TMPL) cb := func(k string, p []string, v *ice.Command) { cgi[k] = func(arg ...interface{}) (res interface{}) { m.TryCatch(m.Spawn(), true, func(msg *ice.Message) { + m.Log("cmd", "%v %v %v", k, p, arg) v.Hand(msg, m.Target(), k, kit.Simple(p, arg)...) buffer := bytes.NewBuffer([]byte{}) @@ -280,7 +276,7 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool { } }) - port := m.Cap(ice.CTX_STREAM, kit.Select(m.Conf(ice.WEB_SPIDE, "self.port"), arg, 0)) + port := m.Cap(ice.CTX_STREAM, kit.Select(m.Conf(ice.WEB_SPIDE, ice.Meta("self", "port")), arg, 0)) m.Log("serve", "listen %s %v", port, m.Conf("cli.runtime", "node")) web.m, web.Server = m, &http.Server{Addr: port, Handler: web} m.Log("serve", "listen %s", web.Server.ListenAndServe()) @@ -293,58 +289,35 @@ func (web *Frame) Close(m *ice.Message, arg ...string) bool { var Index = &ice.Context{Name: "web", Help: "网页模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - ice.WEB_SPIDE: {Name: "客户端", Value: map[string]interface{}{ - "self": map[string]interface{}{"port": ice.WEB_PORT}, - }}, - ice.WEB_SERVE: {Name: "服务端", Value: map[string]interface{}{ + ice.WEB_SPIDE: {Name: "spide", Help: "客户端", Value: ice.Data("self.port", ice.WEB_PORT)}, + ice.WEB_SERVE: {Name: "serve", Help: "服务器", Value: map[string]interface{}{ "static": map[string]interface{}{"/": "usr/volcanos/", "/static/volcanos/": "usr/volcanos/", }, "template": map[string]interface{}{"path": "usr/template", "list": []interface{}{ - `{{define "raw"}}{{.|result}}{{end}}`, + `{{define "raw"}}{{.Result}}{{end}}`, }}, }}, - ice.WEB_SPACE: {Name: "空间端", Value: map[string]interface{}{ - ice.MDB_META: map[string]interface{}{"buffer": 4096, "redial": 3000}, - ice.MDB_HASH: map[string]interface{}{}, - ice.MDB_LIST: map[string]interface{}{}, - }}, + ice.WEB_SPACE: {Name: "space", Help: "空间站", Value: ice.Meta("buffer", 4096, "redial", 3000)}, + ice.WEB_STORY: {Name: "story", Help: "故事会", Value: ice.Data("short", "data")}, + ice.WEB_CACHE: {Name: "cache", Help: "缓存", Value: ice.Data( + "short", "text", "path", "var/file", + "store", "var/data", "limit", "30", "least", "10", + )}, + ice.WEB_ROUTE: {Name: "route", Help: "路由", Value: ice.Data()}, + ice.WEB_PROXY: {Name: "proxy", Help: "代理", Value: ice.Data()}, }, 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) { - m.Done() + 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) { m.Done() }}, + ice.WEB_SPIDE: {Name: "spide", Help: "客户端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }}, ice.WEB_SERVE: {Name: "serve", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Conf("cli.runtime", "node.name", m.Conf("cli.runtime", "boot.hostname")) m.Conf("cli.runtime", "node.type", "server") m.Target().Start(m, arg...) }}, - "/space": &ice.Command{Name: "/space", Help: "工作间", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - r := m.Optionv("request").(*http.Request) - w := m.Optionv("response").(http.ResponseWriter) - if s, e := websocket.Upgrade(w, r, nil, m.Confi("web.space", "meta.buffer"), m.Confi("web.space", "meta.buffer")); m.Assert(e) { - h := m.Option("name") - - meta := map[string]interface{}{ - "create_time": m.Time(), - "socket": s, - "type": m.Option("node"), - "name": m.Option("name"), - } - m.Confv(ice.WEB_SPACE, []string{ice.MDB_HASH, h}, meta) - m.Log("space", "conn %v %v", h, kit.Formats(m.Confv(ice.WEB_SPACE))) - - web := m.Target().Server().(*Frame) - m.Gos(m, func(m *ice.Message) { - web.HandleWSS(m, false, s) - m.Log("space", "close %v %v", h, kit.Formats(m.Confv(ice.WEB_SPACE))) - m.Confv(ice.WEB_SPACE, []string{ice.MDB_HASH, h}, "") - }) - } - }}, - ice.WEB_SPACE: &ice.Command{Name: "space", Help: "工作间", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ice.WEB_SPACE: {Name: "space", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { m.Conf(ice.WEB_SPACE, ice.MDB_HASH, func(key string, value map[string]interface{}) { m.Push(key, value) @@ -413,6 +386,125 @@ var Index = &ice.Context{Name: "web", Help: "网页模块", } } }}, + ice.WEB_STORY: {Name: "story", Help: "故事会", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Confm("story", ice.Meta("head"), func(key string, value map[string]interface{}) { + m.Push(key, value, []string{"key", "type", "time", "story"}) + }) + return + } + + // head list data time text file + switch arg[0] { + case "add": + // 查询索引 + head := kit.Hashs(arg[1]) + prev := m.Conf("story", ice.Meta("head", head, "list")) + m.Log("info", "head: %v prev: %v", head, prev) + + // 添加节点 + meta := map[string]interface{}{ + "time": m.Time(), + "story": arg[1], + "scene": arg[2], + "data": m.Cmdx(ice.WEB_CACHE, "add", "text", arg[2]), + "prev": prev, + } + list := m.Rich("story", nil, meta) + m.Log("info", "list: %v meta: %v", list, kit.Format(meta)) + + // 添加索引 + m.Conf("story", ice.Meta("head", head), map[string]interface{}{ + "time": m.Time(), "type": "text", + "story": arg[1], "list": list, + }) + m.Echo(list) + + case "commit": + // 查询索引 + head := kit.Hashs(arg[1]) + prev := m.Conf("story", ice.Meta("head", head, "list")) + m.Log("info", "head: %v prev: %v", head, prev) + + // 查询节点 + menu := map[string]string{} + for i := 2; i < len(arg); i++ { + if i < len(arg)-1 && m.Confs("story", kit.Keys("hash", arg[i+1])) { + menu[arg[i]] = arg[i+1] + i++ + } else if head := kit.Hashs(arg[i]); m.Confs("story", kit.Keys("meta", "head", head)) { + menu[arg[i]] = head + } else { + m.Error("not found %v", arg[i]) + return + } + } + + // 添加节点 + meta := map[string]interface{}{ + "time": m.Time(), + "story": arg[1], + "list": menu, + "prev": prev, + } + list := m.Rich("story", nil, meta) + m.Log("info", "list: %v meta: %v", list, kit.Format(meta)) + + // 添加索引 + m.Conf("story", ice.Meta("head", head), map[string]interface{}{ + "time": m.Time(), "type": "list", + "story": arg[1], "list": list, + }) + m.Echo(list) + } + }}, + ice.WEB_CACHE: {Name: "cache", Help: "缓存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if len(arg) == 0 { + m.Confm("cache", "hash", func(key string, value map[string]interface{}) { + m.Push(key, value, []string{"time", "text"}) + }) + return + } + + switch arg[0] { + case "add": + // 添加数据 + data := m.Rich("cache", nil, map[string]interface{}{ + "time": m.Time(), "type": arg[1], arg[1]: arg[2], + }) + m.Info("data: %v type: %v text: %v", data, arg[1], arg[2]) + m.Echo(data) + m.Cmd("nfs.save", path.Join(m.Conf("cache", ice.Meta("path")), data[:2], data), arg[2]) + } + }}, + ice.WEB_ROUTE: {Name: "route", Help: "路由", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + }}, + ice.WEB_PROXY: {Name: "proxy", Help: "代理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + }}, + + "/space": &ice.Command{Name: "/space", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + r := m.Optionv("request").(*http.Request) + w := m.Optionv("response").(http.ResponseWriter) + if s, e := websocket.Upgrade(w, r, nil, m.Confi("web.space", "meta.buffer"), m.Confi("web.space", "meta.buffer")); m.Assert(e) { + h := m.Option("name") + + meta := map[string]interface{}{ + "create_time": m.Time(), + "socket": s, + "type": m.Option("node"), + "name": m.Option("name"), + } + m.Confv(ice.WEB_SPACE, []string{ice.MDB_HASH, h}, meta) + m.Log("space", "conn %v %v", h, kit.Formats(m.Confv(ice.WEB_SPACE))) + + web := m.Target().Server().(*Frame) + m.Gos(m, func(m *ice.Message) { + web.HandleWSS(m, false, s) + m.Log("space", "close %v %v", h, kit.Formats(m.Confv(ice.WEB_SPACE))) + m.Confv(ice.WEB_SPACE, []string{ice.MDB_HASH, h}, "") + }) + } + }}, }, } diff --git a/conf.go b/conf.go index 7246fd6e..58d81015 100644 --- a/conf.go +++ b/conf.go @@ -10,6 +10,7 @@ const ( const ( CTX_STATUS = "status" CTX_STREAM = "stream" + CTX_CONFIG = "config" ) const ( MSG_DETAIL = "detail" @@ -21,15 +22,22 @@ const ( MDB_META = "meta" MDB_LIST = "list" MDB_HASH = "hash" + + MDB_TYPE = "_type" ) const ( WEB_PORT = ":9020" WEB_SESS = "sessid" WEB_TMPL = "render" + WEB_LOGIN = "_login" WEB_SPIDE = "spide" WEB_SERVE = "serve" WEB_SPACE = "space" + WEB_STORY = "story" + WEB_CACHE = "cache" + WEB_ROUTE = "route" + WEB_PROXY = "proxy" ) const ( GDB_SIGNAL = "signal" @@ -49,11 +57,19 @@ const ( ) var Alias = map[string]string{ + CTX_CONFIG: "ctx.config", + GDB_SIGNAL: "gdb.signal", GDB_TIMER: "gdb.timer", GDB_EVENT: "gdb.event", WEB_SPIDE: "web.spide", + WEB_SERVE: "web.serve", WEB_SPACE: "web.space", - "note": "web.wiki.note", + WEB_STORY: "web.story", + WEB_CACHE: "web.cache", + WEB_ROUTE: "web.route", + WEB_PROXY: "web.proxy", + + "note": "web.wiki.note", } diff --git a/core/chat/chat.go b/core/chat/chat.go index db624957..a7c90a92 100644 --- a/core/chat/chat.go +++ b/core/chat/chat.go @@ -1,44 +1,43 @@ package chat import ( - "github.com/shylinux/toolkits" - "github.com/shylinux/icebergs" _ "github.com/shylinux/icebergs/base" "github.com/shylinux/icebergs/base/web" + "github.com/shylinux/toolkits" ) var Index = &ice.Context{Name: "chat", Help: "聊天模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "group": {Name: "group", Value: map[string]interface{}{ - ice.MDB_META: map[string]interface{}{}, - ice.MDB_LIST: map[string]interface{}{}, - ice.MDB_HASH: map[string]interface{}{}, - }}, + "group": {Name: "group", Help: "群组", Value: ice.Data()}, }, Commands: map[string]*ice.Command{ ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd("ctx.config", "load", "var/conf/aaa.json") - m.Cmd("ctx.config", "load", "var/conf/chat.json") + m.Cmd(ice.CTX_CONFIG, "load", "aaa.json") + m.Cmd(ice.CTX_CONFIG, "load", "web.json") + m.Cmd(ice.CTX_CONFIG, "load", "chat.json") }}, ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd("ctx.config", "save", "var/conf/chat.json", "web.chat.group") - m.Cmd("ctx.config", "save", "var/conf/aaa.json", "aaa.role", "aaa.user", "aaa.sess") + m.Cmd(ice.CTX_CONFIG, "save", "chat.json", "web.chat.group") + m.Cmd(ice.CTX_CONFIG, "save", "web.json", "web.story", "web.cache") + m.Cmd(ice.CTX_CONFIG, "save", "aaa.json", "aaa.role", "aaa.user", "aaa.sess") }}, - "_login": {Name: "_login", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + ice.WEB_LOGIN: {Name: "login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if cmd != "/login" { if !m.Options(ice.WEB_SESS) || !m.Options("username") { + // 检查失败 + m.Log(ice.LOG_WARN, "not login").Error("not login") m.Option("path", "") - m.Log("warn", "not login") - m.Echo("error").Echo("not login") return } } - if len(arg) > 0 && m.Confs("group", "hash."+arg[0]) { + + // 查询群组 + if len(arg) > 0 && m.Confs("group", kit.Keys("hash", arg[0])) { m.Option("sess.river", arg[0]) - if len(arg) > 1 && m.Confs("group", "hash."+arg[0]+".tool.hash."+arg[1]) { + if len(arg) > 1 && m.Confs("group", kit.Keys("hash", arg[0], "tool", "hash", arg[1])) { m.Option("sess.storm", arg[1]) } } diff --git a/core/wiki/chart.go b/core/wiki/chart.go index 2305dfcb..a5b7fc54 100644 --- a/core/wiki/chart.go +++ b/core/wiki/chart.go @@ -104,7 +104,7 @@ func (b *Chain) Init(m *ice.Message, arg ...string) Chart { width += b.GetWidths(strings.Repeat(" ", v)) } b.Width = width - m.Log("info", "data %v", kit.Formats(b.data)) + // m.Log("info", "data %v", kit.Formats(b.data)) return b } func (b *Chain) Draw(m *ice.Message, x, y int) Chart { @@ -242,7 +242,7 @@ func (b *Table) Init(m *ice.Message, arg ...string) Chart { b.Width = width b.Height = len(b.data) * b.GetHeights() - m.Log("info", "data %v", kit.Formats(b.data)) + // m.Log("info", "data %v", kit.Formats(b.data)) return b } func (b *Table) Draw(m *ice.Message, x, y int) Chart { diff --git a/core/wiki/wiki.go b/core/wiki/wiki.go index 7ff75fe2..4ea0e1d7 100644 --- a/core/wiki/wiki.go +++ b/core/wiki/wiki.go @@ -13,46 +13,54 @@ import ( "strings" ) -var prefix = `` -var title = `{{.Option "prefix"}}{{.Option "content"}}` + +var shell = `
$ {{.Option "input"}} +{{.Option "output"}}
` + +var title = `{{.Option "prefix"}}{{.Option "content"}}` + +var order = `` + +var table = ` +{{range $i, $v := .Optionv "head"}}{{end}} +{{range $index, $value := .Optionv "list"}} +{{range $i, $v := $value}}{{end}} +{{end}} +
{{$v}}
{{$v}}
` + +var premenu = `` +var endmenu = ` +` var Index = &ice.Context{Name: "wiki", Help: "文档模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ - "note": {Name: "note", Help: "笔记", Value: map[string]interface{}{ - ice.MDB_META: map[string]interface{}{ - "temp": "var/tmp/file", - "path": "usr/local/wiki", - "head": "time size line path", - "alias": map[string]interface{}{ - "block": []interface{}{"chart", "block"}, - "chain": []interface{}{"chart", "chain"}, - "table": []interface{}{"chart", "table"}, + "note": {Name: "note", Help: "笔记", Value: ice.Data( + "temp", "var/tmp/file", + "path", "usr/local/wiki", + "head", "time size line path", + "alias", map[string]interface{}{ + "block": []interface{}{"chart", "block"}, + "chain": []interface{}{"chart", "chain"}, - "chapter": []interface{}{"title", "chapter"}, - "section": []interface{}{"title", "section"}, - }, + "chapter": []interface{}{"title", "chapter"}, + "section": []interface{}{"title", "section"}, }, - ice.MDB_LIST: map[string]interface{}{}, - ice.MDB_HASH: map[string]interface{}{}, - }}, - "chart": {Name: "chart", Help: "绘图", Value: map[string]interface{}{ - ice.MDB_META: map[string]interface{}{ - "prefix": prefix, "suffix": ``, - }, - ice.MDB_LIST: map[string]interface{}{}, - ice.MDB_HASH: map[string]interface{}{}, - }}, - "title": {Name: "title", Help: "标题", Value: map[string]interface{}{ - ice.MDB_META: map[string]interface{}{ - "title": title, - }, - ice.MDB_LIST: map[string]interface{}{}, - ice.MDB_HASH: map[string]interface{}{}, - }}, + )}, + "title": {Name: "title", Help: "标题", Value: ice.Data("template", title)}, + "shell": {Name: "shell", Help: "命令", Value: ice.Data("template", shell)}, + "order": {Name: "order", Help: "列表", Value: ice.Data("template", order)}, + "table": {Name: "table", Help: "表格", Value: ice.Data("template", table)}, + "chart": {Name: "chart", Help: "绘图", Value: ice.Data("prefix", prefix, "suffix", ``)}, }, Commands: map[string]*ice.Command{ "chart": {Name: "chart block|chain|table name text [fg bg fs ls p m]", Help: "绘图", Meta: map[string]interface{}{ @@ -76,7 +84,6 @@ var Index = &ice.Context{Name: "wiki", Help: "文档模块", arg[2] = strings.TrimSpace(arg[2]) // 构造数据 - m.Option(ice.WEB_TMPL, "raw") m.Option("name", arg[1]) m.Option("text", arg[2]) chart.Init(m, arg[2:]...) @@ -87,12 +94,73 @@ var Index = &ice.Context{Name: "wiki", Help: "文档模块", m.Render(m.Conf("chart", ice.Meta("prefix"))) chart.Draw(m, 0, 0) m.Render(m.Conf("chart", ice.Meta("suffix"))) - return + }}, + "table": {Name: "table name text", Help: "表格", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + head, list := []string{}, [][]string{} + for i, v := range kit.Split(arg[1], "\n") { + if i == 0 { + head = kit.Split(v) + } else { + list = append(list, kit.Split(v)) + } + } + m.Optionv("head", head) + m.Optionv("list", list) + m.Render(m.Conf("table", ice.Meta("template"))) + }}, + "order": {Name: "order name text", Help: "列表", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Optionv("name", arg[0]) + m.Optionv("text", arg[1]) + m.Optionv("list", kit.Split(arg[1], "\n")) + m.Render(m.Conf("order", ice.Meta("template"))) + }}, + "shell": {Name: "shell dir cmd", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Option("cmd_dir", arg[0]) + m.Option("input", strings.Join(arg[1:], " ")) + m.Option("output", m.Cmdx("cli.system", "sh", "-c", strings.Join(arg[1:], " "))) + m.Render(m.Conf("shell", ice.Meta("template"))) + }}, + "title": {Name: "title text", Help: "标题", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + // 生成序号 + title, _ := m.Optionv("title").(map[string]int) + switch arg[0] { + case "premenu": + m.Echo(premenu) + return + case "endmenu": + m.Render(endmenu) + return + case "section": + arg = arg[1:] + title["section"]++ + m.Option("prefix", fmt.Sprintf("%d.%d ", title["chapter"], title["section"])) + case "chapter": + arg = arg[1:] + title["chapter"]++ + title["section"] = 0 + m.Option("prefix", fmt.Sprintf("%d ", title["chapter"])) + default: + m.Option("prefix", "") + } + + ns := strings.Split(m.Conf("runtime", "node.name"), "-") + + // 生成菜单 + menu, _ := m.Optionv("menu").(map[string]interface{}) + list, _ := menu["list"].([]interface{}) + menu["list"] = append(list, map[string]interface{}{ + "content": m.Option("content", kit.Select(ns[len(ns)-1], arg, 0)), + "prefix": m.Option("prefix"), + }) + + // 生成网页 + m.Render(m.Conf("title", ice.Meta("template"))) }}, "_text": {Name: "_text file", Help: "文章", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { m.Option(ice.WEB_TMPL, "raw") m.Optionv("title", map[string]int{}) + m.Optionv("menu", map[string]interface{}{}) // 生成文章 buffer := bytes.NewBuffer([]byte{}) @@ -117,33 +185,20 @@ var Index = &ice.Context{Name: "wiki", Help: "文档模块", }}, "note": {Name: "note file", Help: "笔记", Meta: map[string]interface{}{ "remote": "true", "display": "inner", - }, List: []interface{}{ - map[string]interface{}{"type": "text", "value": "miss.md", "name": "path"}, - map[string]interface{}{"type": "button", "value": "执行", "action": "auto"}, - map[string]interface{}{"type": "button", "value": "返回", "cb": "Last"}, - }, Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { - m.Cmdy(kit.Select("_tree", "_text", len(arg) > 0 && strings.HasSuffix(arg[0], ".md")), arg) - }}, - - "title": {Name: "title text", Help: "标题", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - title, _ := m.Optionv("title").(map[string]int) - switch arg[0] { - case "section": - arg = arg[1:] - title["section"]++ - m.Option("prefix", fmt.Sprintf("%d.%d ", title["chapter"], title["section"])) - case "chapter": - arg = arg[1:] - title["chapter"]++ - title["section"] = 0 - m.Option("prefix", fmt.Sprintf("%d ", title["chapter"])) - default: - m.Option("prefix", "") + "detail": []string{"add", "commit", "favor", "detail"}, + }, List: ice.List( + ice.MDB_TYPE, "text", "value", "miss.md", "name", "path", + ice.MDB_TYPE, "button", "value", "执行", "action", "auto", + ice.MDB_TYPE, "button", "value", "返回", "cb", "Last", + ), Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + if len(arg) > 0 { + switch arg[0] { + case "story": + m.Cmdy(arg) + return + } } - - ns := strings.Split(m.Conf("runtime", "node.name"), "-") - m.Option("content", kit.Select(ns[len(ns)-1], arg, 0)) - m.Render(m.Conf("title", ice.Meta("title"))) + m.Cmdy(kit.Select("_tree", "_text", len(arg) > 0 && strings.HasSuffix(arg[0], ".md")), arg) }}, }, } diff --git a/demo/usr/local/wiki/miss.md b/demo/usr/local/wiki/miss.md index efcad77f..dfda5df4 100644 --- a/demo/usr/local/wiki/miss.md +++ b/demo/usr/local/wiki/miss.md @@ -1,22 +1,24 @@ # {{title "hello world"}} -{{table "项目" ` +{{shell "" "uptime"}} + +{{title "premenu"}} + +## {{chapter "项目总览"}} +{{table "总览" ` volcano iceberg context toolkit preload appframe `}} -## {{chapter "hello world"}} - -{{table "框架" ` -ctx cli aaa web -lex yac gdb log -tcp nfs ssh mdb +{{order "总览" ` +volcano iceberg +context toolkit +preload appframe `}} -### {{section "hello world"}} - -{{chain "孵化" ` +## {{chapter "项目详情"}} +{{chain "详情" ` context volcanos proto.js @@ -47,4 +49,5 @@ context misc.go `}} -### {{section "hello world"}} +{{title "endmenu"}} + diff --git a/type.go b/type.go index d390e45e..3d87c2ef 100644 --- a/type.go +++ b/type.go @@ -74,6 +74,18 @@ func (c *Context) Cap(key string, arg ...interface{}) string { func (c *Context) Server() Server { return c.server } +func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Message { + m.Hand = true + m.Log(LOG_CMD, "%s.%s %v", c.Name, key, arg) + cmd.Hand(m, c, key, arg...) + return m +} +func (c *Context) Runs(m *Message, cmd string, key string, arg ...string) { + if s, ok := m.Target().Commands[key]; ok { + c.Run(m, s, cmd, arg...) + } + return +} func (c *Context) Register(s *Context, x Server) *Context { Pulse.Log("register", "%s <- %s", c.Name, s.Name) if c.contexts == nil { @@ -345,7 +357,7 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa } for _, k := range list { if k == "key" { - m.Add(MSG_APPEND, k, k) + m.Add(MSG_APPEND, k, key) } else { m.Add(MSG_APPEND, k, kit.Format(value[k])) } @@ -358,6 +370,9 @@ func (m *Message) Echo(str string, arg ...interface{}) *Message { m.meta[MSG_RESULT] = append(m.meta[MSG_RESULT], fmt.Sprintf(str, arg...)) return m } +func (m *Message) Error(str string, arg ...interface{}) *Message { + return m.Echo("error").Echo(str, arg...) +} func (m *Message) Sort(key string, arg ...string) *Message { cmp := "str" if len(arg) > 0 && arg[0] != "" { @@ -581,6 +596,9 @@ func (m *Message) Log(level string, str string, arg ...interface{}) *Message { prefix, level, fmt.Sprintf(str, arg...), suffix) return m } +func (m *Message) Info(str string, arg ...interface{}) *Message { + return m.Log(LOG_INFO, str, arg...) +} func (m *Message) Assert(arg interface{}) bool { switch arg := arg.(type) { case nil: @@ -624,14 +642,6 @@ func (m *Message) Run(arg ...string) *Message { m.target.server.Start(m, arg...) return m } -func (m *Message) Runs(key string, cmd string, arg ...string) *Message { - if s, ok := m.Target().Commands[key]; ok { - m.meta[MSG_DETAIL] = append([]string{cmd}, arg...) - m.Log(LOG_CMD, "%s.%s %s %v", m.Target().Name, key, cmd, arg) - s.Hand(m, m.Target(), cmd, arg...) - } - return m -} func (m *Message) Done() bool { defer func() { recover() }() if m.target.context != nil && m.target.context.wg != nil { @@ -704,19 +714,19 @@ func (m *Message) Travel(cb interface{}) *Message { } return m } -func (m *Message) Search(key interface{}, cb func(p *Context, s *Context, key string)) *Message { +func (m *Message) Search(key interface{}, cb interface{}) *Message { switch key := key.(type) { case string: if k, ok := Alias[key]; ok { key = k } + p := m.target.root if strings.Contains(key, ":") { } else if strings.Contains(key, ".") { list := strings.Split(key, ".") - p := m.target.root for _, v := range list[:len(list)-1] { if s, ok := p.contexts[v]; ok { p = s @@ -729,9 +739,26 @@ func (m *Message) Search(key interface{}, cb func(p *Context, s *Context, key st m.Log(LOG_WARN, "not found %s", key) break } - cb(p.context, p, list[len(list)-1]) + key = list[len(list)-1] } else { - cb(m.target.context, m.target, key) + p = m.target + } + + switch cb := cb.(type) { + case func(p *Context, s *Context, key string, cmd *Command): + for c := p; c != nil; c = c.context { + if cmd, ok := c.Commands[key]; ok { + cb(c.context, c, key, cmd) + } + } + case func(p *Context, s *Context, key string, conf *Config): + for c := p; c != nil; c = c.context { + if cmd, ok := c.Configs[key]; ok { + cb(c.context, c, key, cmd) + } + } + case func(p *Context, s *Context, key string): + cb(p.context, p, key) } } return m @@ -740,7 +767,28 @@ func (m *Message) Search(key interface{}, cb func(p *Context, s *Context, key st func Meta(arg ...interface{}) string { return MDB_META + "." + kit.Keys(arg...) } -func (m *Message) Rich(key string, args interface{}, data interface{}) map[string]interface{} { +func Data(arg ...interface{}) map[string]interface{} { + meta := map[string]interface{}{} + data := map[string]interface{}{ + MDB_META: meta, MDB_LIST: []interface{}{}, MDB_HASH: map[string]interface{}{}, + } + for i := 0; i < len(arg)-1; i += 2 { + kit.Value(meta, arg[i], arg[i+1]) + } + return data +} +func List(arg ...interface{}) []interface{} { + list, data := []interface{}{}, map[string]interface{}{} + for i := 0; i < len(arg)-1; i += 2 { + if arg[i] == MDB_TYPE { + data = map[string]interface{}{} + list = append(list, data) + } + kit.Value(data, arg[i], arg[i+1]) + } + return list +} +func (m *Message) Rich(key string, args interface{}, data interface{}) string { cache := m.Confm(key, args) if cache == nil { cache = map[string]interface{}{} @@ -754,7 +802,15 @@ func (m *Message) Rich(key string, args interface{}, data interface{}) map[strin hash = map[string]interface{}{} } - h := kit.ShortKey(hash, 6) + h := "" + switch short := kit.Format(kit.Value(meta, "short")); short { + case "": + h = kit.ShortKey(hash, 6) + case "data": + h = kit.Hashs(kit.Format(data)) + default: + h = kit.Hashs(kit.Format(kit.Value(data, short))) + } hash[h] = data cache[MDB_HASH] = hash @@ -764,7 +820,7 @@ func (m *Message) Rich(key string, args interface{}, data interface{}) map[strin } else { m.Conf(key, args, cache) } - return meta + return h } func (m *Message) Grow(key string, args interface{}, data interface{}) map[string]interface{} { cache := m.Confm(key, args) @@ -783,11 +839,11 @@ func (m *Message) Grow(key string, args interface{}, data interface{}) map[strin kit.Value(data, "id", meta["count"]) // 保存数据 - if len(list) > kit.Int(kit.Select(m.Conf("cache", "limit"), meta["limit"])) { - least := kit.Int(kit.Select(m.Conf("cache", "least"), meta["least"])) + if len(list) > kit.Int(kit.Select(m.Conf("cache", Meta("limit")), meta["limit"])) { + least := kit.Int(kit.Select(m.Conf("cache", Meta("least")), meta["least"])) // 创建文件 - name := kit.Select(path.Join(m.Conf("cache", "store"), key+".csv"), meta["store"]) + name := kit.Select(path.Join(m.Conf("cache", Meta("store")), key+".csv"), meta["store"]) f, e := os.OpenFile(name, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) if e != nil { f, _, e = kit.Create(name) @@ -973,21 +1029,12 @@ func (m *Message) Cmd(arg ...interface{}) *Message { return m } - m.Search(list[0], func(p *Context, s *Context, key string) { - for c := s; c != nil; c = c.context { - if cmd, ok := c.Commands[key]; ok { - m.TryCatch(m.Spawns(s), true, func(msg *Message) { - - msg.Hand = true - m.Hand = true - m = msg - msg.Log(LOG_CMD, "%s.%s %v", c.Name, key, list[1:]) - msg.meta[MSG_DETAIL] = list - cmd.Hand(msg, c, key, list[1:]...) - }) - break - } - } + m.Search(list[0], func(p *Context, c *Context, key string, cmd *Command) { + m.TryCatch(m.Spawns(c), true, func(msg *Message) { + m.Hand, m = true, msg + msg.meta[MSG_DETAIL] = list + c.Run(msg, cmd, key, list[1:]...) + }) }) return m }