mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-25 16:58:06 +08:00
new web.code
This commit is contained in:
parent
87b8f03e36
commit
d9daf68f2b
@ -48,12 +48,13 @@ install() {
|
||||
|
||||
echo
|
||||
echo
|
||||
curl -o ${ctx_app} "$ctx_dev/publish/${ctx_app}?GOOS=$GOOS&GOARCH=$GOARCH" && chmod a+x ${ctx_app} || return
|
||||
wget -O ${ctx_app} "$ctx_dev/publish/bench?GOOS=$GOOS&GOARCH=$GOARCH" && chmod a+x ${ctx_app} || return
|
||||
|
||||
target=install && [ -n "$1" ] && target=$1
|
||||
${md5} ${ctx_app} && ./${ctx_app} upgrade ${target} || return
|
||||
|
||||
mv ${ctx_app} bin/${ctx_app} && bin/boot.sh
|
||||
mv ${ctx_app} bin/${ctx_app}
|
||||
# && bin/boot.sh
|
||||
}
|
||||
main() {
|
||||
trap HUP hup
|
||||
|
@ -69,18 +69,38 @@ func format(m *ctx.Message, out *bytes.Buffer) {
|
||||
}
|
||||
m.Table()
|
||||
case "cut":
|
||||
c := byte(kit.Select(" ", m.Optionv("cmd_parse"), 2)[0])
|
||||
c := byte(kit.Select(" ", m.Optionv("cmd_parse"), 1)[0])
|
||||
|
||||
bio := bufio.NewScanner(out)
|
||||
|
||||
pos := []int{}
|
||||
heads := []string{}
|
||||
if h := kit.Select("", m.Optionv("cmd_parse"), 3); h != "" {
|
||||
heads = strings.Split(h, " ")
|
||||
} else if bio.Scan() {
|
||||
heads = kit.Split(bio.Text(), c, kit.Int(kit.Select("-1", m.Optionv("cmd_parse"), 1)))
|
||||
h := bio.Text()
|
||||
v := kit.Trans(m.Optionv("cmd_headers"))
|
||||
for i := 0; i < len(v)-1; i += 2 {
|
||||
h = strings.Replace(h, v[i], v[i+1], 1)
|
||||
}
|
||||
|
||||
heads = kit.Split(h, c, kit.Int(kit.Select("-1", m.Optionv("cmd_parse"), 2)))
|
||||
for _, v := range heads {
|
||||
pos = append(pos, strings.Index(h, v))
|
||||
}
|
||||
}
|
||||
|
||||
for bio.Scan() {
|
||||
if len(pos) > 0 {
|
||||
for i, v := range pos {
|
||||
if i == len(pos)-1 {
|
||||
m.Add("append", heads[i], bio.Text()[v:])
|
||||
} else {
|
||||
m.Add("append", heads[i], bio.Text()[v:pos[i+1]])
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
for i, v := range kit.Split(bio.Text(), c, len(heads)) {
|
||||
m.Add("append", heads[i], v)
|
||||
}
|
||||
@ -306,12 +326,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
||||
"cmd_timeout: 命令超时",
|
||||
"cmd_active(true/false): 是否交互",
|
||||
"cmd_daemon(true/false): 是否守护",
|
||||
"cmd_dir: 工作目录",
|
||||
"cmd_env key value: 环境变量",
|
||||
"cmd_dir: 工作目录",
|
||||
"cmd_log: 输出日志",
|
||||
"cmd_temp arg...: 缓存结果",
|
||||
"cmd_parse format|json|csv|cli|cut [count sep]: 解析结果",
|
||||
"cmd_error: 输出错误",
|
||||
"cmd_temp arg...: 缓存结果",
|
||||
"cmd_parse format|json|csv|cli|cut [count sep headers]: 解析结果",
|
||||
"cmd_headers",
|
||||
}, Form: map[string]int{
|
||||
"cmd_timeout": 1,
|
||||
"cmd_active": 1,
|
||||
@ -323,6 +344,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
||||
"cmd_parse": 4,
|
||||
"cmd_error": 0,
|
||||
"cmd_select": -1,
|
||||
"cmd_headers": 2,
|
||||
"app_log": 1,
|
||||
}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
// 管道参数
|
||||
@ -865,7 +887,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
||||
if len(arg) == 1 {
|
||||
m.Cmdy("nfs.git", "sum", "-n", 20)
|
||||
} else {
|
||||
m.Cmdy("nfs.git", "sum", "-n", arg[1:])
|
||||
m.Cmdy("nfs.git", "sum", "--reverse", "--since", arg[1:])
|
||||
}
|
||||
|
||||
case "trends":
|
||||
@ -920,7 +942,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
|
||||
|
||||
// 编译项目
|
||||
if m.Cmdy("cli.compile", ""); m.Has("bin") {
|
||||
target := path.Join(kit.Select(os.Getenv("GOBIN"), ""), m.Conf("compile", "name"))
|
||||
target := path.Join(kit.Select(os.Getenv("GOBIN"), ""), m.Conf("runtime", "boot.ctx_app"))
|
||||
os.Remove(target)
|
||||
m.Append("bin", m.Cmdx("nfs.copy", target, m.Append("bin")))
|
||||
os.Chmod(target, 0777)
|
||||
|
@ -7,5 +7,5 @@ var version = struct {
|
||||
self int
|
||||
}{
|
||||
[]string{"2017-11-01 01:02:03", "2019-07-13 18:02:21"},
|
||||
`2019-11-01 14:34:16`, `mac`, 657,
|
||||
`2019-11-03 00:13:51`, `mac`, 659,
|
||||
}
|
||||
|
@ -109,3 +109,8 @@ func ExecuteFile(m *Message, w io.Writer, p string) error {
|
||||
tmpl.ParseGlob(p)
|
||||
return tmpl.ExecuteTemplate(w, path.Base(p), m)
|
||||
}
|
||||
func ExecuteStr(m *Message, w io.Writer, p string) error {
|
||||
tmpl := template.New("render").Funcs(CGI)
|
||||
tmpl, _ = tmpl.Parse(p)
|
||||
return tmpl.Execute(w, m)
|
||||
}
|
||||
|
@ -250,8 +250,15 @@ func (m *Message) Push(str string, arg ...interface{}) *Message {
|
||||
}
|
||||
func (m *Message) Sort(key string, arg ...string) *Message {
|
||||
cmp := "str"
|
||||
if len(arg) > 0 {
|
||||
if len(arg) > 0 && arg[0] != "" {
|
||||
cmp = arg[0]
|
||||
} else {
|
||||
cmp = "int"
|
||||
for _, v := range m.Meta[key] {
|
||||
if _, e := strconv.Atoi(v); e != nil {
|
||||
cmp = "str"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
number := map[int]int{}
|
||||
@ -274,7 +281,7 @@ func (m *Message) Sort(key string, arg ...string) *Message {
|
||||
for j := i + 1; j < len(table); j++ {
|
||||
result := false
|
||||
switch cmp {
|
||||
case "str":
|
||||
case "", "str":
|
||||
if table[i][key] > table[j][key] {
|
||||
result = true
|
||||
}
|
||||
@ -306,6 +313,106 @@ func (m *Message) Sort(key string, arg ...string) *Message {
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Limit(offset, limit int) *Message {
|
||||
l := len(m.Meta[m.Meta["append"][0]])
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
if offset > l {
|
||||
offset = l
|
||||
}
|
||||
if offset+limit > l {
|
||||
limit = l - offset
|
||||
}
|
||||
for _, k := range m.Meta["append"] {
|
||||
m.Meta[k] = m.Meta[k][offset : offset+limit]
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Filter(value string) *Message {
|
||||
|
||||
return m
|
||||
}
|
||||
func (m *Message) Group(method string, args ...string) *Message {
|
||||
|
||||
nrow := len(m.Meta[m.Meta["append"][0]])
|
||||
|
||||
keys := map[string]bool{}
|
||||
for _, v := range args {
|
||||
keys[v] = true
|
||||
}
|
||||
|
||||
counts := []int{}
|
||||
mis := map[int]bool{}
|
||||
for i := 0; i < nrow; i++ {
|
||||
counts = append(counts, 1)
|
||||
if mis[i] {
|
||||
continue
|
||||
}
|
||||
next:
|
||||
for j := i + 1; j < nrow; j++ {
|
||||
if mis[j] {
|
||||
continue
|
||||
}
|
||||
for key := range keys {
|
||||
if m.Meta[key][i] != m.Meta[key][j] {
|
||||
continue next
|
||||
}
|
||||
}
|
||||
for _, k := range m.Meta["append"] {
|
||||
if !keys[k] {
|
||||
switch method {
|
||||
case "sum", "avg":
|
||||
v1, e1 := strconv.Atoi(m.Meta[k][i])
|
||||
v2, e2 := strconv.Atoi(m.Meta[k][j])
|
||||
if e1 == nil && e2 == nil {
|
||||
m.Meta[k][i] = fmt.Sprintf("%d", v1+v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mis[j] = true
|
||||
counts[i]++
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < nrow; i++ {
|
||||
for _, k := range m.Meta["append"] {
|
||||
if !keys[k] {
|
||||
switch method {
|
||||
case "avg":
|
||||
if v1, e1 := strconv.Atoi(m.Meta[k][i]); e1 == nil {
|
||||
m.Meta[k][i] = strconv.Itoa(v1 / counts[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := 0; i < nrow; i++ {
|
||||
m.Push("_counts", counts[i])
|
||||
}
|
||||
|
||||
for i := 0; i < nrow; i++ {
|
||||
if mis[i] {
|
||||
for j := i + 1; j < nrow; j++ {
|
||||
if !mis[j] {
|
||||
for _, k := range m.Meta["append"] {
|
||||
m.Meta[k][i] = m.Meta[k][j]
|
||||
}
|
||||
mis[i], mis[j] = false, true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if mis[i] {
|
||||
for _, k := range m.Meta["append"] {
|
||||
m.Meta[k] = m.Meta[k][0:i]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Table(cbs ...interface{}) *Message {
|
||||
if len(m.Meta["append"]) == 0 {
|
||||
return m
|
||||
|
@ -1135,7 +1135,9 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
|
||||
}
|
||||
args := arg[i : j+1]
|
||||
if arg[i] == "feature" {
|
||||
feature[arg[i+1]] = arg[i+2]
|
||||
for k := 2; k < len(args); k++ {
|
||||
feature[args[1]] = kit.Merge(feature[args[1]], args[k])
|
||||
}
|
||||
|
||||
} else if arg[i] == "exports" {
|
||||
for k := 1; k < len(args); k += 1 {
|
||||
@ -1147,14 +1149,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
|
||||
"value": kit.Select("", args, 1),
|
||||
}
|
||||
for k := 2; k < len(args)-1; k += 2 {
|
||||
switch val := input[args[k]].(type) {
|
||||
case nil:
|
||||
input[args[k]] = args[k+1]
|
||||
case string:
|
||||
input[args[k]] = []interface{}{input[args[k]], args[k+1]}
|
||||
case []interface{}:
|
||||
input[args[k]] = append(val, args[k+1])
|
||||
}
|
||||
input[args[k]] = kit.Merge(input[args[k]], args[k+1])
|
||||
}
|
||||
inputs = append(inputs, input)
|
||||
}
|
||||
@ -1170,6 +1165,13 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
|
||||
}
|
||||
}
|
||||
|
||||
ctx := m.Cap("module")
|
||||
if strings.Contains(cmd, ".") {
|
||||
cs := strings.Split(cmd, ".")
|
||||
ctx = strings.Join(cs[:len(cs)-1], ".")
|
||||
cmd = cs[len(cs)-1]
|
||||
}
|
||||
|
||||
m.Confv("_index", []interface{}{-2}, map[string]interface{}{
|
||||
"name": kit.Select("", arg, 1),
|
||||
"help": kit.Select("", arg, 2),
|
||||
@ -1177,7 +1179,7 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心",
|
||||
"init": init,
|
||||
"type": right,
|
||||
|
||||
"ctx": m.Cap("module"),
|
||||
"ctx": ctx,
|
||||
"cmd": cmd,
|
||||
"args": args,
|
||||
"inputs": inputs,
|
||||
|
@ -3,29 +3,302 @@ package code
|
||||
import (
|
||||
"contexts/ctx"
|
||||
"contexts/web"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
"toolkit"
|
||||
)
|
||||
|
||||
var Index = &ctx.Context{Name: "code", Help: "代码中心",
|
||||
Caches: map[string]*ctx.Cache{},
|
||||
Configs: map[string]*ctx.Config{},
|
||||
Caches: map[string]*ctx.Cache{},
|
||||
Configs: map[string]*ctx.Config{
|
||||
"docker": {Name: "docker", Help: "容器", Value: map[string]interface{}{
|
||||
"shy": `
|
||||
FROM {{options . "base"}}
|
||||
|
||||
WORKDIR /home/{{options . "user"}}/context
|
||||
Env ctx_dev {{options . "host"}}
|
||||
|
||||
RUN wget -q -O - $ctx_dev/publish/boot.sh | sh -s install
|
||||
|
||||
CMD sh bin/boot.sh
|
||||
|
||||
`,
|
||||
}},
|
||||
},
|
||||
Commands: map[string]*ctx.Command{
|
||||
"zsh": &ctx.Command{Name: "zsh", Help: "终端", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Echo("zsh")
|
||||
"zsh": {Name: "zsh dir grep key [split reg fields] [filter reg fields] [order key method] [group keys method] [sort keys method]",
|
||||
Form: map[string]int{"split": 2, "filter": 2, "order": 2, "group": 2, "sort": 2},
|
||||
Help: "终端", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
p, arg := kit.Select(".", arg[0]), arg[1:]
|
||||
switch arg[0] {
|
||||
case "install":
|
||||
m.Cmd("cli.system", "apk", "add", arg[1])
|
||||
|
||||
case "list":
|
||||
m.Cmdy("nfs.dir", p, "time", "size", "path")
|
||||
|
||||
case "find":
|
||||
m.Cmdy("cli.system", "find", p, "-name", arg[1])
|
||||
|
||||
case "grep":
|
||||
if m.Options("split") {
|
||||
re, _ := regexp.Compile(kit.Select("", m.Optionv("split"), 0))
|
||||
fields := map[string]bool{}
|
||||
for _, v := range strings.Split(kit.Select("", m.Optionv("split"), 1), " ") {
|
||||
if v != "" {
|
||||
fields[v] = true
|
||||
}
|
||||
}
|
||||
|
||||
m.Cmd("cli.system", "grep", "-rn", arg[1], p, "cmd_parse", "cut", ":", "3", "path line text").Table(func(index int, line map[string]string) {
|
||||
if ls := re.FindAllStringSubmatch(line["text"], -1); len(ls) > 0 {
|
||||
m.Push("path", line["path"])
|
||||
m.Push("line", line["line"])
|
||||
for _, v := range ls {
|
||||
if len(fields) == 0 || fields[v[1]] {
|
||||
m.Push(v[1], v[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
m.Table()
|
||||
} else {
|
||||
m.Cmdy("cli.system", "grep", "-rn", arg[1], p, "cmd_parse", "cut", ":", "3", "path line text")
|
||||
}
|
||||
|
||||
if m.Has("filter") {
|
||||
m.Filter(m.Option("filter"))
|
||||
}
|
||||
if m.Has("order") {
|
||||
m.Sort(kit.Select("", m.Optionv("order"), 0), kit.Select("", m.Optionv("order"), 1))
|
||||
}
|
||||
if m.Has("group") {
|
||||
m.Group(kit.Select("sum", m.Optionv("group"), 1), strings.Split(kit.Select("", m.Option("group"), 0), " ")...)
|
||||
}
|
||||
if m.Has("sort") {
|
||||
m.Sort(kit.Select("", m.Optionv("sort"), 0), kit.Select("", m.Optionv("sort"), 1))
|
||||
}
|
||||
|
||||
case "tail":
|
||||
m.Cmdy("cli.system", "tail", path.Join(p, arg[1]))
|
||||
|
||||
}
|
||||
return
|
||||
}},
|
||||
"tmux": {Name: "tmux [session [window [pane cmd]]]", Help: "窗口", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
prefix := []string{"cli.system", "tmux"}
|
||||
if len(arg) > 1 {
|
||||
switch arg[1] {
|
||||
case "modify":
|
||||
switch arg[2] {
|
||||
case "session":
|
||||
m.Cmdy(prefix, "rename-session", "-t", arg[0], arg[3])
|
||||
case "window":
|
||||
m.Cmdy(prefix, "rename-window", "-t", arg[0], arg[3])
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
// 查看会话
|
||||
if m.Cmdy(prefix, "list-session", "-F", "#{session_id},#{session_name},#{session_windows},#{session_height},#{session_width}",
|
||||
"cmd_parse", "cut", ",", "5", "id session windows height width"); len(arg) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建会话
|
||||
if arg[0] != "" && !kit.Contains(m.Meta["session"], arg[0]) {
|
||||
m.Cmdy(prefix, "new-session", "-ds", arg[0])
|
||||
}
|
||||
m.Set("append").Set("result")
|
||||
|
||||
// 查看窗口
|
||||
if m.Cmdy(prefix, "list-windows", "-t", arg[0], "-F", "#{window_id},#{window_name},#{window_panes},#{window_height},#{window_width}",
|
||||
"cmd_parse", "cut", ",", "5", "id window panes height width"); len(arg) == 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// 创建窗口
|
||||
if arg[1] != "" && !kit.Contains(m.Meta["window"], arg[1]) {
|
||||
m.Cmdy(prefix, "new-window", "-dt", arg[0], "-n", arg[1])
|
||||
}
|
||||
m.Set("append").Set("result")
|
||||
|
||||
// 查看面板
|
||||
if len(arg) == 2 {
|
||||
m.Cmdy(prefix, "list-panes", "-t", arg[0]+":"+arg[1], "-F", "#{pane_id},#{pane_index},#{pane_tty},#{pane_height},#{pane_width}",
|
||||
"cmd_parse", "cut", ",", "5", "id pane tty height width")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
target := arg[0] + ":" + arg[1] + "." + arg[2]
|
||||
if len(arg) > 3 {
|
||||
if len(arg) > 5 {
|
||||
switch arg[5] {
|
||||
case "modify":
|
||||
switch arg[6] {
|
||||
case "text":
|
||||
m.Cmdy(prefix, "set-buffer", "-b", arg[4], arg[7])
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
switch arg[3] {
|
||||
case "buffer":
|
||||
if len(arg) > 5 {
|
||||
m.Cmdy(prefix, "set-buffer", "-b", arg[4], arg[5])
|
||||
}
|
||||
if len(arg) > 4 {
|
||||
m.Cmdy(prefix, "show-buffer", "-b", arg[4])
|
||||
return
|
||||
}
|
||||
m.Cmdy(prefix, "list-buffers", "cmd_parse", "cut", ": ", "3", "buffer size text")
|
||||
for i, v := range m.Meta["text"] {
|
||||
if i < 3 {
|
||||
m.Meta["text"][i] = m.Cmdx(prefix, "show-buffer", "-b", m.Meta["buffer"][i])
|
||||
} else {
|
||||
m.Meta["text"][i] = v[2 : len(v)-1]
|
||||
}
|
||||
}
|
||||
return
|
||||
case "layout":
|
||||
default:
|
||||
m.Cmdy(prefix, "send-keys", "-t", target, strings.Join(arg[3:], " "), "Enter")
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
// 查看终端
|
||||
m.Echo(strings.TrimSpace(m.Cmdx(prefix, "capture-pane", "-pt", target)))
|
||||
return
|
||||
}},
|
||||
"tmux": &ctx.Command{Name: "tmux", Help: "窗口", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
"docker": {Name: "docker", Help: "容器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
prefix := []string{"cli.system", "docker"}
|
||||
switch arg[0] {
|
||||
case "image":
|
||||
prefix = append(prefix, "image")
|
||||
pos := kit.Select("shy", arg, 1)
|
||||
tag := kit.Select("2.1", arg, 2)
|
||||
|
||||
// 查看镜像
|
||||
if m.Cmdy(prefix, "ls", "cmd_parse", "cut", "cmd_headers", "IMAGE ID", "IMAGE_ID"); len(arg) == 1 {
|
||||
return
|
||||
} else if i := kit.IndexOf(m.Meta["IMAGE_ID"], arg[1]); i > -1 {
|
||||
arg, pos, tag = arg[2:], strings.TrimSpace(m.Meta["REPOSITORY"][i]), strings.TrimSpace(m.Meta["TAG"][i])
|
||||
} else {
|
||||
arg = arg[3:]
|
||||
}
|
||||
|
||||
// 拉取镜像
|
||||
if len(arg) == 0 {
|
||||
m.Cmdy(prefix, "pull", pos+":"+tag)
|
||||
return
|
||||
}
|
||||
|
||||
switch arg[0] {
|
||||
// 启动容器
|
||||
case "运行":
|
||||
m.Set("append").Set("result")
|
||||
m.Cmdy("cli.system", "docker", "run", "-dt", pos+":"+tag)
|
||||
return
|
||||
// 清理镜像
|
||||
case "清理":
|
||||
m.Cmd(prefix, "prune", "-f")
|
||||
|
||||
// 删除镜像
|
||||
case "delete":
|
||||
m.Cmd(prefix, "rm", pos+":"+tag)
|
||||
|
||||
// 创建镜像
|
||||
default:
|
||||
m.Option("base", pos+":"+tag)
|
||||
m.Option("name", arg[0]+":"+kit.Select("2.1", arg, 1))
|
||||
m.Option("host", "http://"+m.Conf("runtime", "boot.hostname")+".local:9095")
|
||||
m.Option("user", kit.Select("shy", arg, 2))
|
||||
m.Option("file", "etc/Dockerfile")
|
||||
|
||||
if f, _, e := kit.Create(m.Option("file")); m.Assert(e) {
|
||||
defer f.Close()
|
||||
if m.Assert(ctx.ExecuteStr(m, f, m.Conf("docker", arg[0]))) {
|
||||
m.Cmdy("cli.system", "docker", "image", "build", "-f", m.Option("file"), "-t", m.Option("name"), ".")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case "container":
|
||||
prefix = append(prefix, "container")
|
||||
if len(arg) > 1 {
|
||||
switch arg[2] {
|
||||
case "进入":
|
||||
m.Cmdy("cli.system", "tmux", "new-window", "-dPF", "#{session_name}:#{window_name}.1", "docker exec -it "+arg[1]+" sh")
|
||||
return
|
||||
|
||||
case "停止":
|
||||
m.Cmd(prefix, "stop", arg[1])
|
||||
|
||||
case "启动":
|
||||
m.Cmd(prefix, "start", arg[1])
|
||||
|
||||
case "重启":
|
||||
m.Cmd(prefix, "restart", arg[1])
|
||||
|
||||
case "清理":
|
||||
m.Cmd(prefix, "prune", "-f")
|
||||
|
||||
case "modify":
|
||||
switch arg[3] {
|
||||
case "NAMES":
|
||||
m.Cmd(prefix, "rename", arg[1], arg[4:])
|
||||
}
|
||||
|
||||
// 删除容器
|
||||
case "delete":
|
||||
m.Cmd(prefix, "rm", arg[1])
|
||||
|
||||
default:
|
||||
if len(arg) > 2 {
|
||||
m.Cmdy(prefix, "exec", arg[1], arg[2:])
|
||||
} else {
|
||||
m.Cmdy(prefix, "inspect", arg[1])
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
m.Cmdy(prefix, "ls", "-a", "cmd_parse", "cut", "cmd_headers", "CONTAINER ID", "CONTAINER_ID")
|
||||
|
||||
case "network":
|
||||
if len(arg) == 1 {
|
||||
m.Cmdy("cli.system", "docker", "network", "ls", "cmd_parse", "cut", "cmd_headers", "NETWORK ID", "NETWORK_ID")
|
||||
break
|
||||
}
|
||||
|
||||
kit.Map(kit.Chain(kit.UnMarshal(m.Cmdx("cli.system", "docker", "network", "inspect", arg[1])), "0.Containers"), "", func(key string, value map[string]interface{}) {
|
||||
m.Push("CONTAINER_ID", key[:12])
|
||||
m.Push("name", value["Name"])
|
||||
m.Push("IPv4", value["IPv4Address"])
|
||||
m.Push("IPv6", value["IPV4Address"])
|
||||
m.Push("Mac", value["MacAddress"])
|
||||
})
|
||||
m.Table()
|
||||
|
||||
case "volume":
|
||||
if len(arg) == 1 {
|
||||
m.Cmdy("cli.system", "docker", "volume", "ls", "cmd_parse", "cut", "cmd_headers", "VOLUME NAME", "VOLUME_NAME")
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
m.Cmdy("cli.system", "docker", arg)
|
||||
}
|
||||
return
|
||||
}},
|
||||
"git": {Name: "git", Help: "版本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Echo("git")
|
||||
return
|
||||
}},
|
||||
"docker": &ctx.Command{Name: "docker", Help: "容器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Echo("docker")
|
||||
return
|
||||
}},
|
||||
"git": &ctx.Command{Name: "git", Help: "版本", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Echo("git")
|
||||
return
|
||||
}},
|
||||
"vim": &ctx.Command{Name: "vim", Help: "编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
"vim": {Name: "vim", Help: "编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Echo("vim")
|
||||
return
|
||||
}},
|
||||
|
3
src/plugin/docker/index.css
Normal file
3
src/plugin/docker/index.css
Normal file
@ -0,0 +1,3 @@
|
||||
fieldset.item.docker div.output {
|
||||
}
|
||||
|
36
src/plugin/docker/index.go
Normal file
36
src/plugin/docker/index.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"contexts/cli"
|
||||
"contexts/ctx"
|
||||
"toolkit"
|
||||
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var Index = &ctx.Context{Name: `docker`, Help: `plugin`,
|
||||
Caches: map[string]*ctx.Cache{},
|
||||
Configs: map[string]*ctx.Config{
|
||||
"_index": &ctx.Config{Name: "index", Value: []interface{}{
|
||||
map[string]interface{}{"name": "demo", "help": "demo",
|
||||
"tmpl": "componet", "view": "", "init": "",
|
||||
"type": "public", "ctx": "demo", "cmd": "demo",
|
||||
"args": []interface{}{}, "inputs": []interface{}{
|
||||
map[string]interface{}{"type": "text", "name": "pod", "value": "hello world"},
|
||||
map[string]interface{}{"type": "button", "value": "执行"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
Commands: map[string]*ctx.Command{
|
||||
"demo": {Name: "demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
|
||||
m.Echo(kit.Select("hello world", arg, 0))
|
||||
return
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Print(cli.Index.Plugin(Index, os.Args[1:]))
|
||||
}
|
3
src/plugin/docker/index.js
Normal file
3
src/plugin/docker/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
Script["docker/index.js"] = function(field, option, output) {return {
|
||||
}}
|
||||
|
49
src/plugin/docker/index.shy
Normal file
49
src/plugin/docker/index.shy
Normal file
@ -0,0 +1,49 @@
|
||||
kit shell "命令" private "web.code.zsh" \
|
||||
text "" name dir imports plugin_path action auto \
|
||||
select "" name cmd values list values find values grep values tail \
|
||||
exports path path \
|
||||
text "" name txt \
|
||||
feature display editor \
|
||||
button "搜索" \
|
||||
button "返回" cb Last
|
||||
|
||||
kit clip "文本" private "web.code.tmux" "" "" "" "buffer" \
|
||||
text "" name tag imports plugin_buffer action auto \
|
||||
text "" name txt \
|
||||
exports buffer buffer \
|
||||
feature detail "复制" "下载" "修改" \
|
||||
button "查看" action auto \
|
||||
button "返回" cb Last
|
||||
|
||||
kit tmux "终端" private "web.code.tmux" \
|
||||
text "context" name session imports plugin_session action auto \
|
||||
text "" name window imports plugin_window action auto \
|
||||
text "" name pane imports plugin_pane view char action auto \
|
||||
text "" name cmd \
|
||||
exports session session "" window window "" pane pane "" \
|
||||
feature detail "复制" "下载" "修改" \
|
||||
button "查看" action auto
|
||||
|
||||
kit image "镜像" private "web.code.docker" "image" \
|
||||
text "" name pos imports plugin_REPOSITORY \
|
||||
text "" name tag imports plugin_TAG \
|
||||
exports IMAGE_ID IMAGE_ID "" REPOSITORY REPOSITORY "" TAG TAG "" \
|
||||
feature detail "运行" "删除" "清理" \
|
||||
button "查看" action auto
|
||||
|
||||
kit container "容器" private "web.code.docker" "container" \
|
||||
text "" name arg imports plugin_CONTAINER_ID \
|
||||
exports CONTAINER_ID CONTAINER_ID \
|
||||
feature detail "进入" "停止" "启动" "重启" "修改" "删除" "清理" \
|
||||
button "查看" action auto
|
||||
|
||||
kit network "网络" private "web.code.docker" "network" \
|
||||
text "" name arg imports plugin_NETWORK_ID action auto \
|
||||
exports NETWORK_ID NETWORK_ID \
|
||||
button "查看" action auto
|
||||
|
||||
kit volume "存储" private "web.code.docker" "volume" \
|
||||
text "" name arg imports plugin_CONTAINER_ID \
|
||||
exports CONTAINER_ID CONTAINER_ID \
|
||||
button "查看"
|
||||
|
@ -218,3 +218,43 @@ func List(arg interface{}, cb interface{}) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Merge(list interface{}, value string) interface{} {
|
||||
switch val := list.(type) {
|
||||
case nil:
|
||||
return value
|
||||
case string:
|
||||
return []interface{}{val, value}
|
||||
case []interface{}:
|
||||
return append(val, value)
|
||||
}
|
||||
return list
|
||||
}
|
||||
func Contains(list interface{}, value string) bool {
|
||||
switch val := list.(type) {
|
||||
case nil:
|
||||
case string:
|
||||
case []string:
|
||||
for _, v := range val {
|
||||
if v == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
case []interface{}:
|
||||
}
|
||||
return false
|
||||
}
|
||||
func IndexOf(list interface{}, value string) int {
|
||||
switch val := list.(type) {
|
||||
case nil:
|
||||
case string:
|
||||
case []string:
|
||||
for i, v := range val {
|
||||
if strings.TrimSpace(v) == strings.TrimSpace(value) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
case []interface{}:
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
@ -1220,10 +1220,12 @@ function Plugin(page, pane, field, inits, runs) {
|
||||
var meta = arguments.callee.meta
|
||||
var list = arguments.callee.list
|
||||
|
||||
for (var i = 0; i < list.length; i += 3) {
|
||||
(list[1] && line[list[1]] || list[i+1] && line[list[i+1]] || list[i+2]) &&
|
||||
for (var i = 0; i < list.length; i += 3) {if (list[i+1] == name) {
|
||||
for (var i = 0; i < list.length; i += 3) {
|
||||
page.Sync("plugin_"+list[i]).set(meta[list[i+2]||""](list[i+1]? line[list[i+1]]: value, list[i+1]||name, line, list))
|
||||
}
|
||||
}
|
||||
break
|
||||
}}
|
||||
}),
|
||||
onchoice: shy("菜单列表", {
|
||||
"返回": "Last",
|
||||
@ -1232,7 +1234,7 @@ function Plugin(page, pane, field, inits, runs) {
|
||||
"减参": "Remove",
|
||||
"删除": "Delete",
|
||||
}, ["返回", "复制", "加参", "减参", "删除"], function(event, value, meta) {
|
||||
kit._call(plugin, plugin[meta[value]])
|
||||
kit._call(plugin, plugin[meta[value]], [event])
|
||||
return true
|
||||
}),
|
||||
onaction: shy("事件列表", {
|
||||
@ -1290,7 +1292,7 @@ function Inputs(plugin, meta, item, target, option) {
|
||||
onimport: shy("导入数据", {}, [item.imports], function() {
|
||||
kit.List(arguments.callee.list, function(imports) {
|
||||
page.Sync(imports).change(function(value) {
|
||||
plugin.History(target.value, target), target.value = value
|
||||
plugin.History(target.value, target), target.value = value.trim()
|
||||
input.Event(event = document.createEvent("Event"))
|
||||
item.action == "auto" && plugin.Runs(event)
|
||||
})
|
||||
@ -1372,10 +1374,10 @@ function Inputs(plugin, meta, item, target, option) {
|
||||
return true
|
||||
})
|
||||
|
||||
// Event入口 2.1
|
||||
if (event.key == "Enter" && (event.ctrlKey || item.type == "text")) {
|
||||
// Event入口 2.1
|
||||
input.which.set(target.value) != undefined && plugin.History(target.value, target)
|
||||
input.Event(event, {}) && plugin.Check(event, target)
|
||||
input.Event(event, {}) && event.ctrlKey? plugin.Runs(event): plugin.Check(event, target)
|
||||
}
|
||||
},
|
||||
onkeyup: function(event) {
|
||||
@ -1409,11 +1411,27 @@ function Inputs(plugin, meta, item, target, option) {
|
||||
return plugin.Inputs[item.name] = target, target.Input = input
|
||||
}
|
||||
function Output(plugin, type, msg, cb, target, option) {
|
||||
var exports = plugin.target.Meta.exports
|
||||
var name = plugin.target.Meta.name+"."+type
|
||||
var feature = JSON.parse(plugin.target.Meta.feature||'{}')
|
||||
var exports = JSON.parse(plugin.target.Meta.exports||'{}')
|
||||
|
||||
var output = Meta(plugin.Zone(type), target, {
|
||||
_table: function() {plugin.onfigure("table")},
|
||||
_canvas: function() {plugin.onfigure("canvas")},
|
||||
clear: function() {target.innerHTML = ""},
|
||||
Format: function() {
|
||||
var ext = ".csv", txt = kit.Selector(target, "tr", function(tr) {
|
||||
return kit.Selector(tr, "td,th", function(td) {
|
||||
return td.innerText
|
||||
}).join(",")
|
||||
}).join("\n");
|
||||
type == "editor" && msg.file && (ext = ".txt", txt = msg.result.join("\n"));
|
||||
!txt && (ext = ".txt", txt = msg.result.join(""))
|
||||
return [name, ext, txt]
|
||||
},
|
||||
Copy: function(event) {
|
||||
kit.CopyText(output.Format()[2])
|
||||
},
|
||||
|
||||
Jshy: function(event, args) {
|
||||
// 内部命令
|
||||
@ -1425,19 +1443,44 @@ function Output(plugin, type, msg, cb, target, option) {
|
||||
},
|
||||
|
||||
Download: function() {
|
||||
var type = ".csv", text = kit.Selector(target, "tr", function(tr) {
|
||||
return kit.Selector(tr, "td,th", function(td) {
|
||||
return td.innerText
|
||||
}).join(",")
|
||||
}).join("\n")
|
||||
!text && (type = ".txt", text = plugin.msg.result.join(""))
|
||||
var ps = output.Format()
|
||||
|
||||
plugin.ontoast({text:'<a href="'+URL.createObjectURL(new Blob([text]))+'" target="_blank" download="'+name+type+'">'+name+type+'</a>', title: "下载中...", width: 200})
|
||||
plugin.ontoast({text:'<a href="'+URL.createObjectURL(new Blob([ps[2]]))+'" target="_blank" download="'+ps[0]+ps[1]+'">'+ps[0]+ps[1]+'</a>', title: "下载中...", width: 200})
|
||||
kit.Selector(page.toast, "a", function(item) {item.click()})
|
||||
},
|
||||
onimport: shy("导入数据", {
|
||||
_table: function(msg, list) {
|
||||
return list && list.length > 0 && kit.OrderTable(kit.AppendTable(kit.AppendChild(target, "table"), msg.Table(), list), "", output.onexport)
|
||||
return list && list.length > 0 && kit.OrderTable(kit.AppendTable(kit.AppendChild(target, "table"), msg.Table(), list), "", output.onexport, function(event, value, name, line, index) {
|
||||
var td = event.target
|
||||
plugin.oncarte(event, shy("菜单列表", {
|
||||
"修改": "modify",
|
||||
"删除": "delete",
|
||||
"下载": "Download",
|
||||
"复制": function(event, text) {kit.CopyText(text), plugin.ontoast(text, "Copy to ClipBoard!")},
|
||||
}, feature.detail||["复制", "下载"], function(event, item, meta) {
|
||||
var text = td.innerText.trim()
|
||||
if (typeof meta[item] == "function") {meta[item](event, text); return}
|
||||
|
||||
item == "修改"? (text = kit.AppendChilds(td, [{type: "input", value: text, data: {onkeydown: function(event) {
|
||||
if (event.key == "Enter") {
|
||||
var id = ""
|
||||
for (var i = 0; i < exports.length-1; i += 3) {
|
||||
id = (id || line[exports[i+1]] || "").trim()
|
||||
}
|
||||
plugin.Run(event, [id, meta[item], name, event.target.value], function(msg) {
|
||||
td.innerHTML = event.target.value
|
||||
plugin.ontoast("修改成功")
|
||||
}, true)
|
||||
return
|
||||
}
|
||||
}}}]).input, text.focus(), text.setSelectionRange(0, -1)): output[meta[item]]? output[meta[item]](event): plugin.Run(event, [line[exports[1]].trim(), meta[item]||item], function(msg) {
|
||||
console.log(msg)
|
||||
})
|
||||
|
||||
return true
|
||||
}),
|
||||
)
|
||||
})
|
||||
},
|
||||
_code: function(msg) {
|
||||
return msg.result && msg.result.length > 0 && kit.OrderCode(kit.AppendChild(target, [{view: ["code", "div", msg.Results()]}]).first)
|
||||
@ -1489,13 +1532,21 @@ function Output(plugin, type, msg, cb, target, option) {
|
||||
page.output = target
|
||||
meta[type](msg, cb)
|
||||
}),
|
||||
ondetail: shy("菜单列表", {
|
||||
"删除": "_table",
|
||||
"修改": "_canvas",
|
||||
}, ["删除", "修改"], function(event, value, meta) {
|
||||
kit._call(output, output[meta[value]], [event])
|
||||
return true
|
||||
}),
|
||||
onchoice: shy("菜单列表", {
|
||||
"表格": "_table",
|
||||
"绘图": "_canvas",
|
||||
"复制": "Copy",
|
||||
"下载": "Download",
|
||||
"返回": "Last",
|
||||
"清空": "clear",
|
||||
}, ["表格", "绘图", "下载", "返回", "清空"], function(event, value, meta) {
|
||||
}, ["表格", "绘图", "复制", "下载", "返回", "清空"], function(event, value, meta) {
|
||||
kit._call(output, output[meta[value]], [event])
|
||||
return true
|
||||
}),
|
||||
|
@ -303,7 +303,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
|
||||
var td = kit.AppendChild(tr, "td", kit.Color(row[key]))
|
||||
|
||||
if (key == "when") {td.className = "when"}
|
||||
if (row[key].startsWith("http")) {
|
||||
if ((row[key]||"").startsWith("http")) {
|
||||
td.innerHTML = "<a href='"+row[key]+"' target='_blank'>"+row[key]+"</a>"
|
||||
}
|
||||
|
||||
@ -353,8 +353,8 @@ kit = toolkit = (function() {var kit = {__proto__: document,
|
||||
tbody.appendChild(list[i])
|
||||
}
|
||||
},
|
||||
OrderTable: function(table, field, cb) {if (!table) {return}
|
||||
table.onclick = function(event) {var target = event.target
|
||||
OrderTable: function(table, field, cb, cbs) {if (!table) {return}
|
||||
table.oncontextmenu = table.onclick = function(event) {var target = event.target
|
||||
target.parentElement.childNodes.forEach(function(item, i) {if (item != target) {return}
|
||||
if (target.tagName == "TH") {var dataset = target.dataset
|
||||
dataset["sort_asc"] = (dataset["sort_asc"] == "1") ? 0: 1
|
||||
@ -362,7 +362,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
|
||||
} else if (target.tagName == "TD") {var index = 0
|
||||
kit.Selector(table, "tr", function(item, i) {item == target.parentElement && (index = i)})
|
||||
var name = target.parentElement.parentElement.querySelector("tr").childNodes[i].innerText
|
||||
name.startsWith(field) && kit._call(cb, [event, item.innerText, name, item.parentNode.Meta, index])
|
||||
name.startsWith(field) && kit._call(event.type=="contextmenu"? cbs: cb, [event, item.innerText, name, item.parentNode.Meta, index])
|
||||
}
|
||||
})
|
||||
kit.CopyText()
|
||||
@ -439,7 +439,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
|
||||
// HTML输入文本
|
||||
CopyText: function(text) {
|
||||
if (text) {
|
||||
var input = kit.AppendChild(document.body, [{type: "input", value: text}]).input
|
||||
var input = kit.AppendChild(document.body, [{type: "textarea", inner: text}]).last
|
||||
input.focus(), input.setSelectionRange(0, text.length)
|
||||
}
|
||||
|
||||
@ -544,6 +544,7 @@ kit = toolkit = (function() {var kit = {__proto__: document,
|
||||
s = s.replace(/\033\[31m/g, "<span style='color:#f00'>")
|
||||
s = s.replace(/\033\[0m/g, "</span>")
|
||||
s = s.replace(/\033\[m/g, "</span>")
|
||||
s = s.replace(/\n/g, "<br/>")
|
||||
return s
|
||||
},
|
||||
Value: function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user