forked from x/ContextOS
add spide
Change-Id: I6ef91687d1d91b652159d5ce20667aba3541683a
This commit is contained in:
parent
b65bacaf72
commit
aff272235a
@ -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)
|
||||
}
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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" {
|
||||
|
@ -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()
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -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: "组件列表"},
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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 @@
|
||||
</li>
|
||||
<li><div>命令行</div>
|
||||
<ul class="cmd">
|
||||
<li data-action="shrink_cmd">+ 折叠命令行(Ctrl+Z)</li>
|
||||
{{range $name, $cmd := conf . "toolkit"}}
|
||||
<li>{{$name}} <input type="text" data-cmd="{{$name}}" onkeyup="onaction(event, 'toolkit')"><label class="result"></label></li>
|
||||
{{end}}
|
||||
|
||||
<li class="stick" data-action="shrink_cmd">+ 折叠命令行(Ctrl+Z)</li>
|
||||
<li data-action="create_cmd">+ 添加命令行(Ctrl+M)</li>
|
||||
{{if $bench}}
|
||||
{{range $index, $cmd := index $bench "commands"}}
|
||||
|
@ -83,6 +83,7 @@ nav>ul>li>ul>li .mono {
|
||||
|
||||
article {
|
||||
float:right;
|
||||
max-width:calc(100% - 40px);
|
||||
}
|
||||
article h2 {
|
||||
cursor:alias;
|
||||
@ -96,6 +97,7 @@ article h4 {
|
||||
|
||||
article table {
|
||||
border-collapse:collapse;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
article table caption {
|
||||
font-weight:bold;
|
||||
@ -129,9 +131,9 @@ article pre {
|
||||
overflow:scroll;
|
||||
padding:5px;
|
||||
border:solid 2px green;
|
||||
border-left:solid 4px green;
|
||||
max-width:800px;
|
||||
margin:0;
|
||||
margin-bottom:10px;
|
||||
font-size:14px;
|
||||
line-height:16px;
|
||||
}
|
||||
@ -142,6 +144,7 @@ article div.number1 {
|
||||
text-align:right;
|
||||
padding:5px 0;
|
||||
border:solid green 2px;
|
||||
margin-bottom:10px;
|
||||
float:left;
|
||||
}
|
||||
article div.number1 div {
|
||||
@ -167,7 +170,7 @@ footer .title {
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body onkeydown="action(event, 'scroll')">
|
||||
{{end}}
|
||||
|
||||
{{define "header"}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user