diff --git a/README.md b/README.md index 8ce6cf27..2061e1e2 100644 --- a/README.md +++ b/README.md @@ -1,129 +1,3 @@ # 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/ +icebergs 是一个应用框架,通过模块化、集群化、自动化方式,在各种设备上,一键部署完整的个人云计算与云研发平台。 diff --git a/base/aaa/user.go b/base/aaa/user.go index 8b205a63..bab220ad 100644 --- a/base/aaa/user.go +++ b/base/aaa/user.go @@ -83,11 +83,11 @@ func init() { } 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)) - userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2)) - m.Option(ice.MSG_USERNICK, UserNick(m, username)) + usernick := m.Option(ice.MSG_USERNICK, kit.Select(UserNick(m, username), arg, 2)) 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 } return m diff --git a/base/cli/runtime.go b/base/cli/runtime.go index 0bc0f250..6d067bce 100644 --- a/base/cli/runtime.go +++ b/base/cli/runtime.go @@ -216,7 +216,7 @@ func init() { }}, PROCKILL: {Name: "prockill", Help: "结束进程", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(gdb.SIGNAL, gdb.STOP, m.Option("PID")) - m.ProcessRefresh30ms() + m.ProcessRefresh() }}, DISKINFO: {Name: "diskinfo", Help: "磁盘信息", Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index 2ba8b414..cb8649f0 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -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) { - defer m.ProcessRefresh3ms() + defer m.ProcessRefresh() switch arg[2] { case ZONE: // insert key sub type zone arg... _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) { - defer m.ProcessRefresh3ms() + defer m.ProcessRefresh() switch arg[2] { 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]) diff --git a/base/mdb/search.go b/base/mdb/search.go index 87940690..f0b79d84 100644 --- a/base/mdb/search.go +++ b/base/mdb/search.go @@ -9,6 +9,13 @@ const SEARCH = "search" func init() { 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 { return ice.Actions{ diff --git a/base/ssh/script.go b/base/ssh/script.go index 0895dca7..cd4f7b25 100644 --- a/base/ssh/script.go +++ b/base/ssh/script.go @@ -36,6 +36,9 @@ func (f *Frame) prompt(m *ice.Message, list ...string) *Frame { if f.source != STDIO { return f } + if m.Target().Cap(ice.CTX_STATUS) == ice.CTX_CLOSE { + return f + } if len(list) == 0 { 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() { msg.SetResult().Cmdy(cli.SYSTEM, ls) } - f.res = Render(msg, msg.Option(ice.MSG_OUTPUT), msg.Optionv(ice.MSG_ARGS).([]ice.Any)...) return "" } diff --git a/base/web/dream.go b/base/web/dream.go index 143d91df..95814f78 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -31,7 +31,7 @@ func _dream_list(m *ice.Message) *ice.Message { 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) { 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), )) 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)) defer ToastProcess(m)() diff --git a/base/web/serve.go b/base/web/serve.go index dc803362..6601c5ab 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -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)))) 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) @@ -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 { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) } - - 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)) + aaa.UserRoot(m, m.Option(aaa.PASSWORD), m.Option(aaa.USERNAME), m.Option(aaa.USERNICK)) m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...) 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)) } }}, - 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) }}, }, mdb.HashAction())}, @@ -396,7 +392,7 @@ func init() { }}, PP(ice.HELP): {Name: "/help/", Help: "帮助", Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { - arg = append(arg, ice.TUTOR_SHY) + arg = append(arg, "tutor.shy") } if len(arg) > 0 && arg[0] != ctx.ACTION { arg[0] = path.Join(ice.SRC_HELP, arg[0]) @@ -404,4 +400,13 @@ func init() { 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 + }) } diff --git a/conf.go b/conf.go index edda3810..459a1c17 100644 --- a/conf.go +++ b/conf.go @@ -14,12 +14,12 @@ const ( OK = "ok" TRUE = "true" FALSE = "false" - SUCCESS = "success" - FAILURE = "failure" PROCESS = "process" + FAILURE = "failure" + SUCCESS = "success" - AUTO = "auto" HTTP = "http" + AUTO = "auto" LIST = "list" BACK = "back" @@ -28,6 +28,7 @@ const ( MISC = "misc" SHY = "shy" + COM = "com" DEV = "dev" OPS = "ops" ICE = "ice" @@ -49,16 +50,16 @@ const ( // MOD MOD_TIME = "2006-01-02 15:04:05" ) const ( // REPOS - VOLCANOS = "volcanos" - LEARNING = "learning" - ICEBERGS = "icebergs" - TOOLKITS = "toolkits" INTSHELL = "intshell" CONTEXTS = "contexts" + ICEBERGS = "icebergs" + TOOLKITS = "toolkits" + VOLCANOS = "volcanos" + LEARNING = "learning" INSTALL = "install" - RELEASE = "release" PUBLISH = "publish" + RELEASE = "release" REQUIRE = "require" DISPLAY = "display" ) @@ -69,12 +70,12 @@ const ( // DIR VAR = "var" USR = "usr" + SVG = "svg" HTML = "html" CSS = "css" JS = "js" GO = "go" SH = "sh" - SVG = "svg" CSV = "csv" JSON = "json" @@ -89,45 +90,41 @@ const ( // DIR FRAME_JS = "frame.js" INDEX_JS = "index.js" INDEX_SH = "index.sh" - INDEX_IML = "index.iml" - TUTOR_SHY = "tutor.shy" - PLUGIN_INPUT = "/plugin/input" - PLUGIN_STORY = "/plugin/story" - PLUGIN_LOCAL = "/plugin/local" - NODE_MODULES = "node_modules" - ISH_PLUGED = ".ish/pluged" + PLUGIN_INPUT = "/plugin/input/" + PLUGIN_STORY = "/plugin/story/" + PLUGIN_LOCAL = "/plugin/local/" + NODE_MODULES = "node_modules/" + ISH_PLUGED = ".ish/pluged/" - USR_VOLCANOS = "usr/volcanos" - USR_LEARNING = "usr/learning" - USR_ICEBERGS = "usr/icebergs" - USR_TOOLKITS = "usr/toolkits" - USR_INTSHELL = "usr/intshell" - USR_INSTALL = "usr/install" - USR_RELEASE = "usr/release" - USR_PUBLISH = "usr/publish" + USR_VOLCANOS = "usr/volcanos/" + USR_LEARNING = "usr/learning/" + USR_ICEBERGS = "usr/icebergs/" + USR_TOOLKITS = "usr/toolkits/" + USR_INTSHELL = "usr/intshell/" + USR_INSTALL = "usr/install/" + USR_PUBLISH = "usr/publish/" + USR_RELEASE = "usr/release/" - USR_LOCAL = "usr/local" - USR_LOCAL_GO = "usr/local/go" - USR_LOCAL_GO_BIN = "usr/local/go/bin" - USR_LOCAL_BIN = "usr/local/bin" - USR_LOCAL_LIB = "usr/local/lib" - USR_LOCAL_WORK = "usr/local/work" - USR_LOCAL_IMAGE = "usr/local/image" - USR_LOCAL_MEDIA = "usr/local/media" - USR_LOCAL_RIVER = "usr/local/river" - USR_LOCAL_DAEMON = "usr/local/daemon" - USR_LOCAL_EXPORT = "usr/local/export" - USR_LOCAL_REPOS = "usr/local/repos" + USR_LOCAL = "usr/local/" + USR_LOCAL_GO = "usr/local/go/" + USR_LOCAL_GO_BIN = "usr/local/go/bin/" + USR_LOCAL_BIN = "usr/local/bin/" + USR_LOCAL_LIB = "usr/local/lib/" + USR_LOCAL_WORK = "usr/local/work/" + USR_LOCAL_IMAGE = "usr/local/image/" + USR_LOCAL_DAEMON = "usr/local/daemon/" + USR_LOCAL_EXPORT = "usr/local/export/" + USR_LOCAL_REPOS = "usr/local/repos/" - VAR_RUN = "var/run" - VAR_TMP = "var/tmp" - VAR_LOG = "var/log" - VAR_CONF = "var/conf" - VAR_DATA = "var/data" - VAR_FILE = "var/file" - VAR_PROXY = "var/proxy" - VAR_TRASH = "var/trash" + VAR_RUN = "var/run/" + VAR_TMP = "var/tmp/" + VAR_LOG = "var/log/" + VAR_CONF = "var/conf/" + VAR_DATA = "var/data/" + VAR_FILE = "var/file/" + VAR_PROXY = "var/proxy/" + VAR_TRASH = "var/trash/" BIN_ICE_BIN = "bin/ice.bin" BIN_BOOT_LOG = "bin/boot.log" ETC_INIT_SHY = "etc/init.shy" @@ -136,13 +133,13 @@ const ( // DIR ETC_MISS_SH = "etc/miss.sh" ETC_PATH = "etc/path" - SRC_HELP = "src/help" - SRC_DEBUG = "src/debug" - SRC_RELEASE = "src/release" + SRC_HELP = "src/help/" + SRC_DEBUG = "src/debug/" + SRC_RELEASE = "src/release/" + SRC_MAIN_SVG = "src/main.svg" + SRC_MAIN_SHY = "src/main.shy" SRC_MAIN_JS = "src/main.js" 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_BINPACK_GO = "src/binpack.go" SRC_RELAY_GO = "src/relay.go" @@ -167,8 +164,8 @@ const ( // MSG MSG_SOURCE = "_source" MSG_TARGET = "_target" MSG_HANDLE = "_handle" - MSG_DAEMON = "_daemon" MSG_UPLOAD = "_upload" + MSG_DAEMON = "_daemon" MSG_ACTION = "_action" MSG_STATUS = "_status" @@ -193,24 +190,25 @@ const ( // MSG MSG_USERZONE = "user.zone" MSG_LANGUAGE = "user.lang" - MSG_TITLE = "sess.title" - MSG_TOPIC = "sess.topic" - MSG_RIVER = "sess.river" - MSG_STORM = "sess.storm" - MSG_FILES = "file.system" + MSG_TITLE = "sess.title" + MSG_TOPIC = "sess.topic" + MSG_RIVER = "sess.river" + MSG_STORM = "sess.storm" + MSG_FILES = "file.system" + LOG_DISABLE = "log.disable" FIELDS_DETAIL = "detail" ) const ( // RENDER - RENDER_TEMPLATE = "_template" - RENDER_ANCHOR = "_anchor" - RENDER_BUTTON = "_button" - RENDER_IMAGES = "_images" - RENDER_VIDEOS = "_videos" - RENDER_IFRAME = "_iframe" - RENDER_QRCODE = "_qrcode" - RENDER_SCRIPT = "_script" + RENDER_BUTTON = "_button" + RENDER_ANCHOR = "_anchor" + RENDER_QRCODE = "_qrcode" + RENDER_IMAGES = "_images" + RENDER_VIDEOS = "_videos" + RENDER_IFRAME = "_iframe" + RENDER_SCRIPT = "_script" + RENDER_TEMPLATE = "_template" RENDER_STATUS = "_status" RENDER_REDIRECT = "_redirect" RENDER_DOWNLOAD = "_download" @@ -227,9 +225,9 @@ const ( // PROCESS PROCESS_REFRESH = "_refresh" PROCESS_REWRITE = "_rewrite" PROCESS_DISPLAY = "_display" - PROCESS_INNER = "_inner" PROCESS_FIELD = "_field" PROCESS_FLOAT = "_float" + PROCESS_INNER = "_inner" PROCESS_AGAIN = "_again" PROCESS_HOLD = "_hold" @@ -242,6 +240,9 @@ const ( // PROCESS FIELD_PREFIX = "_prefix" ) const ( // CTX + CTX_ARG = "ctx_arg" + CTX_DAEMON = "ctx_daemon" + CTX_FOLLOW = "follow" CTX_STATUS = "status" CTX_STREAM = "stream" @@ -253,50 +254,64 @@ const ( // CTX CTX_INIT = "_init" CTX_EXIT = "_exit" - - CTX_ARG = "ctx_arg" - CTX_DAEMON = "ctx_daemon" ) - const ( // LOG LOG_CMDS = "cmds" LOG_AUTH = "auth" LOG_COST = "cost" LOG_INFO = "info" LOG_WARN = "warn" - LOG_DEBUG = "debug" LOG_ERROR = "error" + LOG_DEBUG = "debug" ) const ( // Err ErrWarn = "warn: " - ErrNotLogin = "not login: " - ErrNotRight = "not right: " - ErrNotFound = "not found: " - ErrNotValid = "not valid: " - ErrNotStart = "not start: " + ErrNotLogin = "not login: " + ErrNotRight = "not right: " + ErrNotFound = "not found: " + ErrNotValid = "not valid: " + ErrNotStart = "not start: " + ErrNotImplement = "not implement: " ) - const ( // ctx COMMAND = "command" ACTION = "action" STYLE = "style" INDEX = "index" ) -const ( // mdb - AAA = "aaa" - MDB = "mdb" - KEY = "key" - VALUE = "value" - FIELD = "field" - EXTRA = "extra" - SCRIPT = "script" - META = "meta" - HASH = "hash" - TIME = "time" - TYPE = "type" - NAME = "name" - TEXT = "text" - LINK = "link" +const ( // web + SERVE = "serve" + SPACE = "space" + + TOPIC = "topic" + TITLE = "title" + WIDTH = "width" + HEIGHT = "height" +) +const ( // nfs + SOURCE = "source" + SCRIPT = "script" +) +const ( // mdb + SEARCH = "search" + SELECT = "select" + + KEY = "key" + VALUE = "value" + EXTRA = "extra" + FIELD = "field" + META = "meta" + HASH = "hash" + TIME = "time" + TYPE = "type" + NAME = "name" + TEXT = "text" + LINK = "link" +) +const ( // ice + MDB = "mdb" + AAA = "aaa" + CLI = "cli" ) diff --git a/core/chat/website.go b/core/chat/website.go index 4f038a18..bb6fde15 100644 --- a/core/chat/website.go +++ b/core/chat/website.go @@ -89,7 +89,7 @@ func _website_parse(m *ice.Message, text string, args ...string) (ice.Map, bool) case ctx.ARGS: data[ls[i]] = kit.Split(ls[i+1]) 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: data[ls[i]] = kit.UnMarshal(ls[i+1]) default: diff --git a/core/mall/asset.go b/core/mall/asset.go index f1b03e78..5973a3c7 100644 --- a/core/mall/asset.go +++ b/core/mall/asset.go @@ -86,7 +86,7 @@ func init() { m.Cmd(ASSET, func(value ice.Maps) { _asset_check(m, value[ACCOUNT]) }) - m.ProcessRefresh30ms() + m.ProcessRefresh() } else { _asset_check(m, m.Option(ACCOUNT)) } diff --git a/core/wiki/word.go b/core/wiki/word.go index 32d0eac5..d9a4b8db 100644 --- a/core/wiki/word.go +++ b/core/wiki/word.go @@ -12,7 +12,7 @@ import ( ) 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))) } diff --git a/data.go b/data.go index 4cc89a45..a91c3248 100644 --- a/data.go +++ b/data.go @@ -7,13 +7,13 @@ import ( ) 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 { - 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 { - 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 { return m.Target().PrefixKey(arg...) diff --git a/exec.go b/exec.go index 797efb15..086edd76 100644 --- a/exec.go +++ b/exec.go @@ -7,23 +7,23 @@ import ( "time" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" "shylinux.com/x/toolkits/task" ) func (m *Message) TryCatch(msg *Message, silent bool, hand ...func(msg *Message)) *Message { defer func() { switch e := recover(); e { - case io.EOF: - case nil: + case nil, io.EOF: 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("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 { m.TryCatch(msg, silent, hand[1:]...) } else if !silent { - m.Assert(e) // 抛出异常 + m.Assert(e) } } }() @@ -36,13 +36,13 @@ func (m *Message) Assert(expr Any) bool { switch e := expr.(type) { case nil: return true - case error: case bool: if e == true { return true } + case error: 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) panic(expr) diff --git a/info.go b/info.go index 7027db34..a90ac1d4 100644 --- a/info.go +++ b/info.go @@ -1,13 +1,13 @@ package ice type MakeInfo struct { - Path string Time string + Path string Hash string + Domain string Module string Remote string Branch string - Domain string Version string HostName string UserName string @@ -21,19 +21,20 @@ var Info = struct { UserName string PassWord string - Colors bool Domain string NodeType string NodeName string CtxShare string CtxRiver string PidPath string + Colors bool Help string - Route Maps // 路由命令 - File Maps // 文件命令 - names Map + File Maps + Route Maps + index Map + merges []MergeHandler render map[string]func(*Message, string, ...Any) string Save 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 source: https://shylinux.com/x/icebergs `, - Route: Maps{}, File: Maps{}, - names: Map{}, + Route: Maps{}, + index: Map{}, render: map[string]func(*Message, string, ...Any) string{}, Save: 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) {}, } + +type MergeHandler func(*Context, string, *Command, string, *Action) (Handler, Handler) + +func AddMerges(h ...MergeHandler) { Info.merges = append(Info.merges, h...) } diff --git a/init.go b/init.go index a061e805..a7ac0c69 100644 --- a/init.go +++ b/init.go @@ -12,10 +12,7 @@ import ( type Frame struct{} -func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server { - return &Frame{} -} -func (f *Frame) Begin(m *Message, arg ...string) Server { +func (s *Frame) Begin(m *Message, arg ...string) Server { list := map[*Context]*Message{m.target: m} m.Travel(func(p *Context, s *Context) { s.root = m.target @@ -24,21 +21,20 @@ func (f *Frame) Begin(m *Message, arg ...string) Server { 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.Cmd(kit.Keys(MDB, CTX_INIT)) - m.Cmd("cli.runtime", CTX_INIT) + m.Cmd(kit.Keys(CLI, CTX_INIT)) m.Cmdy(INIT, arg) - for _, k := range kit.Split(kit.Select("ctx,log,gdb,ssh", os.Getenv(CTX_DAEMON))) { m.Start(k) } - m.Cmd(arg) + m.Cmdy(arg) 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} m.Travel(func(p *Context, s *Context) { if msg, ok := list[p]; ok && msg != nil { @@ -47,9 +43,10 @@ func (f *Frame) Close(m *Message, arg ...string) bool { } }) 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 } +func (s *Frame) Spawn(m *Message, c *Context, arg ...string) Server { return &Frame{} } const ( INIT = "init" @@ -58,9 +55,7 @@ const ( QUIT = "quit" ) -var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{ - HELP: {Value: kit.Data(INDEX, Info.Help)}, -}, Commands: Commands{ +var Index = &Context{Name: ICE, Help: "冰山模块", Configs: Configs{HELP: {Value: kit.Data(INDEX, Info.Help)}}, Commands: Commands{ CTX_INIT: {Hand: func(m *Message, arg ...string) { m.root.Travel(func(p *Context, c *Context) { 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.Cmd("source", ETC_INIT_SHY) + m.Cmd(SOURCE, ETC_INIT_SHY) }}, - HELP: {Name: "help", Help: "帮助", Hand: func(m *Message, arg ...string) { - m.Echo(m.Config(INDEX)) - }}, - 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...) + HELP: {Hand: func(m *Message, arg ...string) { m.Echo(m.Config(INDEX)) }}, + QUIT: {Hand: func(m *Message, arg ...string) { os.Exit(0) }}, + EXIT: {Hand: func(m *Message, arg ...string) { 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) }}, CTX_EXIT: {Hand: func(m *Message, arg ...string) { + defer m.Target().Close(m.root.Spawn(), arg...) m.root.Travel(func(p *Context, c *Context) { if cmd, ok := c.Commands[CTX_EXIT]; ok && p != nil { 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 Run(arg ...string) string { - if len(arg) == 0 { // 进程参数 - arg = kit.Simple(arg, os.Args[1:], kit.Split(os.Getenv(CTX_ARG))) + if len(arg) == 0 && len(os.Args) > 1 { + arg = kit.Simple(os.Args[1:], kit.Split(kit.Env(CTX_ARG))) } - Pulse.meta[MSG_DETAIL] = arg - switch Index.Merge(Index).Begin(Pulse.Spawn(), arg...); kit.Select("", arg, 0) { - case "serve", "space": // 启动服务 + switch Index.Merge(Index).Begin(Pulse, arg...); kit.Select("", arg, 0) { + case SERVE, SPACE: if Index.Start(Pulse, arg...) { conf.Wait() - println() os.Exit(kit.Int(Pulse.Option(EXIT))) } - default: // 执行命令 + default: if logs.Disable(true); len(arg) == 0 { arg = append(arg, HELP) } - Pulse.Cmd(INIT) - if Pulse.Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" { + if Pulse.Cmd(INIT).Cmdy(arg); strings.TrimSpace(Pulse.Result()) == "" { Pulse.Table() } - } - - if !strings.HasSuffix(Pulse.Result(), NL) { - Pulse.Echo(NL) + if !strings.HasSuffix(Pulse.Result(), NL) { + Pulse.Echo(NL) + } } return Pulse.Result() } diff --git a/logs.go b/logs.go index bbb3cc31..11b327a2 100644 --- a/logs.go +++ b/logs.go @@ -29,27 +29,21 @@ func (m *Message) join(arg ...Any) (string, []Any) { continue } switch v := arg[i+1].(type) { - case logs.Meta: - list = append(list, key) - meta = append(meta, v) - continue case time.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 } func (m *Message) log(level string, str string, arg ...Any) *Message { _source := logs.FileLineMeta(logs.FileLine(3, 3)) 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 } - - // 日志颜色 prefix, suffix := "", "" if Info.Colors { switch level { @@ -57,20 +51,16 @@ func (m *Message) log(level string, str string, arg ...Any) *Message { prefix, suffix = "\033[32m", "\033[0m" case LOG_AUTH, LOG_COST: prefix, suffix = "\033[33m", "\033[0m" - case LOG_WARN: + case LOG_WARN, LOG_ERROR: prefix, suffix = "\033[31m", "\033[0m" } } - - // 长度截断 switch level { case LOG_INFO: if len(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)...) return m } @@ -116,32 +106,26 @@ func (m *Message) Warn(err Any, arg ...Any) bool { if !m.IsErr() { if m.error(arg...); len(arg) > 0 { switch kit.Format(arg[0]) { - case ErrNotValid: - m.RenderStatusBadRequest(str) case ErrNotLogin: m.RenderStatusUnauthorized(str) case ErrNotRight: m.RenderStatusForbidden(str) case ErrNotFound: m.RenderStatusNotFound(str) + case ErrNotValid: + m.RenderStatusBadRequest(str) } } } 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 { if err { - m.error(arg...) - m.log(LOG_ERROR, m.FormatStack(1, 100)) str, meta := m.join(arg...) - m.log(LOG_ERROR, str, meta) 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 false @@ -156,12 +140,19 @@ func (m *Message) error(arg ...Any) { arg = append(arg, "") } 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 { - 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 { @@ -187,7 +178,6 @@ func (m *Message) FormatChain() string { for msg := m; msg != nil; msg = msg.message { ms = append(ms, msg) } - meta := append([]string{}, NL) for i := len(ms) - 1; i >= 0; i-- { msg := ms[i] @@ -213,20 +203,16 @@ func (m *Message) FormatChain() string { func (m *Message) FormatStack(s, n int) string { pc := make([]uintptr, n+10) frames := runtime.CallersFrames(pc[:runtime.Callers(s+1, pc)]) - list := []string{} for { frame, more := frames.Next() file := kit.Slice(kit.Split(frame.File, 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) { - // case "reflect", "runtime", "http", "task", "icebergs": case "reflect", "runtime", "http": default: list = append(list, kit.Format("%s:%d\t%s", file, frame.Line, name)) } - if len(list) >= n { break } diff --git a/meta.go b/meta.go index 66b712cb..003cf587 100644 --- a/meta.go +++ b/meta.go @@ -7,6 +7,24 @@ import ( kit "shylinux.com/x/toolkits" ) +func (m *Message) setDetail(key string, arg ...string) *Message { + for i := 0; i < len(m.meta[KEY]); i++ { + if m.meta[KEY][i] == key { + if len(arg) > 0 { + m.meta[VALUE][i] = arg[0] + 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 +} func (m *Message) Set(key string, arg ...string) *Message { switch key { case MSG_DETAIL, MSG_RESULT: @@ -14,61 +32,33 @@ func (m *Message) Set(key string, arg ...string) *Message { 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 + m.setDetail(arg[0], arg[1:]...) + } else { + delete(m.meta, KEY) + delete(m.meta, VALUE) + delete(m.meta, MSG_APPEND) } - 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 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 } + return m default: + if m.FieldsIsDetail() { + return m.setDetail(key, arg...) + } for _, k := range kit.Split(key) { delete(m.meta, k) } - if m.FieldsIsDetail() { - for i := 0; i < len(m.meta[KEY]); i++ { - if m.meta[KEY][i] == key { - if len(arg) > 0 { - m.meta[VALUE][i] = arg[0] - 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 - } + } + if len(arg) == 0 { + return m } return m.Add(key, arg...) } @@ -76,21 +66,15 @@ func (m *Message) Add(key string, arg ...string) *Message { switch key { case MSG_DETAIL, MSG_RESULT: m.meta[key] = append(m.meta[key], arg...) - case MSG_OPTION, MSG_APPEND: if len(arg) == 0 { break } - if key == MSG_APPEND { - if i := kit.IndexOf(m.meta[MSG_OPTION], arg[0]); i > -1 { - m.meta[MSG_OPTION][i] = "" + if index := 0; key == MSG_APPEND { + if m.meta[MSG_OPTION], index = kit.SliceRemove(m.meta[MSG_OPTION], arg[0]); index > -1 { 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 { 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() { head = kit.Split(m.OptionFields()) } - switch value := value.(type) { case Map: - if len(head) == 0 { // 键值排序 - head = kit.SortedKey(kit.KeyValue(Map{}, "", value)) + if len(head) == 0 { + head = kit.SortedKey(kit.KeyValue(nil, "", value)) } - var val Map if len(arg) > 1 { val, _ = arg[1].(Map) } - for _, k := range head { - // 查找数据 var v Any switch k { case KEY, HASH: @@ -158,40 +138,33 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message { break } } - - // 追加数据 switch v := kit.Format(v); key { case FIELDS_DETAIL: switch k { case "_target": 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) default: m.Add(MSG_APPEND, k, v) } } - case Maps: - if len(head) == 0 { // 键值排序 + if len(head) == 0 { head = kit.SortedKey(value) } - for _, k := range head { m.Push(k, value[k]) } - default: for _, v := range kit.Simple(value, arg) { if m.FieldsIsDetail() { - if key != KEY || key != VALUE { - m.Add(MSG_APPEND, KEY, key) - m.Add(MSG_APPEND, VALUE, kit.Format(value)) - continue - } + m.Add(MSG_APPEND, KEY, key) + m.Add(MSG_APPEND, VALUE, kit.Format(value)) + } else { + m.Add(MSG_APPEND, key, v) } - m.Add(MSG_APPEND, key, v) } } return m @@ -200,8 +173,7 @@ func (m *Message) Echo(str string, arg ...Any) *Message { if str == "" { return m } - m.meta[MSG_RESULT] = append(m.meta[MSG_RESULT], kit.Format(str, arg...)) - return m + return m.Add(MSG_RESULT, kit.Format(str, arg...)) } func (m *Message) Copy(msg *Message, arg ...string) *Message { if m == nil || msg == nil || m == msg { @@ -213,12 +185,9 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message { } return m } - for _, k := range msg.meta[MSG_OPTION] { switch k { - case MSG_CMDS: - case MSG_FIELDS: - case MSG_SESSID: + case MSG_CMDS, MSG_FIELDS, MSG_SESSID: continue } 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] { 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 + return m.Add(MSG_RESULT, msg.meta[MSG_RESULT]...) } func (m *Message) Length() (max int) { 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 { return m.Table(func(index int, value Maps, head []string) { for _, cb := range cbs { - if cb != nil { - cb(value) - } + cb(value) } }) } func (m *Message) Table(cbs ...func(index int, value Maps, head []string)) *Message { 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]) + n := m.Length() + if n == 0 { return m } - - n := m.Length() - for i := 0; i < n; i++ { - line := Maps{} - 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 } - const ( TABLE_SPACE = "table.space" TABLE_ROW_SEP = "table.row_sep" TABLE_COL_SEP = "table.col_sep" TABLE_COMPACT = "table.compact" + TABLE_ALIGN = "table.align" ) - //计算列宽 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] { - if len(m.meta[k]) > depth { - depth = len(m.meta[k]) + if len(m.meta[k]) > length { + length = len(m.meta[k]) } width[k] = kit.Width(k, len(space)) 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)) cols := kit.Select(SP, m.Option(TABLE_COL_SEP)) - compact := m.Option(TABLE_COMPACT) == TRUE - cb := func(value Maps, field []string, index int) bool { - for i, v := range field { - if k := m.meta[MSG_APPEND][i]; compact { - v = value[k] - } - - if m.Echo(v); i < len(field)-1 { + show := func(value []string) { + for i, v := range value { + if m.Echo(v); i < len(value)-1 { m.Echo(cols) } } m.Echo(rows) - return true } - - // 输出表头 - row, wor := Maps{}, []string{} - for _, k := range m.meta[MSG_APPEND] { - row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-kit.Width(k, len(space)))) - } - if !cb(row, wor, -1) { - return m - } - - // 输出数据 - 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)))) + compact := m.Option(TABLE_COMPACT) == TRUE + _align := kit.Select("left", m.Option(TABLE_ALIGN)) + align := func(value string, width int) string { + if compact { + return value + space } - if !cb(row, wor, i) { - break + n := width - kit.Width(value, len(space)) + 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 + } + 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 } + +const ( + INT = "int" + STR = "str" + // TIME = "time" + + TIME_R = "time_r" + STR_R = "str_r" + INT_R = "int_r" +) + func (m *Message) Sort(key string, arg ...string) *Message { - ls := kit.Split(key) - if key = ls[0]; m.FieldsIsDetail() && key != KEY { + if m.FieldsIsDetail() { return m } - const ( - STR = "str" - INT = "int" - TIME = "time" - - TIME_R = "time_r" - INT_R = "int_r" - STR_R = "str_r" - - GT = ">" - LT = "<" - ) - - // 排序方法 - cmp := STR - if len(arg) > 0 && arg[0] != "" { - cmp = arg[0] - } else { - cmp = INT - for _, v := range m.meta[key] { - if _, e := strconv.Atoi(v); e != nil { - cmp = STR + keys, cmps := kit.Split(key), kit.Simple() + for i, k := range keys { + cmp := kit.Select("", arg, i) + if cmp == "" { + cmp = INT + for _, v := range m.meta[k] { + if _, e := strconv.Atoi(v); e != nil { + 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])) - } - }) - compare := func(i, j int, op string) bool { - for k := range ls { - if k == 0 { + list := []Maps{} + m.Tables(func(value Maps) { list = append(list, value) }) + gt := func(i, j int) bool { + for s, k := range keys { + a, b := list[i][k], list[j][k] + if a == b { continue } - if table[i][ls[k]] == table[j][ls[k]] { - continue + switch cmp := cmps[s]; cmp { + 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 } - - // 排序数据 - for i := 0; i < len(table)-1; i++ { - 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 swap { - table[i], table[j] = table[j], table[i] - number[i], number[j] = number[j], number[i] + for i := 0; i < len(list)-1; i++ { + min := i + for j := i + 1; j < len(list); j++ { + if gt(min, j) { + min = j } } + if min != i { + list[i], list[min] = list[min], list[i] + } } - - // 输出数据 for _, k := range m.meta[MSG_APPEND] { delete(m.meta, k) } - for _, v := range table { + for _, v := range list { for _, k := range m.meta[MSG_APPEND] { m.Add(MSG_APPEND, k, v[k]) } } return m } -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) SortStrR(key string) { m.Sort(key, "str_r") } -func (m *Message) SortTime(key string) { m.Sort(key, "time") } -func (m *Message) SortTimeR(key string) { m.Sort(key, "time_r") } +func (m *Message) SortInt(key string) { m.Sort(key, INT) } +func (m *Message) SortStr(key string) { m.Sort(key, STR) } +func (m *Message) SortTime(key string) { m.Sort(key, TIME) } +func (m *Message) SortTimeR(key string) { m.Sort(key, TIME_R) } +func (m *Message) SortStrR(key string) { m.Sort(key, STR_R) } +func (m *Message) SortIntR(key string) { m.Sort(key, INT_R) } func (m *Message) Detail(arg ...Any) string { 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 { 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 { 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) } - - switch delete(m.data, key); str := arg[0].(type) { + switch delete(m.data, key); v := arg[0].(type) { case nil: delete(m.meta, key) case string: m.meta[key] = kit.Simple(arg...) case []string: - m.meta[key] = str + m.meta[key] = v default: - m.data[key] = str + m.data[key] = v } } - for msg := m; msg != nil; msg = msg.message { - if list, ok := msg.data[key]; ok { - return list // 读数据 + if v, ok := msg.data[key]; ok { + return v } - if list, ok := msg.meta[key]; ok { - return list // 读选项 + if v, ok := msg.meta[key]; ok { + return v } } return nil } -func (m *Message) Message() *Message { - return m.message -} func (m *Message) Option(key string, arg ...Any) string { 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) } func (m *Message) Appendv(key string, arg ...Any) []string { - if key == MSG_APPEND { - if len(arg) > 0 { - m.meta[MSG_APPEND] = kit.Simple(arg) - } - return m.meta[key] - } - - if m.FieldsIsDetail() && key != KEY { + if m.FieldsIsDetail() { for i, k := range m.meta[KEY] { if k == key || k == kit.Keys(EXTRA, key) { if len(arg) > 0 { @@ -526,7 +451,12 @@ func (m *Message) Appendv(key string, arg ...Any) []string { } 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 { m.meta[key] = kit.Simple(arg...) } diff --git a/misc.go b/misc.go index 6a2ea404..a18b0e4b 100644 --- a/misc.go +++ b/misc.go @@ -8,7 +8,7 @@ import ( "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) field := kit.Select("", arg, 0) 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) == "" { continue } - if i == 0 && (field == "" || field == INDEX) { // 表头行 + if i == 0 && (field == "" || field == INDEX) { if fields = kit.Split(l, sp, sp); field == INDEX { if strings.HasPrefix(l, SP) || strings.HasPrefix(l, TB) { indexs = append(indexs, 0) @@ -37,8 +37,7 @@ func (m *Message) Split(str string, arg ...string) *Message { // field sp nl } continue } - - if len(indexs) > 0 { // 按位切分 + if len(indexs) > 0 { for i, v := range indexs { if v >= len(l) { 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 } - ls := kit.Split(l, sp, sp) for i, v := range ls { 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))) } -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 { for _, k := range m.meta[MSG_APPEND] { m.RenameAppend(k, strings.ToLower(k)) @@ -101,7 +87,7 @@ func (m *Message) RenameOption(from, to string) *Message { m.Option(from, "") 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 { if arg[i] == arg[i+1] { continue @@ -154,9 +140,6 @@ func (m *Message) SetResult(arg ...string) *Message { 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) { list := kit.List() 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) } } +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 { - args, opts := []Any{}, Map{} - var cbs Any - - // 解析参数 - _source := logs.FileLine(3, 3) + args, opts, cbs, _source := []Any{}, Map{}, kit.Value(nil), logs.FileLine(3, 3) for _, v := range arg { switch val := v.(type) { case string: @@ -203,12 +201,10 @@ func (m *Message) _command(arg ...Any) *Message { opts[val.Name] = val.Value case *Option: opts[val.Name] = val.Value - case logs.Meta: if val.Key == "fileline" { _source = val.Value } - case func(int, Maps, []string): defer func() { m.Table(val) }() case func(Maps): @@ -221,8 +217,6 @@ func (m *Message) _command(arg ...Any) *Message { } } } - - // 解析命令 list := kit.Simple(args...) if len(list) == 0 && !m.Hand { list = m.meta[MSG_DETAIL] @@ -230,25 +224,20 @@ func (m *Message) _command(arg ...Any) *Message { if len(list) == 0 { return m } - ok := false 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 { - msg.OptionCB(kit.Slice(kit.Split(list[0], PT), -1)[0], cbs) + msg.OptionCB(key, cbs) } for k, v := range opts { msg.Option(k, v) } - - // 执行命令 msg._source = _source m.TryCatch(msg, true, func(msg *Message) { m = ctx._command(msg, cmd, key, arg...) }) } - - // 查找命令 if list[0] == "" { - list[0] = m._key - run(m.Spawn(), m.target, m._cmd, list[0], list[1:]...) + run(m.Spawn(), m.target, m._cmd, m._key, list[1:]...) } 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:]...) } 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)) 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 { - 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 } - - if m.Hand, m.meta[MSG_DETAIL] = true, kit.Simple(key, arg); cmd.Actions != nil { + if m.Hand, m.meta[MSG_DETAIL] = true, kit.Simple(m.PrefixKey(), arg); cmd.Actions != nil { if len(arg) > 1 && arg[0] == ACTION { if h, ok := cmd.Actions[arg[1]]; ok { 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) } } } - - 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 + return m.CmdHand(cmd, key, arg...) } func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *Action, arg ...string) *Message { if h.Hand == nil { m.Cmdy(kit.Split(h.Name), arg) return m } - - if m._sub = sub; len(h.List) > 0 && sub != "search" { + if m._sub = sub; len(h.List) > 0 && sub != SEARCH { order := false for i, v := range h.List { 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 { m.Option(name, kit.Select(value, arg, i)) - } else if m.Option(name) == "" && value != "" { - m.Option(name, value) + } else { + m.OptionDefault(name, value) } } 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 { 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...) return m } -func MergeActions(list ...Any) Actions { - if len(list) == 0 { +func MergeActions(arg ...Any) Actions { + if len(arg) == 0 { return nil } - base := list[0].(Actions) - for _, from := range list[1:] { + list := arg[0].(Actions) + for _, from := range arg[1:] { switch from := from.(type) { case Actions: for k, v := range from { - if h, ok := base[k]; !ok { - base[k] = v + if h, ok := list[k]; !ok { + list[k] = v } else if h.Hand == nil { h.Hand = v.Hand } else if k == CTX_INIT { - last := base[k].Hand - prev := v.Hand - base[k].Hand = func(m *Message, arg ...string) { - prev(m, arg...) + last := h.Hand + hand := v.Hand + h.Hand = func(m *Message, arg ...string) { + hand(m, arg...) last(m, arg...) } } } 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) { for k, v := range cmd.Actions { func(k string) { - if h, ok := base[k]; !ok { - base[k] = &Action{Name: v.Name, Help: v.Help, Hand: func(m *Message, arg ...string) { - m.Cmdy(from, k, arg) - }} + if h, ok := list[k]; !ok { + list[k] = &Action{Name: v.Name, Help: v.Help, Hand: func(m *Message, arg ...string) { m.Cmdy(from, k, arg) }} } else if h.Hand == nil { - h.Hand = func(m *Message, arg ...string) { - m.Cmdy(from, k, arg) - } + h.Hand = func(m *Message, arg ...string) { m.Cmdy(from, k, arg) } } }(k) } - m.target.Merge(m.target) }) + if h != nil { + h.Hand(m, arg...) + } }} default: Pulse.ErrorNotImplement(from) } } - return base + return list } func SplitCmd(name string, actions Actions) (list []Any) { const ( @@ -414,7 +364,6 @@ func SplitCmd(name string, actions Actions) (list []Any) { PAGE = "page" ARGS = "args" ) - item, button := kit.Dict(), false push := func(arg ...string) { button = kit.Select("", arg, 0) == BUTTON @@ -432,7 +381,7 @@ func SplitCmd(name string, actions Actions) (list []Any) { push(BUTTON, ls[i], AUTO) case AUTO: push(BUTTON, LIST, AUTO) - push(BUTTON, BACK, AUTO) + push(BUTTON, BACK) case PAGE: push(TEXT, "limit") push(TEXT, "offend") diff --git a/misc/git/status.go b/misc/git/status.go index b056f2d7..b1e361c5 100644 --- a/misc/git/status.go +++ b/misc/git/status.go @@ -287,7 +287,7 @@ func init() { } _repos_cmd(m, m.Option(REPOS), TAG, m.Option(VERSION)) _repos_cmd(m, m.Option(REPOS), PUSH, "--tags") - m.ProcessRefresh30ms() + m.ProcessRefresh() }}, 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) { @@ -319,6 +319,9 @@ func init() { m.Cmdy(code.VIMER, code.DEVPACK) }}, web.DREAM_TABLES: {Hand: func(m *ice.Message, arg ...string) { + if m.Option(mdb.TYPE) != web.WORKER { + return + } text := []string{} 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") { diff --git a/misc/lark/group.go b/misc/lark/group.go index 0f808baa..8c04bae2 100644 --- a/misc/lark/group.go +++ b/misc/lark/group.go @@ -11,7 +11,7 @@ func _group_list(m *ice.Message, appid string) { _, data := _lark_get(m, appid, "/open-apis/chat/v4/list") kit.Fetch(kit.Value(data, "data.groups"), func(index int, value ice.Map) { 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.TEXT, value["description"]) m.Push(OPEN_ID, value["owner_open_id"]) diff --git a/misc/vim/tags.go b/misc/vim/tags.go index 58805d6a..717803d6 100644 --- a/misc/vim/tags.go +++ b/misc/vim/tags.go @@ -140,7 +140,7 @@ func init() { } 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: "添加"}, code.INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) { diff --git a/option.go b/option.go index ea3acb96..4319541d 100644 --- a/option.go +++ b/option.go @@ -38,10 +38,10 @@ func (m *Message) OptionSimple(key ...string) (res []string) { if len(key) == 0 { for _, k := range kit.Split(m.Config(FIELD)) { switch k { - case "", TIME, HASH: + case TIME, HASH: continue } - if m.Option(k) == "" { + if k == "" || m.Option(k) == "" { continue } 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)) return m } -func (m *Message) Status(arg ...Any) { - list := kit.List() - args := kit.Simple(arg) +func (m *Message) Status(arg ...Any) *Message { + list, args := kit.List(), kit.Simple(arg) for i := 0; i < len(args)-1; i += 2 { list = append(list, kit.Dict(NAME, args[i], VALUE, args[i+1])) } m.Option(MSG_STATUS, kit.Format(list)) + return m } func (m *Message) StatusTime(arg ...Any) *Message { - m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost()) - return m + return m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost()) } 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 + return m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], arg, kit.MDB_COST, m.FormatCost()) } -func (m *Message) StatusTimeCountTotal(arg ...Any) { - 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) StatusTimeCountTotal(arg ...Any) *Message { + 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) { - m.Option(MSG_PROCESS, action) +func (m *Message) Process(cmd string, arg ...Any) { + m.Option(MSG_PROCESS, cmd) m.Option(PROCESS_ARG, arg...) } func (m *Message) ProcessLocation(arg ...Any) { @@ -128,16 +126,12 @@ func (m *Message) ProcessHistory(arg ...Any) { func (m *Message) ProcessConfirm(arg ...Any) { m.Process(PROCESS_CONFIRM, arg...) } -func (m *Message) ProcessRefresh(arg ...string) { // delay - if d, e := time.ParseDuration(kit.Select("300ms", arg, 0)); e == nil { - m.Option("_delay", int(d/time.Millisecond)) - } +func (m *Message) ProcessRefresh(arg ...string) { 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) { m.Process(PROCESS_REWRITE, arg...) } @@ -146,11 +140,11 @@ func (m *Message) ProcessDisplay(arg ...Any) { m.Option(MSG_DISPLAY, arg...) } -func (m *Message) ProcessInner() { m.Process(PROCESS_INNER) } func (m *Message) ProcessField(arg ...Any) { m.Process(PROCESS_FIELD) m.Option(FIELD_PREFIX, arg...) } +func (m *Message) ProcessInner() { m.Process(PROCESS_INNER) } func (m *Message) ProcessAgain() { m.Process(PROCESS_AGAIN) } func (m *Message) ProcessHold(text ...Any) { m.Process(PROCESS_HOLD, text...) } 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) 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...)) 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 { if file == "" { 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)) } 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 { p := kit.Split(kit.FileLine(n, 100), DF)[0] if strings.Contains(p, "go/pkg/mod") { diff --git a/render.go b/render.go index 128131c7..87ae7787 100644 --- a/render.go +++ b/render.go @@ -14,12 +14,7 @@ func Render(m *Message, cmd string, args ...Any) string { if render, ok := Info.render[cmd]; ok { return render(m, cmd, args...) } - switch arg := kit.Simple(args...); cmd { - case RENDER_ANCHOR: // [name] link - p := kit.Select(arg[0], arg, 1) - return kit.Format(`%s`, p, arg[0]) - case RENDER_BUTTON: list := []string{} for _, k := range args { @@ -44,47 +39,40 @@ func Render(m *Message, cmd string, args ...Any) string { } } return strings.Join(list, "") - - case RENDER_IMAGES: // src [height] - if m.Option("height") != "" && m.Option("width") != "" { - return kit.Format(``, arg[0], m.Option("height"), m.Option("width")) - } - if strings.Contains(m.Option(MSG_USERUA), "Mobile") { - return kit.Format(``, arg[0], kit.Int(kit.Select(kit.Select("120", m.Option("width")), arg, 1))-24) - } - return kit.Format(``, 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(`