1
0
mirror of https://shylinux.com/x/icebergs synced 2025-06-26 18:37:29 +08:00
This commit is contained in:
harveyshao 2022-11-19 22:54:37 +08:00
parent deca0a8e8d
commit 15c6d3f064
25 changed files with 657 additions and 983 deletions

128
README.md
View File

@ -1,129 +1,3 @@
# icebergs # icebergs
icebergs是一个应用框架通过模块化、集群化、自动化快速搭建起完整的个人云计算平台。 icebergs 是一个应用框架,通过模块化、集群化、自动化方式,在各种设备上,一键部署完整的个人云计算与云研发平台。
- 使用icebergs可以将各种模块或项目集成到一起快速开发出集中式的服务器。
- 使用icebergs可以将各种设备自由的组合在一起快速搭建起分布式的服务器。
## 0. 搭建服务
### 0.1 一键部署
```sh
mkdir miss; cd miss && curl -s https://shylinux.com/publish/ice.sh | sh
```
脚本会根据当前系统类型自动下载程序文件ice.bin并自动启动服务。
### 0.2 使用方式
**终端交互**
启动后的进程像bash一样是一个可交互的shell可以执行各种模块命令或系统命令。
**网页交互**
默认还会启动一个web服务访问地址 http://localhost:9020 ,就可以通过网页进行操作。
**重启服务**
在终端按Ctrl+C就可以重新启动服务。
**结束服务**
在终端按Ctrl+\,就可以停止服务。
### 0.3 使用示例
## 1. 项目开发
icebergs是一个应用框架如果官方模块无法满足使用需求还可以搜集第三方模块自行编译程序。
如果第三方模块也无法满足使用需求,还可以自己开发模块,
icebergs提供了模板可以一键创建新模块快速添加自己的功能模块。
### 1.1 部署环境
*开发环境需要提前安装好git和golang*
```sh
mkdir miss; cd miss && curl -s https://shylinux.com/publish/template.sh | sh
```
template.sh会自动创建出项目模板并自动编译生成程序然后启动服务。
为了方便以后创建项目与模块。
可以将辅助脚本template.sh下载并添加到可执行目录中。
### 1.2 添加第三方模块
在src/main.go文件中就可以import任意的第三方模块
执行一下make命令就会重新生成ice.bin。
重新启动服务,就可以使用第三方模块了。
### 1.3 开发模块
```sh
template.sh tutor hello
```
使用之前下载的template.sh调用tutor命令并指定模块名称hello就可以一键创建模块了。
在src/main.go 中import新加的模块
执行make命令程序编译完成后
重启服务,就可以使用新模块了。
### 1.4 开发框架
如果现有的框架,无法满足需求,还可以下载框架源码自行更改。
```sh
git clone https://shylinux.com/x/icebergs usr/icebergs
```
修改go.mod文件引用本地框架。
```go
replace shylinux.com/x/icebergs => ./usr/icebergs
```
## 2 原型 type.go
### 2.1 msg.Detail
### 2.2 msg.Option
### 2.3 msg.Append
### 2.4 msg.Result
### 2.5 msg.Travel
### 2.6 msg.Search
### 2.7 msg.Conf
### 2.8 msg.Cmd
### 2.9 msg.Cap
## 3 框架 base.go
### 3.1 注册模块 Register
### 3.2 创建资源 Begin
### 3.3 加载配置 _init
### 3.4 启动服务 Start
### 3.5 保存配置 _exit
### 3.6 释放资源 Close
## 4 基础模块 base/
### 4.1 模块中心 base/ctx/
### 4.2 命令中心 base/cli/
### 4.3 认证中心 base/aaa/
### 4.4 网页中心 base/web/
### 4.5 词法中心 base/lex/
### 4.6 语法中心 base/yac/
### 4.7 事件中心 base/gdb/
### 4.8 日志中心 base/log/
### 4.9 网络中心 base/tcp/
### 4.10 文件中心 base/nfs/
### 4.11 终端中心 base/ssh/
### 4.12 数据中心 base/mdb/
## 5 核心模块 core/
### 5.1 编程中心 core/code/
### 5.2 文档中心 core/wiki/
### 5.3 聊天中心 core/chat/
### 5.4 团队中心 core/team/
### 5.5 贸易中心 core/mall/
## 6 其它模块 misc/
### 6.1 终端管理 misc/zsh/
### 6.1 终端管理 misc/tmux/
### 6.1 代码管理 misc/git/
### 6.1 代码管理 misc/vim/
### 6.1 公众号 misc/mp/
### 6.1 小程序 misc/wx/
### 6.1 浏览器 misc/chrome/
### 6.1 机器人 misc/lark/
### 6.1 开发板 misc/pi/

View File

@ -83,11 +83,11 @@ func init() {
} }
func UserRoot(m *ice.Message, arg ...string) *ice.Message { // password username userrole func UserRoot(m *ice.Message, arg ...string) *ice.Message { // password username userrole
userrole := m.Option(ice.MSG_USERROLE, ROOT)
username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 1)) username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 1))
userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2)) usernick := m.Option(ice.MSG_USERNICK, kit.Select(UserNick(m, username), arg, 2))
m.Option(ice.MSG_USERNICK, UserNick(m, username))
if len(arg) > 0 { if len(arg) > 0 {
m.Cmd(USER, mdb.CREATE, username, kit.Select("", arg, 0), userrole, kit.Select("", arg, 3)) m.Cmd(USER, mdb.CREATE, username, kit.Select("", arg, 0), userrole, usernick)
ice.Info.UserName = username ice.Info.UserName = username
} }
return m return m

View File

@ -216,7 +216,7 @@ func init() {
}}, }},
PROCKILL: {Name: "prockill", Help: "结束进程", Hand: func(m *ice.Message, arg ...string) { PROCKILL: {Name: "prockill", Help: "结束进程", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID")) m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID"))
m.ProcessRefresh30ms() m.ProcessRefresh()
}}, }},
DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) { DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) {
_runtime_diskinfo(m) _runtime_diskinfo(m)

View File

@ -191,7 +191,7 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands
} }
}}, }},
INSERT: {Name: "insert key sub type arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) { INSERT: {Name: "insert key sub type arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
defer m.ProcessRefresh3ms() defer m.ProcessRefresh()
switch arg[2] { switch arg[2] {
case ZONE: // insert key sub type zone arg... case ZONE: // insert key sub type zone arg...
_zone_insert(m, arg[0], arg[1], arg[3], arg[4:]...) _zone_insert(m, arg[0], arg[1], arg[3], arg[4:]...)
@ -202,7 +202,7 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: ice.Commands
} }
}}, }},
DELETE: {Name: "delete key sub type field value", Help: "删除", Hand: func(m *ice.Message, arg ...string) { DELETE: {Name: "delete key sub type field value", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
defer m.ProcessRefresh3ms() defer m.ProcessRefresh()
switch arg[2] { switch arg[2] {
case ZONE: // delete key sub type zone field value case ZONE: // delete key sub type zone field value
// _list_delete(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4], arg[5]) // _list_delete(m, arg[0], _domain_chain(m, kit.Keys(arg[1], kit.KeyHash(arg[3]))), arg[4], arg[5])

View File

@ -9,6 +9,13 @@ const SEARCH = "search"
func init() { func init() {
Index.MergeCommands(ice.Commands{SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: RenderAction()}}) Index.MergeCommands(ice.Commands{SEARCH: {Name: "search type name text auto", Help: "搜索", Actions: RenderAction()}})
ice.AddMerges(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) {
switch sub {
case SEARCH:
return func(m *ice.Message, arg ...string) { m.Cmd(SEARCH, CREATE, m.CommandKey(), m.PrefixKey()) }, nil
}
return nil, nil
})
} }
func SearchAction() ice.Actions { func SearchAction() ice.Actions {
return ice.Actions{ return ice.Actions{

View File

@ -36,6 +36,9 @@ func (f *Frame) prompt(m *ice.Message, list ...string) *Frame {
if f.source != STDIO { if f.source != STDIO {
return f return f
} }
if m.Target().Cap(ice.CTX_STATUS) == ice.CTX_CLOSE {
return f
}
if len(list) == 0 { if len(list) == 0 {
list = append(list, f.ps1...) list = append(list, f.ps1...)
} }
@ -106,7 +109,6 @@ func (f *Frame) parse(m *ice.Message, h, line string) string {
if msg.Cmdy(ls); h == STDIO && msg.IsErrNotFound() { if msg.Cmdy(ls); h == STDIO && msg.IsErrNotFound() {
msg.SetResult().Cmdy(cli.SYSTEM, ls) msg.SetResult().Cmdy(cli.SYSTEM, ls)
} }
f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...) f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...)
return "" return ""
} }

View File

@ -31,7 +31,7 @@ func _dream_list(m *ice.Message) *ice.Message {
m.PushButton(cli.START, nfs.TRASH) m.PushButton(cli.START, nfs.TRASH)
} }
}) })
return m.Sort("status,type,name").StatusTimeCount(cli.START, len(list)) return m.Sort("status,type,name", ice.STR, ice.STR, ice.STR_R).StatusTimeCount(cli.START, len(list))
} }
func _dream_show(m *ice.Message, name string) { func _dream_show(m *ice.Message, name string) {
if m.Warn(name == "", ice.ErrNotValid) { if m.Warn(name == "", ice.ErrNotValid) {
@ -61,7 +61,7 @@ func _dream_show(m *ice.Message, name string) {
kit.EnvSimple(cli.HOME, cli.TERM, cli.SHELL), m.Configv(cli.ENV), kit.EnvSimple(cli.HOME, cli.TERM, cli.SHELL), m.Configv(cli.ENV),
)) ))
m.Optionv(cli.CMD_OUTPUT, path.Join(p, ice.BIN_BOOT_LOG)) m.Optionv(cli.CMD_OUTPUT, path.Join(p, ice.BIN_BOOT_LOG))
defer m.OptionMulti(cli.CMD_DIR, "", cli.CMD_ENV, "", cli.CMD_OUTPUT, "") defer m.Options(cli.CMD_DIR, "", cli.CMD_ENV, "", cli.CMD_OUTPUT, "")
gdb.Event(m, DREAM_CREATE, m.OptionSimple(mdb.NAME, mdb.TYPE)) gdb.Event(m, DREAM_CREATE, m.OptionSimple(mdb.NAME, mdb.TYPE))
defer ToastProcess(m)() defer ToastProcess(m)()

View File

@ -41,7 +41,7 @@ func _serve_rewrite(m *ice.Message) {
return Render(msg, ice.RENDER_DOWNLOAD, path.Join(msg.Config(kit.Keys(repos, nfs.PATH)), msg.Config(kit.Keys(repos, INDEX)))) return Render(msg, ice.RENDER_DOWNLOAD, path.Join(msg.Config(kit.Keys(repos, nfs.PATH)), msg.Config(kit.Keys(repos, INDEX))))
case PP(ice.HELP): case PP(ice.HELP):
r.URL.Path = P(ice.HELP, ice.TUTOR_SHY) r.URL.Path = P(ice.HELP, "tutor.shy")
} }
p := path.Join(ice.USR, repos, r.URL.Path) p := path.Join(ice.USR, repos, r.URL.Path)
@ -89,11 +89,7 @@ func _serve_start(m *ice.Message) {
if cli.NodeInfo(m, SERVER, kit.Select(ice.Info.HostName, m.Option("nodename"))); m.Option(tcp.PORT) == tcp.RANDOM { if cli.NodeInfo(m, SERVER, kit.Select(ice.Info.HostName, m.Option("nodename"))); m.Option(tcp.PORT) == tcp.RANDOM {
m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT))
} }
aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERNICK))
if m.Option("staffname") != "" {
m.Config("staffname", m.Option(aaa.USERNAME, m.Option("staffname")))
}
aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERROLE), m.Option(aaa.USERNICK))
m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...) m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...)
m.Go(func() { m.Cmd(BROAD, SERVE) }) m.Go(func() { m.Cmd(BROAD, SERVE) })
@ -364,7 +360,7 @@ func init() {
ctx.DisplayStorySpide(m, lex.PREFIX, m.ActionKey(), nfs.ROOT, MergeLink(m, ice.PS)) ctx.DisplayStorySpide(m, lex.PREFIX, m.ActionKey(), nfs.ROOT, MergeLink(m, ice.PS))
} }
}}, }},
cli.START: {Name: "start dev proto=http host port=9020 nodename password username userrole usernick staffname", Help: "启动", Hand: func(m *ice.Message, arg ...string) { cli.START: {Name: "start dev proto=http host port=9020 nodename password username usernick", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
_serve_start(m) _serve_start(m)
}}, }},
}, mdb.HashAction())}, }, mdb.HashAction())},
@ -396,7 +392,7 @@ func init() {
}}, }},
PP(ice.HELP): {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) { PP(ice.HELP): {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
arg = append(arg, ice.TUTOR_SHY) arg = append(arg, "tutor.shy")
} }
if len(arg) > 0 && arg[0] != ctx.ACTION { if len(arg) > 0 && arg[0] != ctx.ACTION {
arg[0] = path.Join(ice.SRC_HELP, arg[0]) arg[0] = path.Join(ice.SRC_HELP, arg[0])
@ -404,4 +400,13 @@ func init() {
m.Cmdy("web.chat./cmd/", arg) m.Cmdy("web.chat./cmd/", arg)
}}, }},
}}) }})
ice.AddMerges(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) {
if strings.HasPrefix(sub, ice.PS) {
if sub = kit.Select(sub, PP(key), sub == ice.PS); action.Hand == nil {
action.Hand = func(m *ice.Message, arg ...string) { m.Cmdy(key, arg) }
}
c.Commands[sub] = &ice.Command{Name: sub, Help: cmd.Help, Hand: action.Hand}
}
return nil, nil
})
} }

143
conf.go
View File

@ -14,12 +14,12 @@ const (
OK = "ok" OK = "ok"
TRUE = "true" TRUE = "true"
FALSE = "false" FALSE = "false"
SUCCESS = "success"
FAILURE = "failure"
PROCESS = "process" PROCESS = "process"
FAILURE = "failure"
SUCCESS = "success"
AUTO = "auto"
HTTP = "http" HTTP = "http"
AUTO = "auto"
LIST = "list" LIST = "list"
BACK = "back" BACK = "back"
@ -28,6 +28,7 @@ const (
MISC = "misc" MISC = "misc"
SHY = "shy" SHY = "shy"
COM = "com"
DEV = "dev" DEV = "dev"
OPS = "ops" OPS = "ops"
ICE = "ice" ICE = "ice"
@ -49,16 +50,16 @@ const ( // MOD
MOD_TIME = "2006-01-02 15:04:05" MOD_TIME = "2006-01-02 15:04:05"
) )
const ( // REPOS const ( // REPOS
VOLCANOS = "volcanos"
LEARNING = "learning"
ICEBERGS = "icebergs"
TOOLKITS = "toolkits"
INTSHELL = "intshell" INTSHELL = "intshell"
CONTEXTS = "contexts" CONTEXTS = "contexts"
ICEBERGS = "icebergs"
TOOLKITS = "toolkits"
VOLCANOS = "volcanos"
LEARNING = "learning"
INSTALL = "install" INSTALL = "install"
RELEASE = "release"
PUBLISH = "publish" PUBLISH = "publish"
RELEASE = "release"
REQUIRE = "require" REQUIRE = "require"
DISPLAY = "display" DISPLAY = "display"
) )
@ -69,12 +70,12 @@ const ( // DIR
VAR = "var" VAR = "var"
USR = "usr" USR = "usr"
SVG = "svg"
HTML = "html" HTML = "html"
CSS = "css" CSS = "css"
JS = "js" JS = "js"
GO = "go" GO = "go"
SH = "sh" SH = "sh"
SVG = "svg"
CSV = "csv" CSV = "csv"
JSON = "json" JSON = "json"
@ -89,45 +90,41 @@ const ( // DIR
FRAME_JS = "frame.js" FRAME_JS = "frame.js"
INDEX_JS = "index.js" INDEX_JS = "index.js"
INDEX_SH = "index.sh" INDEX_SH = "index.sh"
INDEX_IML = "index.iml"
TUTOR_SHY = "tutor.shy"
PLUGIN_INPUT = "/plugin/input" PLUGIN_INPUT = "/plugin/input/"
PLUGIN_STORY = "/plugin/story" PLUGIN_STORY = "/plugin/story/"
PLUGIN_LOCAL = "/plugin/local" PLUGIN_LOCAL = "/plugin/local/"
NODE_MODULES = "node_modules" NODE_MODULES = "node_modules/"
ISH_PLUGED = ".ish/pluged" ISH_PLUGED = ".ish/pluged/"
USR_VOLCANOS = "usr/volcanos" USR_VOLCANOS = "usr/volcanos/"
USR_LEARNING = "usr/learning" USR_LEARNING = "usr/learning/"
USR_ICEBERGS = "usr/icebergs" USR_ICEBERGS = "usr/icebergs/"
USR_TOOLKITS = "usr/toolkits" USR_TOOLKITS = "usr/toolkits/"
USR_INTSHELL = "usr/intshell" USR_INTSHELL = "usr/intshell/"
USR_INSTALL = "usr/install" USR_INSTALL = "usr/install/"
USR_RELEASE = "usr/release" USR_PUBLISH = "usr/publish/"
USR_PUBLISH = "usr/publish" USR_RELEASE = "usr/release/"
USR_LOCAL = "usr/local" USR_LOCAL = "usr/local/"
USR_LOCAL_GO = "usr/local/go" USR_LOCAL_GO = "usr/local/go/"
USR_LOCAL_GO_BIN = "usr/local/go/bin" USR_LOCAL_GO_BIN = "usr/local/go/bin/"
USR_LOCAL_BIN = "usr/local/bin" USR_LOCAL_BIN = "usr/local/bin/"
USR_LOCAL_LIB = "usr/local/lib" USR_LOCAL_LIB = "usr/local/lib/"
USR_LOCAL_WORK = "usr/local/work" USR_LOCAL_WORK = "usr/local/work/"
USR_LOCAL_IMAGE = "usr/local/image" USR_LOCAL_IMAGE = "usr/local/image/"
USR_LOCAL_MEDIA = "usr/local/media" USR_LOCAL_DAEMON = "usr/local/daemon/"
USR_LOCAL_RIVER = "usr/local/river" USR_LOCAL_EXPORT = "usr/local/export/"
USR_LOCAL_DAEMON = "usr/local/daemon" USR_LOCAL_REPOS = "usr/local/repos/"
USR_LOCAL_EXPORT = "usr/local/export"
USR_LOCAL_REPOS = "usr/local/repos"
VAR_RUN = "var/run" VAR_RUN = "var/run/"
VAR_TMP = "var/tmp" VAR_TMP = "var/tmp/"
VAR_LOG = "var/log" VAR_LOG = "var/log/"
VAR_CONF = "var/conf" VAR_CONF = "var/conf/"
VAR_DATA = "var/data" VAR_DATA = "var/data/"
VAR_FILE = "var/file" VAR_FILE = "var/file/"
VAR_PROXY = "var/proxy" VAR_PROXY = "var/proxy/"
VAR_TRASH = "var/trash" VAR_TRASH = "var/trash/"
BIN_ICE_BIN = "bin/ice.bin" BIN_ICE_BIN = "bin/ice.bin"
BIN_BOOT_LOG = "bin/boot.log" BIN_BOOT_LOG = "bin/boot.log"
ETC_INIT_SHY = "etc/init.shy" ETC_INIT_SHY = "etc/init.shy"
@ -136,13 +133,13 @@ const ( // DIR
ETC_MISS_SH = "etc/miss.sh" ETC_MISS_SH = "etc/miss.sh"
ETC_PATH = "etc/path" ETC_PATH = "etc/path"
SRC_HELP = "src/help" SRC_HELP = "src/help/"
SRC_DEBUG = "src/debug" SRC_DEBUG = "src/debug/"
SRC_RELEASE = "src/release" SRC_RELEASE = "src/release/"
SRC_MAIN_SVG = "src/main.svg"
SRC_MAIN_SHY = "src/main.shy"
SRC_MAIN_JS = "src/main.js" SRC_MAIN_JS = "src/main.js"
SRC_MAIN_GO = "src/main.go" SRC_MAIN_GO = "src/main.go"
SRC_MAIN_SHY = "src/main.shy"
SRC_MAIN_SVG = "src/main.svg"
SRC_VERSION_GO = "src/version.go" SRC_VERSION_GO = "src/version.go"
SRC_BINPACK_GO = "src/binpack.go" SRC_BINPACK_GO = "src/binpack.go"
SRC_RELAY_GO = "src/relay.go" SRC_RELAY_GO = "src/relay.go"
@ -167,8 +164,8 @@ const ( // MSG
MSG_SOURCE = "_source" MSG_SOURCE = "_source"
MSG_TARGET = "_target" MSG_TARGET = "_target"
MSG_HANDLE = "_handle" MSG_HANDLE = "_handle"
MSG_DAEMON = "_daemon"
MSG_UPLOAD = "_upload" MSG_UPLOAD = "_upload"
MSG_DAEMON = "_daemon"
MSG_ACTION = "_action" MSG_ACTION = "_action"
MSG_STATUS = "_status" MSG_STATUS = "_status"
@ -198,19 +195,20 @@ const ( // MSG
MSG_RIVER = "sess.river" MSG_RIVER = "sess.river"
MSG_STORM = "sess.storm" MSG_STORM = "sess.storm"
MSG_FILES = "file.system" MSG_FILES = "file.system"
LOG_DISABLE = "log.disable"
FIELDS_DETAIL = "detail" FIELDS_DETAIL = "detail"
) )
const ( // RENDER const ( // RENDER
RENDER_TEMPLATE = "_template"
RENDER_ANCHOR = "_anchor"
RENDER_BUTTON = "_button" RENDER_BUTTON = "_button"
RENDER_ANCHOR = "_anchor"
RENDER_QRCODE = "_qrcode"
RENDER_IMAGES = "_images" RENDER_IMAGES = "_images"
RENDER_VIDEOS = "_videos" RENDER_VIDEOS = "_videos"
RENDER_IFRAME = "_iframe" RENDER_IFRAME = "_iframe"
RENDER_QRCODE = "_qrcode"
RENDER_SCRIPT = "_script" RENDER_SCRIPT = "_script"
RENDER_TEMPLATE = "_template"
RENDER_STATUS = "_status" RENDER_STATUS = "_status"
RENDER_REDIRECT = "_redirect" RENDER_REDIRECT = "_redirect"
RENDER_DOWNLOAD = "_download" RENDER_DOWNLOAD = "_download"
@ -227,9 +225,9 @@ const ( // PROCESS
PROCESS_REFRESH = "_refresh" PROCESS_REFRESH = "_refresh"
PROCESS_REWRITE = "_rewrite" PROCESS_REWRITE = "_rewrite"
PROCESS_DISPLAY = "_display" PROCESS_DISPLAY = "_display"
PROCESS_INNER = "_inner"
PROCESS_FIELD = "_field" PROCESS_FIELD = "_field"
PROCESS_FLOAT = "_float" PROCESS_FLOAT = "_float"
PROCESS_INNER = "_inner"
PROCESS_AGAIN = "_again" PROCESS_AGAIN = "_again"
PROCESS_HOLD = "_hold" PROCESS_HOLD = "_hold"
@ -242,6 +240,9 @@ const ( // PROCESS
FIELD_PREFIX = "_prefix" FIELD_PREFIX = "_prefix"
) )
const ( // CTX const ( // CTX
CTX_ARG = "ctx_arg"
CTX_DAEMON = "ctx_daemon"
CTX_FOLLOW = "follow" CTX_FOLLOW = "follow"
CTX_STATUS = "status" CTX_STATUS = "status"
CTX_STREAM = "stream" CTX_STREAM = "stream"
@ -253,19 +254,15 @@ const ( // CTX
CTX_INIT = "_init" CTX_INIT = "_init"
CTX_EXIT = "_exit" CTX_EXIT = "_exit"
CTX_ARG = "ctx_arg"
CTX_DAEMON = "ctx_daemon"
) )
const ( // LOG const ( // LOG
LOG_CMDS = "cmds" LOG_CMDS = "cmds"
LOG_AUTH = "auth" LOG_AUTH = "auth"
LOG_COST = "cost" LOG_COST = "cost"
LOG_INFO = "info" LOG_INFO = "info"
LOG_WARN = "warn" LOG_WARN = "warn"
LOG_DEBUG = "debug"
LOG_ERROR = "error" LOG_ERROR = "error"
LOG_DEBUG = "debug"
) )
const ( // Err const ( // Err
ErrWarn = "warn: " ErrWarn = "warn: "
@ -275,23 +272,36 @@ const ( // Err
ErrNotFound = "not found: " ErrNotFound = "not found: "
ErrNotValid = "not valid: " ErrNotValid = "not valid: "
ErrNotStart = "not start: " ErrNotStart = "not start: "
ErrNotImplement = "not implement: " ErrNotImplement = "not implement: "
) )
const ( // ctx const ( // ctx
COMMAND = "command" COMMAND = "command"
ACTION = "action" ACTION = "action"
STYLE = "style" STYLE = "style"
INDEX = "index" INDEX = "index"
) )
const ( // web
SERVE = "serve"
SPACE = "space"
TOPIC = "topic"
TITLE = "title"
WIDTH = "width"
HEIGHT = "height"
)
const ( // nfs
SOURCE = "source"
SCRIPT = "script"
)
const ( // mdb const ( // mdb
AAA = "aaa" SEARCH = "search"
MDB = "mdb" SELECT = "select"
KEY = "key" KEY = "key"
VALUE = "value" VALUE = "value"
FIELD = "field"
EXTRA = "extra" EXTRA = "extra"
SCRIPT = "script" FIELD = "field"
META = "meta" META = "meta"
HASH = "hash" HASH = "hash"
TIME = "time" TIME = "time"
@ -300,3 +310,8 @@ const ( // mdb
TEXT = "text" TEXT = "text"
LINK = "link" LINK = "link"
) )
const ( // ice
MDB = "mdb"
AAA = "aaa"
CLI = "cli"
)

View File

@ -89,7 +89,7 @@ func _website_parse(m *ice.Message, text string, args ...string) (ice.Map, bool)
case ctx.ARGS: case ctx.ARGS:
data[ls[i]] = kit.Split(ls[i+1]) data[ls[i]] = kit.Split(ls[i+1])
case ctx.DISPLAY: case ctx.DISPLAY:
data[ls[i]] = ice.Display(ls[i+1])[ctx.DISPLAY] // data[ls[i]] = ice.Display(ls[i+1])[ctx.DISPLAY]
case ctx.STYLE, ctx.ACTION, TITLE, MENUS: case ctx.STYLE, ctx.ACTION, TITLE, MENUS:
data[ls[i]] = kit.UnMarshal(ls[i+1]) data[ls[i]] = kit.UnMarshal(ls[i+1])
default: default:

View File

@ -86,7 +86,7 @@ func init() {
m.Cmd(ASSET, func(value ice.Maps) { m.Cmd(ASSET, func(value ice.Maps) {
_asset_check(m, value[ACCOUNT]) _asset_check(m, value[ACCOUNT])
}) })
m.ProcessRefresh30ms() m.ProcessRefresh()
} else { } else {
_asset_check(m, m.Option(ACCOUNT)) _asset_check(m, m.Option(ACCOUNT))
} }

View File

@ -12,7 +12,7 @@ import (
) )
func _word_show(m *ice.Message, name string, arg ...string) { func _word_show(m *ice.Message, name string, arg ...string) {
m.OptionMulti(ice.MSG_ALIAS, m.Configv(mdb.ALIAS), TITLE, map[string]int{}, MENU, kit.Dict(mdb.LIST, kit.List())) m.Options(ice.MSG_ALIAS, m.Configv(mdb.ALIAS), TITLE, map[string]int{}, MENU, kit.Dict(mdb.LIST, kit.List()))
m.Cmdy(ssh.SOURCE, name, kit.Dict(nfs.DIR_ROOT, _wiki_path(m))) m.Cmdy(ssh.SOURCE, name, kit.Dict(nfs.DIR_ROOT, _wiki_path(m)))
} }

View File

@ -7,13 +7,13 @@ import (
) )
func (m *Message) ActionKey() string { func (m *Message) ActionKey() string {
return strings.TrimSuffix(strings.TrimPrefix(m._sub, PS), PS) return strings.TrimPrefix(strings.TrimSuffix(m._sub, PS), PS)
} }
func (m *Message) CommandKey() string { func (m *Message) CommandKey() string {
return strings.TrimSuffix(strings.TrimPrefix(m._key, PS), PS) return strings.TrimPrefix(strings.TrimSuffix(m._key, PS), PS)
} }
func (m *Message) PrefixKey(arg ...Any) string { func (m *Message) PrefixKey(arg ...Any) string {
return kit.Keys(m.Prefix(m.CommandKey()), kit.Keys(arg)) return kit.Keys(m.Prefix(m.CommandKey()), kit.Keys(arg...))
} }
func (m *Message) Prefix(arg ...string) string { func (m *Message) Prefix(arg ...string) string {
return m.Target().PrefixKey(arg...) return m.Target().PrefixKey(arg...)

14
exec.go
View File

@ -7,23 +7,23 @@ import (
"time" "time"
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
"shylinux.com/x/toolkits/logs"
"shylinux.com/x/toolkits/task" "shylinux.com/x/toolkits/task"
) )
func (m *Message) TryCatch(msg *Message, silent bool, hand ...func(msg *Message)) *Message { func (m *Message) TryCatch(msg *Message, silent bool, hand ...func(msg *Message)) *Message {
defer func() { defer func() {
switch e := recover(); e { switch e := recover(); e {
case io.EOF: case nil, io.EOF:
case nil:
default: default:
fileline := m.FormatStack(2, 1) fileline := m.FormatStack(2, 100)
m.Log(LOG_WARN, "catch: %s %s", e, fileline).Log("chain", msg.FormatChain()) m.Log(LOG_WARN, "catch: %s %s", e, fileline).Log("chain", msg.FormatChain())
m.Log(LOG_WARN, "catch: %s %s", e, fileline).Log("stack", msg.FormatStack(2, 100)) m.Log(LOG_WARN, "catch: %s %s", e, fileline).Log("stack", msg.FormatStack(2, 100))
m.Log(LOG_WARN, "catch: %s %s", e, fileline).Result(ErrWarn, e, " ", fileline) m.Log(LOG_WARN, "catch: %s %s", e, fileline).Result(ErrWarn, e, SP, fileline)
if len(hand) > 1 { if len(hand) > 1 {
m.TryCatch(msg, silent, hand[1:]...) m.TryCatch(msg, silent, hand[1:]...)
} else if !silent { } else if !silent {
m.Assert(e) // 抛出异常 m.Assert(e)
} }
} }
}() }()
@ -36,13 +36,13 @@ func (m *Message) Assert(expr Any) bool {
switch e := expr.(type) { switch e := expr.(type) {
case nil: case nil:
return true return true
case error:
case bool: case bool:
if e == true { if e == true {
return true return true
} }
case error:
default: default:
expr = errors.New(kit.Format("error: %v", e)) expr = errors.New(kit.Format("error: %v %s", e, logs.FileLine(2, 3)))
} }
m.Result(ErrWarn, expr) m.Result(ErrWarn, expr)
panic(expr) panic(expr)

21
info.go
View File

@ -1,13 +1,13 @@
package ice package ice
type MakeInfo struct { type MakeInfo struct {
Path string
Time string Time string
Path string
Hash string Hash string
Domain string
Module string Module string
Remote string Remote string
Branch string Branch string
Domain string
Version string Version string
HostName string HostName string
UserName string UserName string
@ -21,19 +21,20 @@ var Info = struct {
UserName string UserName string
PassWord string PassWord string
Colors bool
Domain string Domain string
NodeType string NodeType string
NodeName string NodeName string
CtxShare string CtxShare string
CtxRiver string CtxRiver string
PidPath string PidPath string
Colors bool
Help string Help string
Route Maps // 路由命令 File Maps
File Maps // 文件命令 Route Maps
names Map index Map
merges []MergeHandler
render map[string]func(*Message, string, ...Any) string render map[string]func(*Message, string, ...Any) string
Save func(m *Message, key ...string) *Message Save func(m *Message, key ...string) *Message
Load func(m *Message, key ...string) *Message Load func(m *Message, key ...string) *Message
@ -47,12 +48,16 @@ report: shylinuxc@gmail.com
server: https://shylinux.com server: https://shylinux.com
source: https://shylinux.com/x/icebergs source: https://shylinux.com/x/icebergs
`, `,
Route: Maps{},
File: Maps{}, File: Maps{},
names: Map{}, Route: Maps{},
index: Map{},
render: map[string]func(*Message, string, ...Any) string{}, render: map[string]func(*Message, string, ...Any) string{},
Save: func(m *Message, key ...string) *Message { return m }, Save: func(m *Message, key ...string) *Message { return m },
Load: func(m *Message, key ...string) *Message { return m }, Load: func(m *Message, key ...string) *Message { return m },
Log: func(m *Message, p, l, s string) {}, Log: func(m *Message, p, l, s string) {},
} }
type MergeHandler func(*Context, string, *Command, string, *Action) (Handler, Handler)
func AddMerges(h ...MergeHandler) { Info.merges = append(Info.merges, h...) }

59
init.go
View File

@ -12,10 +12,7 @@ import (
type Frame struct{} type Frame struct{}
func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server { func (s *Frame) Begin(m *Message, arg ...string) Server {
return &Frame{}
}
func (f *Frame) Begin(m *Message, arg ...string) Server {
list := map[*Context]*Message{m.target: m} list := map[*Context]*Message{m.target: m}
m.Travel(func(p *Context, s *Context) { m.Travel(func(p *Context, s *Context) {
s.root = m.target s.root = m.target
@ -24,21 +21,20 @@ func (f *Frame) Begin(m *Message, arg ...string) Server {
s.Begin(list[s], arg...) s.Begin(list[s], arg...)
} }
}) })
return f return s
} }
func (f *Frame) Start(m *Message, arg ...string) bool { func (s *Frame) Start(m *Message, arg ...string) bool {
m.Cap(CTX_STREAM, strings.Split(m.Time(), SP)[1]) m.Cap(CTX_STREAM, strings.Split(m.Time(), SP)[1])
m.Cmd(kit.Keys(MDB, CTX_INIT)) m.Cmd(kit.Keys(MDB, CTX_INIT))
m.Cmd("cli.runtime", CTX_INIT) m.Cmd(kit.Keys(CLI, CTX_INIT))
m.Cmdy(INIT, arg) m.Cmdy(INIT, arg)
for _, k := range kit.Split(kit.Select("ctx,log,gdb,ssh", os.Getenv(CTX_DAEMON))) { for _, k := range kit.Split(kit.Select("ctx,log,gdb,ssh", os.Getenv(CTX_DAEMON))) {
m.Start(k) m.Start(k)
} }
m.Cmd(arg) m.Cmdy(arg)
return true return true
} }
func (f *Frame) Close(m *Message, arg ...string) bool { func (s *Frame) Close(m *Message, arg ...string) bool {
list := map[*Context]*Message{m.target: m} list := map[*Context]*Message{m.target: m}
m.Travel(func(p *Context, s *Context) { m.Travel(func(p *Context, s *Context) {
if msg, ok := list[p]; ok && msg != nil { if msg, ok := list[p]; ok && msg != nil {
@ -47,9 +43,10 @@ func (f *Frame) Close(m *Message, arg ...string) bool {
} }
}) })
conf.Close() conf.Close()
go func() { m.Sleep("1s"); os.Exit(kit.Int(Pulse.Option(EXIT))) }() go func() { m.Sleep3s(); os.Exit(kit.Int(Pulse.Option(EXIT))) }()
return true return true
} }
func (s *Frame) Spawn(m *Message, c *Context, arg ...string) Server { return &Frame{} }
const ( const (
INIT = "init" INIT = "init"
@ -58,9 +55,7 @@ const (
QUIT = "quit" QUIT = "quit"
) )
var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{HELP: {Value: kit.Data(INDEX, Info.Help)}}, Commands: Commands{
HELP: {Value: kit.Data(INDEX, Info.Help)},
}, Commands: Commands{
CTX_INIT: {Hand: func(m *Message, arg ...string) { CTX_INIT: {Hand: func(m *Message, arg ...string) {
m.root.Travel(func(p *Context, c *Context) { m.root.Travel(func(p *Context, c *Context) {
if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil { if cmd, ok := c.Commands[CTX_INIT]; ok && p != nil {
@ -68,23 +63,19 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{
} }
}) })
}}, }},
INIT: {Name: "init", Help: "启动", Hand: func(m *Message, arg ...string) { INIT: {Hand: func(m *Message, arg ...string) {
m.root.Cmd(CTX_INIT) m.root.Cmd(CTX_INIT)
m.Cmd("source", ETC_INIT_SHY) m.Cmd(SOURCE, ETC_INIT_SHY)
}}, }},
HELP: {Name: "help", Help: "帮助", Hand: func(m *Message, arg ...string) { HELP: {Hand: func(m *Message, arg ...string) { m.Echo(m.Config(INDEX)) }},
m.Echo(m.Config(INDEX)) QUIT: {Hand: func(m *Message, arg ...string) { os.Exit(0) }},
}}, EXIT: {Hand: func(m *Message, arg ...string) {
QUIT: {Name: "quit", Help: "结束", Hand: func(m *Message, arg ...string) {
os.Exit(0)
}},
EXIT: {Name: "exit", Help: "退出", Hand: func(m *Message, arg ...string) {
defer m.Target().Close(m.root.Spawn(), arg...)
m.root.Option(EXIT, kit.Select("0", arg, 0)) m.root.Option(EXIT, kit.Select("0", arg, 0))
m.Cmd("source", ETC_EXIT_SHY) m.Cmd(SOURCE, ETC_EXIT_SHY)
m.root.Cmd(CTX_EXIT) m.root.Cmd(CTX_EXIT)
}}, }},
CTX_EXIT: {Hand: func(m *Message, arg ...string) { CTX_EXIT: {Hand: func(m *Message, arg ...string) {
defer m.Target().Close(m.root.Spawn(), arg...)
m.root.Travel(func(p *Context, c *Context) { m.root.Travel(func(p *Context, c *Context) {
if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil { if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil {
m.TryCatch(m.Spawn(c), true, func(msg *Message) { m.TryCatch(m.Spawn(c), true, func(msg *Message) {
@ -102,30 +93,26 @@ var Pulse = &Message{time: time.Now(), code: 0,
func init() { Index.root, Pulse.root = Index, Pulse } func init() { Index.root, Pulse.root = Index, Pulse }
func Run(arg ...string) string { func Run(arg ...string) string {
if len(arg) == 0 { // 进程参数 if len(arg) == 0 && len(os.Args) > 1 {
arg = kit.Simple(arg, os.Args[1:], kit.Split(os.Getenv(CTX_ARG))) arg = kit.Simple(os.Args[1:], kit.Split(kit.Env(CTX_ARG)))
} }
Pulse.meta[MSG_DETAIL] = arg Pulse.meta[MSG_DETAIL] = arg
switch Index.Merge(Index).Begin(Pulse.Spawn(), arg...); kit.Select("", arg, 0) { switch Index.Merge(Index).Begin(Pulse, arg...); kit.Select("", arg, 0) {
case "serve", "space": // 启动服务 case SERVE, SPACE:
if Index.Start(Pulse, arg...) { if Index.Start(Pulse, arg...) {
conf.Wait() conf.Wait()
println()
os.Exit(kit.Int(Pulse.Option(EXIT))) os.Exit(kit.Int(Pulse.Option(EXIT)))
} }
default: // 执行命令 default:
if logs.Disable(true); len(arg) == 0 { if logs.Disable(true); len(arg) == 0 {
arg = append(arg, HELP) arg = append(arg, HELP)
} }
Pulse.Cmd(INIT) if Pulse.Cmd(INIT).Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" {
if Pulse.Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" {
Pulse.Table() Pulse.Table()
} }
}
if !strings.HasSuffix(Pulse.Result(), NL) { if !strings.HasSuffix(Pulse.Result(), NL) {
Pulse.Echo(NL) Pulse.Echo(NL)
} }
}
return Pulse.Result() return Pulse.Result()
} }

54
logs.go
View File

@ -29,27 +29,21 @@ func (m *Message) join(arg ...Any) (string, []Any) {
continue continue
} }
switch v := arg[i+1].(type) { switch v := arg[i+1].(type) {
case logs.Meta:
list = append(list, key)
meta = append(meta, v)
continue
case time.Time: case time.Time:
arg[i+1] = v.Format(MOD_TIME) arg[i+1] = v.Format(MOD_TIME)
} }
list = append(list, key+kit.Select("", DF, !strings.HasSuffix(key, DF)), kit.Format(kit.Select("", kit.Simple(arg[i+1]), 0))) list = append(list, key+kit.Select("", DF, !strings.Contains(key, DF)), kit.Format(arg[i+1]))
} }
return kit.Join(list, SP), meta return kit.Join(list, SP), meta
} }
func (m *Message) log(level string, str string, arg ...Any) *Message { func (m *Message) log(level string, str string, arg ...Any) *Message {
_source := logs.FileLineMeta(logs.FileLine(3, 3)) _source := logs.FileLineMeta(logs.FileLine(3, 3))
if Info.Log != nil { if Info.Log != nil {
Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...)) // 日志回调 Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...))
} }
if m.Option("log.disable") == TRUE { if m.Option(LOG_DISABLE) == TRUE {
return m return m
} }
// 日志颜色
prefix, suffix := "", "" prefix, suffix := "", ""
if Info.Colors { if Info.Colors {
switch level { switch level {
@ -57,20 +51,16 @@ func (m *Message) log(level string, str string, arg ...Any) *Message {
prefix, suffix = "\033[32m", "\033[0m" prefix, suffix = "\033[32m", "\033[0m"
case LOG_AUTH, LOG_COST: case LOG_AUTH, LOG_COST:
prefix, suffix = "\033[33m", "\033[0m" prefix, suffix = "\033[33m", "\033[0m"
case LOG_WARN: case LOG_WARN, LOG_ERROR:
prefix, suffix = "\033[31m", "\033[0m" prefix, suffix = "\033[31m", "\033[0m"
} }
} }
// 长度截断
switch level { switch level {
case LOG_INFO: case LOG_INFO:
if len(str) > 4096 { if len(str) > 4096 {
str = str[:4096] str = str[:4096]
} }
} }
// 输出日志
logs.Infof(str, append(arg, logs.PrefixMeta(kit.Format("%02d %4s->%-4s %s%s ", m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...) logs.Infof(str, append(arg, logs.PrefixMeta(kit.Format("%02d %4s->%-4s %s%s ", m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...)
return m return m
} }
@ -116,32 +106,26 @@ func (m *Message) Warn(err Any, arg ...Any) bool {
if !m.IsErr() { if !m.IsErr() {
if m.error(arg...); len(arg) > 0 { if m.error(arg...); len(arg) > 0 {
switch kit.Format(arg[0]) { switch kit.Format(arg[0]) {
case ErrNotValid:
m.RenderStatusBadRequest(str)
case ErrNotLogin: case ErrNotLogin:
m.RenderStatusUnauthorized(str) m.RenderStatusUnauthorized(str)
case ErrNotRight: case ErrNotRight:
m.RenderStatusForbidden(str) m.RenderStatusForbidden(str)
case ErrNotFound: case ErrNotFound:
m.RenderStatusNotFound(str) m.RenderStatusNotFound(str)
case ErrNotValid:
m.RenderStatusBadRequest(str)
} }
} }
} }
return true return true
} }
func (m *Message) Debug(str string, arg ...Any) {
if str == "" {
str = m.FormatMeta()
}
m.log(LOG_DEBUG, str, arg...)
}
func (m *Message) Error(err bool, arg ...Any) bool { func (m *Message) Error(err bool, arg ...Any) bool {
if err { if err {
m.error(arg...)
m.log(LOG_ERROR, m.FormatStack(1, 100))
str, meta := m.join(arg...) str, meta := m.join(arg...)
m.log(LOG_ERROR, str, meta)
m.log(LOG_ERROR, m.FormatChain()) m.log(LOG_ERROR, m.FormatChain())
m.log(LOG_ERROR, str, meta)
m.log(LOG_ERROR, m.FormatStack(1, 100))
m.error(arg...)
return true return true
} }
return false return false
@ -156,12 +140,19 @@ func (m *Message) error(arg ...Any) {
arg = append(arg, "") arg = append(arg, "")
} }
str, meta := m.join(arg[2:]...) str, meta := m.join(arg[2:]...)
m.meta[MSG_RESULT] = kit.Simple(ErrWarn, arg[0], arg[1], str, meta) m.Resultv(ErrWarn, arg[0], arg[1], str, meta)
}
func (m *Message) IsErrNotFound() bool {
return m.IsErr(ErrNotFound)
} }
func (m *Message) IsErrNotFound() bool { return m.IsErr(ErrNotFound) }
func (m *Message) IsErr(arg ...string) bool { func (m *Message) IsErr(arg ...string) bool {
return len(arg) > 0 && m.Result(1) == arg[0] || len(arg) == 0 && m.Result(0) == ErrWarn return len(arg) == 0 && m.Result(0) == ErrWarn || len(arg) > 0 && m.Result(1) == arg[0]
}
func (m *Message) Debug(str string, arg ...Any) {
if str == "" {
str = m.FormatMeta()
}
m.log(LOG_DEBUG, str, arg...)
} }
func (m *Message) FormatPrefix() string { func (m *Message) FormatPrefix() string {
@ -187,7 +178,6 @@ func (m *Message) FormatChain() string {
for msg := m; msg != nil; msg = msg.message { for msg := m; msg != nil; msg = msg.message {
ms = append(ms, msg) ms = append(ms, msg)
} }
meta := append([]string{}, NL) meta := append([]string{}, NL)
for i := len(ms) - 1; i >= 0; i-- { for i := len(ms) - 1; i >= 0; i-- {
msg := ms[i] msg := ms[i]
@ -213,20 +203,16 @@ func (m *Message) FormatChain() string {
func (m *Message) FormatStack(s, n int) string { func (m *Message) FormatStack(s, n int) string {
pc := make([]uintptr, n+10) pc := make([]uintptr, n+10)
frames := runtime.CallersFrames(pc[:runtime.Callers(s+1, pc)]) frames := runtime.CallersFrames(pc[:runtime.Callers(s+1, pc)])
list := []string{} list := []string{}
for { for {
frame, more := frames.Next() frame, more := frames.Next()
file := kit.Slice(kit.Split(frame.File, PS, PS), -1)[0] file := kit.Slice(kit.Split(frame.File, PS, PS), -1)[0]
name := kit.Slice(kit.Split(frame.Function, PS, PS), -1)[0] name := kit.Slice(kit.Split(frame.Function, PS, PS), -1)[0]
switch ls := kit.Split(name, PT, PT); kit.Select("", ls, 0) { switch ls := kit.Split(name, PT, PT); kit.Select("", ls, 0) {
// case "reflect", "runtime", "http", "task", "icebergs":
case "reflect", "runtime", "http": case "reflect", "runtime", "http":
default: default:
list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name)) list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name))
} }
if len(list) >= n { if len(list) >= n {
break break
} }

406
meta.go
View File

@ -7,51 +7,7 @@ import (
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func (m *Message) Set(key string, arg ...string) *Message { func (m *Message) setDetail(key string, arg ...string) *Message {
switch key {
case MSG_DETAIL, MSG_RESULT:
delete(m.meta, key)
case MSG_OPTION, MSG_APPEND:
if m.FieldsIsDetail() {
if len(arg) > 0 {
for i := 0; i < len(m.meta[KEY]); i++ {
if m.meta[KEY][i] == arg[0] {
if len(arg) > 1 {
m.meta[VALUE][i] = arg[1]
break
}
for ; i < len(m.meta[KEY])-1; i++ {
m.meta[KEY][i] = m.meta[KEY][i+1]
m.meta[VALUE][i] = m.meta[VALUE][i+1]
}
m.meta[KEY] = kit.Slice(m.meta[KEY], 0, -1)
m.meta[VALUE] = kit.Slice(m.meta[VALUE], 0, -1)
break
}
}
return m
}
delete(m.meta, KEY)
delete(m.meta, VALUE)
delete(m.meta, MSG_APPEND)
return m
}
if len(arg) > 0 {
if delete(m.meta, arg[0]); len(arg) == 1 {
return m
}
} else {
for _, k := range m.meta[key] {
delete(m.meta, k)
}
delete(m.meta, key)
return m
}
default:
for _, k := range kit.Split(key) {
delete(m.meta, k)
}
if m.FieldsIsDetail() {
for i := 0; i < len(m.meta[KEY]); i++ { for i := 0; i < len(m.meta[KEY]); i++ {
if m.meta[KEY][i] == key { if m.meta[KEY][i] == key {
if len(arg) > 0 { if len(arg) > 0 {
@ -68,7 +24,41 @@ func (m *Message) Set(key string, arg ...string) *Message {
} }
} }
return m return m
}
func (m *Message) Set(key string, arg ...string) *Message {
switch key {
case MSG_DETAIL, MSG_RESULT:
delete(m.meta, key)
case MSG_OPTION, MSG_APPEND:
if m.FieldsIsDetail() {
if len(arg) > 0 {
m.setDetail(arg[0], arg[1:]...)
} else {
delete(m.meta, KEY)
delete(m.meta, VALUE)
delete(m.meta, MSG_APPEND)
} }
} else if len(arg) > 0 {
if delete(m.meta, arg[0]); len(arg) > 1 {
m.meta[arg[0]] = arg[1:]
}
} else {
for _, k := range m.meta[key] {
delete(m.meta, k)
}
delete(m.meta, key)
}
return m
default:
if m.FieldsIsDetail() {
return m.setDetail(key, arg...)
}
for _, k := range kit.Split(key) {
delete(m.meta, k)
}
}
if len(arg) == 0 {
return m
} }
return m.Add(key, arg...) return m.Add(key, arg...)
} }
@ -76,21 +66,15 @@ func (m *Message) Add(key string, arg ...string) *Message {
switch key { switch key {
case MSG_DETAIL, MSG_RESULT: case MSG_DETAIL, MSG_RESULT:
m.meta[key] = append(m.meta[key], arg...) m.meta[key] = append(m.meta[key], arg...)
case MSG_OPTION, MSG_APPEND: case MSG_OPTION, MSG_APPEND:
if len(arg) == 0 { if len(arg) == 0 {
break break
} }
if key == MSG_APPEND { if index := 0; key == MSG_APPEND {
if i := kit.IndexOf(m.meta[MSG_OPTION], arg[0]); i > -1 { if m.meta[MSG_OPTION], index = kit.SliceRemove(m.meta[MSG_OPTION], arg[0]); index > -1 {
m.meta[MSG_OPTION][i] = ""
delete(m.meta, arg[0]) delete(m.meta, arg[0])
} }
if kit.IndexOf(m.meta[key], arg[0]) == -1 {
m.meta[arg[0]] = []string{}
} }
}
if kit.IndexOf(m.meta[key], arg[0]) == -1 { if kit.IndexOf(m.meta[key], arg[0]) == -1 {
m.meta[key] = append(m.meta[key], arg[0]) m.meta[key] = append(m.meta[key], arg[0])
} }
@ -116,20 +100,16 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message {
if len(head) == 0 && !m.FieldsIsDetail() { if len(head) == 0 && !m.FieldsIsDetail() {
head = kit.Split(m.OptionFields()) head = kit.Split(m.OptionFields())
} }
switch value := value.(type) { switch value := value.(type) {
case Map: case Map:
if len(head) == 0 { // 键值排序 if len(head) == 0 {
head = kit.SortedKey(kit.KeyValue(Map{}, "", value)) head = kit.SortedKey(kit.KeyValue(nil, "", value))
} }
var val Map var val Map
if len(arg) > 1 { if len(arg) > 1 {
val, _ = arg[1].(Map) val, _ = arg[1].(Map)
} }
for _, k := range head { for _, k := range head {
// 查找数据
var v Any var v Any
switch k { switch k {
case KEY, HASH: case KEY, HASH:
@ -158,50 +138,42 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message {
break break
} }
} }
// 追加数据
switch v := kit.Format(v); key { switch v := kit.Format(v); key {
case FIELDS_DETAIL: case FIELDS_DETAIL:
switch k { switch k {
case "_target": case "_target":
continue continue
} }
m.Add(MSG_APPEND, KEY, strings.TrimPrefix(k, "extra.")) m.Add(MSG_APPEND, KEY, strings.TrimPrefix(k, EXTRA+PT))
m.Add(MSG_APPEND, VALUE, v) m.Add(MSG_APPEND, VALUE, v)
default: default:
m.Add(MSG_APPEND, k, v) m.Add(MSG_APPEND, k, v)
} }
} }
case Maps: case Maps:
if len(head) == 0 { // 键值排序 if len(head) == 0 {
head = kit.SortedKey(value) head = kit.SortedKey(value)
} }
for _, k := range head { for _, k := range head {
m.Push(k, value[k]) m.Push(k, value[k])
} }
default: default:
for _, v := range kit.Simple(value, arg) { for _, v := range kit.Simple(value, arg) {
if m.FieldsIsDetail() { if m.FieldsIsDetail() {
if key != KEY || key != VALUE {
m.Add(MSG_APPEND, KEY, key) m.Add(MSG_APPEND, KEY, key)
m.Add(MSG_APPEND, VALUE, kit.Format(value)) m.Add(MSG_APPEND, VALUE, kit.Format(value))
continue } else {
}
}
m.Add(MSG_APPEND, key, v) m.Add(MSG_APPEND, key, v)
} }
} }
}
return m return m
} }
func (m *Message) Echo(str string, arg ...Any) *Message { func (m *Message) Echo(str string, arg ...Any) *Message {
if str == "" { if str == "" {
return m return m
} }
m.meta[MSG_RESULT] = append(m.meta[MSG_RESULT], kit.Format(str, arg...)) return m.Add(MSG_RESULT, kit.Format(str, arg...))
return m
} }
func (m *Message) Copy(msg *Message, arg ...string) *Message { func (m *Message) Copy(msg *Message, arg ...string) *Message {
if m == nil || msg == nil || m == msg { if m == nil || msg == nil || m == msg {
@ -213,12 +185,9 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message {
} }
return m return m
} }
for _, k := range msg.meta[MSG_OPTION] { for _, k := range msg.meta[MSG_OPTION] {
switch k { switch k {
case MSG_CMDS: case MSG_CMDS, MSG_FIELDS, MSG_SESSID:
case MSG_FIELDS:
case MSG_SESSID:
continue continue
} }
if v, ok := msg.data[k]; ok { if v, ok := msg.data[k]; ok {
@ -231,8 +200,7 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message {
for _, k := range msg.meta[MSG_APPEND] { for _, k := range msg.meta[MSG_APPEND] {
m.Add(MSG_APPEND, kit.Simple(k, msg.meta[k])...) m.Add(MSG_APPEND, kit.Simple(k, msg.meta[k])...)
} }
m.meta[MSG_RESULT] = append(m.meta[MSG_RESULT], msg.meta[MSG_RESULT]...) return m.Add(MSG_RESULT, msg.meta[MSG_RESULT]...)
return m
} }
func (m *Message) Length() (max int) { func (m *Message) Length() (max int) {
for _, k := range m.meta[MSG_APPEND] { for _, k := range m.meta[MSG_APPEND] {
@ -245,49 +213,49 @@ func (m *Message) Length() (max int) {
func (m *Message) Tables(cbs ...func(value Maps)) *Message { func (m *Message) Tables(cbs ...func(value Maps)) *Message {
return m.Table(func(index int, value Maps, head []string) { return m.Table(func(index int, value Maps, head []string) {
for _, cb := range cbs { for _, cb := range cbs {
if cb != nil {
cb(value) cb(value)
} }
}
}) })
} }
func (m *Message) Table(cbs ...func(index int, value Maps, head []string)) *Message { func (m *Message) Table(cbs ...func(index int, value Maps, head []string)) *Message {
if len(cbs) > 0 && cbs[0] != nil { if len(cbs) > 0 && cbs[0] != nil {
if m.FieldsIsDetail() {
if m.Length() == 0 {
return m
}
line := Maps{}
for i, k := range m.meta[KEY] {
line[k] = kit.Select("", m.meta[VALUE], i)
}
cbs[0](0, line, m.meta[KEY])
return m
}
n := m.Length() n := m.Length()
for i := 0; i < n; i++ { if n == 0 {
line := Maps{} return m
for _, k := range m.meta[MSG_APPEND] { }
line[k] = kit.Select("", m.meta[k], i) if m.FieldsIsDetail() {
value := Maps{}
for i, k := range m.meta[KEY] {
value[k] = kit.Select("", m.meta[VALUE], i)
}
for _, cb := range cbs {
cb(0, value, m.meta[KEY])
}
return m
}
for i := 0; i < n; i++ {
value := Maps{}
for _, k := range m.meta[MSG_APPEND] {
value[k] = kit.Select("", m.meta[k], i)
}
for _, cb := range cbs {
cb(i, value, m.meta[MSG_APPEND])
} }
cbs[0](i, line, m.meta[MSG_APPEND])
} }
return m return m
} }
const ( const (
TABLE_SPACE = "table.space" TABLE_SPACE = "table.space"
TABLE_ROW_SEP = "table.row_sep" TABLE_ROW_SEP = "table.row_sep"
TABLE_COL_SEP = "table.col_sep" TABLE_COL_SEP = "table.col_sep"
TABLE_COMPACT = "table.compact" TABLE_COMPACT = "table.compact"
TABLE_ALIGN = "table.align"
) )
//计算列宽
space := kit.Select(SP, m.Option(TABLE_SPACE)) space := kit.Select(SP, m.Option(TABLE_SPACE))
depth, width := 0, map[string]int{} length, width := 0, map[string]int{}
for _, k := range m.meta[MSG_APPEND] { for _, k := range m.meta[MSG_APPEND] {
if len(m.meta[k]) > depth { if len(m.meta[k]) > length {
depth = len(m.meta[k]) length = len(m.meta[k])
} }
width[k] = kit.Width(k, len(space)) width[k] = kit.Width(k, len(space))
for _, v := range m.meta[k] { for _, v := range m.meta[k] {
@ -296,165 +264,128 @@ func (m *Message) Table(cbs ...func(index int, value Maps, head []string)) *Mess
} }
} }
} }
// 回调函数
rows := kit.Select(NL, m.Option(TABLE_ROW_SEP)) rows := kit.Select(NL, m.Option(TABLE_ROW_SEP))
cols := kit.Select(SP, m.Option(TABLE_COL_SEP)) cols := kit.Select(SP, m.Option(TABLE_COL_SEP))
compact := m.Option(TABLE_COMPACT) == TRUE show := func(value []string) {
cb := func(value Maps, field []string, index int) bool { for i, v := range value {
for i, v := range field { if m.Echo(v); i < len(value)-1 {
if k := m.meta[MSG_APPEND][i]; compact {
v = value[k]
}
if m.Echo(v); i < len(field)-1 {
m.Echo(cols) m.Echo(cols)
} }
} }
m.Echo(rows) m.Echo(rows)
return true
} }
compact := m.Option(TABLE_COMPACT) == TRUE
// 输出表头 _align := kit.Select("left", m.Option(TABLE_ALIGN))
row, wor := Maps{}, []string{} align := func(value string, width int) string {
for _, k := range m.meta[MSG_APPEND] { if compact {
row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-kit.Width(k, len(space)))) return value + space
} }
if !cb(row, wor, -1) { n := width - kit.Width(value, len(space))
return m switch _align {
case "left":
return value + strings.Repeat(space, n)
case "right":
return strings.Repeat(space, n) + value
case "center":
return strings.Repeat(space, n/2) + value + strings.Repeat(space, n-n/2)
} }
return value + space
// 输出数据
for i := 0; i < depth; i++ {
row, wor := Maps{}, []string{}
for _, k := range m.meta[MSG_APPEND] {
data := ""
if i < len(m.meta[k]) {
data = m.meta[k][i]
}
row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-kit.Width(data, len(space))))
}
if !cb(row, wor, i) {
break
} }
show(kit.Simple(m.meta[MSG_APPEND], func(k string) string { return align(k, width[k]) }))
for i := 0; i < length; i++ {
show(kit.Simple(m.meta[MSG_APPEND], func(k string) string { return align(kit.Select("", m.meta[k], i), width[k]) }))
} }
return m return m
} }
func (m *Message) Sort(key string, arg ...string) *Message {
ls := kit.Split(key) const (
if key = ls[0]; m.FieldsIsDetail() && key != KEY {
return m
}
const (
STR = "str"
INT = "int" INT = "int"
TIME = "time" STR = "str"
// TIME = "time"
TIME_R = "time_r" TIME_R = "time_r"
INT_R = "int_r"
STR_R = "str_r" STR_R = "str_r"
INT_R = "int_r"
)
GT = ">" func (m *Message) Sort(key string, arg ...string) *Message {
LT = "<" if m.FieldsIsDetail() {
) return m
}
// 排序方法 keys, cmps := kit.Split(key), kit.Simple()
cmp := STR for i, k := range keys {
if len(arg) > 0 && arg[0] != "" { cmp := kit.Select("", arg, i)
cmp = arg[0] if cmp == "" {
} else {
cmp = INT cmp = INT
for _, v := range m.meta[key] { for _, v := range m.meta[k] {
if _, e := strconv.Atoi(v); e != nil { if _, e := strconv.Atoi(v); e != nil {
cmp = STR cmp = STR
} }
} }
} }
cmps = append(cmps, cmp)
// 排序因子
number := map[int]int64{}
table := []Maps{}
m.Table(func(index int, value Maps, head []string) {
switch table = append(table, value); cmp {
case INT:
number[index] = kit.Int64(value[key])
case INT_R:
number[index] = -kit.Int64(value[key])
case TIME:
number[index] = int64(kit.Time(value[key]))
case TIME_R:
number[index] = -int64(kit.Time(value[key]))
} }
}) list := []Maps{}
compare := func(i, j int, op string) bool { m.Tables(func(value Maps) { list = append(list, value) })
for k := range ls { gt := func(i, j int) bool {
if k == 0 { for s, k := range keys {
a, b := list[i][k], list[j][k]
if a == b {
continue continue
} }
if table[i][ls[k]] == table[j][ls[k]] { switch cmp := cmps[s]; cmp {
continue case INT, INT_R:
if kit.Int(a) > kit.Int(b) {
return cmp == INT
}
if kit.Int(a) < kit.Int(b) {
return cmp == INT_R
}
case STR, STR_R:
if a > b {
return cmp == STR
}
if a < b {
return cmp == STR_R
}
case TIME, TIME_R:
if kit.Time(a) > kit.Time(b) {
return cmp == TIME
}
if kit.Time(a) < kit.Time(b) {
return cmp == TIME_R
} }
if op == GT && table[i][ls[k]] > table[j][ls[k]] {
return true
} }
if op == LT && table[i][ls[k]] < table[j][ls[k]] {
return true
} }
return false return false
} }
return false for i := 0; i < len(list)-1; i++ {
} min := i
for j := i + 1; j < len(list); j++ {
// 排序数据 if gt(min, j) {
for i := 0; i < len(table)-1; i++ { min = j
for j := i + 1; j < len(table); j++ {
swap := false
switch cmp {
case "", STR:
if table[i][key] > table[j][key] {
swap = true
} else if table[i][key] == table[j][key] && compare(i, j, GT) {
swap = true
}
case STR_R:
if table[i][key] < table[j][key] {
swap = true
} else if table[i][key] == table[j][key] && compare(i, j, LT) {
swap = true
}
default:
if number[i] > number[j] {
swap = true
} else if table[i][key] == table[j][key] && compare(i, j, GT) {
swap = true
} }
} }
if min != i {
if swap { list[i], list[min] = list[min], list[i]
table[i], table[j] = table[j], table[i]
number[i], number[j] = number[j], number[i]
} }
} }
}
// 输出数据
for _, k := range m.meta[MSG_APPEND] { for _, k := range m.meta[MSG_APPEND] {
delete(m.meta, k) delete(m.meta, k)
} }
for _, v := range table { for _, v := range list {
for _, k := range m.meta[MSG_APPEND] { for _, k := range m.meta[MSG_APPEND] {
m.Add(MSG_APPEND, k, v[k]) m.Add(MSG_APPEND, k, v[k])
} }
} }
return m return m
} }
func (m *Message) SortInt(key string) { m.Sort(key, "int") } func (m *Message) SortInt(key string) { m.Sort(key, INT) }
func (m *Message) SortIntR(key string) { m.Sort(key, "int_r") } func (m *Message) SortStr(key string) { m.Sort(key, STR) }
func (m *Message) SortStr(key string) { m.Sort(key, "str") } func (m *Message) SortTime(key string) { m.Sort(key, TIME) }
func (m *Message) SortStrR(key string) { m.Sort(key, "str_r") } func (m *Message) SortTimeR(key string) { m.Sort(key, TIME_R) }
func (m *Message) SortTime(key string) { m.Sort(key, "time") } func (m *Message) SortStrR(key string) { m.Sort(key, STR_R) }
func (m *Message) SortTimeR(key string) { m.Sort(key, "time_r") } func (m *Message) SortIntR(key string) { m.Sort(key, INT_R) }
func (m *Message) Detail(arg ...Any) string { func (m *Message) Detail(arg ...Any) string {
return kit.Select("", m.meta[MSG_DETAIL], 0) return kit.Select("", m.meta[MSG_DETAIL], 0)
@ -462,37 +393,38 @@ func (m *Message) Detail(arg ...Any) string {
func (m *Message) Detailv(arg ...Any) []string { func (m *Message) Detailv(arg ...Any) []string {
return m.meta[MSG_DETAIL] return m.meta[MSG_DETAIL]
} }
func (m *Message) Options(arg ...Any) Any {
for i := 0; i < len(arg)-1; i += 2 {
m.Optionv(kit.Format(arg[i]), arg[i+1])
}
return m.Optionv(kit.Format(arg[0]))
}
func (m *Message) Optionv(key string, arg ...Any) Any { func (m *Message) Optionv(key string, arg ...Any) Any {
if len(arg) > 0 { if len(arg) > 0 {
if kit.IndexOf(m.meta[MSG_OPTION], key) == -1 { // 写数据 if kit.IndexOf(m.meta[MSG_OPTION], key) == -1 {
m.meta[MSG_OPTION] = append(m.meta[MSG_OPTION], key) m.meta[MSG_OPTION] = append(m.meta[MSG_OPTION], key)
} }
switch delete(m.data, key); v := arg[0].(type) {
switch delete(m.data, key); str := arg[0].(type) {
case nil: case nil:
delete(m.meta, key) delete(m.meta, key)
case string: case string:
m.meta[key] = kit.Simple(arg...) m.meta[key] = kit.Simple(arg...)
case []string: case []string:
m.meta[key] = str m.meta[key] = v
default: default:
m.data[key] = str m.data[key] = v
} }
} }
for msg := m; msg != nil; msg = msg.message { for msg := m; msg != nil; msg = msg.message {
if list, ok := msg.data[key]; ok { if v, ok := msg.data[key]; ok {
return list // 读数据 return v
} }
if list, ok := msg.meta[key]; ok { if v, ok := msg.meta[key]; ok {
return list // 读选项 return v
} }
} }
return nil return nil
} }
func (m *Message) Message() *Message {
return m.message
}
func (m *Message) Option(key string, arg ...Any) string { func (m *Message) Option(key string, arg ...Any) string {
return kit.Select("", kit.Simple(m.Optionv(key, arg...)), 0) return kit.Select("", kit.Simple(m.Optionv(key, arg...)), 0)
} }
@ -503,14 +435,7 @@ func (m *Message) Append(key string, arg ...Any) string {
return kit.Select("", m.Appendv(key, arg...), 0) return kit.Select("", m.Appendv(key, arg...), 0)
} }
func (m *Message) Appendv(key string, arg ...Any) []string { func (m *Message) Appendv(key string, arg ...Any) []string {
if key == MSG_APPEND { if m.FieldsIsDetail() {
if len(arg) > 0 {
m.meta[MSG_APPEND] = kit.Simple(arg)
}
return m.meta[key]
}
if m.FieldsIsDetail() && key != KEY {
for i, k := range m.meta[KEY] { for i, k := range m.meta[KEY] {
if k == key || k == kit.Keys(EXTRA, key) { if k == key || k == kit.Keys(EXTRA, key) {
if len(arg) > 0 { if len(arg) > 0 {
@ -526,7 +451,12 @@ func (m *Message) Appendv(key string, arg ...Any) []string {
} }
return nil return nil
} }
if key == MSG_APPEND {
if len(arg) > 0 {
m.meta[MSG_APPEND] = kit.Simple(arg)
}
return m.meta[key]
}
if len(arg) > 0 { if len(arg) > 0 {
m.meta[key] = kit.Simple(arg...) m.meta[key] = kit.Simple(arg...)
} }

157
misc.go
View File

@ -8,7 +8,7 @@ import (
"shylinux.com/x/toolkits/logs" "shylinux.com/x/toolkits/logs"
) )
func (m *Message) Split(str string, arg ...string) *Message { // field sp nl func (m *Message) Split(str string, arg ...string) *Message {
m.Set(MSG_APPEND).Set(MSG_RESULT) m.Set(MSG_APPEND).Set(MSG_RESULT)
field := kit.Select("", arg, 0) field := kit.Select("", arg, 0)
sp := kit.Select(SP, arg, 1) sp := kit.Select(SP, arg, 1)
@ -21,7 +21,7 @@ func (m *Message) Split(str string, arg ...string) *Message { // field sp nl
if strings.TrimSpace(l) == "" { if strings.TrimSpace(l) == "" {
continue continue
} }
if i == 0 && (field == "" || field == INDEX) { // 表头行 if i == 0 && (field == "" || field == INDEX) {
if fields = kit.Split(l, sp, sp); field == INDEX { if fields = kit.Split(l, sp, sp); field == INDEX {
if strings.HasPrefix(l, SP) || strings.HasPrefix(l, TB) { if strings.HasPrefix(l, SP) || strings.HasPrefix(l, TB) {
indexs = append(indexs, 0) indexs = append(indexs, 0)
@ -37,8 +37,7 @@ func (m *Message) Split(str string, arg ...string) *Message { // field sp nl
} }
continue continue
} }
if len(indexs) > 0 {
if len(indexs) > 0 { // 按位切分
for i, v := range indexs { for i, v := range indexs {
if v >= len(l) { if v >= len(l) {
m.Push(strings.TrimSpace(kit.Select(SP, fields, i)), "") m.Push(strings.TrimSpace(kit.Select(SP, fields, i)), "")
@ -52,7 +51,6 @@ func (m *Message) Split(str string, arg ...string) *Message { // field sp nl
} }
continue continue
} }
ls := kit.Split(l, sp, sp) ls := kit.Split(l, sp, sp)
for i, v := range ls { for i, v := range ls {
if i == len(fields)-1 { if i == len(fields)-1 {
@ -78,18 +76,6 @@ func (m *Message) PushDetail(value Any, arg ...string) *Message {
return m.Push(FIELDS_DETAIL, value, kit.Split(kit.Join(arg))) return m.Push(FIELDS_DETAIL, value, kit.Split(kit.Join(arg)))
} }
func (m *Message) Options(arg ...Any) *Message {
for i := 0; i < len(arg); i += 2 {
m.Option(kit.Format(arg[i]), arg[i+1])
}
return m
}
func (m *Message) OptionMulti(arg ...Any) *Message {
for i := 0; i < len(arg); i += 2 {
m.Option(kit.Format(arg[i]), arg[i+1])
}
return m
}
func (m *Message) ToLowerAppend(arg ...string) *Message { func (m *Message) ToLowerAppend(arg ...string) *Message {
for _, k := range m.meta[MSG_APPEND] { for _, k := range m.meta[MSG_APPEND] {
m.RenameAppend(k, strings.ToLower(k)) m.RenameAppend(k, strings.ToLower(k))
@ -101,7 +87,7 @@ func (m *Message) RenameOption(from, to string) *Message {
m.Option(from, "") m.Option(from, "")
return m return m
} }
func (m *Message) RenameAppend(arg ...string) *Message { // [from to]... func (m *Message) RenameAppend(arg ...string) *Message {
for i := 0; i < len(arg)-1; i += 2 { for i := 0; i < len(arg)-1; i += 2 {
if arg[i] == arg[i+1] { if arg[i] == arg[i+1] {
continue continue
@ -154,9 +140,6 @@ func (m *Message) SetResult(arg ...string) *Message {
return m.Set(MSG_RESULT, arg...) return m.Set(MSG_RESULT, arg...)
} }
func (m *Message) IsMobile() bool {
return strings.Contains(m.Option(MSG_USERUA), "Mobile")
}
func (m *Message) Design(action Any, help string, input ...Any) { func (m *Message) Design(action Any, help string, input ...Any) {
list := kit.List() list := kit.List()
for _, input := range input { for _, input := range input {
@ -181,12 +164,27 @@ func (m *Message) Design(action Any, help string, input ...Any) {
kit.Value(m._cmd.Meta, kit.Keys("_trans", k), help) kit.Value(m._cmd.Meta, kit.Keys("_trans", k), help)
} }
} }
func (m *Message) CmdHand(cmd *Command, key string, arg ...string) *Message {
if m._key, m._cmd = key, cmd; cmd == nil {
return m
}
if m._target = kit.FileLine(cmd.Hand, 3); cmd.RawHand != nil {
m._target = kit.Format(cmd.RawHand)
}
if fileline := kit.Select(m._target, m._source, m.target.Name == MDB); key == SELECT {
m.Log(LOG_CMDS, "%s.%s %d %v %v", m.Target().Name, key, len(arg), arg, m.Optionv(MSG_FIELDS), logs.FileLineMeta(fileline))
} else {
m.Log(LOG_CMDS, "%s.%s %d %v", m.Target().Name, key, len(arg), arg, logs.FileLineMeta(fileline))
}
if cmd.Hand != nil {
cmd.Hand(m, arg...)
} else if cmd.Actions != nil && cmd.Actions[SELECT] != nil {
cmd.Actions[SELECT].Hand(m, arg...)
}
return m
}
func (m *Message) _command(arg ...Any) *Message { func (m *Message) _command(arg ...Any) *Message {
args, opts := []Any{}, Map{} args, opts, cbs, _source := []Any{}, Map{}, kit.Value(nil), logs.FileLine(3, 3)
var cbs Any
// 解析参数
_source := logs.FileLine(3, 3)
for _, v := range arg { for _, v := range arg {
switch val := v.(type) { switch val := v.(type) {
case string: case string:
@ -203,12 +201,10 @@ func (m *Message) _command(arg ...Any) *Message {
opts[val.Name] = val.Value opts[val.Name] = val.Value
case *Option: case *Option:
opts[val.Name] = val.Value opts[val.Name] = val.Value
case logs.Meta: case logs.Meta:
if val.Key == "fileline" { if val.Key == "fileline" {
_source = val.Value _source = val.Value
} }
case func(int, Maps, []string): case func(int, Maps, []string):
defer func() { m.Table(val) }() defer func() { m.Table(val) }()
case func(Maps): case func(Maps):
@ -221,8 +217,6 @@ func (m *Message) _command(arg ...Any) *Message {
} }
} }
} }
// 解析命令
list := kit.Simple(args...) list := kit.Simple(args...)
if len(list) == 0 && !m.Hand { if len(list) == 0 && !m.Hand {
list = m.meta[MSG_DETAIL] list = m.meta[MSG_DETAIL]
@ -230,25 +224,20 @@ func (m *Message) _command(arg ...Any) *Message {
if len(list) == 0 { if len(list) == 0 {
return m return m
} }
ok := false ok := false
run := func(msg *Message, ctx *Context, cmd *Command, key string, arg ...string) { run := func(msg *Message, ctx *Context, cmd *Command, key string, arg ...string) {
key = kit.Slice(strings.Split(key, PT), -1)[0]
if ok = true; cbs != nil { if ok = true; cbs != nil {
msg.OptionCB(kit.Slice(kit.Split(list[0], PT), -1)[0], cbs) msg.OptionCB(key, cbs)
} }
for k, v := range opts { for k, v := range opts {
msg.Option(k, v) msg.Option(k, v)
} }
// 执行命令
msg._source = _source msg._source = _source
m.TryCatch(msg, true, func(msg *Message) { m = ctx._command(msg, cmd, key, arg...) }) m.TryCatch(msg, true, func(msg *Message) { m = ctx._command(msg, cmd, key, arg...) })
} }
// 查找命令
if list[0] == "" { if list[0] == "" {
list[0] = m._key run(m.Spawn(), m.target, m._cmd, m._key, list[1:]...)
run(m.Spawn(), m.target, m._cmd, list[0], list[1:]...)
} else if cmd, ok := m.target.Commands[strings.TrimPrefix(list[0], m.target.Cap(CTX_FOLLOW)+PT)]; ok { } else if cmd, ok := m.target.Commands[strings.TrimPrefix(list[0], m.target.Cap(CTX_FOLLOW)+PT)]; ok {
run(m.Spawn(), m.target, cmd, list[0], list[1:]...) run(m.Spawn(), m.target, cmd, list[0], list[1:]...)
} else if cmd, ok := m.source.Commands[strings.TrimPrefix(list[0], m.source.Cap(CTX_FOLLOW)+PT)]; ok { } else if cmd, ok := m.source.Commands[strings.TrimPrefix(list[0], m.source.Cap(CTX_FOLLOW)+PT)]; ok {
@ -261,32 +250,11 @@ func (m *Message) _command(arg ...Any) *Message {
m.Warn(!ok, ErrNotFound, kit.Format(list)) m.Warn(!ok, ErrNotFound, kit.Format(list))
return m return m
} }
func (m *Message) CmdHand(cmd *Command, key string, arg ...string) *Message {
if m._key, m._cmd = key, cmd; cmd == nil {
return m
}
if m._target = kit.FileLine(cmd.Hand, 3); cmd.RawHand != nil {
m._target = kit.Format(cmd.RawHand)
}
if fileline := kit.Select(m._target, m._source, m.target.Name == MDB); key == "select" {
m.Log(LOG_CMDS, "%s.%s %d %v %v", m.Target().Name, key, len(arg), arg, m.Optionv(MSG_FIELDS), logs.FileLineMeta(fileline))
} else {
m.Log(LOG_CMDS, "%s.%s %d %v", m.Target().Name, key, len(arg), arg, logs.FileLineMeta(fileline))
}
if cmd.Hand != nil {
cmd.Hand(m, arg...)
} else if cmd.Actions != nil && cmd.Actions["select"] != nil {
cmd.Actions["select"].Hand(m, arg...)
}
return m
}
func (c *Context) _command(m *Message, cmd *Command, key string, arg ...string) *Message { func (c *Context) _command(m *Message, cmd *Command, key string, arg ...string) *Message {
key = kit.Slice(strings.Split(key, PT), -1)[0] if m._key, m._sub, m._cmd = key, SELECT, cmd; cmd == nil {
if m._key, m._sub, m._cmd = key, "select", cmd; cmd == nil {
return m return m
} }
if m.Hand, m.meta[MSG_DETAIL] = true, kit.Simple(m.PrefixKey(), arg); cmd.Actions != nil {
if m.Hand, m.meta[MSG_DETAIL] = true, kit.Simple(key, arg); cmd.Actions != nil {
if len(arg) > 1 && arg[0] == ACTION { if len(arg) > 1 && arg[0] == ACTION {
if h, ok := cmd.Actions[arg[1]]; ok { if h, ok := cmd.Actions[arg[1]]; ok {
return c._action(m, cmd, key, arg[1], h, arg[2:]...) return c._action(m, cmd, key, arg[1], h, arg[2:]...)
@ -298,30 +266,14 @@ func (c *Context) _command(m *Message, cmd *Command, key string, arg ...string)
} }
} }
} }
return m.CmdHand(cmd, key, arg...)
if m._target = kit.FileLine(cmd.Hand, 3); cmd.RawHand != nil {
m._target = kit.Format(cmd.RawHand)
}
if fileline := kit.Select(m._target, m._source, m.target.Name == MDB); key == "select" {
m.Log(LOG_CMDS, "%s.%s %d %v %v", c.Name, key, len(arg), arg, m.Optionv(MSG_FIELDS), logs.FileLineMeta(fileline))
} else {
m.Log(LOG_CMDS, "%s.%s %d %v", c.Name, key, len(arg), arg, logs.FileLineMeta(fileline))
}
if cmd.Hand != nil {
cmd.Hand(m, arg...)
} else if cmd.Actions != nil && cmd.Actions["select"] != nil {
cmd.Actions["select"].Hand(m, arg...)
}
return m
} }
func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *Action, arg ...string) *Message { func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *Action, arg ...string) *Message {
if h.Hand == nil { if h.Hand == nil {
m.Cmdy(kit.Split(h.Name), arg) m.Cmdy(kit.Split(h.Name), arg)
return m return m
} }
if m._sub = sub; len(h.List) > 0 && sub != SEARCH {
if m._sub = sub; len(h.List) > 0 && sub != "search" {
order := false order := false
for i, v := range h.List { for i, v := range h.List {
name := kit.Format(kit.Value(v, NAME)) name := kit.Format(kit.Value(v, NAME))
@ -331,8 +283,8 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A
} }
if order { if order {
m.Option(name, kit.Select(value, arg, i)) m.Option(name, kit.Select(value, arg, i))
} else if m.Option(name) == "" && value != "" { } else {
m.Option(name, value) m.OptionDefault(name, value)
} }
} }
if !order { if !order {
@ -341,7 +293,6 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A
} }
} }
} }
if m._target = kit.FileLine(h.Hand, 3); cmd.RawHand != nil { if m._target = kit.FileLine(h.Hand, 3); cmd.RawHand != nil {
m._target = kit.Format(cmd.RawHand) m._target = kit.Format(cmd.RawHand)
} }
@ -350,52 +301,51 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A
h.Hand(m, arg...) h.Hand(m, arg...)
return m return m
} }
func MergeActions(list ...Any) Actions { func MergeActions(arg ...Any) Actions {
if len(list) == 0 { if len(arg) == 0 {
return nil return nil
} }
base := list[0].(Actions) list := arg[0].(Actions)
for _, from := range list[1:] { for _, from := range arg[1:] {
switch from := from.(type) { switch from := from.(type) {
case Actions: case Actions:
for k, v := range from { for k, v := range from {
if h, ok := base[k]; !ok { if h, ok := list[k]; !ok {
base[k] = v list[k] = v
} else if h.Hand == nil { } else if h.Hand == nil {
h.Hand = v.Hand h.Hand = v.Hand
} else if k == CTX_INIT { } else if k == CTX_INIT {
last := base[k].Hand last := h.Hand
prev := v.Hand hand := v.Hand
base[k].Hand = func(m *Message, arg ...string) { h.Hand = func(m *Message, arg ...string) {
prev(m, arg...) hand(m, arg...)
last(m, arg...) last(m, arg...)
} }
} }
} }
case string: case string:
base[CTX_INIT] = &Action{Hand: func(m *Message, arg ...string) { h := list[CTX_INIT]
list[CTX_INIT] = &Action{Hand: func(m *Message, arg ...string) {
m.Search(from, func(p *Context, s *Context, key string, cmd *Command) { m.Search(from, func(p *Context, s *Context, key string, cmd *Command) {
for k, v := range cmd.Actions { for k, v := range cmd.Actions {
func(k string) { func(k string) {
if h, ok := base[k]; !ok { if h, ok := list[k]; !ok {
base[k] = &Action{Name: v.Name, Help: v.Help, Hand: func(m *Message, arg ...string) { list[k] = &Action{Name: v.Name, Help: v.Help, Hand: func(m *Message, arg ...string) { m.Cmdy(from, k, arg) }}
m.Cmdy(from, k, arg)
}}
} else if h.Hand == nil { } else if h.Hand == nil {
h.Hand = func(m *Message, arg ...string) { h.Hand = func(m *Message, arg ...string) { m.Cmdy(from, k, arg) }
m.Cmdy(from, k, arg)
}
} }
}(k) }(k)
} }
m.target.Merge(m.target)
}) })
if h != nil {
h.Hand(m, arg...)
}
}} }}
default: default:
Pulse.ErrorNotImplement(from) Pulse.ErrorNotImplement(from)
} }
} }
return base return list
} }
func SplitCmd(name string, actions Actions) (list []Any) { func SplitCmd(name string, actions Actions) (list []Any) {
const ( const (
@ -414,7 +364,6 @@ func SplitCmd(name string, actions Actions) (list []Any) {
PAGE = "page" PAGE = "page"
ARGS = "args" ARGS = "args"
) )
item, button := kit.Dict(), false item, button := kit.Dict(), false
push := func(arg ...string) { push := func(arg ...string) {
button = kit.Select("", arg, 0) == BUTTON button = kit.Select("", arg, 0) == BUTTON
@ -432,7 +381,7 @@ func SplitCmd(name string, actions Actions) (list []Any) {
push(BUTTON, ls[i], AUTO) push(BUTTON, ls[i], AUTO)
case AUTO: case AUTO:
push(BUTTON, LIST, AUTO) push(BUTTON, LIST, AUTO)
push(BUTTON, BACK, AUTO) push(BUTTON, BACK)
case PAGE: case PAGE:
push(TEXT, "limit") push(TEXT, "limit")
push(TEXT, "offend") push(TEXT, "offend")

View File

@ -287,7 +287,7 @@ func init() {
} }
_repos_cmd(m, m.Option(REPOS), TAG, m.Option(VERSION)) _repos_cmd(m, m.Option(REPOS), TAG, m.Option(VERSION))
_repos_cmd(m, m.Option(REPOS), PUSH, "--tags") _repos_cmd(m, m.Option(REPOS), PUSH, "--tags")
m.ProcessRefresh30ms() m.ProcessRefresh()
}}, }},
BRANCH: {Name: "branch", Help: "分支", Hand: func(m *ice.Message, arg ...string) { BRANCH: {Name: "branch", Help: "分支", Hand: func(m *ice.Message, arg ...string) {
for _, line := range kit.Split(_repos_cmd(m.Spawn(), arg[0], BRANCH).Result(), ice.NL, ice.NL) { for _, line := range kit.Split(_repos_cmd(m.Spawn(), arg[0], BRANCH).Result(), ice.NL, ice.NL) {
@ -319,6 +319,9 @@ func init() {
m.Cmdy(code.VIMER, code.DEVPACK) m.Cmdy(code.VIMER, code.DEVPACK)
}}, }},
web.DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) { web.DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) {
if m.Option(mdb.TYPE) != web.WORKER {
return
}
text := []string{} text := []string{}
for _, line := range kit.Split(m.Cmdx(web.SPACE, m.Option(mdb.NAME), cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) { for _, line := range kit.Split(m.Cmdx(web.SPACE, m.Option(mdb.NAME), cli.SYSTEM, "git", "diff", "--shortstat"), ice.FS, ice.FS) {
if list := kit.Split(line); strings.Contains(line, "file") { if list := kit.Split(line); strings.Contains(line, "file") {

View File

@ -11,7 +11,7 @@ func _group_list(m *ice.Message, appid string) {
_, data := _lark_get(m, appid, "/open-apis/chat/v4/list") _, data := _lark_get(m, appid, "/open-apis/chat/v4/list")
kit.Fetch(kit.Value(data, "data.groups"), func(index int, value ice.Map) { kit.Fetch(kit.Value(data, "data.groups"), func(index int, value ice.Map) {
m.Push(CHAT_ID, value[CHAT_ID]) m.Push(CHAT_ID, value[CHAT_ID])
m.PushImages(aaa.AVATAR, kit.Format(value[aaa.AVATAR]), "72") m.PushImages(aaa.AVATAR, kit.Format(value[aaa.AVATAR]))
m.Push(mdb.NAME, value[mdb.NAME]) m.Push(mdb.NAME, value[mdb.NAME])
m.Push(mdb.TEXT, value["description"]) m.Push(mdb.TEXT, value["description"])
m.Push(OPEN_ID, value["owner_open_id"]) m.Push(OPEN_ID, value["owner_open_id"])

View File

@ -140,7 +140,7 @@ func init() {
} }
m.Cmd(TAGS, mdb.INSERT, mdb.ZONE, value[mdb.ZONE], kit.Simple(value)) m.Cmd(TAGS, mdb.INSERT, mdb.ZONE, value[mdb.ZONE], kit.Simple(value))
}) })
m.ProcessRefresh300ms() m.ProcessRefresh()
}}, }},
mdb.INSERT: {Name: "insert zone=core type name=hi text=hello path file line", Help: "添加"}, mdb.INSERT: {Name: "insert zone=core type name=hi text=hello path file line", Help: "添加"},
code.INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) { code.INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) {

View File

@ -38,10 +38,10 @@ func (m *Message) OptionSimple(key ...string) (res []string) {
if len(key) == 0 { if len(key) == 0 {
for _, k := range kit.Split(m.Config(FIELD)) { for _, k := range kit.Split(m.Config(FIELD)) {
switch k { switch k {
case "", TIME, HASH: case TIME, HASH:
continue continue
} }
if m.Option(k) == "" { if k == "" || m.Option(k) == "" {
continue continue
} }
res = append(res, k, m.Option(k)) res = append(res, k, m.Option(k))
@ -92,28 +92,26 @@ func (m *Message) Action(arg ...Any) *Message {
m.Option(MSG_ACTION, kit.Format(arg)) m.Option(MSG_ACTION, kit.Format(arg))
return m return m
} }
func (m *Message) Status(arg ...Any) { func (m *Message) Status(arg ...Any) *Message {
list := kit.List() list, args := kit.List(), kit.Simple(arg)
args := kit.Simple(arg)
for i := 0; i < len(args)-1; i += 2 { for i := 0; i < len(args)-1; i += 2 {
list = append(list, kit.Dict(NAME, args[i], VALUE, args[i+1])) list = append(list, kit.Dict(NAME, args[i], VALUE, args[i+1]))
} }
m.Option(MSG_STATUS, kit.Format(list)) m.Option(MSG_STATUS, kit.Format(list))
return m
} }
func (m *Message) StatusTime(arg ...Any) *Message { func (m *Message) StatusTime(arg ...Any) *Message {
m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost()) return m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost())
return m
} }
func (m *Message) StatusTimeCount(arg ...Any) *Message { func (m *Message) StatusTimeCount(arg ...Any) *Message {
m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], arg, kit.MDB_COST, m.FormatCost()) return m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], arg, kit.MDB_COST, m.FormatCost())
return m
} }
func (m *Message) StatusTimeCountTotal(arg ...Any) { func (m *Message) StatusTimeCountTotal(arg ...Any) *Message {
m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], kit.MDB_TOTAL, arg, kit.MDB_COST, m.FormatCost()) return m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], kit.MDB_TOTAL, arg, kit.MDB_COST, m.FormatCost())
} }
func (m *Message) Process(action string, arg ...Any) { func (m *Message) Process(cmd string, arg ...Any) {
m.Option(MSG_PROCESS, action) m.Option(MSG_PROCESS, cmd)
m.Option(PROCESS_ARG, arg...) m.Option(PROCESS_ARG, arg...)
} }
func (m *Message) ProcessLocation(arg ...Any) { func (m *Message) ProcessLocation(arg ...Any) {
@ -128,16 +126,12 @@ func (m *Message) ProcessHistory(arg ...Any) {
func (m *Message) ProcessConfirm(arg ...Any) { func (m *Message) ProcessConfirm(arg ...Any) {
m.Process(PROCESS_CONFIRM, arg...) m.Process(PROCESS_CONFIRM, arg...)
} }
func (m *Message) ProcessRefresh(arg ...string) { // delay func (m *Message) ProcessRefresh(arg ...string) {
if d, e := time.ParseDuration(kit.Select("300ms", arg, 0)); e == nil {
m.Option("_delay", int(d/time.Millisecond))
}
m.Process(PROCESS_REFRESH) m.Process(PROCESS_REFRESH)
if d, e := time.ParseDuration(kit.Select("30ms", arg, 0)); e == nil {
m.Option(PROCESS_ARG, int(d/time.Millisecond))
}
} }
func (m *Message) ProcessRefresh3ms() { m.ProcessRefresh("3ms") }
func (m *Message) ProcessRefresh30ms() { m.ProcessRefresh("30ms") }
func (m *Message) ProcessRefresh300ms() { m.ProcessRefresh("300ms") }
func (m *Message) ProcessRefresh3s() { m.ProcessRefresh("3s") }
func (m *Message) ProcessRewrite(arg ...Any) { func (m *Message) ProcessRewrite(arg ...Any) {
m.Process(PROCESS_REWRITE, arg...) m.Process(PROCESS_REWRITE, arg...)
} }
@ -146,11 +140,11 @@ func (m *Message) ProcessDisplay(arg ...Any) {
m.Option(MSG_DISPLAY, arg...) m.Option(MSG_DISPLAY, arg...)
} }
func (m *Message) ProcessInner() { m.Process(PROCESS_INNER) }
func (m *Message) ProcessField(arg ...Any) { func (m *Message) ProcessField(arg ...Any) {
m.Process(PROCESS_FIELD) m.Process(PROCESS_FIELD)
m.Option(FIELD_PREFIX, arg...) m.Option(FIELD_PREFIX, arg...)
} }
func (m *Message) ProcessInner() { m.Process(PROCESS_INNER) }
func (m *Message) ProcessAgain() { m.Process(PROCESS_AGAIN) } func (m *Message) ProcessAgain() { m.Process(PROCESS_AGAIN) }
func (m *Message) ProcessHold(text ...Any) { m.Process(PROCESS_HOLD, text...) } func (m *Message) ProcessHold(text ...Any) { m.Process(PROCESS_HOLD, text...) }
func (m *Message) ProcessBack() { m.Process(PROCESS_BACK) } func (m *Message) ProcessBack() { m.Process(PROCESS_BACK) }
@ -158,40 +152,22 @@ func (m *Message) ProcessRich(arg ...Any) { m.Process(PROCESS_RICH, arg...) }
func (m *Message) ProcessGrow(arg ...Any) { m.Process(PROCESS_GROW, arg...) } func (m *Message) ProcessGrow(arg ...Any) { m.Process(PROCESS_GROW, arg...) }
func (m *Message) ProcessOpen(url string) { m.Process(PROCESS_OPEN, url) } func (m *Message) ProcessOpen(url string) { m.Process(PROCESS_OPEN, url) }
func (m *Message) Display(file string, arg ...Any) *Message { // repos local file func (m *Message) Display(file string, arg ...Any) *Message {
m.Option(MSG_DISPLAY, kit.MergeURL(displayRequire(2, file)[DISPLAY], arg...)) m.Option(MSG_DISPLAY, kit.MergeURL(displayRequire(2, file)[DISPLAY], arg...))
return m return m
} }
func DisplayLocal(file string, arg ...string) Maps { // /plugin/local/file
if file == "" {
file = path.Join(kit.PathName(2), kit.Keys(kit.FileName(2), JS))
}
if !strings.HasPrefix(file, HTTP) && !strings.HasPrefix(file, PS) {
file = path.Join(PLUGIN_LOCAL, file)
}
return DisplayBase(file, arg...)
}
func DisplayStory(file string, arg ...string) Maps { // /plugin/story/file
if !strings.HasPrefix(file, HTTP) && !strings.HasPrefix(file, PS) {
file = path.Join(PLUGIN_STORY, file)
}
return DisplayBase(file, arg...)
}
func DisplayBase(file string, arg ...string) Maps {
return Maps{DISPLAY: file, STYLE: kit.Join(arg, SP)}
}
func Display(file string, arg ...string) Maps { // repos local file
return displayRequire(2, file, arg...)
}
func displayRequire(n int, file string, arg ...string) Maps { func displayRequire(n int, file string, arg ...string) Maps {
if file == "" { if file == "" {
file = kit.Keys(kit.FileName(n+1), JS) file = kit.Keys(kit.FileName(n+1), JS)
} }
if !strings.HasPrefix(file, HTTP) && !strings.HasPrefix(file, PS) { if !strings.HasPrefix(file, PS) && !strings.HasPrefix(file, HTTP) {
file = path.Join(PS, path.Join(path.Dir(FileRequire(n+2)), file)) file = path.Join(PS, path.Join(path.Dir(FileRequire(n+2)), file))
} }
return DisplayBase(file, arg...) return DisplayBase(file, arg...)
} }
func DisplayBase(file string, arg ...string) Maps {
return Maps{DISPLAY: file, STYLE: kit.Join(arg, SP)}
}
func FileRequire(n int) string { func FileRequire(n int) string {
p := kit.Split(kit.FileLine(n, 100), DF)[0] p := kit.Split(kit.FileLine(n, 100), DF)[0]
if strings.Contains(p, "go/pkg/mod") { if strings.Contains(p, "go/pkg/mod") {

161
render.go
View File

@ -14,12 +14,7 @@ func Render(m *Message, cmd string, args ...Any) string {
if render, ok := Info.render[cmd]; ok { if render, ok := Info.render[cmd]; ok {
return render(m, cmd, args...) return render(m, cmd, args...)
} }
switch arg := kit.Simple(args...); cmd { switch arg := kit.Simple(args...); cmd {
case RENDER_ANCHOR: // [name] link
p := kit.Select(arg[0], arg, 1)
return kit.Format(`<a href="%s" target="_blank">%s</a>`, p, arg[0])
case RENDER_BUTTON: case RENDER_BUTTON:
list := []string{} list := []string{}
for _, k := range args { for _, k := range args {
@ -44,47 +39,40 @@ func Render(m *Message, cmd string, args ...Any) string {
} }
} }
return strings.Join(list, "") return strings.Join(list, "")
case RENDER_ANCHOR:
case RENDER_IMAGES: // src [height] return kit.Format(`<a href="%s" target="_blank">%s</a>`, kit.Select(arg[0], arg, 1), arg[0])
if m.Option("height") != "" && m.Option("width") != "" { case RENDER_IMAGES:
return kit.Format(`<img src="%s" style="max-height:%spx; max-width:%spx">`, arg[0], m.Option("height"), m.Option("width")) return kit.Format(`<img src="%s" style="max-height:%spx; max-width:%spx">`, arg[0], m.Option(HEIGHT), m.Option(WIDTH))
} case RENDER_VIDEOS:
if strings.Contains(m.Option(MSG_USERUA), "Mobile") { return kit.Format(`<video src="%s" style="max-height:%spx; max-width:%spx" controls>`, arg[0], m.Option(HEIGHT), m.Option(WIDTH))
return kit.Format(`<img src="%s" width=%d>`, arg[0], kit.Int(kit.Select(kit.Select("120", m.Option("width")), arg, 1))-24)
}
return kit.Format(`<img src="%s" height=%d>`, arg[0], kit.Int(kit.Select(kit.Select("240", m.Option("height")), arg, 1))/2-24)
case RENDER_VIDEOS: // src [height]
if m.Option("height") != "" && m.Option("width") != "" {
return kit.Format(`<video src="%s" controls style="max-height:%spx; max-width:%spx">`, arg[0], m.Option("height"), m.Option("width"))
}
return kit.Format(`<video src="%s" height=%s controls>`, arg[0], kit.Select("120", arg, 1))
case RENDER_IFRAME: case RENDER_IFRAME:
return kit.Format(`<iframe src="%s"></iframe>`, arg[0]) return kit.Format(`<iframe src="%s"></iframe>`, arg[0])
case RENDER_SCRIPT:
return kit.Format(`<code>%s</code>`, arg[0])
default: default:
return arg[0] if len(arg) == 1 {
return kit.Format(`<%s>%s</%s>`, cmd, arg[0], cmd)
}
return kit.Format(`<%s style="%s">%s</%s>`, cmd, kit.JoinKV(":", ";", arg[1:]...), arg[0], cmd)
} }
return ""
} }
func (m *Message) Render(cmd string, args ...Any) *Message { func (m *Message) Render(cmd string, arg ...Any) *Message {
switch cmd { switch cmd {
case RENDER_TEMPLATE: // text [data] case RENDER_TEMPLATE:
if len(args) == 1 { if len(arg) == 1 {
args = append(args, m) arg = append(arg, m)
} }
if res, err := kit.Render(args[0].(string), args[1]); m.Assert(err) { if res, err := kit.Render(arg[0].(string), arg[1]); m.Assert(err) {
m.Echo(string(res)) m.Echo(string(res))
} }
return m return m
} }
m.Optionv(MSG_OUTPUT, cmd) m.Options(MSG_OUTPUT, cmd, MSG_ARGS, arg)
m.Optionv(MSG_ARGS, args)
return m return m
} }
func (m *Message) RenderTemplate(args ...Any) *Message { func (m *Message) RenderTemplate(arg ...Any) *Message {
return m.Render(RENDER_TEMPLATE, args...) return m.Render(RENDER_TEMPLATE, arg...)
} }
func (m *Message) RenderStatus(status int, arg ...string) *Message { func (m *Message) RenderStatus(status int, arg ...string) *Message {
return m.Render(RENDER_STATUS, status, arg) return m.Render(RENDER_STATUS, status, arg)
@ -101,65 +89,61 @@ func (m *Message) RenderStatusForbidden(arg ...string) *Message {
func (m *Message) RenderStatusNotFound(arg ...string) *Message { func (m *Message) RenderStatusNotFound(arg ...string) *Message {
return m.Render(RENDER_STATUS, http.StatusNotFound, arg) return m.Render(RENDER_STATUS, http.StatusNotFound, arg)
} }
func (m *Message) RenderRedirect(args ...Any) *Message { func (m *Message) RenderRedirect(arg ...Any) *Message {
return m.Render(RENDER_REDIRECT, args...) return m.Render(RENDER_REDIRECT, arg...)
} }
func (m *Message) RenderDownload(args ...Any) *Message { func (m *Message) RenderDownload(arg ...Any) *Message {
return m.Render(RENDER_DOWNLOAD, args...) return m.Render(RENDER_DOWNLOAD, arg...)
} }
func (m *Message) RenderResult(args ...Any) *Message { // [fmt arg...] func (m *Message) RenderResult(arg ...Any) *Message {
return m.Render(RENDER_RESULT, args...) return m.Render(RENDER_RESULT, arg...)
} }
func (m *Message) RenderJson(args ...Any) *Message { // [key value]... func (m *Message) RenderJson(arg ...Any) *Message {
return m.Render(RENDER_JSON, kit.Format(kit.Dict(args...))) return m.Render(RENDER_JSON, kit.Format(kit.Dict(arg...)))
} }
func (m *Message) IsMobileUA() bool {
return strings.Contains(m.Option(MSG_USERUA), "Mobile")
}
func (m *Message) IsCliUA() bool { func (m *Message) IsCliUA() bool {
if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla") { if m.Option(MSG_USERUA) == "" || !strings.HasPrefix(m.Option(MSG_USERUA), "Mozilla") {
return true return true
} }
return false return false
} }
func (m *Message) PushAction(list ...Any) *Message { func (m *Message) IsMobileUA() bool {
if len(m.meta[MSG_APPEND]) == 0 { return strings.Contains(m.Option(MSG_USERUA), "Mobile")
return m
}
return m.Set(MSG_APPEND, ACTION).Tables(func(value Maps) { m.PushButton(list...) })
} }
func (m *Message) PushSearch(args ...Any) { func (m *Message) PushSearch(arg ...Any) {
data := kit.Dict(args...) data := kit.Dict(arg...)
for i := 0; i < len(args); i += 2 { for i := 0; i < len(arg); i += 2 {
switch k := args[i].(type) { switch k := arg[i].(type) {
case string: case string:
if i+1 < len(args) { if i+1 < len(arg) {
data[k] = args[i+1] data[k] = arg[i+1]
} }
} }
} }
for _, k := range kit.Split(m.OptionFields()) { for _, k := range kit.Split(m.OptionFields()) {
switch k { switch k {
case TIME:
m.Push(k, kit.Select(m.Time(), data[k]))
case POD: case POD:
m.Push(k, kit.Select("", data[k])) m.Push(k, kit.Select("", data[k]))
case CTX: case CTX:
m.Push(k, kit.Select(m.Prefix(), data[k])) m.Push(k, kit.Select(m.Prefix(), data[k]))
case CMD: case CMD:
m.Push(k, kit.Select(m.CommandKey(), data[k])) m.Push(k, kit.Select(m.CommandKey(), data[k]))
case TIME:
m.Push(k, kit.Select(m.Time(), data[k]))
default: default:
m.Push(k, kit.Select("", data[k])) m.Push(k, kit.Select("", data[k]))
} }
} }
} }
func (m *Message) PushAnchor(arg ...Any) { // [name] link func (m *Message) PushAction(arg ...Any) *Message {
if !m.IsCliUA() { if len(m.meta[MSG_APPEND]) == 0 {
m.Push(LINK, Render(m, RENDER_ANCHOR, arg...)) return m
} }
return m.Set(MSG_APPEND, ACTION).Tables(func(value Maps) { m.PushButton(arg...) })
} }
func (m *Message) PushButton(arg ...Any) *Message { // name...
func (m *Message) PushButton(arg ...Any) *Message {
if !m.IsCliUA() { if !m.IsCliUA() {
if m.FieldsIsDetail() { if m.FieldsIsDetail() {
for i, k := range m.meta[KEY] { for i, k := range m.meta[KEY] {
@ -175,58 +159,63 @@ func (m *Message) PushButton(arg ...Any) *Message { // name...
} }
return m return m
} }
func (m *Message) PushImages(key, src string, arg ...string) { // key src [height] func (m *Message) PushAnchor(arg ...string) {
if !m.IsCliUA() { if !m.IsCliUA() {
m.Push(key, Render(m, RENDER_IMAGES, src, arg)) m.Push(LINK, Render(m, RENDER_ANCHOR, arg))
} }
} }
func (m *Message) PushVideos(key, src string, arg ...string) { // key src [height] func (m *Message) PushQRCode(key, src string) {
if !m.IsCliUA() { if !m.IsCliUA() {
m.Push(key, Render(m, RENDER_VIDEOS, src, arg)) m.Push(key, Render(m, RENDER_QRCODE, src))
} }
} }
func (m *Message) PushIFrame(key, src string, arg ...string) { // key src func (m *Message) PushImages(key, src string) {
if !m.IsCliUA() { if !m.IsCliUA() {
m.Push(key, Render(m, RENDER_IFRAME, src, arg)) m.Push(key, Render(m, RENDER_IMAGES, src))
} }
} }
func (m *Message) PushQRCode(key string, src string, arg ...string) { // key src [height] func (m *Message) PushVideos(key, src string) {
if !m.IsCliUA() { if !m.IsCliUA() {
m.Push(key, Render(m, RENDER_QRCODE, src, arg)) m.Push(key, Render(m, RENDER_VIDEOS, src))
} }
} }
func (m *Message) PushScript(arg ...string) { // [type] text... func (m *Message) PushIFrame(key, src string) {
if !m.IsCliUA() {
m.Push(key, Render(m, RENDER_IFRAME, src))
}
}
func (m *Message) PushScript(arg ...string) {
if !m.IsCliUA() { if !m.IsCliUA() {
m.Push(SCRIPT, Render(m, RENDER_SCRIPT, arg)) m.Push(SCRIPT, Render(m, RENDER_SCRIPT, arg))
} }
} }
func (m *Message) PushDownload(key string, arg ...Any) { // [name] file func (m *Message) PushDownload(key string, arg ...string) {
if !m.IsCliUA() { if !m.IsCliUA() {
m.Push(key, Render(m, RENDER_DOWNLOAD, arg...)) m.Push(key, Render(m, RENDER_DOWNLOAD, arg))
} }
} }
func (m *Message) EchoAnchor(arg ...Any) *Message { // [name] link func (m *Message) EchoButton(arg ...Any) *Message {
return m.Echo(Render(m, RENDER_ANCHOR, arg...))
}
func (m *Message) EchoButton(arg ...Any) *Message { // name...
return m.Echo(Render(m, RENDER_BUTTON, arg...)) return m.Echo(Render(m, RENDER_BUTTON, arg...))
} }
func (m *Message) EchoImages(src string, arg ...string) *Message { // src [height] func (m *Message) EchoAnchor(arg ...string) *Message {
return m.Echo(Render(m, RENDER_IMAGES, src, arg)) return m.Echo(Render(m, RENDER_ANCHOR, arg))
} }
func (m *Message) EchoVideos(src string, arg ...string) *Message { // src [height] func (m *Message) EchoQRCode(src string) *Message {
return m.Echo(Render(m, RENDER_VIDEOS, src, arg)) return m.Echo(Render(m, RENDER_QRCODE, src))
} }
func (m *Message) EchoIFrame(src string, arg ...string) *Message { // src func (m *Message) EchoImages(src string) *Message {
return m.Echo(Render(m, RENDER_IFRAME, src, arg)) return m.Echo(Render(m, RENDER_IMAGES, src))
} }
func (m *Message) EchoQRCode(src string, arg ...string) *Message { // src [height] func (m *Message) EchoVideos(src string) *Message {
return m.Echo(Render(m, RENDER_QRCODE, src, arg)) return m.Echo(Render(m, RENDER_VIDEOS, src))
} }
func (m *Message) EchoScript(arg ...string) *Message { // [type] text... func (m *Message) EchoIFrame(src string) *Message {
return m.Echo(Render(m, RENDER_IFRAME, src))
}
func (m *Message) EchoScript(arg ...string) *Message {
return m.Echo(Render(m, RENDER_SCRIPT, arg)) return m.Echo(Render(m, RENDER_SCRIPT, arg))
} }
func (m *Message) EchoDownload(arg ...Any) *Message { // [name] file func (m *Message) EchoDownload(arg ...string) *Message {
return m.Echo(Render(m, RENDER_DOWNLOAD, arg...)) return m.Echo(Render(m, RENDER_DOWNLOAD, arg))
} }

288
type.go
View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"path"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
@ -63,21 +62,33 @@ type Context struct {
root *Context root *Context
server Server server Server
begin *Message
start *Message
id int32 id int32
} }
type Server interface { type Server interface {
Spawn(m *Message, c *Context, arg ...string) Server
Begin(m *Message, arg ...string) Server Begin(m *Message, arg ...string) Server
Start(m *Message, arg ...string) bool Start(m *Message, arg ...string) bool
Close(m *Message, arg ...string) bool Close(m *Message, arg ...string) bool
Spawn(m *Message, c *Context, arg ...string) Server
} }
func (c *Context) ID() int32 { func (c *Context) ID() int32 {
return atomic.AddInt32(&c.id, 1) return atomic.AddInt32(&c.id, 1)
} }
func (c *Context) Cap(key string, arg ...Any) string {
if len(arg) > 0 {
c.Caches[key].Value = kit.Format(arg[0])
}
return c.Caches[key].Value
}
func (c *Context) Cmd(m *Message, key string, arg ...string) *Message {
return c._command(m, c.Commands[key], key, arg...)
}
func (c *Context) Server() Server {
return c.server
}
func (c *Context) PrefixKey(arg ...string) string {
return kit.Keys(c.Cap(CTX_FOLLOW), arg)
}
func (c *Command) GetFileLine() string { func (c *Command) GetFileLine() string {
if c.RawHand != nil { if c.RawHand != nil {
switch h := c.RawHand.(type) { switch h := c.RawHand.(type) {
@ -92,25 +103,10 @@ func (c *Command) GetFileLine() string {
return "" return ""
} }
} }
func (c *Context) Cap(key string, arg ...Any) string {
if len(arg) > 0 {
c.Caches[key].Value = kit.Format(arg[0])
}
return c.Caches[key].Value
}
func (c *Context) Cmd(m *Message, key string, arg ...string) *Message {
return c._command(m, c.Commands[key], key, arg...)
}
func (c *Context) Server() Server {
return c.server
}
func (c *Context) PrefixKey(arg ...string) string {
return kit.Keys(c.Cap(CTX_FOLLOW), arg)
}
func (c *Context) Register(s *Context, x Server, n ...string) *Context { func (c *Context) Register(s *Context, x Server, n ...string) *Context {
for _, n := range n { for _, n := range n {
if s, ok := Info.names[n]; ok { if s, ok := Info.index[n]; ok {
last := "" last := ""
switch s := s.(type) { switch s := s.(type) {
case *Context: case *Context:
@ -118,10 +114,9 @@ func (c *Context) Register(s *Context, x Server, n ...string) *Context {
} }
panic(kit.Format("%s %s %v", ErrWarn, n, last)) panic(kit.Format("%s %s %v", ErrWarn, n, last))
} }
Info.names[n] = s Info.index[n] = s
} }
if c.Contexts == nil {
if s.Merge(s); c.Contexts == nil {
c.Contexts = Contexts{} c.Contexts = Contexts{}
} }
c.Contexts[s.Name] = s c.Contexts[s.Name] = s
@ -147,14 +142,12 @@ func (c *Context) Merge(s *Context) *Context {
if c.Commands[CTX_EXIT] == nil { if c.Commands[CTX_EXIT] == nil {
c.Commands[CTX_EXIT] = &Command{Hand: func(m *Message, arg ...string) { Info.Save(m) }} c.Commands[CTX_EXIT] = &Command{Hand: func(m *Message, arg ...string) { Info.Save(m) }}
} }
merge := func(pre *Command, init bool, key string, cmd *Command, cb ...Handler) {
merge := func(pre *Command, before bool, key string, cmd *Command, cb ...Handler) {
last := pre.Hand last := pre.Hand
pre.Hand = func(m *Message, arg ...string) { pre.Hand = func(m *Message, arg ...string) {
if before { if init {
last(m, arg...) last(m, arg...)
} }
_key, _cmd := m._key, m._cmd _key, _cmd := m._key, m._cmd
m._key, m._cmd = key, cmd m._key, m._cmd = key, cmd
for _, cb := range cb { for _, cb := range cb {
@ -163,76 +156,60 @@ func (c *Context) Merge(s *Context) *Context {
} }
} }
m._key, m._cmd = _key, _cmd m._key, m._cmd = _key, _cmd
if !before { if !init {
last(m, arg...) last(m, arg...)
} }
} }
} }
for key, cmd := range s.Commands { for key, cmd := range s.Commands {
if p, ok := c.Commands[key]; ok && s != c { if pre, ok := c.Commands[key]; ok && s != c {
switch hand := cmd.Hand; key { switch hand := cmd.Hand; key {
case CTX_INIT: case CTX_INIT:
merge(p, true, key, cmd, hand) merge(pre, true, key, cmd, hand)
continue
case CTX_EXIT: case CTX_EXIT:
merge(p, false, key, cmd, hand) merge(pre, false, key, cmd, hand)
continue
} }
} }
if c.Commands[key] = cmd; cmd.List == nil { if c.Commands[key] = cmd; cmd.List == nil {
cmd.List = SplitCmd(cmd.Name, cmd.Actions) cmd.List = SplitCmd(cmd.Name, cmd.Actions)
} }
if cmd.Meta == nil { if cmd.Meta == nil {
cmd.Meta = kit.Dict() cmd.Meta = kit.Dict()
} }
for sub, action := range cmd.Actions {
for k, a := range cmd.Actions { if pre, ok := c.Commands[sub]; ok && s == c {
if p, ok := c.Commands[k]; ok { switch h := action.Hand; sub {
switch h := a.Hand; k {
case CTX_INIT: case CTX_INIT:
merge(p, true, key, cmd, func(m *Message, arg ...string) { h(m, arg...) }) merge(pre, true, key, cmd, h)
case CTX_EXIT: case CTX_EXIT:
merge(p, false, key, cmd, func(m *Message, arg ...string) { h(m, arg...) }) merge(pre, false, key, cmd, h)
} }
} }
if strings.HasPrefix(k, PS) { if s == c {
k = kit.Select(k, path.Join(PS, key)+PS, k == PS) for _, h := range Info.merges {
c.Commands[k] = &Command{Name: k, Help: cmd.Help, Hand: func(m *Message, arg ...string) { m.Cmdy(m.CommandKey(), arg) }} init, exit := h(c, key, cmd, sub, action)
merge(c.Commands[CTX_INIT], true, key, cmd, init)
merge(c.Commands[CTX_EXIT], false, key, cmd, exit)
}
}
if help := kit.Split(action.Help, " :"); len(help) > 0 {
if kit.Value(cmd.Meta, kit.Keys("_trans", strings.TrimPrefix(sub, "_")), help[0]); len(help) > 1 {
kit.Value(cmd.Meta, kit.Keys("_title", sub), help[1])
}
}
if action.Hand == nil {
continue continue
} }
if action.List == nil {
if s != c { action.List = SplitCmd(action.Name, nil)
switch k {
case "search":
merge(c.Commands[CTX_INIT], true, key, cmd, func(m *Message, arg ...string) {
if m.CommandKey() != "search" {
m.Cmd("search", "create", m.CommandKey(), m.PrefixKey())
} }
}) if len(action.List) > 0 {
cmd.Meta[sub] = action.List
} }
} }
help := strings.SplitN(a.Help, "", 2)
if len(help) == 1 || help[1] == "" {
help = strings.SplitN(help[0], ":", 2)
} }
if kit.Value(cmd.Meta, kit.Keys("_trans", strings.TrimPrefix(k, "_")), help[0]); len(help) > 1 {
kit.Value(cmd.Meta, kit.Keys("title", k), help[1])
}
if a.Hand == nil {
continue // alias cmd
}
if a.List == nil {
a.List = SplitCmd(a.Name, nil)
}
if len(a.List) > 0 {
cmd.Meta[k] = a.List
}
}
delete(cmd.Actions, CTX_INIT)
delete(cmd.Actions, CTX_EXIT)
}
if c.Configs == nil { if c.Configs == nil {
c.Configs = Configs{} c.Configs = Configs{}
} }
@ -247,6 +224,44 @@ func (c *Context) Merge(s *Context) *Context {
} }
return c return c
} }
func (c *Context) Begin(m *Message, arg ...string) *Context {
follow := c.Name
if c.context != nil && c.context != Index {
follow = kit.Keys(c.context.Cap(CTX_FOLLOW), c.Name)
}
if c.Caches == nil {
c.Caches = Caches{}
}
c.Caches[CTX_FOLLOW] = &Cache{Name: CTX_FOLLOW, Value: follow}
c.Caches[CTX_STATUS] = &Cache{Name: CTX_STATUS, Value: CTX_BEGIN}
c.Caches[CTX_STREAM] = &Cache{Name: CTX_STREAM, Value: ""}
if c.Merge(c); c.server != nil {
c.server.Begin(m, arg...)
}
return c
}
func (c *Context) Start(m *Message, arg ...string) bool {
wait := make(chan bool, 1)
defer func() { <-wait }()
m.Go(func() {
wait <- true
m.Log(CTX_START, c.Cap(CTX_FOLLOW))
c.Cap(CTX_STATUS, CTX_START)
if c.server != nil {
c.server.Start(m, arg...)
}
})
return true
}
func (c *Context) Close(m *Message, arg ...string) bool {
m.Log(CTX_CLOSE, c.Cap(CTX_FOLLOW))
c.Cap(CTX_STATUS, CTX_CLOSE)
if c.server != nil {
return c.server.Close(m, arg...)
}
return true
}
func (c *Context) Spawn(m *Message, name string, help string, arg ...string) *Context { func (c *Context) Spawn(m *Message, name string, help string, arg ...string) *Context {
s := &Context{Name: name, Help: help} s := &Context{Name: name, Help: help}
if c.server != nil { if c.server != nil {
@ -257,44 +272,6 @@ func (c *Context) Spawn(m *Message, name string, help string, arg ...string) *Co
m.target = s m.target = s
return s return s
} }
func (c *Context) Begin(m *Message, arg ...string) *Context {
follow := c.Name
if c.context != nil && c.context != Index {
follow = kit.Keys(c.context.Cap(CTX_FOLLOW), c.Name)
}
c.Caches[CTX_FOLLOW] = &Cache{Name: CTX_FOLLOW, Value: follow}
c.Caches[CTX_STATUS] = &Cache{Name: CTX_STATUS, Value: CTX_BEGIN}
c.Caches[CTX_STREAM] = &Cache{Name: CTX_STREAM, Value: ""}
if c.begin = m; c.server != nil {
c.server.Begin(m, arg...)
}
return c
}
func (c *Context) Start(m *Message, arg ...string) bool {
wait := make(chan bool, 1)
defer func() { <-wait }()
m.Go(func() {
m.Log(CTX_START, c.Cap(CTX_FOLLOW))
c.Cap(CTX_STATUS, CTX_START)
wait <- true
if c.start = m; c.server != nil {
c.server.Start(m, arg...)
}
})
return true
}
func (c *Context) Close(m *Message, arg ...string) bool {
m.Log(CTX_CLOSE, c.Cap(CTX_FOLLOW))
c.Cap(CTX_STATUS, CTX_CLOSE)
if c.server != nil {
return c.server.Close(m, arg...)
}
return true
}
type Message struct { type Message struct {
time time.Time time time.Time
@ -321,28 +298,11 @@ type Message struct {
I io.Reader I io.Reader
} }
// func (m *Message) getMeta(key string) []string { func (m *Message) Time(args ...Any) string {
// defer m.lock.RLock()()
// return m.meta[key]
// }
// func (m *Message) setMeta(key string, value []string) {
// defer m.lock.Lock()()
// if value == nil {
// delete(m.meta, key)
// } else {
// m.meta[key] = value
// }
// }
// func (m *Message) getData(key string) Any {
// defer m.lock.RLock()()
// return m._data[key]
// }
//
func (m *Message) Time(args ...Any) string { // [duration] [format [args...]]
t := m.time t := m.time
if len(args) > 0 { if len(args) > 0 {
switch arg := args[0].(type) { switch arg := args[0].(type) {
case string: // 时间偏移 case string:
if d, e := time.ParseDuration(arg); e == nil { if d, e := time.ParseDuration(arg); e == nil {
t, args = t.Add(d), args[1:] t, args = t.Add(d), args[1:]
} }
@ -351,7 +311,7 @@ func (m *Message) Time(args ...Any) string { // [duration] [format [args...]]
f := MOD_TIME f := MOD_TIME
if len(args) > 0 { if len(args) > 0 {
switch arg := args[0].(type) { switch arg := args[0].(type) {
case string: // 时间格式 case string:
if f = arg; len(args) > 1 { if f = arg; len(args) > 1 {
f = fmt.Sprintf(f, args[1:]...) f = fmt.Sprintf(f, args[1:]...)
} }
@ -365,6 +325,9 @@ func (m *Message) Target() *Context {
func (m *Message) Source() *Context { func (m *Message) Source() *Context {
return m.source return m.source
} }
func (m *Message) Message() *Message {
return m.message
}
func (m *Message) Spawn(arg ...Any) *Message { func (m *Message) Spawn(arg ...Any) *Message {
msg := &Message{ msg := &Message{
time: time.Now(), code: int(m.target.root.ID()), time: time.Now(), code: int(m.target.root.ID()),
@ -373,7 +336,6 @@ func (m *Message) Spawn(arg ...Any) *Message {
source: m.target, target: m.target, _cmd: m._cmd, _key: m._key, _sub: m._sub, source: m.target, target: m.target, _cmd: m._cmd, _key: m._key, _sub: m._sub,
W: m.W, R: m.R, O: m.O, I: m.I, W: m.W, R: m.R, O: m.O, I: m.I,
} }
for _, val := range arg { for _, val := range arg {
switch val := val.(type) { switch val := val.(type) {
case []byte: case []byte:
@ -401,27 +363,24 @@ func (m *Message) Spawn(arg ...Any) *Message {
return msg return msg
} }
func (m *Message) Start(key string, arg ...string) *Message { func (m *Message) Start(key string, arg ...string) *Message {
m.Search(key+PT, func(p *Context, s *Context) { s.Start(m.Spawn(s), arg...) }) return m.Search(key+PT, func(p *Context, s *Context) { s.Start(m.Spawn(s), arg...) })
return m
} }
func (m *Message) Travel(cb Any) *Message { func (m *Message) Travel(cb Any) *Message {
list := []*Context{m.root.target} list := []*Context{m.root.target}
for i := 0; i < len(list); i++ { for i := 0; i < len(list); i++ {
switch cb := cb.(type) { switch cb := cb.(type) {
case func(*Context, *Context): // 遍历模块 case func(*Context, *Context):
cb(list[i].context, list[i]) cb(list[i].context, list[i])
case func(*Context, *Context, string, *Command): case func(*Context, *Context, string, *Command):
target := m.target target := m.target
for _, k := range kit.SortedKey(list[i].Commands) { // 命令列表 for _, k := range kit.SortedKey(list[i].Commands) {
m.target = list[i] m.target = list[i]
cb(list[i].context, list[i], k, list[i].Commands[k]) cb(list[i].context, list[i], k, list[i].Commands[k])
} }
m.target = target m.target = target
case func(*Context, *Context, string, *Config): case func(*Context, *Context, string, *Config):
target := m.target target := m.target
for _, k := range kit.SortedKey(list[i].Configs) { // 配置列表 for _, k := range kit.SortedKey(list[i].Configs) {
m.target = list[i] m.target = list[i]
cb(list[i].context, list[i], k, list[i].Configs[k]) cb(list[i].context, list[i], k, list[i].Configs[k])
} }
@ -429,8 +388,7 @@ func (m *Message) Travel(cb Any) *Message {
default: default:
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
for _, k := range kit.SortedKey(list[i].Contexts) {
for _, k := range kit.SortedKey(list[i].Contexts) { // 遍历递进
list = append(list, list[i].Contexts[k]) list = append(list, list[i].Contexts[k])
} }
} }
@ -440,14 +398,12 @@ func (m *Message) Search(key string, cb Any) *Message {
if key == "" { if key == "" {
return m return m
} }
// 查找模块
p := m.target.root p := m.target.root
if key = strings.TrimPrefix(key, "ice."); key == PT { if key = strings.TrimPrefix(key, "ice."); key == PT {
p, key = m.target, "" p, key = m.target, ""
} else if key == ".." { } else if key == ".." {
p, key = m.target.context, "" p, key = m.target.context, ""
} else if key == "ice." { } else if key == "..." {
p, key = m.target.root, "" p, key = m.target.root, ""
} else if strings.Contains(key, PT) { } else if strings.Contains(key, PT) {
ls := strings.Split(key, PT) ls := strings.Split(key, PT)
@ -468,37 +424,33 @@ func (m *Message) Search(key string, cb Any) *Message {
return m return m
} }
key = ls[len(ls)-1] key = ls[len(ls)-1]
} else if ctx, ok := Info.names[key].(*Context); ok { } else if ctx, ok := Info.index[key].(*Context); ok {
p = ctx p = ctx
} else { } else {
p = m.target p = m.target
} }
switch cb := cb.(type) { switch cb := cb.(type) {
case func(key string, cmd *Command): case func(key string, cmd *Command):
if key == "" { if key == "" {
for k, v := range p.Commands { for k, v := range p.Commands {
cb(k, v) // 遍历命令 cb(k, v)
} }
break break
} }
if cmd, ok := p.Commands[key]; ok { if cmd, ok := p.Commands[key]; ok {
cb(key, cmd) // 查找命令 cb(key, cmd)
} }
case func(p *Context, s *Context, key string, cmd *Command): case func(p *Context, s *Context, key string, cmd *Command):
if key == "" { if key == "" {
for k, v := range p.Commands { for k, v := range p.Commands {
cb(p.context, p, k, v) // 遍历命令 cb(p.context, p, k, v)
} }
break break
} }
for _, p := range []*Context{p, m.target, m.source} { for _, p := range []*Context{p, m.target, m.source} {
for s := p; s != nil; s = s.context { for s := p; s != nil; s = s.context {
if cmd, ok := s.Commands[key]; ok { if cmd, ok := s.Commands[key]; ok {
cb(s.context, s, key, cmd) // 查找命令 cb(s.context, s, key, cmd)
return m return m
} }
} }
@ -506,23 +458,22 @@ func (m *Message) Search(key string, cb Any) *Message {
case func(p *Context, s *Context, key string, conf *Config): case func(p *Context, s *Context, key string, conf *Config):
if key == "" { if key == "" {
for k, v := range p.Configs { for k, v := range p.Configs {
cb(p.context, p, k, v) // 遍历命令 cb(p.context, p, k, v)
} }
break break
} }
for _, p := range []*Context{p, m.target, m.source} { for _, p := range []*Context{p, m.target, m.source} {
for s := p; s != nil; s = s.context { for s := p; s != nil; s = s.context {
if cmd, ok := s.Configs[key]; ok { if cmd, ok := s.Configs[key]; ok {
cb(s.context, s, key, cmd) // 查找配置 cb(s.context, s, key, cmd)
return m return m
} }
} }
} }
case func(p *Context, s *Context, key string): case func(p *Context, s *Context, key string):
cb(p.context, p, key) // 查找模块 cb(p.context, p, key)
case func(p *Context, s *Context): case func(p *Context, s *Context):
cb(p.context, p) // 查找模块 cb(p.context, p)
default: default:
m.ErrorNotImplement(cb) m.ErrorNotImplement(cb)
} }
@ -542,9 +493,7 @@ func (m *Message) CmdAppend(arg ...Any) string {
} }
func (m *Message) CmdMap(arg ...string) map[string]map[string]string { func (m *Message) CmdMap(arg ...string) map[string]map[string]string {
field, list := kit.Slice(arg, -1)[0], map[string]map[string]string{} field, list := kit.Slice(arg, -1)[0], map[string]map[string]string{}
m._command(kit.Slice(arg, 0, -1)).Tables(func(value Maps) { m._command(kit.Slice(arg, 0, -1)).Tables(func(value Maps) { list[value[field]] = value })
list[value[field]] = value
})
return list return list
} }
func (m *Message) Cmd(arg ...Any) *Message { func (m *Message) Cmd(arg ...Any) *Message {
@ -563,23 +512,21 @@ func (m *Message) Cmdy(arg ...Any) *Message {
func (m *Message) Confi(key string, sub string) int { func (m *Message) Confi(key string, sub string) int {
return kit.Int(m.Conf(key, sub)) return kit.Int(m.Conf(key, sub))
} }
func (m *Message) Confv(arg ...Any) (val Any) { // key sub val func (m *Message) Confv(arg ...Any) (val Any) {
run := func(conf *Config) { run := func(conf *Config) {
if len(arg) == 1 { if len(arg) == 1 {
val = conf.Value val = conf.Value
return // 读配置 return
} }
if len(arg) > 2 { if len(arg) > 2 {
if arg[1] == nil || arg[1] == "" { if arg[1] == nil || arg[1] == "" {
conf.Value = arg[2] // 写配置 conf.Value = arg[2]
} else { } else {
kit.Value(conf.Value, arg[1:]...) // 写配置项 kit.Value(conf.Value, arg[1:]...)
} }
} }
val = kit.Value(conf.Value, arg[1]) // 读配置项 val = kit.Value(conf.Value, arg[1])
} }
key := kit.Format(arg[0]) key := kit.Format(arg[0])
if key == "" { if key == "" {
key = m._key key = m._key
@ -601,7 +548,7 @@ func (m *Message) Confm(key string, sub Any, cbs ...Any) Map {
value, _ := val.(Map) value, _ := val.(Map)
return value return value
} }
func (m *Message) Conf(arg ...Any) string { // key sub val func (m *Message) Conf(arg ...Any) string {
return kit.Format(m.Confv(arg...)) return kit.Format(m.Confv(arg...))
} }
func (m *Message) Capi(key string, val ...Any) int { func (m *Message) Capi(key string, val ...Any) int {
@ -616,14 +563,13 @@ func (m *Message) Capv(arg ...Any) Any {
case string: case string:
key, arg = val, arg[1:] key, arg = val, arg[1:]
} }
for _, s := range []*Context{m.target} { for _, s := range []*Context{m.target} {
for c := s; c != nil; c = c.context { for c := s; c != nil; c = c.context {
if caps, ok := c.Caches[key]; ok { if caps, ok := c.Caches[key]; ok {
if len(arg) > 0 { // 写数据 if len(arg) > 0 {
caps.Value = kit.Format(arg[0]) caps.Value = kit.Format(arg[0])
} }
return caps.Value // 读数据 return caps.Value
} }
} }
} }