1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-27 17:58:29 +08:00

add web.story

This commit is contained in:
shaoying 2019-12-21 15:15:18 +08:00
parent 6c32418390
commit 68a2e9525e
12 changed files with 434 additions and 198 deletions

19
base.go
View File

@ -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...)
})
}
})

View File

@ -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) {
}},

View File

@ -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]))
}
}},
},

View File

@ -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)
}
}
}
}},
},
}

View File

@ -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++
}

View File

@ -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}, "")
})
}
}},
},
}

18
conf.go
View File

@ -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",
}

View File

@ -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])
}
}

View File

@ -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 {

View File

@ -13,46 +13,54 @@ import (
"strings"
)
var prefix = `<svg vertion="1.1" xmlns="http://www.w3.org/2000/svg"
var prefix = `<svg class="story" data-name="{{.Option "name"}}" data-text="{{.Option "text"}}" vertion="1.1" xmlns="http://www.w3.org/2000/svg"
width="{{.Option "width"}}" height="{{.Option "height"}}" style="{{.Option "style"}}"
data-name="{{.Option "name"}}"
>`
var title = `<span>{{.Option "prefix"}}{{.Option "content"}}</span>`
var shell = `<div class="story code" data-name="{{.Option "name"}}" data-text="{{.Option "text"}}" data-input="{{.Option "input"}}">$ {{.Option "input"}}
{{.Option "output"}}</div>`
var title = `<span class="story">{{.Option "prefix"}}{{.Option "content"}}</span>`
var order = `<ul class="story" data-name="{{.Option "name"}}" data-text="{{.Option "text"}}">{{range $index, $value := .Optionv "list"}}<li>{{$value}}</li>{{end}}</ul>`
var table = `<table class="story" data-name="{{.Option "name"}} data-text="{{.Option "text"}}>
<tr>{{range $i, $v := .Optionv "head"}}<th>{{$v}}</th>{{end}}</tr>
{{range $index, $value := .Optionv "list"}}
<tr>{{range $i, $v := $value}}<td>{{$v}}</td>{{end}}</tr>
{{end}}
</table>`
var premenu = `<ul class="story premenu"></ul>`
var endmenu = `<ul class="story endmenu">
{{$menu := .Optionv "menu"}}
{{range $index, $value := Value $menu "list"}}
<li>{{Value $value "prefix"}} {{Value $value "content"}}</li>
{{end}}
</ul>
`
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": `</svg>`,
},
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", `</svg>`)},
},
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)
}},
},
}

View File

@ -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"}}

115
type.go
View File

@ -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
}