1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-09-10 20:57:46 +08:00
parent ef58635054
commit 0b39e8ebae
16 changed files with 334 additions and 508 deletions

View File

@ -12,6 +12,7 @@ const (
USERZONE = "userzone"
USERNICK = "usernick"
USERNAME = "username"
HOSTNAME = "hostname"
PASSWORD = "password"
USERROLE = "userrole"
USERNODE = "usernode"

View File

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

View File

@ -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: "数据模块",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(`<input type="button" value="%s">`, k))
}
for _, k := range arg {
list = append(list, fmt.Sprintf(`<input type="button" value="%s">`, 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 {

View File

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

View File

@ -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 ]`

View File

@ -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<span>%s</span>", 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)
}},
},
}

View File

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

15
type.go
View File

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