diff --git a/base/aaa/aaa.go b/base/aaa/aaa.go index c2d510cf..8517be05 100644 --- a/base/aaa/aaa.go +++ b/base/aaa/aaa.go @@ -12,6 +12,7 @@ const ( USERZONE = "userzone" USERNICK = "usernick" USERNAME = "username" + HOSTNAME = "hostname" PASSWORD = "password" USERROLE = "userrole" USERNODE = "usernode" diff --git a/base/cli/cli.go b/base/cli/cli.go index 50ce9b2b..a5c06ede 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -105,12 +105,12 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块", msg.Split(m.Cmdx(SYSTEM, "ps", "ux"), "", " ", "\n") msg.Table(func(index int, value map[string]string, head []string) { if m.Appendv(ice.MSG_APPEND, "action", head); len(arg) == 2 && value["PID"] == arg[1] { - m.Push("action", m.Cmdx(mdb.RENDER, "button", "结束")) + m.PushRender("action", "button", "结束") m.Push("", value) return } if len(arg) == 0 || len(arg) == 1 && strings.Contains(value["COMMAND"], arg[0]) { - m.Push("action", m.Cmdx(mdb.RENDER, "button", "结束")) + m.PushRender("action", "button", "结束") m.Push("", value) } }) diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index 223977ea..5a05bc51 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -301,6 +301,7 @@ const ( ) const ( FIELDS = "fields" + DETAIL = "detail" CREATE = "create" RENAME = "rename" REMOVE = "remove" @@ -313,8 +314,9 @@ const ( IMPORT = "import" EXPORT = "export" - INPUTS = "inputs" PRUNES = "prunes" + INPUTS = "inputs" + SCRIPT = "script" ) var Index = &ice.Context{Name: "mdb", Help: "数据模块", diff --git a/base/ssh/server.go b/base/ssh/server.go index 09d7b94e..5537cfbf 100644 --- a/base/ssh/server.go +++ b/base/ssh/server.go @@ -13,7 +13,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "os/exec" @@ -104,18 +103,11 @@ func _ssh_watch(m *ice.Message, meta map[string]string, input io.Reader, output switch buf[i] { case '\r', '\n': cmd := strings.TrimSpace(string(buf[:i])) - m.Log_IMPORT("hostname", meta["hostname"], "username", meta["username"], "cmd", cmd, "buf", buf[:i+n]) + m.Log_IMPORT(aaa.HOSTNAME, meta[aaa.HOSTNAME], aaa.USERNAME, meta[aaa.USERNAME], "cmd", cmd, "buf", buf[:i+n]) m.Conf(CONNECT, kit.Keys(kit.MDB_HASH, meta[CONNECT], "duration"), m.Format("cost")) m.Conf(SESSION, kit.Keys(kit.MDB_HASH, meta[SESSION], "cmd"), cmd) - // msg := m.Cmd(cmd).Table() - // res := strings.TrimSpace(strings.ReplaceAll(msg.Result(), "\n", "\r\n")) - // - // m.Debug("%v", msg.Format("meta")) - // if len(res) > 0 { - // fmt.Fprintf(display, "\r\n") - // fmt.Fprintf(display, res) - // } + m.Cmdy(mdb.INSERT, m.Prefix(COMMAND), "", mdb.LIST, aaa.HOSTNAME, meta[aaa.HOSTNAME], aaa.USERNAME, meta[aaa.USERNAME], "cmd", cmd) i = 0 default: if i += n; i >= 1024 { @@ -186,8 +178,8 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh } m.Gos(m, func(m *ice.Message) { io.Copy(channel, tty) }) - // _ssh_watch(m, meta, channel, tty, channel) - _ssh_trace(m, meta, channel, tty, channel) + _ssh_watch(m, meta, channel, tty, channel) + // _ssh_trace(m, meta, channel, tty, channel) } request.Reply(true, nil) } @@ -317,12 +309,12 @@ const ( CHANNEL = "channel" SESSION = "session" REQUEST = "request" + COMMAND = "command" ) const ( METHOD = "method" PUBLIC = "public" LISTEN = "listen" - COUNTS = "counts" DIAL = "dial" ) @@ -335,83 +327,77 @@ func init() { "goodbye", "\r\ngoodbye of context world\r\n", kit.MDB_SHORT, kit.MDB_TEXT, )}, + LISTEN: {Name: LISTEN, Help: "服务", Value: kit.Data(kit.MDB_SHORT, aaa.HOSTPORT, - mdb.FIELDS, "time,hash,hostport,status", + kit.MDB_FIELD, "time,hash,hostport,status", )}, CONNECT: {Name: CONNECT, Help: "连接", Value: kit.Data( - mdb.FIELDS, "time,hash,hostport,status,duration,close_time,hostname,username", + kit.MDB_FIELD, "time,hash,hostport,status,duration,close_time,hostname,username", )}, SESSION: {Name: SESSION, Help: "会话", Value: kit.Data( - mdb.FIELDS, "time,hash,hostport,status,tty,cmd", + kit.MDB_FIELD, "time,hash,hostport,status,tty,cmd", )}, - COUNTS: {Name: COUNTS, Help: "统计", Value: kit.Data( - mdb.FIELDS, "time,hash,hostport,status,tty,cmd", + COMMAND: {Name: COMMAND, Help: "命令", Value: kit.Data( + kit.MDB_FIELD, "time,id,username,hostname,cmd", )}, DIAL: {Name: DIAL, Help: "连接", Value: kit.Data( - mdb.FIELDS, "time,hash,hostport,username", + kit.MDB_FIELD, "time,hash,hostport,username", )}, }, Commands: map[string]*ice.Command{ PUBLIC: {Name: "public hash=auto auto 添加 导出 导入", Help: "公钥", Action: map[string]*ice.Action{ - mdb.IMPORT: {Name: "import", Help: "导入", List: kit.List( - kit.MDB_INPUT, "text", kit.MDB_NAME, "file", kit.MDB_VALUE, ".ssh/authorized_keys", - ), Hand: func(m *ice.Message, arg ...string) { - p := path.Join(os.Getenv("HOME"), kit.Select(arg[0], arg, 1)) - for _, pub := range strings.Split(m.Cmdx(nfs.CAT, p), "\n") { - if len(pub) > 10 { - m.Cmd(PUBLIC, mdb.CREATE, pub) - } - } - m.Echo(p) - }}, - mdb.EXPORT: {Name: "export", Help: "导出", List: kit.List( - kit.MDB_INPUT, "text", kit.MDB_NAME, "file", kit.MDB_VALUE, ".ssh/authorized_keys", - ), Hand: func(m *ice.Message, arg ...string) { - list := []string{} - m.Richs(PUBLIC, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) { - list = append(list, fmt.Sprintf("%s %s %s", value[kit.MDB_TYPE], value[kit.MDB_TEXT], value[kit.MDB_NAME])) - }) - if len(list) > 0 { - m.Cmdy(nfs.SAVE, path.Join(os.Getenv("HOME"), kit.Select(arg[0], arg, 1)), strings.Join(list, "\n")+"\n") - } - }}, - mdb.CREATE: {Name: "create", Help: "添加", List: kit.List( - kit.MDB_INPUT, "textarea", kit.MDB_NAME, "publickey", kit.MDB_VALUE, "", kit.MDB_STYLE, kit.Dict("width", "800", "height", "100"), - ), Hand: func(m *ice.Message, arg ...string) { - ls := kit.Split(kit.Select(arg[0], arg, 1)) + mdb.CREATE: {Name: "create publickey:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + ls := kit.Split(m.Option("publickey")) m.Cmdy(mdb.INSERT, m.Prefix(PUBLIC), "", mdb.HASH, kit.MDB_TYPE, ls[0], kit.MDB_NAME, ls[len(ls)-1], kit.MDB_TEXT, strings.Join(ls[1:len(ls)-1], "+")) }}, mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.DELETE, m.Prefix(PUBLIC), "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) }}, + mdb.EXPORT: {Name: "export file=.ssh/authorized_keys", Help: "导出", Hand: func(m *ice.Message, arg ...string) { + list := []string{} + if m.Cmd(mdb.SELECT, m.Prefix(PUBLIC), "", mdb.HASH).Table(func(index int, value map[string]string, head []string) { + list = append(list, fmt.Sprintf("%s %s %s", value[kit.MDB_TYPE], value[kit.MDB_TEXT], value[kit.MDB_NAME])) + }); len(list) > 0 { + m.Cmdy(nfs.SAVE, path.Join(os.Getenv("HOME"), m.Option(kit.MDB_FILE)), strings.Join(list, "\n")+"\n") + } + }}, + mdb.IMPORT: {Name: "import file=.ssh/authorized_keys", Help: "导入", Hand: func(m *ice.Message, arg ...string) { + p := path.Join(os.Getenv("HOME"), m.Option(kit.MDB_FILE)) + for _, pub := range strings.Split(m.Cmdx(nfs.CAT, p), "\n") { + if len(pub) > 10 { + m.Cmd(PUBLIC, mdb.CREATE, "publickey", pub) + } + } + m.Echo(p) + }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 { - m.Option(mdb.FIELDS, "detail") + m.Option(mdb.FIELDS, mdb.DETAIL) + } else { + defer m.PushAction("删除") } m.Cmdy(mdb.SELECT, m.Prefix(PUBLIC), "", mdb.HASH, kit.MDB_HASH, arg) - m.Sort(kit.MDB_NAME) - m.PushAction("删除") }}, - LISTEN: {Name: "listen hash auto", Help: "服务", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - m.Option(mdb.FIELDS, m.Conf(LISTEN, kit.META_FIELDS)) - m.Cmdy(mdb.SELECT, m.Prefix(LISTEN), "", mdb.HASH) - return + LISTEN: {Name: "listen hash=auto auto", Help: "服务", Action: map[string]*ice.Action{ + mdb.CREATE: {Name: "create port=9030", Help: "启动", Hand: func(m *ice.Message, arg ...string) { + m.Gos(m, func(m *ice.Message) { _ssh_listen(m, ":"+m.Option("port")) }) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if m.Option(mdb.FIELDS, m.Conf(LISTEN, kit.META_FIELD)); len(arg) > 0 { + m.Option(mdb.FIELDS, mdb.DETAIL) } - m.Gos(m, func(m *ice.Message) { _ssh_listen(m, arg[0]) }) + m.Cmdy(mdb.SELECT, m.Prefix(LISTEN), "", mdb.HASH, kit.MDB_HASH, arg) }}, - CONNECT: {Name: "connect hash auto 清理", Help: "连接", Action: map[string]*ice.Action{ + CONNECT: {Name: "connect hash=auto auto 清理", Help: "连接", Action: map[string]*ice.Action{ mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.PRUNES, m.Prefix(CONNECT), "", mdb.HASH, kit.MDB_STATUS, "close") }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - m.Option(mdb.FIELDS, m.Conf(CONNECT, kit.META_FIELDS)) - } else { - m.Option(mdb.FIELDS, "detail") + if m.Option(mdb.FIELDS, m.Conf(CONNECT, kit.META_FIELD)); len(arg) > 0 { + m.Option(mdb.FIELDS, mdb.DETAIL) } m.Cmdy(mdb.SELECT, m.Prefix(CONNECT), "", mdb.HASH, kit.MDB_HASH, arg) }}, @@ -420,67 +406,38 @@ func init() { m.Cmdy(mdb.PRUNES, m.Prefix(SESSION), "", mdb.HASH, kit.MDB_STATUS, "close") }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - m.Option(mdb.FIELDS, m.Conf(SESSION, kit.META_FIELDS)) - } else { - m.Option(mdb.FIELDS, "detail") + if m.Option(mdb.FIELDS, m.Conf(SESSION, kit.META_FIELD)); len(arg) > 0 { + m.Option(mdb.FIELDS, mdb.DETAIL) } m.Cmdy(mdb.SELECT, m.Prefix(SESSION), "", mdb.HASH, kit.MDB_HASH, arg) }}, - - DIAL: {Name: "dial hash auto 受控 登录 cmd:textarea=pwd", Help: "连接", Action: map[string]*ice.Action{ - mdb.CREATE: {Name: "create", Help: "登录", List: kit.List( - kit.MDB_INPUT, "text", kit.MDB_NAME, aaa.USERNAME, kit.MDB_VALUE, "shy", - kit.MDB_INPUT, "text", kit.MDB_NAME, aaa.HOSTPORT, kit.MDB_VALUE, "shylinux.com:22", - ), Hand: func(m *ice.Message, arg ...string) { - for i := 0; i < len(arg); i += 2 { - m.Option(arg[i], arg[i+1]) - } - - connect, e := _ssh_dial(m, m.Option(aaa.USERNAME), m.Option(aaa.HOSTPORT)) - m.Assert(e) - - h := m.Rich(DIAL, "", kit.Dict( - aaa.USERNAME, m.Option(aaa.USERNAME), - aaa.HOSTPORT, m.Option(aaa.HOSTPORT), - CONNECT, connect, - )) - m.Echo(h) + COMMAND: {Name: "command id=auto auto", Help: "命令", Action: map[string]*ice.Action{ + mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.PRUNES, m.Prefix(CONNECT), "", mdb.HASH, kit.MDB_STATUS, "close") }}, - "revert": {Name: "revert", Help: "受控", List: kit.List( - kit.MDB_INPUT, "text", kit.MDB_NAME, aaa.HOSTPORT, kit.MDB_VALUE, "192.168.0.105:9030", - ), Hand: func(m *ice.Message, arg ...string) { - for i := 0; i < len(arg); i += 2 { - m.Option(arg[i], arg[i+1]) + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if m.Option(mdb.FIELDS, m.Conf(COMMAND, kit.META_FIELD)); len(arg) > 0 { + m.Option(mdb.FIELDS, mdb.DETAIL) + } + m.Cmdy(mdb.SELECT, m.Prefix(COMMAND), "", mdb.LIST, kit.MDB_ID, arg) + }}, + + DIAL: {Name: "dial hash=auto auto 登录 cmd:textarea=pwd", Help: "连接", Action: map[string]*ice.Action{ + mdb.CREATE: {Name: "create username=shy hostname=shylinux.com port=22", Help: "登录", Hand: func(m *ice.Message, arg ...string) { + if connect, e := _ssh_dial(m, m.Option(aaa.USERNAME), + m.Option(aaa.HOSTPORT, m.Option("hostname")+":"+m.Option("port"))); m.Assert(e) { + h := m.Rich(DIAL, "", kit.Dict( + aaa.USERNAME, m.Option(aaa.USERNAME), aaa.HOSTPORT, m.Option(aaa.HOSTPORT), CONNECT, connect, + )) + m.Echo(h) } - - connect, e := _ssh_dial(m, "revert", m.Option(aaa.HOSTPORT)) - m.Assert(e) - - h := m.Rich(DIAL, "", kit.Dict( - aaa.USERNAME, "revert", - aaa.HOSTPORT, m.Option(aaa.HOSTPORT), - CONNECT, connect, - )) - - session, e := connect.NewSession() - m.Assert(e) - - r, w := io.Pipe() - session.Stdout = w - - _ssh_watch(m, map[string]string{}, r, ioutil.Discard, ioutil.Discard) - - session.Start("bash") - m.Echo(h) }}, - mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.DELETE, m.Prefix(DIAL), "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 || arg[0] == "" { - m.Option(mdb.FIELDS, m.Conf(DIAL, kit.META_FIELDS)) + m.Option(mdb.FIELDS, m.Conf(DIAL, kit.META_FIELD)) m.Cmdy(mdb.SELECT, m.Prefix(DIAL), "", mdb.HASH) m.PushAction("删除") return @@ -501,8 +458,7 @@ func init() { var b bytes.Buffer session.Stdout = &b - err := session.Run(arg[1]) - m.Assert(err) + m.Assert(session.Run(arg[1])) m.Echo(b.String()) }) }}, diff --git a/base/web/dream.go b/base/web/dream.go index dd1dc8dc..69218219 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -37,6 +37,11 @@ func _dream_show(m *ice.Message, name string) { p := path.Join(m.Conf(DREAM, "meta.path"), name) os.MkdirAll(p, ice.MOD_DIR) + m.Debug("what %v", m.Option("repos")) + if m.Option("repos") != "" { + m.Cmd("web.code.git.repos", "create", "remote", m.Option("repos"), "path", p) + } + miss := path.Join(p, "etc/miss.sh") if _, e := os.Stat(miss); e != nil { m.Cmd(nfs.SAVE, miss, m.Conf(DREAM, "meta.miss")) diff --git a/base/web/route.go b/base/web/route.go index be0db322..99a4d131 100644 --- a/base/web/route.go +++ b/base/web/route.go @@ -60,7 +60,7 @@ func init() { m.Cmdy(SPACE, m.Option("route"), "dream") } }}, - "start": {Name: "start type=worker,server name=hi@key", Help: "启动", Hand: func(m *ice.Message, arg ...string) { + "start": {Name: "start type=worker,server name=hi@key repos", Help: "启动", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SPACE, m.Option("route"), "dream", "start", arg) m.Sleep("3s") }}, diff --git a/base/web/spide.go b/base/web/spide.go index f715fc20..f6fc1f87 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -305,7 +305,9 @@ func init() { if web.Client == nil { web.Client = &http.Client{Timeout: kit.Duration(kit.Format(client["timeout"]))} } - m.Info("%s: %s", req.Header.Get(ContentLength), req.Header.Get(ContentType)) + if req.Method == SPIDE_POST { + m.Info("%s: %s", req.Header.Get(ContentLength), req.Header.Get(ContentType)) + } // 发送请求 res, e := web.Client.Do(req) diff --git a/core/chat/paste.go b/core/chat/paste.go index 30658917..a01372e2 100644 --- a/core/chat/paste.go +++ b/core/chat/paste.go @@ -17,32 +17,31 @@ func init() { ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save(PASTE) }}, - PASTE: {Name: "paste text auto 粘贴:button", Help: "粘贴板", Meta: kit.Dict( - "display", "/plugin/story/paste.js", - ), Action: map[string]*ice.Action{ - mdb.INSERT: {Name: "insert [key value]...", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + PASTE: {Name: "paste hash=auto auto 添加 导出 导入", Help: "粘贴板", Action: map[string]*ice.Action{ + mdb.INSERT: {Name: "insert text:textarea=hi", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.INSERT, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH, arg) }}, - mdb.MODIFY: {Name: "modify key value", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.MODIFY, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH, kit.MDB_TEXT, m.Option("text"), arg[0], arg[1]) - }}, mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.DELETE, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH, kit.MDB_TEXT, m.Option("text")) }}, - mdb.EXPORT: {Name: "export file", Help: "导出", Hand: func(m *ice.Message, arg ...string) { + mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.EXPORT, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH) }}, - mdb.IMPORT: {Name: "import file", Help: "导入", Hand: func(m *ice.Message, arg ...string) { + mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.IMPORT, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 { - m.Cmdy(mdb.INSERT, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH, kit.MDB_TEXT, arg[0]) + text := m.Cmd(mdb.SELECT, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH, kit.MDB_HASH, arg[0]).Append("text") + m.Cmdy("web.wiki.spark", "inner", text) + m.Cmdy("web.wiki.image", "qrcode", text) + m.Render("") + return } m.Cmdy(mdb.SELECT, m.Prefix(PASTE), m.Option(ice.MSG_DOMAIN), mdb.HASH) - m.PushAction("复制", "删除") - m.Sort("time", "time_r") + m.Sort(kit.MDB_TIME, "time_r") + m.PushAction("删除") }}, }, }, nil) diff --git a/core/code/code.go b/core/code/code.go index 0a65a24a..238744eb 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -52,7 +52,7 @@ var Index = &ice.Context{Name: "code", Help: "编程中心", m.Cmd(mdb.ENGINE, mdb.CREATE, BENCH) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Save("login") + m.Save(INSTALL) }}, "_install": {Name: "install url 安装:button", Help: "安装", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { diff --git a/core/code/install.go b/core/code/install.go index ab2640b8..7d4ba111 100644 --- a/core/code/install.go +++ b/core/code/install.go @@ -15,22 +15,15 @@ import ( "strings" ) -const INSTALL = "install" - -func init() { - Index.Merge(&ice.Context{ - Configs: map[string]*ice.Config{ - INSTALL: {Name: INSTALL, Help: "安装", Value: kit.Data( - kit.MDB_SHORT, kit.MDB_NAME, kit.MDB_PATH, "usr/install", - "contexts", kit.Dict( - "tmux", `yum install -y tmux +var _contexts = kit.Dict( + "tmux", `yum install -y tmux curl -o tmux.conf {{.Option "httphost"}}/publish/tmux.conf tmux -f tmux.conf`, - "base", `mkdir contexts; cd contexts + "base", `mkdir contexts; cd contexts export ctx_dev={{.Option "httphost"}} ctx_log=/dev/stdout; curl $ctx_dev/publish/ice.sh |sh export ctx_dev={{.Option "httphost"}} ctx_log=/dev/stdout; wget -O - $ctx_dev/publish/ice.sh | sh bin/ice.sh`, - "miss", ` + "miss", ` yum install -y git vim make go mkdir ~/.ssh &>/dev/null; touch ~/.ssh/config; [ -z "$(cat ~/.ssh/config|grep 'HOST {{.Option "hostname"}}')" ] && echo -e "HOST {{.Option "hostname"}}\n Port 9030" >> ~/.ssh/config export ISH_CONF_HUB_PROXY={{.Option "userhost"}}:.ish/pluged/ @@ -41,20 +34,29 @@ touch ~/.gitconfig; [ -z "$(cat ~/.gitconfig|grep '\[url \"{{.Option "userhost"} git clone https://github.com/shylinux/contexts && cd contexts source etc/miss.sh `, - ), +) + +const INSTALL = "install" + +func init() { + Index.Merge(&ice.Context{ + Configs: map[string]*ice.Config{ + INSTALL: {Name: INSTALL, Help: "安装", Value: kit.Data( + kit.MDB_SHORT, kit.MDB_NAME, kit.MDB_PATH, "usr/install", + "contexts", _contexts, )}, }, Commands: map[string]*ice.Command{ INSTALL: {Name: "install name=auto port=auto path=auto auto", Help: "安装", Meta: kit.Dict(), Action: map[string]*ice.Action{ - "contexts": {Name: "contexts item os", Help: "下载", Hand: func(m *ice.Message, arg ...string) { + "contexts": {Name: "contexts", Help: "环境", Hand: func(m *ice.Message, arg ...string) { u := kit.ParseURL(m.Option(ice.MSG_USERWEB)) - m.Option("userhost", fmt.Sprintf("%s@%s", m.Option(ice.MSG_USERNAME), strings.Split(u.Host, ":")[0])) - m.Option("hostpath", kit.Path("./.ish/pluged")) - m.Option("httphost", fmt.Sprintf("%s://%s:%s", u.Scheme, strings.Split(u.Host, ":")[0], kit.Select(kit.Select("80", "443", u.Scheme == "https"), strings.Split(u.Host, ":"), 1))) m.Option("hostport", fmt.Sprintf("%s:%s", strings.Split(u.Host, ":")[0], kit.Select(kit.Select("80", "443", u.Scheme == "https"), strings.Split(u.Host, ":"), 1))) m.Option("hostname", strings.Split(u.Host, ":")[0]) + m.Option("userhost", fmt.Sprintf("%s@%s", m.Option(ice.MSG_USERNAME), strings.Split(u.Host, ":")[0])) + m.Option("hostpath", kit.Path("./.ish/pluged")) + if buf, err := kit.Render(m.Conf(INSTALL, kit.Keys("meta.contexts", kit.Select("base", arg, 0))), m); m.Assert(err) { m.Cmdy("web.wiki.spark", "shell", string(buf)) } @@ -63,7 +65,8 @@ source etc/miss.sh name := path.Base(arg[0]) if m.Richs(INSTALL, "", name, func(key string, value map[string]interface{}) { if _, e := os.Stat(path.Join(m.Conf(INSTALL, kit.META_PATH), kit.Format(value[kit.MDB_NAME]))); e == nil { - m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_STEP, kit.MDB_SIZE, kit.MDB_NAME, kit.MDB_LINK}) + m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_STEP, kit.MDB_SIZE, kit.MDB_TOTAL, kit.MDB_NAME, kit.MDB_LINK}) + m.Option("_process", "_progress") } }) != nil && len(m.Appendv(kit.MDB_NAME)) > 0 { // 已经下载 @@ -86,22 +89,20 @@ source etc/miss.sh p := path.Join(m.Conf(INSTALL, kit.META_PATH), name) m.Cmd(cli.SYSTEM, "touch", p) - // 代理 - to := m.Cmd("web.spide_rewrite", arg[0]).Append("to") - m.Debug("to: %s", to) - arg[0] = kit.Select(arg[0], to) + m.Option("_process", "_progress") + m.Gos(m, func(m *ice.Message) { + // 下载 + m.Option(cli.CMD_DIR, m.Conf(INSTALL, kit.META_PATH)) + if strings.HasPrefix(arg[0], "ftp") { + m.Cmdy(cli.SYSTEM, "wget", arg[0]) + } else { + msg := m.Cmd(web.SPIDE, web.SPIDE_DEV, web.SPIDE_CACHE, web.SPIDE_GET, arg[0]) + m.Cmdy(nfs.LINK, p, msg.Append(kit.MDB_FILE)) + } - // 下载 - m.Option(cli.CMD_DIR, m.Conf(INSTALL, kit.META_PATH)) - if strings.HasPrefix(arg[0], "ftp") { - m.Cmdy(cli.SYSTEM, "wget", arg[0]) - } else { - msg := m.Cmd(web.SPIDE, web.SPIDE_DEV, web.SPIDE_CACHE, web.SPIDE_GET, arg[0]) - m.Cmdy(nfs.LINK, p, msg.Append(kit.MDB_FILE)) - } - - // 解压 - m.Cmd(cli.SYSTEM, "tar", "xvf", name) + // 解压 + m.Cmd(cli.SYSTEM, "tar", "xvf", name) + }) }}, "build": {Name: "build link", Help: "构建", Hand: func(m *ice.Message, arg ...string) { p := m.Option(cli.CMD_DIR, path.Join(m.Conf(INSTALL, kit.META_PATH), kit.TrimExt(arg[0]))) @@ -110,10 +111,19 @@ source etc/miss.sh cb(p) default: m.Cmdy(cli.SYSTEM, "./configure", "--prefix="+kit.Path(path.Join(p, INSTALL)), arg[1:]) + if m.Append(cli.CMD_CODE) != "0" { + return + } } m.Cmdy(cli.SYSTEM, "make", "-j8") + if m.Append(cli.CMD_CODE) != "0" { + return + } m.Cmdy(cli.SYSTEM, "make", "PREFIX="+kit.Path(path.Join(p, INSTALL)), "install") + if m.Append(cli.CMD_CODE) != "0" { + return + } }}, "spawn": {Name: "spawn link", Help: "新建", Hand: func(m *ice.Message, arg ...string) { port := m.Cmdx(tcp.PORT, "select") diff --git a/misc.go b/misc.go index 92f3ea4c..ec67ddd1 100644 --- a/misc.go +++ b/misc.go @@ -69,6 +69,9 @@ func (m *Message) PushRender(key, view, name string, arg ...string) *Message { for _, k := range kit.Split(name) { list = append(list, fmt.Sprintf(``, k)) } + for _, k := range arg { + list = append(list, fmt.Sprintf(``, k)) + } m.Push(key, strings.Join(list, "")) case "a": if m.W != nil { @@ -81,11 +84,7 @@ func (m *Message) PushRender(key, view, name string, arg ...string) *Message { } func (m *Message) PushAction(list ...interface{}) { m.Table(func(index int, value map[string]string, head []string) { - action := []string{} - for _, k := range kit.Simple(list...) { - action = append(action, m.Cmdx("render", "button", k)) - } - m.Push("action", strings.Join(action, "")) + m.PushRender("action", "button", strings.Join(kit.Simple(list...), ",")) }) } func (m *Message) PushDetail(value interface{}, arg ...interface{}) *Message { diff --git a/misc/git/git.go b/misc/git/git.go index 3712b330..396deeac 100644 --- a/misc/git/git.go +++ b/misc/git/git.go @@ -3,7 +3,6 @@ package git import ( ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" - "github.com/shylinux/icebergs/base/gdb" "github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/nfs" "github.com/shylinux/icebergs/base/web" @@ -48,7 +47,8 @@ var Index = &ice.Context{Name: GIT, Help: "代码库", ), )}, REPOS: {Name: REPOS, Help: "仓库", Value: kit.Data( - kit.MDB_SHORT, kit.MDB_NAME, "owner", "https://github.com/shylinux", + kit.MDB_SHORT, kit.MDB_NAME, kit.MDB_FIELD, "time,name,branch,last", + "owner", "https://github.com/shylinux", )}, TOTAL: {Name: TOTAL, Help: "统计", Value: kit.Data( kit.MDB_SHORT, kit.MDB_NAME, "skip", kit.Dict( @@ -59,22 +59,18 @@ var Index = &ice.Context{Name: GIT, Help: "代码库", }, Commands: map[string]*ice.Command{ ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Watch(gdb.SYSTEM_INIT, m.AddCmd(&ice.Command{Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd(REPOS, "volcanos", "usr/volcanos") - }})) - }}, - "init": {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { // 系统项目 wd, _ := os.Getwd() _repos_insert(m, path.Base(wd), wd) - + }}, + "init": {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { // 官方项目 m.Cmd(nfs.DIR, "usr", "name path").Table(func(index int, value map[string]string, head []string) { _repos_insert(m, value["name"], value["path"]) }) }}, - GIT: {Name: "git port=auto path=auto auto 构建 下载", Help: "编辑器", Action: map[string]*ice.Action{ + GIT: {Name: "git port=auto path=auto auto 构建 下载", Help: "代码库", Action: map[string]*ice.Action{ "download": {Name: "download", Help: "下载", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(code.INSTALL, "download", m.Conf(GIT, kit.META_SOURCE)) }}, @@ -97,30 +93,41 @@ var Index = &ice.Context{Name: GIT, Help: "代码库", m.Cmdy(code.INSTALL, path.Base(m.Conf(GIT, kit.META_SOURCE)), arg) }}, - REPOS: {Name: "repos [name=auto [path [remote [branch]]]] auto", Help: "代码仓库", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) > 1 { - if _, e := os.Stat(path.Join(arg[1], ".git")); e != nil && os.IsNotExist(e) { - // 下载仓库 - m.Cmd(cli.SYSTEM, GIT, "clone", "-b", kit.Select("master", arg, 3), - kit.Select(m.Conf(REPOS, "meta.owner")+"/"+arg[0], arg, 2), arg[1]) - _repos_insert(m, arg[0], arg[1]) - } - } + REPOS: {Name: "repos name=auto path=auto auto 添加", Help: "代码库", Action: map[string]*ice.Action{ + mdb.CREATE: {Name: `create remote branch name path`, Help: "添加", Hand: func(m *ice.Message, arg ...string) { + m.Option("name", kit.Select(strings.TrimSuffix(path.Base(m.Option("remote")), ".git"), m.Option("name"))) + m.Option("path", kit.Select(path.Join("usr", m.Option("name")), m.Option("path"))) + m.Option("remote", kit.Select(m.Conf(REPOS, "meta.owner")+"/"+m.Option("name"), m.Option("remote"))) + if _, e := os.Stat(path.Join(m.Option("path"), ".git")); e != nil && os.IsNotExist(e) { + // 下载仓库 + if _, e := os.Stat(m.Option("path")); e == nil { + m.Option(cli.CMD_DIR, m.Option("path")) + m.Cmd(cli.SYSTEM, GIT, "init") + m.Cmd(cli.SYSTEM, GIT, "remote", "add", "origin", m.Option("remote")) + m.Cmd(cli.SYSTEM, GIT, "pull", "origin", "master") + } else { + m.Cmd(cli.SYSTEM, GIT, "clone", "-b", kit.Select("master", m.Option("branch")), + m.Option("remote"), m.Option("path")) + + } + _repos_insert(m, m.Option("name"), m.Option("path")) + } + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 { - // 仓库详情 - m.Richs(REPOS, nil, arg[0], func(key string, value map[string]interface{}) { - m.Push("detail", value[kit.MDB_META]) - }) + if wd, _ := os.Getwd(); arg[0] != path.Base(wd) { + m.Option(nfs.DIR_ROOT, path.Join("usr", arg[0])) + } + m.Cmdy(nfs.DIR, kit.Select("./", path.Join(arg[1:]...))) return } - // 仓库列表 - m.Richs(REPOS, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) { - m.Push(key, value[kit.MDB_META], []string{kit.MDB_TIME, kit.MDB_NAME, "branch", "last"}) - }) + m.Option(mdb.FIELDS, m.Conf(REPOS, kit.META_FIELD)) + m.Cmdy(mdb.SELECT, m.Prefix(REPOS), "", mdb.HASH, kit.MDB_NAME, arg) m.Sort(kit.MDB_NAME) }}, + TOTAL: {Name: "total name=auto auto", Help: "提交统计", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) > 0 { // 提交详情 @@ -416,13 +423,6 @@ var Index = &ice.Context{Name: GIT, Help: "代码库", }) m.Sort("name") }}, - - "/proxy/": {Name: "/repos/", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Render(ice.RENDER_VOID) - }}, - "/serve/": {Name: "/repos/", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Render(ice.RENDER_RESULT) - }}, }, } diff --git a/misc/git/git.shy b/misc/git/git.shy index 4badcdef..15987e7b 100644 --- a/misc/git/git.shy +++ b/misc/git/git.shy @@ -27,11 +27,11 @@ chapter "应用" refer ` go https://github.com/google/gitprotocolio ` -field "代码统计" web.code.git.total +field "代码库" web.code.git.repos +field "统计量" web.code.git.total +field "代码管理" web.code.git.status field "提交趋势" web.code.git.trend args icebergs field "代码结构" web.code.git.spide args icebergs -field status web.code.git.status - chapter "项目" field icebergs web.code.inner args `[ usr/icebergs misc/git/git.go ]` diff --git a/misc/tmux/tmux.go b/misc/tmux/tmux.go index ec9f7242..7f63730a 100644 --- a/misc/tmux/tmux.go +++ b/misc/tmux/tmux.go @@ -3,62 +3,52 @@ package tmux import ( ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/cli" - "github.com/shylinux/icebergs/base/gdb" "github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/web" "github.com/shylinux/icebergs/core/code" kit "github.com/shylinux/toolkits" - "os" "path" "strings" "time" ) -const TMUX = "tmux" const ( TEXT = "text" BUFFER = "buffer" + SCRIPT = "script" SESSION = "session" WINDOW = "window" PANE = "pane" VIEW = "view" - - LOCAL = "local" - RELAY = "relay" ) -var _tmux = []string{cli.SYSTEM, TMUX} +const TMUX = "tmux" var Index = &ice.Context{Name: TMUX, Help: "工作台", Configs: map[string]*ice.Config{ - TMUX: {Name: "tmux", Help: "终端", Value: kit.Data( + TMUX: {Name: TMUX, Help: "服务", Value: kit.Data( "source", "https://github.com/tmux/tmux/releases/download/3.1b/tmux-3.1b.tar.gz", )}, - SESSION: {Name: "session", Help: "会话", Value: kit.Data( + BUFFER: {Name: BUFFER, Help: "缓存", Value: kit.Data()}, + SCRIPT: {Name: SCRIPT, Help: "脚本", Value: kit.Data( + kit.MDB_SHORT, kit.MDB_NAME, kit.MDB_FIELD, "time,type,name,text", + )}, + SESSION: {Name: SESSION, Help: "会话", Value: kit.Data( "format", "#{session_id},#{session_attached},#{session_name},#{session_windows},#{session_height},#{session_width}", "fields", "id,tag,session,windows,height,width", )}, - WINDOW: {Name: "windows", Help: "窗口", Value: kit.Data( + WINDOW: {Name: WINDOW, Help: "窗口", Value: kit.Data( "format", "#{window_id},#{window_active},#{window_name},#{window_panes},#{window_height},#{window_width}", "fields", "id,tag,window,panes,height,width", )}, - PANE: {Name: "panes", Help: "终端", Value: kit.Data( + PANE: {Name: PANE, Help: "终端", Value: kit.Data( "format", "#{pane_id},#{pane_active},#{pane_index},#{pane_tty},#{pane_height},#{pane_width}", "fields", "id,tag,pane,tty,height,width", )}, - - LOCAL: {Name: "local", Help: "虚拟机", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)}, - RELAY: {Name: "relay", Help: "跳板机", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME, - "count", 100, "sleep", "100ms", "tail", kit.Dict( - "verify", "Verification code:", - "password", "Password:", - "login", "[relay ~]$", - ), - )}, }, Commands: map[string]*ice.Command{ - TMUX: {Name: "git port=auto path=auto auto 启动:button 构建:button 下载:button", Help: "命令行", Action: map[string]*ice.Action{ + TMUX: {Name: "tmux port=auto path=auto auto 启动:button 构建:button 下载:button", Help: "服务", Action: map[string]*ice.Action{ "download": {Name: "download", Help: "下载", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(code.INSTALL, "download", m.Conf(TMUX, kit.META_SOURCE)) }}, @@ -75,366 +65,209 @@ var Index = &ice.Context{Name: TMUX, Help: "工作台", }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Cmdy(code.INSTALL, path.Base(m.Conf(TMUX, kit.META_SOURCE)), arg) }}, - - TEXT: {Name: "text auto 保存:button 清空:button text:textarea", Help: "文本", Action: map[string]*ice.Action{ + TEXT: {Name: "text 查看:button 保存:button 清空:button text:textarea", Help: "文本", Action: map[string]*ice.Action{ "save": {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) { if len(arg) > 0 && arg[0] != "" { - m.Cmd(_tmux, "set-buffer", arg[0]) + m.Cmd(cli.SYSTEM, TMUX, "set-buffer", arg[0]) } - - text := m.Cmdx(_tmux, "show-buffer") - m.Cmdy("web.wiki.image", "qrcode", text) - m.Echo("\n%s", text).Render("") + m.Cmdy(TEXT) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + text := m.Cmdx(cli.SYSTEM, TMUX, "show-buffer") + m.Cmdy("web.wiki.spark", "inner", text) + m.Cmdy("web.wiki.image", "qrcode", text) + m.Render("") }}, - BUFFER: {Name: "buffer [buffer=auto [value]] auto", Help: "缓存", Action: map[string]*ice.Action{ + BUFFER: {Name: "buffer buffer=auto value auto 导出 导入", Help: "缓存", Action: map[string]*ice.Action{ mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { case "text": - m.Cmd(_tmux, "set-buffer", "-b", m.Option("buffer"), arg[1]) + m.Cmd(cli.SYSTEM, TMUX, "set-buffer", "-b", m.Option("buffer"), arg[1]) } }}, + mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { + m.Conf(BUFFER, mdb.LIST, "") + m.Conf(BUFFER, kit.Keys(mdb.META, "count"), "0") + + m.Cmd(BUFFER).Table(func(index int, value map[string]string, head []string) { + m.Grow(BUFFER, "", kit.Dict( + "name", value[head[0]], "text", m.Cmdx(cli.SYSTEM, TMUX, "show-buffer", "-b", value[head[0]]), + )) + }) + m.Cmdy(mdb.EXPORT, m.Prefix(BUFFER), "", mdb.LIST) + }}, + mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { + m.Conf(BUFFER, mdb.LIST, "") + m.Conf(BUFFER, kit.Keys(mdb.META, "count"), "0") + + m.Cmdy(mdb.IMPORT, m.Prefix(BUFFER), "", mdb.LIST) + m.Grows(BUFFER, "", "", "", func(index int, value map[string]interface{}) { + m.Cmd(cli.SYSTEM, TMUX, "set-buffer", "-b", value["name"], value["text"]) + }) + }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) > 1 { + if len(arg) > 1 && arg[1] != "" { // 设置缓存 - m.Cmd(_tmux, "set-buffer", "-b", arg[0], arg[1]) + m.Cmd(cli.SYSTEM, TMUX, "set-buffer", "-b", arg[0], arg[1]) } if len(arg) > 0 { // 查看缓存 - m.Echo(m.Cmdx(_tmux, "show-buffer", "-b", arg[0])) + m.Echo(m.Cmdx(cli.SYSTEM, TMUX, "show-buffer", "-b", arg[0])) return } // 缓存列表 - for i, v := range kit.Split(m.Cmdx(_tmux, "list-buffers"), "\n", "\n", "\n") { + for i, v := range kit.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-buffers"), "\n", "\n", "\n") { ls := strings.SplitN(v, ": ", 3) m.Push("buffer", ls[0]) m.Push("size", ls[1]) if i < 3 { - m.Push("text", m.Cmdx(_tmux, "show-buffer", "-b", ls[0])) + m.Push("text", m.Cmdx(cli.SYSTEM, TMUX, "show-buffer", "-b", ls[0])) } else { - m.Push("text", ls[2][1:]) + m.Push("text", ls[2][1:len(ls[2])-1]) } } }}, - SESSION: {Name: "session [session=auto [window=auto [pane=auto [cmd]]]] auto", Help: "会话管理", Meta: kit.Dict( - "detail", []string{"选择", "编辑", "删除"}, - ), Action: map[string]*ice.Action{ - "choice": {Name: "choice", Help: "选择", Hand: func(m *ice.Message, arg ...string) { - m.Cmd(_tmux, "switch-client", "-t", m.Option(SESSION)) + SCRIPT: {Name: "script name=auto auto 添加 导出 导入", Help: "脚本", Action: map[string]*ice.Action{ + mdb.INSERT: {Name: "insert type=shell,tmux,vim name=hi text:textarea=pwd", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.INSERT, m.Prefix(SCRIPT), "", mdb.HASH, arg) + }}, + mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.MODIFY, m.Prefix(SCRIPT), "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME), arg) + }}, + mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.DELETE, m.Prefix(SCRIPT), "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME)) + }}, + mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.EXPORT, m.Prefix(SCRIPT), "", mdb.HASH) + }}, + mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.IMPORT, m.Prefix(SCRIPT), "", mdb.HASH) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + if m.Option(mdb.FIELDS, m.Conf(SCRIPT, kit.META_FIELD)); len(arg) > 0 { + m.Option(mdb.FIELDS, mdb.DETAIL) + } + m.Cmdy(mdb.SELECT, m.Prefix(SCRIPT), "", mdb.HASH, kit.MDB_NAME, arg) + }}, + SESSION: {Name: "session session=auto window=auto pane=auto cmd auto 脚本 创建 ", Help: "会话管理", Action: map[string]*ice.Action{ + mdb.CREATE: {Name: "create name", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + m.Option(cli.CMD_ENV, "TMUX", "") + if m.Option(PANE) != "" { + m.Cmd(cli.SYSTEM, TMUX, "split-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE)) + + } else if m.Option(WINDOW) != "" { + m.Cmd(cli.SYSTEM, TMUX, "split-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)) + + } else if m.Option(SESSION) != "" { + // 创建窗口 + m.Cmd(cli.SYSTEM, TMUX, "new-window", "-t", m.Option(SESSION), "-dn", m.Option("name")) + } else { + // 创建会话 + m.Cmd(cli.SYSTEM, TMUX, "new-session", "-ds", m.Option("name")) + } + }}, + mdb.SELECT: {Name: "select", Help: "进入", Hand: func(m *ice.Message, arg ...string) { + m.Cmd(cli.SYSTEM, TMUX, "switch-client", "-t", m.Option(SESSION)) if m.Option(WINDOW) != "" { - m.Cmd(_tmux, "select-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)) + m.Cmd(cli.SYSTEM, TMUX, "select-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)) } if m.Option(PANE) != "" { - m.Cmd(_tmux, "select-pane", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE)) + m.Cmd(cli.SYSTEM, TMUX, "select-pane", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE)) } }}, mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { switch arg[0] { - case SESSION: - // 重命名会话 - m.Cmd(_tmux, "rename-session", "-t", m.Option(SESSION), arg[1]) case WINDOW: // 重命名窗口 - m.Cmd(_tmux, "rename-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW), arg[1]) + m.Cmd(cli.SYSTEM, TMUX, "rename-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW), arg[1]) + case SESSION: + // 重命名会话 + m.Cmd(cli.SYSTEM, TMUX, "rename-session", "-t", m.Option(SESSION), arg[1]) } }}, - gdb.CLEAR: {Name: "clear", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { if m.Option(PANE) != "" { - m.Cmd(_tmux, "kill-pane", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE)) - return - } - if m.Option(WINDOW) != "" { - m.Cmd(_tmux, "kill-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)) - return - } - if m.Option(SESSION) != "" { - m.Cmd(_tmux, "kill-session", "-t", m.Option(SESSION)) - return + m.Cmd(cli.SYSTEM, TMUX, "kill-pane", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE)) + } else if m.Option(WINDOW) != "" { + m.Cmd(cli.SYSTEM, TMUX, "kill-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)) + } else if m.Option(SESSION) != "" { + m.Cmd(cli.SYSTEM, TMUX, "kill-session", "-t", m.Option(SESSION)) } }}, + + mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { + m.Option(mdb.FIELDS, "time,type,name,text") + m.Cmdy(mdb.SELECT, SCRIPT, "", mdb.HASH) + }}, + + mdb.SCRIPT: {Name: "script name", Help: "脚本", Hand: func(m *ice.Message, arg ...string) { + m.Cmd(mdb.SELECT, SCRIPT, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME)).Table(func(index int, value map[string]string, head []string) { + switch value[kit.MDB_TYPE] { + case "shell": + for _, line := range kit.Split(value[kit.MDB_TEXT]) { + m.Cmd(cli.SYSTEM, TMUX, "send-keys", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE), line, "Enter") + } + case "tmux": + for _, line := range kit.Split(value[kit.MDB_TEXT]) { + m.Cmd(cli.SYSTEM, TMUX, line) + } + case "vim": + } + }) + }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - target := "" if len(arg) > 3 { // 执行命令 - target = arg[0] + ":" + arg[1] + "." + arg[2] - m.Cmd(_tmux, "send-keys", "-t", target, strings.Join(arg[3:], " "), "Enter") + target := arg[0] + ":" + arg[1] + "." + arg[2] + m.Cmd(cli.SYSTEM, TMUX, "send-keys", "-t", target, strings.Join(arg[3:], " "), "Enter") time.Sleep(1 * time.Second) } if len(arg) > 2 { // 终端内容 + target := arg[0] + ":" + arg[1] + "." + arg[2] m.Echo(strings.TrimSpace(m.Cmdx(VIEW, target))) return } if len(arg) == 0 { // 会话列表 - m.Split(m.Cmdx(_tmux, "list-session", "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n") - + m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-session", "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n") m.Table(func(index int, value map[string]string, head []string) { - for _, k := range []string{"clear"} { - m.Push(k, m.Cmdx(mdb.RENDER, web.RENDER.Button, k)) + switch value["tag"] { + case "1": + m.PushRender("action", "button", "") + default: + m.PushRender("action", "button", "进入", "删除") } }) return } - target = arg[0] - if m.Cmd(_tmux, "has-session", "-t", target).Append(cli.CMD_CODE) != "0" { - // 创建会话 - m.Option(cli.CMD_ENV, "TMUX", "") - m.Option(cli.CMD_DIR, m.Conf(web.DREAM, "meta.path")) - m.Cmd(_tmux, "new-session", "-ds", arg[0]) - // m.Cmd("auto", arg[0]) - } if len(arg) == 1 { // 窗口列表 - m.Cmdy(WINDOW, target) + m.Cmdy(WINDOW, arg[0]) + m.PushAction("进入", "删除") return } - switch arg[1] { - case "has": - m.Cmd(WINDOW, target).Table(func(index int, value map[string]string, head []string) { - if value["window"] == arg[2] { - m.Echo("true") - } - }) - return - } - - if target = arg[0] + ":" + arg[1]; m.Cmd(_tmux, "rename-window", "-t", target, arg[1]).Append(cli.CMD_CODE) != "0" { - // 创建窗口 - m.Cmd(_tmux, "switch-client", "-t", arg[0]) - m.Cmd(_tmux, "new-window", "-t", arg[0], "-dn", arg[1]) - } if len(arg) == 2 { // 终端列表 - m.Cmdy(PANE, target) + m.Cmdy(PANE, arg[0]+":"+arg[1]) + m.PushAction("进入", "删除") return } }}, WINDOW: {Name: "windows", Help: "窗口", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Split(m.Cmdx(_tmux, "list-windows", "-t", kit.Select("", arg, 0), + m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-windows", "-t", kit.Select("", arg, 0), "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n") }}, PANE: {Name: "panes", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Split(m.Cmdx(_tmux, "list-panes", "-t", kit.Select("", arg, 0), + m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-panes", "-t", kit.Select("", arg, 0), "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n") }}, VIEW: {Name: "view", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmdy(_tmux, "capture-pane", "-pt", kit.Select("", arg, 0)).Set(ice.MSG_APPEND) - }}, - - ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if m.Cmdy(cli.SYSTEM, "tmux", "ls"); m.Append("code") != "0" { - return - } - - m.Cmd(web.PROXY, "add", "tmux", m.AddCmd(&ice.Command{Name: "proxy", Help: "代理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd("session").Table(func(index int, value map[string]string, head []string) { - if value["tag"] == "1" { - m.Echo(value["session"]) - } - }) - }})) - }}, - "_install": {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option("cmd_dir", m.Conf("install", "meta.path")) - m.Cmd(cli.SYSTEM, "git", "clone", "https://github.com/tmux/tmux") - }}, - code.PREPARE: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Cmd("nfs.link", path.Join(os.Getenv("HOME"), ".tmux.conf"), "etc/conf/tmux.conf") - }}, - code.PROJECT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, - - gdb.INIT: {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Watch(gdb.DREAM_START) - return - - if m.Richs(web.FAVOR, nil, "tmux.auto", nil) == nil { - m.Cmd(web.FAVOR, "tmux.auto", web.TYPE_SHELL, "脚本", `curl $ctx_dev/publish/auto.sh > auto.sh`) - m.Cmd(web.FAVOR, "tmux.auto", web.TYPE_SHELL, "脚本", `source auto.sh`) - m.Cmd(web.FAVOR, "tmux.auto", web.TYPE_SHELL, "脚本", `ShyInit && ShyLogin && trap ShyLogout EXIT`) - } - - for _, v := range []string{"auto.sh", "auto.vim", "auto.tmux"} { - p := path.Join(m.Conf("web.code.publish", "meta.path"), v) - if _, e := os.Stat(p); e != nil && os.IsNotExist(e) { - // 下载脚本 - if h := m.Cmdx(web.SPIDE, "shy", "cache", "GET", "/publish/"+v); h != "" { - m.Cmd(web.STORY, web.WATCH, h, p) - } - } - } - }}, - gdb.AUTO: {Name: "auto", Help: "自动化", Action: map[string]*ice.Action{ - web.DREAM_START: {Name: "dream.start", Hand: func(m *ice.Message, arg ...string) { - if m.Cmd(_tmux, "has-session", "-t", arg[0]).Append(cli.CMD_CODE) == "0" { - return - } - // 创建会话 - m.Option(cli.CMD_ENV, "TMUX", "", "ctx_pod", arg[0], "ctx_dev", m.Conf(cli.RUNTIME, "conf.ctx_dev")) - m.Option(cli.CMD_DIR, path.Join(m.Conf(web.DREAM, "meta.path"), arg[0])) - m.Cmd(_tmux, "new-session", "-ds", arg[0]) - return - - // 共享空间 - share, dev := "", kit.Select(m.Conf(cli.RUNTIME, "conf.ctx_dev"), m.Conf(cli.RUNTIME, "host.ctx_self")) - m.Richs(web.SPACE, nil, arg[0], func(key string, value map[string]interface{}) { - share = kit.Format(value["share"]) - }) - - // 环境变量 - m.Option("cmd_env", "TMUX", "", "ctx_dev", dev, "ctx_share", share) - m.Option("cmd_dir", path.Join(m.Conf(web.DREAM, "meta.path"), arg[0])) - - if arg[0] != "" && m.Cmd(_tmux, "has-session", "-t", arg[0]).Append("code") != "0" { - // 创建会话 - m.Cmd(_tmux, "new-session", "-ds", arg[0]) - } - - if m.Option("local") != "" { - // 创建容器 - m.Cmd("local", m.Option("local"), arg[0]) - } - if m.Option("relay") != "" { - // 远程登录 - m.Cmd("relay", m.Option("relay"), arg[0]) - } - - for _, v := range kit.Simple(m.Optionv("before")) { - // 前置命令 - m.Cmdy(_tmux, "send-keys", "-t", arg[0], v, "Enter") - } - - // 连接参数 - m.Cmdy(_tmux, "send-keys", "-t", arg[0], "export ctx_dev=", dev, "Enter") - m.Cmdy(_tmux, "send-keys", "-t", arg[0], "export ctx_share=", share, "Enter") - - m.Cmd(web.FAVOR, kit.Select("tmux.auto", arg, 1)).Table(func(index int, value map[string]string, head []string) { - switch value["type"] { - case web.TYPE_SHELL: - // 发送命令 - m.Cmdy(_tmux, "send-keys", "-t", arg[0], value["text"], "Enter") - time.Sleep(10 * time.Millisecond) - } - }) - - for _, v := range kit.Simple(m.Optionv("after")) { - // 后置命令 - m.Cmdy(_tmux, "send-keys", "-t", arg[0], v, "Enter") - } - }}, - }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, - - "make": {Name: "make name cmd...", Help: "个性化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - session := m.Conf(cli.RUNTIME, "node.name") - if arg[1] == "session" { - session, arg[2], arg = arg[2], arg[0], arg[2:] - } - - if m.Warn(m.Cmd(_tmux, "has-session", "-t", session).Append("code") != "0", "session miss") { - // 会话不存在 - return - } - - if m.Cmdx("session", session, "has", arg[0]) != "" { - // 窗口已存在 - return - } - - switch arg[1] { - case "init": - m.Cmdx(_tmux, "rename-window", "-t", session, arg[0]) - arg[1], arg = arg[0], arg[1:] - case "link": - m.Cmdx(_tmux, "link-window", "-dt", session, "-s", arg[2]) - return - default: - m.Cmd(_tmux, "new-window", "-dt", session, "-n", arg[0]) - } - - for _, v := range arg[1:] { - switch ls := kit.Split(v); ls[1] { - case "v": - m.Cmd(_tmux, "split-window", "-h", "-dt", session+":"+arg[0]+"."+ls[0], ls[2:]) - case "u", "split-window": - m.Cmd(_tmux, "split-window", "-dt", session+":"+arg[0]+"."+ls[0], ls[2:]) - case "k": - m.Cmd(_tmux, "send-key", "-t", session+":"+arg[0]+"."+ls[0], ls[2:]) - default: - m.Cmd(_tmux, ls[1], "-t", session+":"+arg[0]+"."+ls[0], ls[2:]) - } - } - }}, - - "relay": {Name: "relay [name [favor]]", Help: "跳板机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - if len(arg) == 0 { - // 认证列表 - m.Richs(cmd, nil, "*", func(key string, value map[string]interface{}) { - m.Push(key, value, []string{"name", "username", "website"}) - }) - return - } - if len(arg) == 1 { - // 认证详情 - m.Richs(cmd, nil, arg[0], func(key string, value map[string]interface{}) { - m.Push("detail", value) - }) - return - } - - if len(arg) > 4 { - // 添加认证 - m.Rich(cmd, nil, kit.Dict(kit.MDB_NAME, arg[0], kit.MDB_TEXT, arg[1], - "username", arg[2], "website", arg[3], "password", arg[4], - )) - return - } - - m.Richs(cmd, nil, arg[0], func(key string, value map[string]interface{}) { - // 登录命令 - m.Cmdy(_tmux, "send-keys", "-t", arg[1], kit.Format("ssh %s@%s", value["username"], value["website"]), "Enter") - - sleep := kit.Duration(m.Conf(cmd, "meta.sleep")) - for i := 0; i < kit.Int(m.Conf(cmd, "meta.count")); i++ { - time.Sleep(sleep) - list := strings.Split(strings.TrimSpace(m.Cmdx(_tmux, "capture-pane", "-p")), "\n") - - if tail := list[len(list)-1]; tail == m.Conf(cmd, "meta.tail.login") { - // 登录成功 - break - } else if tail == m.Conf(cmd, "meta.tail.password") { - // 输入密码 - m.Cmdy(_tmux, "send-keys", "-t", arg[1], value["password"], "Enter") - } else if tail == m.Conf(cmd, "meta.tail.verify") { - // 输入密码 - m.Cmdy(_tmux, "send-keys", "-t", arg[1], m.Cmdx("aaa.totp.get", value["text"]), "Enter") - } - } - }) - }}, - - "/favor": {Name: "/favor", Help: "收藏", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - current := "" - m.Cmd("session").Table(func(index int, value map[string]string, head []string) { - if value["tag"] == "1" { - current = value["session"] - } - }) - - m.Option(ice.MSG_OUTPUT, ice.RENDER_RESULT) - switch arg = kit.Split(kit.Select("tmux.auto", arg, 0)); arg[0] { - case "ice": - if m.Cmdy(arg[1:]); len(m.Resultv()) == 0 { - m.Table() - } - default: - m.Cmd("auto", current, arg) - } + m.Cmdy(cli.SYSTEM, TMUX, "capture-pane", "-pt", kit.Select("", arg, 0)).Set(ice.MSG_APPEND) }}, }, } diff --git a/misc/tmux/tmux.shy b/misc/tmux/tmux.shy index e704faa3..45fb6eea 100644 --- a/misc/tmux/tmux.shy +++ b/misc/tmux/tmux.shy @@ -12,10 +12,14 @@ field tmux web.code.inner args `[ usr/install/tmux-3.1b cmd-bind-key.c ]` chapter "安装" section "编译安装" spark shell ` +yum install -y gcc make libevent-devel.x86_64 ncurses-devel.x86_64 + wget https://github.com/tmux/tmux/releases/download/3.1b/tmux-3.1b.tar.gz tar xvf tmux-3.1b.tar.gz && cd tmux-3.1b + ./configure --prefix=$PWD/install make -j8 && make install + ` section "使用体验" @@ -25,13 +29,17 @@ cd ./install ` chapter "应用" +field paste web.chat.paste.paste + field text web.code.tmux.text -field buffer web.code.tmux.buffer args 0 +field buffer web.code.tmux.buffer +field script web.code.tmux.script field session web.code.tmux.session chapter "项目" field icebergs web.code.inner args `[ usr/icebergs misc/tmux/tmux.go ]` return + section "libevent" spark shell ` wget https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz diff --git a/type.go b/type.go index 91b39b07..63e115ce 100644 --- a/type.go +++ b/type.go @@ -80,8 +80,10 @@ func (c *Context) Cap(key string, arg ...interface{}) string { } func (c *Context) _hand(m *Message, cmd *Command, key string, k string, h *Action, arg ...string) *Message { m.Log(LOG_CMDS, "%s.%s %s %d %v %s", c.Name, key, k, len(arg), arg, kit.FileLine(h.Hand, 3)) - for i := 0; i < len(arg)-1; i += 2 { - m.Option(arg[i], arg[i+1]) + if len(h.List) > 0 { + for i := 0; i < len(arg)-1; i += 2 { + m.Option(arg[i], arg[i+1]) + } } h.Hand(m, arg...) return m @@ -167,7 +169,16 @@ func (c *Context) Merge(s *Context, x Server) *Context { switch ls[i] { case ":": kit.Value(item, kit.MDB_INPUT, ls[i+1]) + switch ls[i+1] { + case "textarea": + kit.Value(item, "style.width", "300") + kit.Value(item, "style.height", "150") + + } case "=": + if len(ls) <= i+1 { + continue + } if strings.Contains(ls[i+1], ",") { kit.Value(item, kit.MDB_INPUT, "select") kit.Value(item, "values", strings.Split(ls[i+1], ","))