From aff272235a70fbb84467f23dd5b2dd61dbf03b2a Mon Sep 17 00:00:00 2001 From: shaoying Date: Tue, 25 Dec 2018 15:03:54 +0800 Subject: [PATCH] add spide Change-Id: I6ef91687d1d91b652159d5ce20667aba3541683a --- src/contexts/cli/cli.go | 305 ++++++++++++++++++++++++++---------- src/contexts/ctx/ctx.go | 83 +++------- src/contexts/nfs/nfs.go | 28 ++++ src/contexts/web/web.go | 152 +++++++++++++++++- src/examples/chat/chat.go | 173 +++++++++++++++++++- src/examples/code/code.go | 184 +++++++++++----------- usr/librarys/code.js | 53 +++++-- usr/librarys/context.js | 47 ++++++ usr/librarys/wiki.js | 14 ++ usr/template/code/code.tmpl | 16 +- usr/template/wiki/wiki.tmpl | 7 +- 11 files changed, 793 insertions(+), 269 deletions(-) diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 87e9154c..91fbde84 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -5,6 +5,7 @@ import ( "contexts/ctx" "encoding/csv" "path" + "syscall" "toolkit" "fmt" @@ -30,9 +31,23 @@ type CLI struct { target *ctx.Context stack []*Frame + *time.Timer *ctx.Context } +func (cli *CLI) schedule(m *ctx.Message) string { + first, timer := "", int64(1<<50) + for k, v := range m.Confv("timer").(map[string]interface{}) { + val := v.(map[string]interface{}) + if val["action_time"].(int64) < timer && !val["done"].(bool) { + first, timer = k, val["action_time"].(int64) + } + } + cli.Timer.Reset(time.Until(time.Unix(0, timer/int64(m.Confi("time_unit"))*1000000000))) + m.Log("fuck", "what %v %d", first, timer) + return m.Conf("timer_next", first) +} + func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { c.Caches = map[string]*ctx.Cache{ "level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"}, @@ -97,6 +112,7 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { + cli.target = m.Target() return cli } func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { @@ -159,6 +175,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", "top": map[string]interface{}{"active": true}, "ls": map[string]interface{}{"arg": []interface{}{"-l"}}, }, Help: "系统命令配置, active: 交互方式, cmd: 命令映射, arg: 命令参数, args: 子命令参数, path: 命令目录, env: 环境变量, dir: 工作目录"}, + + "timer": &ctx.Config{Name: "timer", Value: map[string]interface{}{}, Help: "定时器"}, + "timer_next": &ctx.Config{Name: "timer_next", Value: "", Help: "定时器"}, }, Commands: map[string]*ctx.Command{ "alias": &ctx.Command{Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]", @@ -275,7 +294,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", execexec = execexec || ctx.Right(detail[i+1]) i++ case "<": - pipe := m.Spawn().Cmd("import", detail[i+1]) + pipe := m.Sess("nfs").Cmd("import", detail[i+1]) msg.Copy(pipe, "append") i++ case ">": @@ -312,8 +331,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } detail = args + msg.Set("detail", detail...) - if msg.Cmd(detail); msg.Hand { + if msg.Cmd(); msg.Hand { m.Cap("ps_target", msg.Cap("module")) } else { msg.Copy(m, "target").Copy(m, "result").Detail(-1, "system") @@ -632,8 +652,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", arg = append(args, arg...) m.Option("current_ctx", "") } else { - args := []string{"context", m.Source().Name} - arg = append(args, arg...) + if !strings.HasPrefix(arg[0], "context") { + args := []string{"context", m.Source().Name} + arg = append(args, arg...) + } } m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message { @@ -664,87 +686,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Copy(msg, "append").Copy(msg, "result") }}, - "sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if d, e := time.ParseDuration(arg[0]); m.Assert(e) { - m.Log("info", "sleep %v", d) - time.Sleep(d) - m.Log("info", "sleep %v done", d) - } - }}, - "time": &ctx.Command{Name: "time when [begin|end|yestoday|tommorow|monday|sunday|first|last|origin|last]", - Help: "查看时间, when: 输入的时间戳, 剩余参数是时间偏移", - Form: map[string]int{"time_format": 1, "time_close": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - t, stamp := time.Now(), true - if len(arg) > 0 { - if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil { - t = time.Unix(int64(i/int64(m.Confi("time_unit"))), 0) - arg = arg[1:] - stamp = false - } else if n, e := time.ParseInLocation(m.Confx("time_format"), arg[0], time.Local); e == nil { - arg = arg[1:] - t = n - } - } - - if len(arg) > 0 { - switch arg[0] { - case "begin": - d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds", t.Hour(), t.Minute(), t.Second())) - m.Assert(e) - t = t.Add(-d) - case "end": - d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds%dns", t.Hour(), t.Minute(), t.Second(), t.Nanosecond())) - m.Assert(e) - t = t.Add(time.Duration(24*time.Hour) - d) - if m.Confx("time_close") == "close" { - t = t.Add(-time.Second) - } - case "yestoday": - t = t.Add(-time.Duration(24 * time.Hour)) - case "tomorrow": - t = t.Add(time.Duration(24 * time.Hour)) - case "monday": - d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds", int((t.Weekday()-time.Monday+7)%7)*24+t.Hour(), t.Minute(), t.Second())) - m.Assert(e) - t = t.Add(-d) - case "sunday": - d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds", int((t.Weekday()-time.Monday+7)%7)*24+t.Hour(), t.Minute(), t.Second())) - m.Assert(e) - t = t.Add(time.Duration(7*24*time.Hour) - d) - if m.Confx("time_close") == "close" { - t = t.Add(-time.Second) - } - case "first": - t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local) - case "last": - month, year := t.Month()+1, t.Year() - if month >= 13 { - month, year = 1, year+1 - } - t = time.Date(year, month, 1, 0, 0, 0, 0, time.Local) - if m.Confx("time_close") == "close" { - t = t.Add(-time.Second) - } - case "origin": - t = time.Date(t.Year(), 1, 1, 0, 0, 0, 0, time.Local) - case "final": - t = time.Date(t.Year()+1, 1, 1, 0, 0, 0, 0, time.Local) - if m.Confx("time_close") == "close" { - t = t.Add(-time.Second) - } - } - } - - m.Append("datetime", t.Format(m.Confx("time_format"))) - m.Append("timestamp", t.Unix()*int64(m.Confi("time_unit"))) - - if stamp { - m.Echo("%d", t.Unix()*int64(m.Confi("time_unit"))) - } else { - m.Echo(t.Format(m.Confx("time_format"))) - } - }}, "tmux": &ctx.Command{Name: "tmux buffer", Help: "终端管理, buffer: 查看复制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { switch arg[0] { case "buffer": @@ -854,8 +795,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } else { if out, e := cmd.Output(); e != nil { - m.Echo("error: ").Echo("%s\n", e) - m.Echo("%s\n", string(out)) + if e == exec.ErrNotFound { + m.Echo("error: ").Echo("not found\n") + } else { + m.Echo("error: ").Echo("%s\n", e) + m.Echo("%s\n", string(out)) + } } else { switch m.Option("cmd_parse") { case "csv": @@ -911,6 +856,14 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Append("lookups", mem.Lookups) m.Append("objects", mem.HeapObjects) + + sys := &syscall.Sysinfo_t{} + syscall.Sysinfo(sys) + + m.Append("total", kit.FmtSize(uint64(sys.Totalram))) + m.Append("free", kit.FmtSize(uint64(sys.Freeram))) + m.Append("mper", fmt.Sprintf("%d%%", sys.Freeram*100/sys.Totalram)) + m.Table() }}, "windows": &ctx.Command{Name: "windows", Help: "windows", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { @@ -1037,6 +990,184 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } } }}, + + "sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if d, e := time.ParseDuration(arg[0]); m.Assert(e) { + m.Log("info", "sleep %v", d) + time.Sleep(d) + m.Log("info", "sleep %v done", d) + } + }}, + "time": &ctx.Command{Name: "time when [begin|end|yestoday|tommorow|monday|sunday|first|last|new|eve] [offset]", + Help: "查看时间, when: 输入的时间戳, 剩余参数是时间偏移", + Form: map[string]int{"time_format": 1, "time_close": 1}, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + t, stamp := time.Now(), true + if len(arg) > 0 { + if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil { + t, stamp, arg = time.Unix(int64(i/int64(m.Confi("time_unit"))), 0), false, arg[1:] + } else if n, e := time.ParseInLocation(m.Confx("time_format"), arg[0], time.Local); e == nil { + t, arg = n, arg[1:] + } else { + for _, v := range []string{"01-02", "2006-01-02", "15:04:05", "15:04"} { + if n, e := time.ParseInLocation(v, arg[0], time.Local); e == nil { + t, arg = n, arg[1:] + break + } + } + } + } + + if len(arg) > 0 { + switch arg[0] { + case "begin": + d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds", t.Hour(), t.Minute(), t.Second())) + m.Assert(e) + t, arg = t.Add(-d), arg[1:] + case "end": + d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds%dns", t.Hour(), t.Minute(), t.Second(), t.Nanosecond())) + m.Assert(e) + t, arg = t.Add(time.Duration(24*time.Hour)-d), arg[1:] + if m.Confx("time_close") == "close" { + t = t.Add(-time.Second) + } + case "yestoday": + t, arg = t.Add(-time.Duration(24*time.Hour)), arg[1:] + case "tomorrow": + t, arg = t.Add(time.Duration(24*time.Hour)), arg[1:] + case "monday": + d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds", int((t.Weekday()-time.Monday+7)%7)*24+t.Hour(), t.Minute(), t.Second())) + m.Assert(e) + t, arg = t.Add(-d), arg[1:] + case "sunday": + d, e := time.ParseDuration(fmt.Sprintf("%dh%dm%ds", int((t.Weekday()-time.Monday+7)%7)*24+t.Hour(), t.Minute(), t.Second())) + m.Assert(e) + t, arg = t.Add(time.Duration(7*24*time.Hour)-d), arg[1:] + if m.Confx("time_close") == "close" { + t = t.Add(-time.Second) + } + case "first": + t, arg = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.Local), arg[1:] + case "last": + month, year := t.Month()+1, t.Year() + if month >= 13 { + month, year = 1, year+1 + } + t, arg = time.Date(year, month, 1, 0, 0, 0, 0, time.Local), arg[1:] + if m.Confx("time_close") == "close" { + t = t.Add(-time.Second) + } + case "new": + t, arg = time.Date(t.Year(), 1, 1, 0, 0, 0, 0, time.Local), arg[1:] + case "eve": + t, arg = time.Date(t.Year()+1, 1, 1, 0, 0, 0, 0, time.Local), arg[1:] + if m.Confx("time_close") == "close" { + t = t.Add(-time.Second) + } + case "": + arg = arg[1:] + } + } + + if len(arg) > 0 { + if d, e := time.ParseDuration(arg[0]); e == nil { + t, arg = t.Add(d), arg[1:] + } + } + + m.Append("datetime", t.Format(m.Confx("time_format"))) + m.Append("timestamp", t.Unix()*int64(m.Confi("time_unit"))) + + if stamp { + m.Echo("%d", t.Unix()*int64(m.Confi("time_unit"))) + } else { + m.Echo(t.Format(m.Confx("time_format"))) + } + }}, + "timer": &ctx.Command{Name: "timer [begin time] [repeat] [order time] time cmd", Help: "定时任务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if cli, ok := c.Server.(*CLI); m.Assert(ok) { + if len(arg) == 0 { // 查看任务列表 + for k, v := range m.Confv("timer").(map[string]interface{}) { + val := v.(map[string]interface{}) + m.Add("append", "key", k) + m.Add("append", "action_time", time.Unix(0, val["action_time"].(int64)/int64(m.Confi("time_unit"))*1000000000).Format(m.Conf("time_format"))) + m.Add("append", "order", val["order"]) + m.Add("append", "time", val["time"]) + m.Add("append", "cmd", val["cmd"]) + m.Add("append", "msg", val["msg"]) + m.Add("append", "results", fmt.Sprintf("%v", val["result"])) + } + m.Table() + return + } + + now := int64(m.Spawn().Cmd("time").Appendi("timestamp")) + begin := now + if len(arg) > 0 && arg[0] == "begin" { + begin, arg = int64(m.Spawn().Cmd("time", arg[1]).Appendi("timestamp")), arg[2:] + } + + repeat := false + if len(arg) > 0 && arg[0] == "repeat" { + repeat, arg = true, arg[1:] + } + + order := "" + if len(arg) > 0 && arg[0] == "order" { + order, arg = arg[1], arg[2:] + } + + action := int64(m.Spawn().Cmd("time", begin, order, arg[0]).Appendi("timestamp")) + + // 创建任务 + hash := m.Sess("aaa").Cmd("md5", arg, now).Result(0) + m.Confv("timer", hash, map[string]interface{}{ + "create_time": now, + "begin_time": begin, + "action_time": action, + "repeat": repeat, + "order": order, + "done": false, + "time": arg[0], + "cmd": arg[1:], + "msg": 0, + "result": "", + }) + + if cli.Timer == nil { // 创建时间队列 + cli.Timer = time.NewTimer((time.Duration)((action - now) / int64(m.Confi("time_unit")) * 1000000000)) + go func() { + for { + select { + case <-cli.Timer.C: + m.Log("info", "timer %s", m.Conf("timer_next")) + if m.Conf("timer_next") == "" { + break + } + timer := m.Confv("timer", m.Conf("timer_next")).(map[string]interface{}) + m.Log("info", "timer %s %v", m.Conf("timer_next"), timer["cmd"]) + + msg := m.Sess("cli").Cmd("source", timer["cmd"]) + timer["result"] = msg.Meta["result"] + timer["msg"] = msg.Code() + + if timer["repeat"].(bool) { + timer["action_time"] = int64(m.Spawn().Cmd("time", timer["action_time"], timer["order"], timer["time"]).Appendi("timestamp")) + } else { + timer["done"] = true + } + cli.schedule(m) + } + } + cli.Timer = nil + }() + } + + // 调度任务 + cli.schedule(m) + m.Echo(hash) + } + }}, }, } diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 939bc03b..4f16bbff 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -1,7 +1,6 @@ package ctx import ( - "encoding/csv" "encoding/json" "errors" "fmt" @@ -1454,6 +1453,7 @@ func (m *Message) Cmd(args ...interface{}) *Message { if m == nil { return m } + if len(args) > 0 { m.Set("detail", Trans(args...)...) } @@ -3050,7 +3050,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", arg, all = arg[1:], true } - action, which, chain := "", "-1", "" + action, which := "", "-1" have := map[string]bool{} if len(arg) > 0 { switch arg[0] { @@ -3066,8 +3066,6 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } case "create", "delete": action, arg = arg[0], arg[1:] - case "parse": - chain, arg = arg[1], arg[2:] } } @@ -3149,9 +3147,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", value = m.Confv(arg[0]) } - msg := m.Spawn() - msg.Put("option", "_cache", value) - msg.Cmd("trans", "_cache", chain) + msg := m.Spawn().Put("option", "_cache", value).Cmd("trans", "_cache") m.Copy(msg, "append").Copy(msg, "result") }}, "cache": &Command{Name: "cache [all] |key [value]|key = value|key name value help|delete key]", @@ -3188,25 +3184,26 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } }}, - "trans": &Command{Name: "trans key index", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) { + "trans": &Command{Name: "trans key [index]", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) { value := m.Data[arg[0]] - if arg[1] != "" { - v := Chain(m, value, arg[1]) - value = v + if len(arg) > 1 && arg[1] != "" { + value = Chain(m, value, arg[1]) } switch val := value.(type) { case map[string]interface{}: for k, v := range val { m.Add("append", "key", k) - switch value := v.(type) { + switch val := v.(type) { + case nil: + m.Add("append", "value", "") case string: - m.Add("append", "value", value) + m.Add("append", "value", val) case float64: - m.Add("append", "value", fmt.Sprintf("%d", int(value))) + m.Add("append", "value", fmt.Sprintf("%d", int(val))) default: - b, _ := json.Marshal(value) - m.Add("append", "value", fmt.Sprintf("%v", string(b))) + b, _ := json.Marshal(val) + m.Add("append", "value", fmt.Sprintf("%s", string(b))) } } m.Sort("key", "str").Table() @@ -3218,9 +3215,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Sort("key", "str").Table() case []interface{}: for i, v := range val { - switch value := v.(type) { + switch val := v.(type) { case map[string]interface{}: - for k, v := range value { + for k, v := range val { switch value := v.(type) { case string: m.Add("append", k, value) @@ -3233,13 +3230,16 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } case string: m.Add("append", "index", i) - m.Add("append", "value", value) + m.Add("append", "value", val) case float64: m.Add("append", "index", i) - m.Add("append", "value", fmt.Sprintf("%v", int(value))) + m.Add("append", "value", fmt.Sprintf("%v", int(val))) + case nil: + m.Add("append", "index", i) + m.Add("append", "value", "") default: m.Add("append", "index", i) - b, _ := json.Marshal(value) + b, _ := json.Marshal(val) m.Add("append", "value", fmt.Sprintf("%v", string(b))) } } @@ -3472,47 +3472,6 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Set("result").Table() }}, - "import": &Command{Name: "import filename", Help: "导入数据", Hand: func(m *Message, c *Context, key string, arg ...string) { - f, e := os.Open(arg[0]) - m.Assert(e) - defer f.Close() - - switch { - case strings.HasSuffix(arg[0], ".json"): - var data interface{} - de := json.NewDecoder(f) - de.Decode(&data) - m.Optionv("data", data) - - switch d := data.(type) { - case []interface{}: - for _, value := range d { - switch val := value.(type) { - case map[string]interface{}: - for k, v := range val { - m.Add("append", k, v) - } - } - } - } - case strings.HasSuffix(arg[0], ".csv"): - r := csv.NewReader(f) - l, e := r.Read() - m.Assert(e) - m.Meta["append"] = l - - for { - l, e := r.Read() - if e != nil { - break - } - for i, v := range l { - m.Add("append", m.Meta["append"][i], v) - } - } - } - m.Table() - }}, }, } diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 4ce2a54a..bfc6b063 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -1084,6 +1084,34 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } m.Set("append").Set("result").Add("append", "directory", name).Echo(name) }}, + "import": &ctx.Command{Name: "import filename [index]", Help: "导入数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + _, f, e := open(m, arg[0]) + m.Assert(e) + defer f.Close() + + switch { + case strings.HasSuffix(arg[0], ".json"): + var data interface{} + de := json.NewDecoder(f) + de.Decode(&data) + + msg := m.Spawn().Put("option", "data", data).Cmd("trans", "data", arg[1:]) + m.Copy(msg, "append").Copy(msg, "result") + case strings.HasSuffix(arg[0], ".csv"): + r := csv.NewReader(f) + + l, e := r.Read() + m.Assert(e) + m.Meta["append"] = l + + for l, e = r.Read(); e != nil; l, e = r.Read() { + for i, v := range l { + m.Add("append", m.Meta["append"][i], v) + } + } + m.Table() + } + }}, "pwd": &ctx.Command{Name: "pwd [all] | [[index] path] ", Help: "工作目录,all: 查看所有, index path: 设置路径, path: 设置当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if len(arg) > 0 && arg[0] == "all" { diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index 75ac9233..58d71682 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -322,6 +322,8 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "body_response": &ctx.Config{Name: "body_response", Value: "response", Help: "响应缓存"}, "multipart_bsize": &ctx.Config{Name: "multipart_bsize", Value: "102400", Help: "缓存大小"}, "brow_home": &ctx.Config{Name: "brow_home", Value: "http://localhost:9094", Help: "浏览服务"}, + "spide": &ctx.Config{Name: "spide", Value: map[string]interface{}{}, Help: "浏览服务"}, + "client_timeout": &ctx.Config{Name: "client_timeout", Value: "100s", Help: "浏览服务"}, "directory": &ctx.Config{Name: "directory", Value: "usr", Help: "服务目录"}, "protocol": &ctx.Config{Name: "protocol", Value: "http", Help: "服务协议"}, @@ -334,6 +336,12 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "login_lark": &ctx.Config{Name: "login_lark", Value: "false", Help: "会话认证"}, "cas_url": &ctx.Config{Name: "cas_url", Value: "", Help: "单点登录"}, + "toolkit": &ctx.Config{Name: "toolkit", Value: map[string]interface{}{ + "time": map[string]interface{}{ + "cmd": "time", + }, + }, Help: "小工具"}, + "library_dir": &ctx.Config{Name: "library_dir", Value: "usr/librarys", Help: "脚本目录"}, "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "模板目录"}, "template_debug": &ctx.Config{Name: "template_debug", Value: "true", Help: "模板调试"}, @@ -415,7 +423,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", }}, "get": &ctx.Command{Name: "get [method GET|POST] url arg...", Help: "访问服务, method: 请求方法, url: 请求地址, arg: 请求参数", - Form: map[string]int{"method": 1, "headers": 2, "content_type": 1, "body": 1, "path_value": 1, "body_response": 1, "parse": 1, "save": 1}, + Form: map[string]int{"method": 1, "headers": 2, "content_type": 1, "body": 1, "path_value": 1, "body_response": 1, "parse": 1, "sub_parse": 3, "save": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { if m.Has("path_value") { @@ -470,10 +478,13 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } if web.Client == nil { - web.Client = &http.Client{} + d, e := time.ParseDuration(m.Conf("client_timeout")) + m.Assert(e) + web.Client = &http.Client{Timeout: d} } res, e := web.Client.Do(req) if e != nil { + m.Log("info", "get error %v", e) return } m.Assert(e) @@ -495,7 +506,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", }() if m.Has("save") { - p := m.Option("save") if !strings.Contains(m.Option("save"), "/") { p = path.Join(m.Sess("nfs").Cmd("pwd").Result(0), m.Option("save")) @@ -512,27 +522,44 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", ct := res.Header.Get("Content-Type") m.Log("info", "content: %s", ct) + switch { case strings.HasPrefix(ct, "application/json"): json.NewDecoder(res.Body).Decode(&result) if m.Has("parse") { - msg := m.Spawn() - msg.Put("option", "response", result) - msg.Cmd("trans", "response", m.Option("parse")) + msg := m.Spawn().Put("option", "data", result).Cmd("trans", "data", m.Option("parse")) m.Copy(msg, "append").Copy(msg, "result") return } b, _ := json.MarshalIndent(result, "", " ") result = string(b) case strings.HasPrefix(ct, "text/html"): - html, e := goquery.NewDocumentFromReader(res.Body) + page, e := goquery.NewDocumentFromReader(res.Body) m.Assert(e) - query := html.Find("html") + + query := page.Find("html") if m.Has("parse") { query = query.Find(m.Option("parse")) } query.Each(func(n int, s *goquery.Selection) { + if m.Options("sub_parse") { + for i := 0; i < len(m.Meta["sub_parse"])-2; i += 3 { + item := s.Find(m.Meta["sub_parse"][i+1]) + if m.Meta["sub_parse"][i+1] == "" { + item = s + } + if v, ok := item.Attr(m.Meta["sub_parse"][i+2]); ok { + m.Add("append", m.Meta["sub_parse"][i], v) + m.Log("info", "item attr %v", v) + } else { + m.Add("append", m.Meta["sub_parse"][i], strings.Replace(item.Text(), "\n", "", -1)) + m.Log("info", "item text %v", item.Text()) + } + } + return + } + s.Find("a").Each(func(n int, s *goquery.Selection) { if attr, ok := s.Attr("href"); ok { s.SetAttr("href", proxy(m, attr)) @@ -551,10 +578,13 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", s.SetAttr("src", proxy(m, attr)) } }) + if html, e := s.Html(); e == nil { m.Add("append", "html", html) } }) + m.Table() + result = "" case strings.HasPrefix(ct, "text"): buf, e := ioutil.ReadAll(res.Body) m.Assert(e) @@ -1024,6 +1054,17 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", } } + if m.Options("toolkit") { + m.Log("what", "waht %v", m.Optionv("toolkit")) + m.Log("what", "waht %v", m.Confv("toolkit")) + if kit, ok := m.Confv("toolkit", m.Option("toolkit")).(map[string]interface{}); ok { + m.Log("what", "waht %v", kit) + msg := m.Sess("cli").Cmd(kit["cmd"], m.Option("argument")) + m.Copy(msg, "append").Copy(msg, "result") + } + return + } + bench_share := "" bench, ok := m.Confv("bench", m.Option("bench")).(map[string]interface{}) if right && !m.Confs("bench_disable") { @@ -1180,6 +1221,101 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", msg := m.Spawn().Cmd("get", strings.TrimPrefix(key, "/proxy/"), arg) m.Copy(msg, "append").Copy(msg, "result") }}, + + "spide": &ctx.Command{Name: "spide", Help: "spide", Form: map[string]int{"fields": 1, "limit": 1, "offset": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if len(arg) == 0 { + for k, v := range m.Confv("spide").(map[string]interface{}) { + val := v.(map[string]interface{}) + m.Add("append", "key", k) + m.Add("append", "limit", val["limit"]) + m.Add("append", "site", val["site"]) + } + m.Sort("key", "str").Table() + return + } + + if len(arg) > 0 && arg[0] == "add" { + m.Confv("spide", arg[1], map[string]interface{}{ + "site": arg[2], + "narg": strings.Count(arg[2], "%s"), + "parse": arg[3], + "sub_parse": arg[4:], + "fields": m.Option("fields"), + "offset": m.Option("offset"), + "limit": m.Option("limit"), + }) + return + } + + spide := m.Confv("spide", arg[0]).(map[string]interface{}) + arg = arg[1:] + + sub_parse := spide["sub_parse"].([]string) + + args := []interface{}{} + for i := 0; i < spide["narg"].(int); i++ { + args = append(args, url.QueryEscape(arg[i])) + } + + msg := m.Spawn().Cmd("get", fmt.Sprintf(spide["site"].(string), args...), + "parse", spide["parse"], sub_parse) + arg = arg[spide["narg"].(int):] + + offset := spide["offset"].(string) + if m.Has("offset") { + offset = m.Option("offset") + } + if len(arg) > 0 { + offset, arg = arg[0], arg[1:] + } + + limit := spide["limit"].(string) + if m.Has("limit") { + limit = m.Option("limit") + } + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + fields := spide["fields"].(string) + if m.Has("fields") { + fields = m.Option("fields") + } + if len(arg) > 0 { + fields, arg = arg[0], arg[1:] + } + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit, "offset", offset, "fields", fields) + + }}, + "12306": &ctx.Command{Name: "12306", Help: "12306", Form: map[string]int{"fields": 1, "limit": 1, "offset": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + date := "2018-12-24" + if len(arg) > 0 { + date, arg = arg[0], arg[1:] + } + to := "QFK" + if len(arg) > 0 { + to, arg = arg[0], arg[1:] + } + from := "BJP" + if len(arg) > 0 { + from, arg = arg[0], arg[1:] + } + m.Echo("%s->%s %s\n", from, to, date) + + msg := m.Spawn().Cmd("get", fmt.Sprintf("https://kyfw.12306.cn/otn/leftTicket/queryX?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT", date, from, to), "parse", "data.result") + for _, v := range msg.Meta["value"] { + fields := strings.Split(v, "|") + m.Add("append", "车次--", fields[3]) + m.Add("append", "出发----", fields[8]) + m.Add("append", "到站----", fields[9]) + m.Add("append", "时长----", fields[10]) + m.Add("append", "二等座", fields[30]) + m.Add("append", "一等座", fields[31]) + } + m.Table() + }}, }, } diff --git a/src/examples/chat/chat.go b/src/examples/chat/chat.go index 1ce5d9ce..4f4557e0 100644 --- a/src/examples/chat/chat.go +++ b/src/examples/chat/chat.go @@ -12,7 +12,16 @@ import ( var Index = &ctx.Context{Name: "chat", Help: "会议中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{ - "chat_msg": &ctx.Config{Name: "chat_msg", Value: []interface{}{}, Help: "聊天记录"}, + "chat_msg": &ctx.Config{Name: "chat_msg", Value: []interface{}{}, Help: "聊天记录"}, + "default": &ctx.Config{Name: "default", Value: "", Help: "聊天记录"}, + "weather_site": &ctx.Config{Name: "weather_site", Value: "http://weather.sina.com.cn", Help: "聊天记录"}, + "calendar_site": &ctx.Config{Name: "calendar_site", Value: "http://tools.2345.com/rili.htm", Help: "聊天记录"}, + "topic_site": &ctx.Config{Name: "topic_site", Value: "https://s.weibo.com/top/summary?cate=realtimehot", Help: "聊天记录"}, + "pedia_site": &ctx.Config{Name: "pedia_site", Value: "https://zh.wikipedia.org/wiki", Help: "聊天记录"}, + "baike_site": &ctx.Config{Name: "baike_site", Value: "https://baike.baidu.com/item", Help: "聊天记录"}, + "sinas_site": &ctx.Config{Name: "sinas_site", Value: "http://www.sina.com.cn/mid/search.shtml?range=all&c=news&q=%s&from=home&ie=utf-8", Help: "聊天记录"}, + "zhihu_site": &ctx.Config{Name: "zhihu_site", Value: "https://www.zhihu.com/search?type=content&q=%s", Help: "聊天记录"}, + "toutiao_site": &ctx.Config{Name: "toutiao_site", Value: "https://www.toutiao.com/search/?keyword=%s", Help: "聊天记录"}, }, Commands: map[string]*ctx.Command{ "/chat": &ctx.Command{Name: "user", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { @@ -34,6 +43,168 @@ var Index = &ctx.Context{Name: "chat", Help: "会议中心", } m.Confv("chat_msg", "-1", data) }}, + "talk": &ctx.Command{Name: "talk", Help: "talk", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if m.Confs("default") { + m.Echo(m.Conf("default")) + } + }}, + "weather": &ctx.Command{Name: "weather where field", Help: "weather", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + where := "beijing" + if len(arg) > 0 { + where, arg = arg[0], arg[1:] + } + + msg := m.Spawn().Cmd("get", fmt.Sprintf("%s/%s", m.Conf("weather_site"), where), + "parse", "div.blk_fc_c0_i", + "sub_parse", "date", "p.wt_fc_c0_i_date", "text", + "sub_parse", "day", "p.wt_fc_c0_i_day", "text", + "sub_parse", "weather", "p.wt_fc_c0_i_icons.clearfix img", "title", + "sub_parse", "temp", "p.wt_fc_c0_i_temp", "text", + "sub_parse", "wind", "p.wt_fc_c0_i_tip", "text", + "sub_parse", "pm", "ul.wt_fc_c0_i_level li.l", "text", + "sub_parse", "env", "ul.wt_fc_c0_i_level li.r", "text", + ) + + m.Copy(msg, "append").Copy(msg, "result") + + if len(arg) == 0 { + arg = append(arg, "temp") + } + + switch arg[0] { + case "all": + case "temp": + m.Cmd("select", "fields", "date day weather temp") + case "wind": + m.Cmd("select", "fields", "date day weather wind") + case "env": + m.Cmd("select", "fields", "date day weather pm env") + default: + m.Cmd("select", "date", arg[0], "vertical") + } + }}, + "calendar": &ctx.Command{Name: "calendar", Help: "calendar", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + msg := m.Spawn().Cmd("get", m.Conf("calendar_site"), + "parse", "div.almanac-hd") + m.Copy(msg, "append").Copy(msg, "result") + }}, + "topic": &ctx.Command{Name: "topic", Help: "topic", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + limit := "10" + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + msg := m.Spawn().Cmd("get", m.Conf("topic_site"), + "parse", "table tr", + "sub_parse", "mark", "td.td-03", "text", + "sub_parse", "count", "td.td-02 span", "text", + "sub_parse", "rank", "td.td-01", "text", + "sub_parse", "topic", "td.td-02 a", "text", + ) + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit) + }}, + "pedia": &ctx.Command{Name: "pedia", Help: "pedia", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + msg := m.Spawn().Cmd("get", fmt.Sprintf("%s/%s", m.Conf("pedia_site"), arg[0]), + "parse", "div.mw-parser-output>p,div.mw-parser-output>ul", + "sub_parse", "content", "", "text", + ) + arg = arg[1:] + + offset := "0" + if len(arg) > 0 { + offset, arg = arg[0], arg[1:] + } + + limit := "3" + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit, "offset", offset) + }}, + "baike": &ctx.Command{Name: "baike", Help: "baike", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + msg := m.Spawn().Cmd("get", fmt.Sprintf("%s/%s", m.Conf("baike_site"), arg[0]), + "parse", "div.mw-body", + "sub_parse", "content", "p", "text", + ) + arg = arg[1:] + + offset := "0" + if len(arg) > 0 { + offset, arg = arg[0], arg[1:] + } + + limit := "3" + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit, "offset", offset) + }}, + "sinas": &ctx.Command{Name: "sinas", Help: "sinas", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + msg := m.Spawn().Cmd("get", fmt.Sprintf(m.Conf("sinas_site"), arg[0]), + "parse", "div.box-result.clearfix", + "sub_parse", "title", "h2", "text", + ) + arg = arg[1:] + + offset := "0" + if len(arg) > 0 { + offset, arg = arg[0], arg[1:] + } + + limit := "3" + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit, "offset", offset) + }}, + "zhihu": &ctx.Command{Name: "zhihu", Help: "zhihu", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + msg := m.Spawn().Cmd("get", fmt.Sprintf(m.Conf("zhihu_site"), arg[0]), + "parse", "div.SearchMain div.Card.SearchResult-Card", + "sub_parse", "title", "", "text", + ) + arg = arg[1:] + + offset := "0" + if len(arg) > 0 { + offset, arg = arg[0], arg[1:] + } + + limit := "3" + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit, "offset", offset) + }}, + "toutiao": &ctx.Command{Name: "toutiao", Help: "toutiao", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + msg := m.Spawn().Cmd("get", fmt.Sprintf(m.Conf("toutiao_site"), arg[0]), + "parse", "div.articleCard", + "sub_parse", "title", "", "text", + ) + arg = arg[1:] + + offset := "0" + if len(arg) > 0 { + offset, arg = arg[0], arg[1:] + } + + limit := "3" + if len(arg) > 0 { + limit, arg = arg[0], arg[1:] + } + + m.Copy(msg, "append").Copy(msg, "result") + m.Cmd("select", "limit", limit, "offset", offset) + }}, }, } diff --git a/src/examples/code/code.go b/src/examples/code/code.go index f06d65ac..6756511a 100644 --- a/src/examples/code/code.go +++ b/src/examples/code/code.go @@ -37,19 +37,19 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", "index": []interface{}{ map[string]interface{}{"componet_name": "head", "template": "head"}, map[string]interface{}{"componet_name": "docker", "componet_help": "docker", "template": "docker"}, - map[string]interface{}{"componet_name": "login", "componet_help": "login", "template": "componet", - "componet_ctx": "aaa", "componet_cmd": "login", "arguments": []interface{}{"@username", "@password"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "username", "label": "username"}, - map[string]interface{}{"type": "password", "name": "password", "label": "password"}, - map[string]interface{}{"type": "button", "value": "login"}, - }, - "display_append": "", "display_result": "", - }, - map[string]interface{}{"componet_name": "userinfo", "componet_help": "userinfo", "template": "componet", - "componet_ctx": "aaa", "componet_cmd": "login", "arguments": []interface{}{"@sessid"}, - "pre_run": true, - }, + // map[string]interface{}{"componet_name": "login", "componet_help": "login", "template": "componet", + // "componet_ctx": "aaa", "componet_cmd": "login", "arguments": []interface{}{"@username", "@password"}, + // "inputs": []interface{}{ + // map[string]interface{}{"type": "text", "name": "username", "label": "username"}, + // map[string]interface{}{"type": "password", "name": "password", "label": "password"}, + // map[string]interface{}{"type": "button", "value": "login"}, + // }, + // "display_append": "", "display_result": "", + // }, + // map[string]interface{}{"componet_name": "userinfo", "componet_help": "userinfo", "template": "componet", + // "componet_ctx": "aaa", "componet_cmd": "login", "arguments": []interface{}{"@sessid"}, + // "pre_run": true, + // }, map[string]interface{}{"componet_name": "clipboard", "componet_help": "clipboard", "template": "clipboard"}, map[string]interface{}{"componet_name": "buffer", "componet_help": "buffer", "template": "componet", "componet_ctx": "cli", "componet_cmd": "tmux", "arguments": []interface{}{"buffer"}, "inputs": []interface{}{ @@ -59,23 +59,23 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", }, "pre_run": true, }, - map[string]interface{}{"componet_name": "time", "componet_help": "time", "template": "componet", - "componet_ctx": "cli", "componet_cmd": "time", "arguments": []interface{}{"@string"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "time_format", - "label": "format", "value": "2006-01-02 15:04:05", - }, - map[string]interface{}{"type": "text", "name": "string", "label": "string"}, - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - }, - map[string]interface{}{"componet_name": "json", "componet_help": "json", "template": "componet", - "componet_ctx": "nfs", "componet_cmd": "json", "arguments": []interface{}{"@string"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "string", "label": "string"}, - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - }, + // map[string]interface{}{"componet_name": "time", "componet_help": "time", "template": "componet", + // "componet_ctx": "cli", "componet_cmd": "time", "arguments": []interface{}{"@string"}, + // "inputs": []interface{}{ + // map[string]interface{}{"type": "text", "name": "time_format", + // "label": "format", "value": "2006-01-02 15:04:05", + // }, + // map[string]interface{}{"type": "text", "name": "string", "label": "string"}, + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // }, + // map[string]interface{}{"componet_name": "json", "componet_help": "json", "template": "componet", + // "componet_ctx": "nfs", "componet_cmd": "json", "arguments": []interface{}{"@string"}, + // "inputs": []interface{}{ + // map[string]interface{}{"type": "text", "name": "string", "label": "string"}, + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // }, map[string]interface{}{"componet_name": "dir", "componet_help": "dir", "template": "componet", "componet_ctx": "nfs", "componet_cmd": "dir", "arguments": []interface{}{"@dir", "dir_sort", "@sort_order", "@sort_field"}, "pre_run": true, "display_result": "", @@ -117,16 +117,16 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", }, "display_result": "", }, - map[string]interface{}{"componet_name": "download", "componet_help": "download", "template": "componet", - "componet_ctx": "cli.shy", "componet_cmd": "source", "arguments": []interface{}{"@cmds"}, - "display_result": "", "download_file": "", - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "download_file", "value": "data_2006_0102_1504.txt", "class": "file_name"}, - map[string]interface{}{"type": "text", "name": "cmds", "value": "", - "class": "file_cmd", "clipstack": "clistack", - }, - }, - }, + // map[string]interface{}{"componet_name": "download", "componet_help": "download", "template": "componet", + // "componet_ctx": "cli.shy", "componet_cmd": "source", "arguments": []interface{}{"@cmds"}, + // "display_result": "", "download_file": "", + // "inputs": []interface{}{ + // map[string]interface{}{"type": "text", "name": "download_file", "value": "data_2006_0102_1504.txt", "class": "file_name"}, + // map[string]interface{}{"type": "text", "name": "cmds", "value": "", + // "class": "file_cmd", "clipstack": "clistack", + // }, + // }, + // }, map[string]interface{}{"componet_name": "command", "componet_help": "command", "template": "componet", "componet_ctx": "cli.shy", "componet_cmd": "source", "arguments": []interface{}{"@cmd"}, "inputs": []interface{}{ @@ -143,50 +143,50 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", map[string]interface{}{"type": "button", "value": "refresh"}, }, }, - map[string]interface{}{"componet_name": "ccc", "componet_help": "ccc", "template": "componet", - "componet_ctx": "cli.shy", "componet_cmd": "context", "arguments": []interface{}{"@current_ctx", "@ccc"}, - "display_result": "", - "inputs": []interface{}{ - map[string]interface{}{"type": "choice", "name": "ccc", - "label": "ccc", "value": "command", "choice": []interface{}{ - map[string]interface{}{"name": "command", "value": "command"}, - map[string]interface{}{"name": "config", "value": "config"}, - map[string]interface{}{"name": "cache", "value": "cache"}, - }, - }, - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - }, - map[string]interface{}{"componet_name": "cmd", "componet_help": "cmd", "template": "componet", - "componet_ctx": "cli.shy", "componet_cmd": "context", "arguments": []interface{}{"@current_ctx", "command", "list"}, - "pre_run": true, "display_result": "", - "inputs": []interface{}{ - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - }, - map[string]interface{}{"componet_name": "history", "componet_help": "history", "template": "componet", - "componet_ctx": "cli", "componet_cmd": "config", "arguments": []interface{}{"source_list"}, - "pre_run": true, "display_result": "", - "inputs": []interface{}{ - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - }, - map[string]interface{}{"componet_name": "develop", "componet_help": "develop", "template": "componet", - "componet_ctx": "web.code", "componet_cmd": "config", "arguments": []interface{}{"counter"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - "pre_run": true, - "display_result": "", - }, - map[string]interface{}{"componet_name": "windows", "componet_help": "windows", "template": "componet", - "componet_ctx": "cli", "componet_cmd": "windows", - "inputs": []interface{}{ - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - "pre_run": true, - "display_result": "", - }, + // map[string]interface{}{"componet_name": "ccc", "componet_help": "ccc", "template": "componet", + // "componet_ctx": "cli.shy", "componet_cmd": "context", "arguments": []interface{}{"@current_ctx", "@ccc"}, + // "display_result": "", + // "inputs": []interface{}{ + // map[string]interface{}{"type": "choice", "name": "ccc", + // "label": "ccc", "value": "command", "choice": []interface{}{ + // map[string]interface{}{"name": "command", "value": "command"}, + // map[string]interface{}{"name": "config", "value": "config"}, + // map[string]interface{}{"name": "cache", "value": "cache"}, + // }, + // }, + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // }, + // map[string]interface{}{"componet_name": "cmd", "componet_help": "cmd", "template": "componet", + // "componet_ctx": "cli.shy", "componet_cmd": "context", "arguments": []interface{}{"@current_ctx", "command", "list"}, + // "pre_run": true, "display_result": "", + // "inputs": []interface{}{ + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // }, + // map[string]interface{}{"componet_name": "history", "componet_help": "history", "template": "componet", + // "componet_ctx": "cli", "componet_cmd": "config", "arguments": []interface{}{"source_list"}, + // "pre_run": true, "display_result": "", + // "inputs": []interface{}{ + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // }, + // map[string]interface{}{"componet_name": "develop", "componet_help": "develop", "template": "componet", + // "componet_ctx": "web.code", "componet_cmd": "config", "arguments": []interface{}{"counter"}, + // "inputs": []interface{}{ + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // "pre_run": true, + // "display_result": "", + // }, + // map[string]interface{}{"componet_name": "windows", "componet_help": "windows", "template": "componet", + // "componet_ctx": "cli", "componet_cmd": "windows", + // "inputs": []interface{}{ + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // "pre_run": true, + // "display_result": "", + // }, map[string]interface{}{"componet_name": "runtime", "componet_help": "runtime", "template": "componet", "componet_ctx": "cli", "componet_cmd": "runtime", "inputs": []interface{}{ @@ -195,14 +195,14 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心", "pre_run": true, "display_result": "", }, - map[string]interface{}{"componet_name": "sysinfo", "componet_help": "sysinfo", "template": "componet", - "componet_ctx": "cli", "componet_cmd": "sysinfo", - "inputs": []interface{}{ - map[string]interface{}{"type": "button", "value": "refresh"}, - }, - "pre_run": true, - "display_result": "", - }, + // map[string]interface{}{"componet_name": "sysinfo", "componet_help": "sysinfo", "template": "componet", + // "componet_ctx": "cli", "componet_cmd": "sysinfo", + // "inputs": []interface{}{ + // map[string]interface{}{"type": "button", "value": "refresh"}, + // }, + // "pre_run": true, + // "display_result": "", + // }, map[string]interface{}{"componet_name": "tail", "template": "tail"}, }, }, Help: "组件列表"}, diff --git a/usr/librarys/code.js b/usr/librarys/code.js index a06c2b2d..3e48fd1e 100644 --- a/usr/librarys/code.js +++ b/usr/librarys/code.js @@ -10,7 +10,7 @@ var code = { ncommand: 1, current_cmd: "", - show_result: true, + show_result: false, show_height: "30px", hide_height: "14px", scroll_x: 50, @@ -105,15 +105,19 @@ function add_sort(append, field, cb) { typeof cb == "function" && cb(event) } - var text = window.getSelection().toString() - if (!text) { - var has = document.querySelector("td.clip") - has && (has.className = "") - target.className = "clip" - text = target.innerText + var has = document.querySelector("td.clip") + has && (has.className = "") + target.className = "clip" + + if (event.shiftKey) { + copy_to_clipboard(target.innerText, false, false) + return } - copy_to_clipboard(text, true, !event.shiftKey) + var text = window.getSelection().toString() + if (text) { + copy_to_clipboard(text, true, !event.shiftKey) + } } } } @@ -222,13 +226,6 @@ function send_command(form, cb) { var result = document.querySelector("code.result."+name+" pre") var append = document.querySelector("table.append."+name) - if (result && msg) { - if (msg["Content-Type"] && msg["Content-Type"].join("") == "text/html") { - append_child(result, "iframe").innerHTML = (msg.result || []).join("") - } else { - result.innerHTML = (msg.result || []).join("") - } - } if (append && msg) { append.innerHTML = "" if (msg.append) { @@ -245,9 +242,20 @@ function send_command(form, cb) { append_child(tr, "td", msg[msg.append[k]][i]) } } + + result && ( result.style.height = code.show_result? "": code.show_height) } } + if (result && msg) { + if (msg["Content-Type"] && msg["Content-Type"].join("") == "text/html") { + append_child(result, "iframe").innerHTML = (msg.result || []).join("") + } else { + result.innerHTML = (msg.result || []).join("") + } + init_result() + } + typeof(cb) == "function" && cb(msg) }) } @@ -363,6 +371,8 @@ function onaction(event, action, arg) { break case "z": shrink_command_result() + var target = document.querySelector("div.workflow>ul>li>ul>li[data-action=shrink_cmd]") + target.className = code.show_result? "": "stick" break case "r": location.reload() @@ -568,6 +578,14 @@ function onaction(event, action, arg) { case "command": check_option(target.form, target) break + case "toolkit": + if (event.key == "Enter") { + context.GET("", {"toolkit": dataset["cmd"], "argument": target.value}, function(msg) { + target.nextElementSibling.innerText = msg.result + event + }) + } + break } } @@ -814,10 +832,13 @@ function init_docker() { save_clipboard(item) return case "create_txt": - copy_to_clipboard(prompt("text")) + var text = prompt("text") + text && copy_to_clipboard(text) return case "shrink_cmd": shrink_command_result() + var target = document.querySelector("div.workflow>ul>li>ul>li[data-action=shrink_cmd]") + target.className = code.show_result? "": "stick" return case "create_cmd": add_command() diff --git a/usr/librarys/context.js b/usr/librarys/context.js index 1d3930e7..82d4465d 100644 --- a/usr/librarys/context.js +++ b/usr/librarys/context.js @@ -297,4 +297,51 @@ function add_sort(append, field, cb) { } } } +function scroll_page(event, page) { + var body = document.querySelector("body") + + switch (event.key) { + case "h": + if (event.ctrlKey) { + window.scrollBy(-page.scroll_x*10, 0) + } else { + window.scrollBy(-page.scroll_x, 0) + } + break + case "H": + window.scrollBy(-body.scrollWidth, 0) + break + case "l": + if (event.ctrlKey) { + window.scrollBy(page.scroll_x*10, 0) + } else { + window.scrollBy(page.scroll_x, 0) + } + break + case "L": + window.scrollBy(body.scrollWidth, 0) + break + case "j": + if (event.ctrlKey) { + window.scrollBy(0, page.scroll_y*10) + } else { + window.scrollBy(0, page.scroll_y) + } + break + case "J": + window.scrollBy(0, body.scrollHeight) + break + case "k": + if (event.ctrlKey) { + window.scrollBy(0, -page.scroll_y*10) + } else { + window.scrollBy(0, -page.scroll_y) + } + break + case "K": + window.scrollBy(0, -body.scrollHeight) + break + } + return +} diff --git a/usr/librarys/wiki.js b/usr/librarys/wiki.js index 34bff23c..f8fe80c5 100644 --- a/usr/librarys/wiki.js +++ b/usr/librarys/wiki.js @@ -13,6 +13,12 @@ var wiki = { height: 40, }, }, + + show_result: false, + show_height: "30px", + hide_height: "14px", + scroll_x: 50, + scroll_y: 50, } function set_layout() { @@ -30,6 +36,9 @@ function set_layout() { } function action(event, cmd) { + var target = event.target + var dataset = target.dataset + switch (cmd) { case "toggle_nav": var nav = document.querySelector("nav") @@ -40,6 +49,11 @@ function action(event, cmd) { var list = event.target.nextElementSibling list.hidden = !list.hidden break + case "scroll": + if (target.tagName == "BODY") { + scroll_page(event, wiki) + } + break } } function init_layout() { diff --git a/usr/template/code/code.tmpl b/usr/template/code/code.tmpl index ef526446..fe6dbb32 100644 --- a/usr/template/code/code.tmpl +++ b/usr/template/code/code.tmpl @@ -45,6 +45,16 @@ div.workflow div.stick, div.workflow li li.stick { background-color:red; } + div.workflow li>label.result{ + background-color:rgba(0,0,0,0.2); + padding:0 5px; + border:2px solid green; + margin-left: 10px; + } + div.workflow li>input { + background-color:rgba(0,0,0,0.2); + } + form.option div { float:left; @@ -168,7 +178,11 @@
  • 命令行