diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index e2679e6d..b145b17b 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -244,9 +244,20 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", args := []string{} rest := []string{} + exec := true + execexec := false exports := []map[string]string{} for i := 0; i < len(detail); i++ { switch detail[i] { + case "?": + if !ctx.Right(detail[i+1]) { + return + } + i++ + case "??": + exec = false + execexec = execexec || ctx.Right(detail[i+1]) + i++ case "<": pipe := m.Spawn().Cmd("import", detail[i+1]) msg.Copy(pipe, "append") @@ -254,12 +265,36 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", case ">": exports = append(exports, map[string]string{"file": detail[i+1]}) i++ + case ">$": + if i == len(detail)-2 { + exports = append(exports, map[string]string{"cache": detail[i+1], "index": "result"}) + i += 1 + break + } + exports = append(exports, map[string]string{"cache": detail[i+1], "index": detail[i+2]}) + i += 2 + case ">@": + if i == len(detail)-2 { + exports = append(exports, map[string]string{"config": detail[i+1], "index": "result"}) + i += 1 + break + } + exports = append(exports, map[string]string{"config": detail[i+1], "index": detail[i+2]}) + i += 2 case "|": detail, rest = detail[:i], detail[i+1:] + case "%": + rest = append(rest, "select") + detail, rest = detail[:i], append(rest, detail[i+1:]...) default: args = append(args, detail[i]) } } + + if !exec && !execexec { + return + } + detail = args if msg.Cmd(detail); msg.Hand { @@ -270,7 +305,24 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } for _, v := range exports { - m.Spawn().Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"]) + m.Log("info", "export %v", v) + if v["file"] != "" { + m.Spawn().Copy(msg, "option").Copy(msg, "append").Copy(msg, "result").Cmd("export", v["file"]) + } + if v["cache"] != "" { + if v["index"] == "result" { + m.Cap(v["cache"], strings.Join(msg.Meta["result"], "")) + } else { + m.Cap(v["cache"], msg.Append(v["index"])) + } + } + if v["config"] != "" { + if v["index"] == "result" { + m.Conf(v["config"], strings.Join(msg.Meta["result"], "")) + } else { + m.Conf(v["config"], msg.Append(v["index"])) + } + } } if len(rest) > 0 { @@ -298,7 +350,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", case "$": m.Echo(msg.Cap(arg[1])) case "@": - m.Echo(msg.Conf(arg[1])) + value := msg.Option(arg[1]) + if value == "" { + value = msg.Conf(arg[1]) + } + + m.Echo(value) default: m.Echo(arg[0]).Echo(arg[1]) } @@ -551,7 +608,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", yac.Cmd("train", "stm", "echo", "echo", "rep{", "exp", "}") yac.Cmd("train", "stm", "return", "return", "rep{", "exp", "}") - yac.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\|", "\\<", "\\>", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}") + yac.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\?\\?", "\\?", "<", ">$", ">@", ">", "\\|", "%", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}") yac.Cmd("train", "cmd", "cmd", "rep{", "word", "}") yac.Cmd("train", "exe", "exe", "$", "(", "cmd", ")") diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 9ee00de4..5e76e786 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -261,6 +261,42 @@ func Elect(last interface{}, args ...interface{}) string { return "" } +func Array(m *Message, list []string, index int, arg ...interface{}) []string { + m.Log("fuck", "waht %v %v", list, index) + if len(arg) == 0 { + if -1 < index && index < len(list) { + return []string{list[index]} + } + return []string{""} + } + + index = (index+2)%(len(list)+2) - 2 + + str := Trans(arg...) + + if index == -1 { + index, list = 0, append(str, list...) + } else if index == -2 { + index, list = len(list), append(list, str...) + } else { + if index < -2 { + index += len(list) + 2 + } + if index < 0 { + index = 0 + } + + for i := len(list); i < index+len(str); i++ { + list = append(list, "") + } + for i := 0; i < len(str); i++ { + list[index+i] = str[i] + } + } + + return list +} + type Cache struct { Name string Value string @@ -328,6 +364,8 @@ func (c *Context) Spawn(m *Message, name string, help string) *Context { c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...)) } else { c.Register(s, nil) + s.Caches = map[string]*Cache{} + s.Configs = map[string]*Config{} } item := []string{name} @@ -2263,6 +2301,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", "page_offset": &Config{Name: "page_offset", Value: "0", Help: "列表偏移"}, "page_limit": &Config{Name: "page_limit", Value: "10", Help: "列表大小"}, + + "time_layout": &Config{Name: "time_layout", Value: "2006/01/02 15:04:05", Help: "默认时间格式"}, }, Commands: map[string]*Command{ "help": &Command{Name: "help topic", Help: "帮助", Hand: func(m *Message, c *Context, key string, arg ...string) { @@ -2333,7 +2373,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", case "command": for k, v := range msg.Target().Commands { if k == arg[3] { - m.Echo("%s: %s\n %s\n", k, v.Name, v.Help) + m.Echo("%s: %s\n%s\n", k, v.Name, v.Help) } } case "config": @@ -2360,7 +2400,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心", continue } if len(arg) > 1 && k == arg[1] { - m.Echo("%s: %s\n %s\n", k, v.Name, v.Help) + m.Echo("%s: %s\n%s\n", k, v.Name, v.Help) for k, v := range v.Form { m.Echo(" option: %s(%d)\n", k, v) } @@ -2418,17 +2458,10 @@ var Index = &Context{Name: "ctx", Help: "模块中心", }}, - "message": &Command{Name: "message [code] [all]|[cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { - if len(arg) > 0 && arg[0] == "spawn" { - m.Echo("%d", m.Spawn().code) - return - } - msg := m.Search(m.Cap("ps_target"))[0] - if msg != nil { - msg = msg.target.message - } - if msg == nil { - msg = m + "message": &Command{Name: "message [code] [cmd...]", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { + msg := m + if ms := m.Find(m.Cap("ps_target")); ms != nil { + msg = ms } if len(arg) > 0 { @@ -2439,104 +2472,62 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } - all := false - if len(arg) > 0 && arg[0] == "all" { - all, arg = true, arg[1:] - } - - if len(arg) == 0 { - m.Echo("%s\n", msg.Format()) - if len(msg.Meta["option"]) > 0 { - m.Color(31, "option(%d): %v\n", len(msg.Meta["option"]), msg.Meta["option"]) - for _, k := range msg.Meta["option"] { - if v, ok := msg.Data[k]; ok { - m.Echo(" %s: %#v\n", k, v) - } else { - m.Echo(" %s(%d): %v\n", k, len(msg.Meta[k]), msg.Meta[k]) - } - } - } - - m.Color(31, "result(%d): %v\n", len(msg.Meta["result"]), msg.Meta["result"]) - if len(msg.Meta["append"]) > 0 { - m.Color(31, "append(%d): %v\n", len(msg.Meta["append"]), msg.Meta["append"]) - for _, k := range msg.Meta["append"] { - if v, ok := msg.Data[k]; ok { - m.Echo(" %s: %v\n", k, v) - } else { - m.Echo(" %s(%d): %v\n", k, len(msg.Meta[k]), msg.Meta[k]) - } - } - } - - if msg.message != nil { - m.Color(31, "message:\n") - m.Echo(" %s\n", msg.message.Format()) - } - - if len(msg.messages) > 0 { - m.Color(31, "messages(%d):\n", len(msg.messages)) - for i, v := range msg.messages { - if !all { - switch v.target.Name { - case "lex", "yac", "log", "gdb": - continue - } - } - m.Echo(" %d %s\n", i, v.Format()) - } - } - - if len(msg.Sessions) > 0 { - m.Color(31, "sessions(%d):\n", len(msg.Sessions)) - for k, v := range msg.Sessions { - m.Echo(" %s %s\n", k, v.Format()) - } - } - if msg.callback != nil { - m.Color(31, "callback(1): %p\n", msg.callback) - } + if len(arg) > 0 && arg[0] == "spawn" { + sub := msg.Spawn() + m.Echo("%d", sub.code) return } - switch arg[0] { - case "list": - ms := []*Message{msg} - for i := 0; i < len(ms); i++ { - ms = append(ms, ms[i].messages...) - m.Add("append", "code", ms[i].code) - m.Add("append", "msg", fmt.Sprintf("%s->%s: %v", ms[i].source.Name, ms[i].target.Name, ms[i].Meta["detail"])) - } - m.Sort("code", "int") - m.Table() - case "message": - for msg := msg; msg != nil; msg = msg.message { - m.Echo("%s\n", msg.Format()) - } - case "messages": - ms := []*Message{msg} - for i := 0; i < len(ms); i++ { - ms = append(ms, ms[i].messages...) - if ms[i].Instance(m.root.Sess("lex", false), true) || - ms[i].Instance(m.root.Sess("yac", false), true) || - ms[i].Instance(m.root.Sess("log", false), true) || - ms[i].Instance(m.root.Sess("lex", false)) || - ms[i].Instance(m.root.Sess("yac", false)) || - ms[i].Instance(m.root.Sess("log", false)) { - continue - } - m.Echo("%s\n", ms[i].Format()) - } - default: - sub := msg.Spawn().Cmd(arg) - m.Copy(sub, "result").Copy(sub, "append") + if len(arg) > 0 { + msg = msg.Spawn().Cmd(arg) + m.Copy(msg, "append").Copy(msg, "result") + return } + if msg.message != nil { + m.Add("append", "time", msg.message.time.Format("15:04:05")) + m.Add("append", "code", msg.message.code) + m.Add("append", "source", msg.message.source.Name) + m.Add("append", "target", msg.message.target.Name) + if msg.message.Meta != nil { + m.Add("append", "details", fmt.Sprintf("%v", msg.message.Meta["detail"])) + m.Add("append", "options", fmt.Sprintf("%v", msg.message.Meta["option"])) + } else { + m.Add("append", "details", "") + m.Add("append", "options", "") + } + } else { + m.Add("append", "time", "") + m.Add("append", "code", "") + m.Add("append", "source", "") + m.Add("append", "target", "") + m.Add("append", "details", "") + m.Add("append", "options", "") + } + m.Add("append", "time", msg.time.Format("15:04:05")) + m.Add("append", "code", msg.code) + m.Add("append", "source", msg.source.Name) + m.Add("append", "target", msg.target.Name) + m.Add("append", "details", fmt.Sprintf("%v", msg.Meta["detail"])) + m.Add("append", "options", fmt.Sprintf("%v", msg.Meta["option"])) + for _, v := range msg.messages { + m.Add("append", "time", v.time.Format("15:04:05")) + m.Add("append", "code", v.code) + m.Add("append", "source", v.source.Name) + m.Add("append", "target", v.target.Name) + m.Add("append", "details", fmt.Sprintf("%v", v.Meta["detail"])) + m.Add("append", "options", fmt.Sprintf("%v", v.Meta["option"])) + } + m.Table() }}, "detail": &Command{Name: "detail [index] [value...]", Help: "查看或添加参数", Hand: func(m *Message, c *Context, key string, arg ...string) { msg := m.message if len(arg) == 0 { - m.Echo("%v\n", msg.Meta["detail"]) + for i, v := range msg.Meta["detail"] { + m.Add("append", "index", i) + m.Add("append", "value", v) + } + m.Table() return } @@ -2545,42 +2536,70 @@ var Index = &Context{Name: "ctx", Help: "模块中心", index, arg = i, arg[1:] } m.Echo("%s", msg.Detail(index, arg)) - }}, - "option": &Command{Name: "option [key [value...]]", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) { - msg := m.message - if len(arg) == 0 { - keys := []string{} - values := map[string][]string{} - - for msg = msg; msg != nil; msg = msg.message { - for _, k := range msg.Meta["option"] { - if _, ok := values[k]; ok { - continue - } - keys = append(keys, k) - values[k] = msg.Meta[k] - } - } - - sort.Strings(keys) - for _, k := range keys { - m.Echo("%s: %v\n", k, values[k]) - } - return + "option": &Command{Name: "option [all] [key [index] [value...]]", Help: "查看或添加选项", Hand: func(m *Message, c *Context, key string, arg ...string) { + all := false + if len(arg) > 0 && arg[0] == "all" { + all, arg = true, arg[1:] } + index := -100 if len(arg) > 1 { - m.Echo("%s", msg.Option(arg[0], arg[1:])) - } else { - m.Echo("%s", msg.Option(arg[0])) + if i, e := strconv.Atoi(arg[1]); e == nil { + index = i + for i := 1; i < len(arg)-1; i++ { + arg[i] = arg[i+1] + } + arg = arg[:len(arg)-1] + } } + msg := m.message + for msg = msg; msg != nil; msg = msg.message { + for _, k := range msg.Meta["option"] { + if len(arg) == 0 { + m.Add("append", "key", k) + m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k])) + continue + } + + if k != arg[0] { + continue + } + + if len(arg) > 1 { + msg.Meta[k] = Array(m, msg.Meta[k], index, arg[1:]) + m.Echo("%v", msg.Meta[k]) + return + } + + if index != -100 { + m.Echo(Array(m, msg.Meta[k], index)[0]) + return + } + + for i, v := range msg.Meta[k] { + m.Add("append", "index", i) + m.Add("append", "value", v) + } + m.Table() + return + } + + if !all { + break + } + } + m.Table() }}, - "result": &Command{Name: "result [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) { + "result": &Command{Name: "result [index] [value...]", Help: "查看或添加返回值", Hand: func(m *Message, c *Context, key string, arg ...string) { msg := m.message if len(arg) == 0 { - m.Echo("%v\n", msg.Meta["result"]) + for i, v := range msg.Meta["result"] { + m.Add("append", "index", i) + m.Add("append", "value", strings.Replace(v, "\n", "\\n", -1)) + } + m.Table() return } @@ -2589,125 +2608,120 @@ var Index = &Context{Name: "ctx", Help: "模块中心", index, arg = i, arg[1:] } m.Echo("%s", msg.Result(index, arg)) - }}, - "append": &Command{Name: "append [key [value...]]", Help: "查看或添加附加值", Hand: func(m *Message, c *Context, key string, arg ...string) { - msg := m.message - if len(arg) == 0 { - keys := []string{} - values := map[string][]string{} + "append": &Command{Name: "append [all] [key [index] [value...]]", Help: "查看或添加附加值", Hand: func(m *Message, c *Context, key string, arg ...string) { + all := false + if len(arg) > 0 && arg[0] == "all" { + all, arg = true, arg[1:] + } - ms := []*Message{msg} - for i := 0; i < len(ms); i++ { - ms = append(ms, ms[i].messages...) - for _, k := range ms[i].Meta["append"] { - if _, ok := values[k]; ok { - continue - } - - keys = append(keys, k) - values[k] = ms[i].Meta[k] + index := -100 + if len(arg) > 1 { + if i, e := strconv.Atoi(arg[1]); e == nil { + index = i + for i := 1; i < len(arg)-1; i++ { + arg[i] = arg[i+1] } - } - - sort.Strings(keys) - for _, k := range keys { - m.Echo("%s: %v\n", k, values[k]) - } - return - } - - switch arg[0] { - case "ncol": - if msg.Meta != nil && len(msg.Meta["append"]) > 0 { - m.Echo("%d", len(msg.Meta["append"])) - } else { - m.Echo("0") - } - case "nrow": - if msg.Meta != nil && len(msg.Meta["append"]) > 0 { - m.Echo("%d", len(msg.Meta[msg.Meta["append"][0]])) - } else { - m.Echo("0") + arg = arg[:len(arg)-1] } } - m.Echo("%s", msg.Append(arg[0], arg[1:])) + msg := m.message + for msg = msg; msg != nil; msg = msg.message { + for _, k := range msg.Meta["append"] { + if len(arg) == 0 { + m.Add("append", "key", k) + m.Add("append", "value", fmt.Sprintf("%v", msg.Meta[k])) + continue + } + if k != arg[0] { + continue + } + + if len(arg) > 1 { + msg.Meta[k] = Array(m, msg.Meta[k], index, arg[1:]) + m.Echo("%v", msg.Meta[k]) + return + } + + if index != -100 { + m.Echo(Array(m, msg.Meta[k], index)[0]) + return + } + + for i, v := range msg.Meta[k] { + m.Add("append", "index", i) + m.Add("append", "value", v) + } + m.Table() + return + } + + if !all { + break + } + } + m.Table() }}, - "session": &Command{Name: "session [key [cmd...]]", Help: "查看或添加会话", Hand: func(m *Message, c *Context, key string, arg ...string) { - msg := m.message - if len(arg) == 0 { - keys := []string{} - values := map[string]*Message{} - - for msg = msg; msg != nil; msg = msg.message { - for k, v := range msg.Sessions { - if _, ok := values[k]; ok { - continue - } - keys = append(keys, k) - values[k] = v - } - } - sort.Strings(keys) - for _, k := range keys { - m.Echo("%s: %s\n", k, values[k].Format()) - - } - return + "session": &Command{Name: "session [all] [key [module]]", Help: "查看或添加会话", Hand: func(m *Message, c *Context, key string, arg ...string) { + all := false + if len(arg) > 0 && arg[0] == "all" { + all, arg = true, arg[1:] } - if len(arg) == 1 { - for msg = msg; msg != nil; msg = msg.message { - for k, v := range msg.Sessions { + msg := m.message + for msg = msg; msg != nil; msg = msg.message { + for k, v := range msg.Sessions { + if len(arg) > 1 { + msg.Sessions[arg[0]] = msg.Find(arg[1]) + return + } else if len(arg) > 0 { if k == arg[0] { m.Echo("%d", v.code) return } + continue } + + m.Add("append", "key", k) + m.Add("append", "time", v.time.Format("15:04:05")) + m.Add("append", "code", v.code) + m.Add("append", "source", v.source.Name) + m.Add("append", "target", v.target.Name) + m.Add("append", "details", fmt.Sprintf("%v", v.Meta["detail"])) + m.Add("append", "options", fmt.Sprintf("%v", v.Meta["option"])) } - return - } - sub := msg - root := m.Confx("search_root", arg, 3) - switch m.Confx("search_method", arg, 2) { - case "find": - sub = msg.Find(arg[1], Right(root)) - case "search": - sub = msg.Search(arg[1], Right(root))[0] - default: - sub = nil + if len(arg) == 0 && !all { + break + } } - if msg.Sessions == nil { - msg.Sessions = map[string]*Message{} - } - if sub != nil { - msg.Sessions[arg[0]] = sub - } - + m.Table() }}, "callback": &Command{Name: "callback", Help: "查看消息", Hand: func(m *Message, c *Context, key string, arg ...string) { msg := m.message - if len(arg) == 0 { - for msg := msg; msg != nil; msg = msg.message { - m.Echo("%d: %p\n", msg.code, msg.callback) - } + for msg := msg; msg != nil; msg = msg.message { + m.Add("append", "msg", msg.code) + m.Add("append", "fun", msg.callback) } - + m.Table() }}, - "context": &Command{ - Name: "context [[find [root|home]|search [root|home] [name|help] [magic|rand|first|last]] name] [list|info|cache|config|command|switch] [args]", - Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块,args:启动参数", + "context": &Command{Name: "context [find|search] [root|back|home] [first|last|rand|magic] [module] [cmd|switch|list|spawn|start|close]", + Help: "查找并操作模块;\n查找方法, find: 精确查找, search: 模糊搜索;\n查找起点, root: 根模块, back: 父模块, home: 本模块;\n过滤结果, first: 取第一个, last: 取最后一个, rand: 随机选择, magic: 智能选择;\n操作方法, cmd: 执行命令, switch: 切换为当前, list: 查看所有子模块, spwan: 创建子模块并初始化, start: 启动模块, close: 结束模块", Hand: func(m *Message, c *Context, key string, arg ...string) { - action := m.Conf("search_action") + if len(arg) == 1 && arg[0] == "~" && m.target.context != nil { + m.target = m.target.context + return + } + + action := "switch" if len(arg) == 0 { action = "list" } - method := m.Conf("search_method") + method := "search" if len(arg) > 0 { switch arg[0] { case "find", "search": @@ -2715,13 +2729,18 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } } - root := m.Confs("search_root") + root := true if len(arg) > 0 { switch arg[0] { case "root": root, arg = true, arg[1:] case "home": root, arg = false, arg[1:] + case "back": + root, arg = false, arg[1:] + if m.target.context != nil { + m.target = m.target.context + } } } @@ -2733,366 +2752,214 @@ var Index = &Context{Name: "ctx", Help: "模块中心", ms, arg = append(ms, msg), arg[1:] } case "search": - choice := m.Conf("search_choice") - switch arg[0] { - case "magic", "rand", "first", "last": - choice, arg = arg[0], arg[1:] + msg := m.Search(arg[0], root) + if len(msg) > 1 || msg[0] != nil { + if len(arg) > 1 { + switch arg[1] { + case "first": + ms, arg = append(ms, msg[0]), arg[2:] + case "last": + ms, arg = append(ms, msg[len(msg)-1]), arg[2:] + case "rand": + ms, arg = append(ms, msg[rand.Intn(len(msg))]), arg[2:] + case "magic": + ms, arg = append(ms, msg...), arg[2:] + default: + ms, arg = append(ms, msg[0]), arg[1:] + } + } else { + ms, arg = append(ms, msg[0]), arg[1:] + } } - if s := m.Search(arg[0], root); len(s) > 0 && s[0] != nil { - switch choice { - case "first": - ms = append(ms, s[0]) - case "last": - ms = append(ms, s[len(s)-1]) - case "rand": - ms = append(ms, s[rand.Intn(len(s))]) - case "magic": - ms = append(ms, s...) - } - arg = arg[1:] - } } - } else { + } + + if len(ms) == 0 { ms = append(ms, m) } - if len(arg) == 0 { - arg = []string{action} + if len(arg) > 0 { + switch arg[0] { + case "switch", "list", "spawn", "start", "close": + action, arg = arg[0], arg[1:] + default: + action = "cmd" + } } for _, msg := range ms { - switch arg[0] { + if msg == nil { + continue + } + + switch action { + case "cmd": + msg.Cmd(arg) + m.Copy(msg, "append").Copy(msg, "result") case "switch": m.target = msg.target case "list": - which := "" - if len(arg) > 1 { - which = arg[1] - } - switch which { - case "cache": - keys := []string{} - for k, _ := range msg.target.Caches { - keys = append(keys, k) + msg.Travel(func(msg *Message, n int) bool { + m.Add("append", "name", msg.target.Name) + if msg.target.context != nil { + m.Add("append", "ctx", msg.target.context.Name) + } else { + m.Add("append", "ctx", "") } - sort.Strings(keys) - for _, k := range keys { - v := msg.target.Caches[k] - m.Add("append", "key", k) - m.Add("append", "name", v.Name) - m.Add("append", "value", v.Value) - m.Add("append", "help", v.Help) - - } - case "config": - keys := []string{} - for k, _ := range msg.target.Configs { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - v := msg.target.Configs[k] - m.Add("append", "key", k) - m.Add("append", "name", v.Name) - m.Add("append", "value", v.Value) - m.Add("append", "help", v.Help) - } - case "command": - keys := []string{} - for k, _ := range msg.target.Commands { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - v := msg.target.Commands[k] - m.Add("append", "key", k) - m.Add("append", "name", v.Name) - m.Add("append", "help", v.Help) - } - case "module": - m.Travel(func(msg *Message, i int) bool { - m.Add("append", "name", msg.target.Name) - m.Add("append", "help", msg.target.Help) - m.Add("append", "module", msg.Cap("module")) - m.Add("append", "status", msg.Cap("status")) - m.Add("append", "stream", msg.Cap("stream")) - return true - }, msg.target) - case "domain": - m.Find("ssh", true).Travel(func(msg *Message, i int) bool { - m.Add("append", "name", msg.target.Name) - m.Add("append", "help", msg.target.Help) - m.Add("append", "domain", msg.Cap("domain")+"."+msg.Conf("domains")) - return true - }) - default: - msg.Travel(func(msg *Message, i int) bool { - m.Add("append", "name", msg.target.Name) - if msg.target.context != nil { - m.Add("append", "context", msg.target.context.Name) - } else { - m.Add("append", "context", "") - } - if msg.target.message != nil { - m.Add("append", "message", msg.target.message.code) - } else { - m.Add("append", "message", "") - } - - m.Add("append", "status", msg.Cap("status")) - m.Add("append", "stream", msg.Cap("stream")) - m.Add("append", "help", msg.target.Help) - return true - }) - - m.Table() - } - default: - msg.Cmd(arg) - m.Meta["result"] = append(m.Meta["result"], msg.Meta["result"]...) - m.Copy(msg, "append") - // m.target = msg.target - } - } - - }}, - "server": &Command{ - Name: "server [spawn|begin|start|close][args]", - Help: "查看、新建、初始化、启动、停止服务", - Hand: func(m *Message, c *Context, key string, arg ...string) { - switch len(arg) { - case 0: - m.Travel(func(m *Message, i int) bool { - if m.Cap("status") == "start" { - m.Echo("%s(%s): %s\n", m.Cap("module"), m.Cap("stream"), m.target.Help) - } - return true - }, m.target.root) - - default: - switch arg[0] { + m.Add("append", "msg", msg.target.message.code) + m.Add("append", "status", msg.Cap("status")) + m.Add("append", "stream", msg.Cap("stream")) + m.Add("append", "help", msg.target.Help) + return true + }) case "spawn": - if len(arg) > 2 { - msg := m.Spawn().Set("detail", arg[3:]...) - msg.target.Spawn(msg, arg[1], arg[2]) - m.target = msg.target - } - case "begin": - msg := m.Spawn().Set("detail", arg...) - msg.target.Begin(msg) + msg.target.Spawn(msg, arg[0], arg[1]).Begin(msg, arg[2:]...) + m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") case "start": - msg := m.Spawn().Set("detail", arg...) - msg.target.Start(msg) + msg.target.Start(msg, arg...) + m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") case "close": - msg := m.Spawn().Set("detail", arg...) - m.target = msg.target.context - msg.target.Close(msg) + msg.target.Close(msg, arg...) } } - }}, - "command": &Command{ - Name: "command [all|add cmd arg...|list [begin [end]]|test [begin [end]]|delete cmd]", - Help: []string{ - "查看或修改命令", - "list_export filename", - }, - Form: map[string]int{ - "list_name": 1, - "list_help": 1, - "list_cache": 2, - "list_index": 1, - "condition": -1, - "list_export": 1, - }, - Hand: func(m *Message, c *Context, key string, arg ...string) { - if len(arg) == 0 { - keys := []string{} - for k, _ := range m.target.Commands { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - m.Echo("%s: %s\n", k, m.target.Commands[k].Name) - } - return + if action == "list" { + m.Table() } - switch arg[0] { - case "all": - keys := []string{} - values := map[string]*Command{} - for s := m.target; s != nil; s = s.context { - for k, v := range s.Commands { - if _, ok := values[k]; !ok { - keys = append(keys, k) - values[k] = v + }}, + "command": &Command{Name: "command [all] [show]|[list [begin [end]] [prefix] test [key val]...]|[add [list_name name] [list_help help] cmd...]|[delete cmd]", + Help: "查看或修改命令, show: 查看命令;\nlist: 查看列表命令, begin: 起始索引, end: 截止索引, prefix: 过滤前缀, test: 执行命令;\nadd: 添加命令, list_name: 命令别名, list_help: 命令帮助;\ndelete: 删除命令", + Hand: func(m *Message, c *Context, key string, arg ...string) { + all := false + if len(arg) > 0 && arg[0] == "all" { + all, arg = true, arg[1:] + } + + action := "show" + if len(arg) > 0 { + switch arg[0] { + case "show", "list", "add", "delete": + action, arg = arg[0], arg[1:] + } + } + + switch action { + case "show": + m.BackTrace(func(m *Message) bool { + for k, v := range m.target.Commands { + if len(arg) > 0 { + if k == arg[0] { + m.Add("append", "key", k) + m.Add("append", "name", v.Name) + m.Add("append", "help", v.Name) + } + } else { + m.Add("append", "key", k) + m.Add("append", "name", v.Name) + } + } + + return all + }) + m.Table() + case "list": + begin, end := 0, m.Capi("list_count") + if len(arg) > 0 { + if n, e := strconv.Atoi(arg[0]); e == nil { + begin, arg = n, arg[1:] + } + } + if len(arg) > 0 { + if n, e := strconv.Atoi(arg[0]); e == nil { + end, arg = n, arg[1:] + } + } + prefix := "" + if len(arg) > 0 && arg[0] != "test" { + prefix, arg = arg[0], arg[1:] + } + + test := false + if len(arg) > 0 && arg[0] == "test" { + test, arg = true, arg[1:] + for i := 0; i < len(arg)-1; i += 2 { + m.Add("option", arg[i], arg[i+1]) + } + } + + for i := begin; i < end; i++ { + index := fmt.Sprintf("%d", i) + if c, ok := m.target.Commands[index]; ok { + if prefix != "" && !strings.HasPrefix(c.Help.(string), prefix) { + continue + } + + if test { + msg := m.Spawn().Cmd(index) + m.Add("append", "index", i) + m.Add("append", "help", c.Help) + m.Add("append", "msg", msg.messages[0].code) + m.Add("append", "res", msg.Result(0)) + } else { + m.Add("append", "index", i) + m.Add("append", "command", fmt.Sprintf("%s: %s", c.Help, strings.Replace(c.Name, "\n", "\\n", -1))) } } } - sort.Strings(keys) - for _, k := range keys { - m.Echo("%s: %s\n", k, values[k].Name) - } - return + m.Table() case "add": if m.target.Caches == nil { m.target.Caches = map[string]*Cache{} } if _, ok := m.target.Caches["list_count"]; !ok { m.target.Caches["list_count"] = &Cache{Name: "list_count", Value: "0", Help: "list_count"} - m.target.Caches["list_begin"] = &Cache{Name: "list_begin", Value: "0", Help: "list_begin"} } - if m.target.Commands == nil { m.target.Commands = map[string]*Command{} } - cache_name := "" - cache_index := "" - if m.Has("list_cache") { - cache_name = m.Meta["list_cache"][0] - cache_index = m.Meta["list_cache"][1] - m.Cap(cache_name, cache_name, "", cache_index) + + list_name, list_help := "", "list_cmd" + if len(arg) > 1 && arg[0] == "list_name" { + list_name, arg = arg[1], arg[2:] + } + if len(arg) > 1 && arg[0] == "list_help" { + list_help, arg = arg[1], arg[2:] } - list_index := 0 - if m.Has("list_index") { - if m.Option("list_index") == "_" { - list_index = -1 - } else { - list_index = m.Optioni("list_index") - } - } - - m.target.Commands[m.Cap("list_count")] = &Command{ - Name: strings.Join(arg[1:], " "), - Help: m.Confx("list_help"), - Hand: func(cmd *Message, c *Context, key string, args ...string) { - li := list_index - if li == -1 { + m.target.Commands[m.Cap("list_count")] = &Command{Name: strings.Join(arg, " "), Help: list_help, Hand: func(cmd *Message, c *Context, key string, args ...string) { + list := []string{} + for _, v := range arg { + if v == "_" { if len(args) > 0 { - if i, e := strconv.Atoi(args[0]); e == nil { - li, args = i, args[1:] - } + v, args = args[0], args[1:] + } else { + v = "''" } - } - list := []string{} - j := 0 - for i := 1; i < len(arg); i++ { - if arg[i] == "_" && cmd.Assert(j < len(args)) { - list = append(list, args[j]) - j++ + } else if v == "__" { + if len(args) > 0 { + v, args = args[0], args[1:] + } else { continue } - list = append(list, arg[i]) } - list = append(list, args[j:]...) + list = append(list, v) + } - msg := cmd.Spawn().Cmd(list) - if len(msg.Meta["append"]) > 0 { - for i, _ := range msg.Meta[msg.Meta["append"][0]] { - cmd.Add("append", "index", i) - } - } - if cache_name != "" && li > -1 { - // cmd.Echo(cmd.Cap(cache_name, msg.Meta[cache_index][li])) - cmd.Echo(cmd.Cap(cache_name, fmt.Sprint(msg.Confv(cmd.Confx("body_response"), cache_index)))) - } else { - cmd.Copy(msg, "result").Copy(msg, "append") - if m.Has("list_export") { - export := cmd.Spawn() - export.Copy(cmd, "option").Copy(cmd, "append") - export.Cmd("export", m.Option("list_export")) - } - } - }, + msg := cmd.Sess("cli").Cmd("source", strings.Join(list, " ")) + cmd.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") + }} + + if list_name != "" { + m.target.Commands[list_name] = m.target.Commands[m.Cap("list_count")] } - - if m.Has("list_name") { - m.target.Commands[m.Option("list_name")] = m.target.Commands[m.Cap("list_count")] - } - m.Capi("list_count", 1) - return - case "list": - if m.Cap("list_begin") == "" { - return - } - begin, end := m.Capi("list_begin"), m.Capi("list_count") - if len(arg) > 1 { - n, e := strconv.Atoi(arg[1]) - if e != nil { - return - } - m.Assert(e) - begin = n - } - if len(arg) > 2 { - n, e := strconv.Atoi(arg[2]) - if e != nil { - return - } - m.Assert(e) - end = n - } - for i := begin; i < end; i++ { - if c, ok := m.target.Commands[fmt.Sprintf("%d", i)]; ok { - m.Echo("%d(%s): %s\n", i, c.Help, strings.Replace(c.Name, "\n", " ", -1)) - } - } - return - case "test": - begin, end := 0, m.Capi("list_count") - if len(arg) > 1 { - n, e := strconv.Atoi(arg[1]) - m.Assert(e) - begin = n - } - if len(arg) > 2 { - n, e := strconv.Atoi(arg[2]) - m.Assert(e) - end = n - } - - success, failure := 0, 0 - for i := begin; i < end; i++ { - key := fmt.Sprintf("%d", i) - if c, ok := m.target.Commands[key]; ok { - msg := m.Spawn().Cmd(key) - if m.Options("condition") { - done := true - condition := m.Meta["condition"] - for j := 0; j < len(condition)-1; j += 2 { - if !msg.Has(condition[j]) || msg.Append(condition[j]) != condition[j+1] { - m.Color(31, "%s %s %s\n", key, " fail", c.Name) - done = false - failure++ - } - } - if done { - // m.Echo("%s %s\n", key, " done") - m.Echo("%s %s %s\n", key, " done", c.Name) - success++ - } - } else { - for _, v := range msg.Meta["result"] { - m.Echo("%v", v) - } - m.Echo("\n") - success++ - } - } - } - m.Color(32, "success: %d, ", success) - m.Color(31, "failure: %d, ", failure) - m.Color(33, "total: %d", success+failure) - return case "delete": - if _, ok := m.target.Commands[arg[1]]; ok { - delete(m.target.Commands, arg[1]) - } + m.BackTrace(func(m *Message) bool { + delete(m.target.Commands, arg[0]) + return all + }) } - }}, "config": &Command{Name: "config [all] [export key..] [save|load file key...] [create map|list|string key name help] [delete key]", Help: "配置管理, export: 导出配置, save: 保存配置到文件, load: 从文件加载配置, create: 创建配置, delete: 删除配置", @@ -3216,8 +3083,19 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Sort("key", "str").Table() case []interface{}: for i, v := range val { - m.Add("append", "index", i) - m.Add("append", "value", v) + switch value := v.(type) { + case map[string]interface{}: + for k, v := range value { + m.Add("append", k, v) + } + case map[string]string: + for k, v := range value { + m.Add("append", k, v) + } + default: + m.Add("append", "index", i) + m.Add("append", "value", v) + } } m.Table() case []string: @@ -3230,37 +3108,39 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Echo("%v", value) } }}, - "cache": &Command{Name: "cache [all] |key [value]|key = value|key name value help|delete key]", Help: "查看、读写、赋值、新建、删除缓存变量", Hand: func(m *Message, c *Context, key string, arg ...string) { - all := false - if len(arg) > 0 && arg[0] == "all" { - arg, all = arg[1:], true - } + "cache": &Command{Name: "cache [all] |key [value]|key = value|key name value help|delete key]", + Help: "查看、读写、赋值、新建、删除缓存变量", + Hand: func(m *Message, c *Context, key string, arg ...string) { + all := false + if len(arg) > 0 && arg[0] == "all" { + arg, all = arg[1:], true + } - switch len(arg) { - case 0: - m.BackTrace(func(m *Message) bool { - for k, v := range m.target.Caches { - m.Add("append", "key", k) - m.Add("append", "value", m.Cap(k)) - m.Add("append", "name", v.Name) + switch len(arg) { + case 0: + m.BackTrace(func(m *Message) bool { + for k, v := range m.target.Caches { + m.Add("append", "key", k) + m.Add("append", "value", m.Cap(k)) + m.Add("append", "name", v.Name) + } + return all + }) + m.Sort("key", "str").Table() + return + case 2: + if arg[0] == "delete" { + delete(m.target.Caches, arg[1]) + return } - return all - }) - m.Sort("key", "str").Table() - return - case 2: - if arg[0] == "delete" { - delete(m.target.Caches, arg[1]) + m.Cap(arg[0], arg[1]) + case 3: + m.Cap(arg[0], arg[0], arg[2], arg[0]) + default: + m.Echo(m.Cap(arg[0], arg[1:]...)) return } - m.Cap(arg[0], arg[1]) - case 3: - m.Cap(arg[0], arg[0], arg[2], arg[0]) - default: - m.Echo(m.Cap(arg[0], arg[1:]...)) - return - } - }}, + }}, "trans": &Command{Name: "trans key index", Help: "数据转换", Hand: func(m *Message, c *Context, key string, arg ...string) { value := m.Data[(arg[0])] @@ -3309,77 +3189,99 @@ var Index = &Context{Name: "ctx", Help: "模块中心", m.Echo("%v", val) } }}, - "select": &Command{Name: "select key value", Form: map[string]int{"parse": 2, "order": 2, "limit": 1, "offset": 1, "vertical": 0}, Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) { - msg := m.Spawn() + "select": &Command{Name: "select key value field", + Form: map[string]int{"parse": 2, "order": 2, "limit": 1, "offset": 1, "fields": 1, "format": 2, "vertical": 0}, + Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) { + msg := m.Spawn() - nrow := len(m.Meta[m.Meta["append"][0]]) - for i := 0; i < nrow; i++ { - if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) { - for _, k := range m.Meta["append"] { - if m.Has("parse") && m.Option("parse") == k { - var value interface{} - m.Assert(json.Unmarshal([]byte(m.Meta[k][i]), &value)) - if m.Meta["parse"][1] != "" { - value = Chain(m, value, m.Meta["parse"][1]) - } - - switch val := value.(type) { - case map[string]interface{}: - for k, v := range val { - msg.Add("append", k, v) + nrow := len(m.Meta[m.Meta["append"][0]]) + for i := 0; i < nrow; i++ { + if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) { + for _, k := range m.Meta["append"] { + if m.Has("parse") && m.Option("parse") == k { + var value interface{} + m.Assert(json.Unmarshal([]byte(m.Meta[k][i]), &value)) + if m.Meta["parse"][1] != "" { + value = Chain(m, value, m.Meta["parse"][1]) } - case []interface{}: - default: + + switch val := value.(type) { + case map[string]interface{}: + for k, v := range val { + msg.Add("append", k, v) + } + case []interface{}: + default: + } + } else { + msg.Add("append", k, m.Meta[k][i]) } - } else { - msg.Add("append", k, m.Meta[k][i]) } } } - } - if m.Set("append").Copy(msg, "append"); m.Has("order") { - m.Sort(m.Option("order"), m.Meta["order"][1]) - } + if m.Set("append").Copy(msg, "append"); m.Has("order") { + m.Sort(m.Meta["order"][1], m.Option("order")) + } - offset := 0 - limit := 10 - if m.Has("limit") { - limit = m.Optioni("limit") - } - if m.Has("offset") { - offset = m.Optioni("offset") - } - nrow = len(m.Meta[m.Meta["append"][0]]) - if offset > nrow { - offset = nrow - } - if limit+offset > nrow { - limit = nrow - offset - } - for _, k := range m.Meta["append"] { - m.Meta[k] = m.Meta[k][offset : offset+limit] - } + offset := 0 + limit := 10 + if m.Has("limit") { + limit = m.Optioni("limit") + } + if m.Has("offset") { + offset = m.Optioni("offset") + } + nrow = len(m.Meta[m.Meta["append"][0]]) + if offset > nrow { + offset = nrow + } + if limit+offset > nrow { + limit = nrow - offset + } + for _, k := range m.Meta["append"] { + m.Meta[k] = m.Meta[k][offset : offset+limit] + } - if m.Has("vertical") { - msg := m.Spawn() - nrow := len(m.Meta[m.Meta["append"][0]]) - sort.Strings(m.Meta["append"]) - msg.Add("append", "field", "") - msg.Add("append", "value", "") - for i := 0; i < nrow; i++ { - for _, k := range m.Meta["append"] { - msg.Add("append", "field", k) - msg.Add("append", "value", m.Meta[k][i]) + if m.Option("fields") != "" { + msg = m.Spawn() + msg.Copy(m, "append", strings.Split(m.Option("fields"), " ")...) + m.Set("append").Copy(msg, "append") + } + + for i := 0; i < len(m.Meta["format"])-1; i += 2 { + format := m.Meta["format"] + for j, v := range m.Meta[format[i]] { + m.Meta[format[i]][j] = fmt.Sprintf(format[i+1], v) } + } + + if m.Has("vertical") { + msg := m.Spawn() + nrow := len(m.Meta[m.Meta["append"][0]]) + sort.Strings(m.Meta["append"]) msg.Add("append", "field", "") msg.Add("append", "value", "") + for i := 0; i < nrow; i++ { + for _, k := range m.Meta["append"] { + msg.Add("append", "field", k) + msg.Add("append", "value", m.Meta[k][i]) + } + msg.Add("append", "field", "") + msg.Add("append", "value", "") + } + m.Set("append").Copy(msg, "append") } - m.Set("append").Copy(msg, "append") - } - m.Table() - }}, + if len(arg) > 2 { + if len(m.Meta[arg[2]]) > 0 { + m.Echo(m.Meta[arg[2]][0]) + } + return + } + + m.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) diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index e34cd992..beb2c394 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -27,9 +27,10 @@ type MUX interface { } type WEB struct { *http.Client + + *http.Server *http.ServeMux - server *http.Server - template *template.Template + *template.Template *ctx.Context } @@ -173,16 +174,24 @@ func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { web.Configs["root_index"] = &ctx.Config{Name: "root_index", Value: "/render", Help: "默认路由"} web.Configs["logheaders"] = &ctx.Config{Name: "logheaders(yes/no)", Value: "no", Help: "日志输出报文头"} + web.Configs["template_sub"] = &ctx.Config{Name: "template_sub", Value: web.Context.Name, Help: "模板文件"} + web.Caches["directory"] = &ctx.Cache{Name: "directory", Value: m.Confx("directory", arg, 0), Help: "服务目录"} web.Caches["route"] = &ctx.Cache{Name: "route", Value: "/" + web.Context.Name + "/", Help: "模块路由"} web.Caches["register"] = &ctx.Cache{Name: "register(yes/no)", Value: "no", Help: "是否已初始化"} web.Caches["master"] = &ctx.Cache{Name: "master(yes/no)", Value: "no", Help: "服务入口"} + web.ServeMux = http.NewServeMux() + web.Template = template.New("render").Funcs(ctx.CGI) + web.Template.ParseGlob(path.Join(m.Conf("template_dir"), "/*.tmpl")) + web.Template.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("template_sub"), "/*.tmpl")) return web } func (web *WEB) Start(m *ctx.Message, arg ...string) bool { m.Cap("directory", m.Confx("directory", arg, 0)) + render := m.Target().Commands["/render"] + m.Travel(func(m *ctx.Message, i int) bool { if h, ok := m.Target().Server.(MUX); ok && m.Cap("register") == "no" { m.Cap("register", "yes") @@ -193,10 +202,15 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { s.Handle(m.Cap("route"), http.StripPrefix(path.Dir(m.Cap("route")), h)) } + if m.Target().Commands["/render"] == nil { + m.Target().Commands["/render"] = render + } + + msg := m.Target().Message() for k, x := range m.Target().Commands { if k[0] == '/' { m.Log("info", "route: %s", k) - h.HandleCmd(m, k, x) + h.HandleCmd(msg, k, x) m.Capi("nroute", 1) } } @@ -209,19 +223,23 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { return true }) + if len(arg) == 0 { + return false + } + web.Caches["protocol"] = &ctx.Cache{Name: "protocol", Value: m.Confx("protocol", arg, 2), Help: "服务协议"} web.Caches["address"] = &ctx.Cache{Name: "address", Value: m.Confx("address", arg, 1), Help: "服务地址"} m.Log("info", "%d %s://%s", m.Capi("nserve", 1), m.Cap("protocol"), m.Cap("stream", m.Cap("address"))) - web.server = &http.Server{Addr: m.Cap("address"), Handler: web} + web.Server = &http.Server{Addr: m.Cap("address"), Handler: web} if m.Caps("master", true); m.Cap("protocol") == "https" { web.Caches["cert"] = &ctx.Cache{Name: "cert", Value: m.Confx("cert", arg, 3), Help: "服务证书"} web.Caches["key"] = &ctx.Cache{Name: "key", Value: m.Confx("key", arg, 4), Help: "服务密钥"} m.Log("info", "cert [%s]", m.Cap("cert")) m.Log("info", "key [%s]", m.Cap("key")) - web.server.ListenAndServeTLS(m.Cap("cert"), m.Cap("key")) + web.Server.ListenAndServeTLS(m.Cap("cert"), m.Cap("key")) } else { - web.server.ListenAndServe() + web.Server.ListenAndServe() } return true } @@ -250,51 +268,15 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "cert": &ctx.Config{Name: "cert", Value: "etc/cert.pem", Help: "路由数量"}, "key": &ctx.Config{Name: "key", Value: "etc/key.pem", Help: "路由数量"}, - "web_site": &ctx.Config{Name: "web_site", Value: []interface{}{ - map[string]interface{}{"_name": "MDN", "site": "https://developer.mozilla.org"}, - map[string]interface{}{"_name": "github", "site": "https://github.com"}, - }, Help: "web_site"}, - "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "模板路径"}, - + "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "模板路径"}, + "template_debug": &ctx.Config{Name: "template_debug", Value: "true", Help: "模板调试"}, "componet_context": &ctx.Config{Name: "component_context", Value: "nfs", Help: "默认模块"}, "componet_command": &ctx.Config{Name: "component_command", Value: "pwd", Help: "默认命令"}, "componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"}, "componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{ - "login": []interface{}{ - map[string]interface{}{"name": "head", "template": "head"}, - map[string]interface{}{"name": "userinfo", "help": "userinfo", - "context": "aaa", "command": "userinfo", "arguments": []interface{}{"@sessid"}, - }, - map[string]interface{}{"name": "login", "help": "login", "template": "componet", - "context": "aaa", "command": "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", "label": "login"}, - }, - "display_append": "", "display_result": "", "result_reload": "10", - }, - map[string]interface{}{"name": "tail", "template": "tail"}, - }, "index": []interface{}{ map[string]interface{}{"name": "head", "template": "head"}, map[string]interface{}{"name": "clipbaord", "help": "clipbaord", "template": "clipboard"}, - map[string]interface{}{"name": "buffer", "help": "buffer", "template": "componet", - "context": "cli", "command": "tmux", "arguments": []interface{}{"buffer"}, "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "limit", "label": "limit", "value": "3"}, - map[string]interface{}{"type": "text", "name": "index", "label": "index"}, - map[string]interface{}{"type": "button", "label": "refresh"}, - }, - "pre_run": true, - }, - map[string]interface{}{"name": "command", "help": "command", "template": "componet", - "context": "cli.shell1", "command": "source", "arguments": []interface{}{"@cmd"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "cmd", "value": "", - "class": "cmd", "clipstack": "clistack", - }, - }, - }, map[string]interface{}{"name": "time", "help": "time", "template": "componet", "context": "cli", "command": "time", "arguments": []interface{}{"@string"}, "inputs": []interface{}{ @@ -305,83 +287,6 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", map[string]interface{}{"type": "button", "label": "refresh"}, }, }, - map[string]interface{}{"name": "json", "help": "json", "template": "componet", - "context": "nfs", "command": "json", "arguments": []interface{}{"@string"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "string", "label": "string"}, - map[string]interface{}{"type": "button", "label": "refresh"}, - }, - }, - map[string]interface{}{"name": "upload", "help": "upload", "template": "componet", - "form_type": "upload", - "inputs": []interface{}{ - map[string]interface{}{"type": "file", "name": "upload"}, - map[string]interface{}{"type": "submit", "value": "submit"}, - }, - "display_result": "", - }, - map[string]interface{}{"name": "dir", "help": "dir", "template": "componet", - "context": "nfs", "command": "dir", "arguments": []interface{}{"@dir", - "dir_deep", "no", "dir_name", "name", "dir_info", "", - "dir_link", "%s", - }, - "pre_run": true, - "inputs": []interface{}{ - map[string]interface{}{"type": "choice", "name": "dir_type", - "label": "dir_type", "value": "both", "choice": []interface{}{ - map[string]interface{}{"name": "both", "value": "both"}, - map[string]interface{}{"name": "file", "value": "file"}, - map[string]interface{}{"name": "dir", "value": "dir"}, - }, - }, - map[string]interface{}{"type": "choice", "name": "sort_field", - "label": "sort_field", "value": "time", "choice": []interface{}{ - map[string]interface{}{"name": "filename", "value": "filename"}, - map[string]interface{}{"name": "is_dir", "value": "is_dir"}, - map[string]interface{}{"name": "line", "value": "line"}, - map[string]interface{}{"name": "size", "value": "size"}, - map[string]interface{}{"name": "time", "value": "time"}, - }, - }, - map[string]interface{}{"type": "choice", "name": "sort_order", - "label": "sort_order", "value": "time_r", "choice": []interface{}{ - map[string]interface{}{"name": "str", "value": "str"}, - map[string]interface{}{"name": "str_r", "value": "str_r"}, - map[string]interface{}{"name": "int", "value": "int"}, - map[string]interface{}{"name": "int_r", "value": "int_r"}, - map[string]interface{}{"name": "time", "value": "time"}, - map[string]interface{}{"name": "time_r", "value": "time_r"}, - }, - }, - map[string]interface{}{"type": "text", "name": "dir", "label": "dir"}, - }, - }, - map[string]interface{}{"name": "web_site", "help": "web_site", "template": "componet", - "context": "web", "command": "config", "arguments": []interface{}{ - "web_site", "format_field", "site", "%s", - }, - "display_result": "", - }, - map[string]interface{}{"name": "prompt", "help": "prompt", "template": "componet", - "context": "nfs.stdio", "command": "prompt", "arguments": []interface{}{"@string"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "string", "label": "string"}, - map[string]interface{}{"type": "button", "label": "refresh"}, - }, - }, - map[string]interface{}{"name": "exec", "help": "exec", "template": "componet", - "context": "nfs.stdio", "command": "exec", "arguments": []interface{}{"@string"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "string"}, - }, - }, - map[string]interface{}{"name": "show", "help": "show", "template": "componet", - "context": "nfs.stdio", "command": "show", "arguments": []interface{}{"\n", "@string", "\n"}, - "inputs": []interface{}{ - map[string]interface{}{"type": "text", "name": "string", "label": "string"}, - map[string]interface{}{"type": "button", "label": "refresh"}, - }, - }, map[string]interface{}{"name": "tail", "template": "tail"}, }, }, Help: "组件列表"}, @@ -599,6 +504,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Spawn().Cmd("open", url) } }}, + "serve": &ctx.Command{Name: "serve [directory [address [protocol [cert [key]]]]", Help: "启动服务, directory: 服务路径, address: 服务地址, protocol: 服务协议(https/http), cert: 服务证书, key: 服务密钥", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { m.Set("detail", arg...).Target().Start(m) }}, @@ -660,26 +566,26 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", "template": &ctx.Command{Name: "template [file [directory]]|[name [content]]", Help: "添加模板, content: 模板内容, directory: 模板目录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { if len(arg) == 0 { - for _, v := range web.template.Templates() { + for _, v := range web.Template.Templates() { m.Add("append", "name", v.Name()) } m.Sort("name").Table() return } - if web.template == nil { - web.template = template.New("render").Funcs(ctx.CGI) + if web.Template == nil { + web.Template = template.New("render").Funcs(ctx.CGI) } dir := path.Join(m.Confx("template_dir", arg, 1), arg[0]) - if t, e := web.template.ParseGlob(dir); e == nil { - web.template = t + if t, e := web.Template.ParseGlob(dir); e == nil { + web.Template = t } else { m.Log("info", "%s", e) if len(arg) > 1 { - web.template = template.Must(web.template.New(arg[0]).Parse(arg[1])) + web.Template = template.Must(web.Template.New(arg[0]).Parse(arg[1])) } else { - tmpl, e := web.template.Clone() + tmpl, e := web.Template.Clone() m.Assert(e) tmpl.Funcs(ctx.CGI) @@ -765,16 +671,21 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", m.Append("redirect", m.Option("referer")) }}, "/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if _, ok := m.Target().Server.(*WEB); m.Assert(ok) { + if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { accept_json := strings.HasPrefix(m.Option("accept"), "application/json") list := []interface{}{} - // tmpl, e := web.template.Clone() + // tmpl, e := web.Template.Clone() // m.Assert(e) // tmpl.Funcs(ctx.CGI) // - tmpl := template.New("render").Funcs(ctx.CGI) - tmpl.ParseGlob(fmt.Sprintf("%s/context/usr/template/common/base.tmpl", os.Getenv("HOME"))) + + tmpl := web.Template + if m.Confs("template_debug") { + tmpl = template.New("render").Funcs(ctx.CGI) + tmpl.ParseGlob(path.Join(m.Conf("template_dir"), "/*.tmpl")) + tmpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("template_sub"), "/*.tmpl")) + } w := m.Optionv("response").(http.ResponseWriter) if accept_json { diff --git a/src/examples/code/code.go b/src/examples/code/code.go index bbf5adc0..8b5166ab 100644 --- a/src/examples/code/code.go +++ b/src/examples/code/code.go @@ -1,650 +1,151 @@ package code import ( - "bytes" "contexts/ctx" "contexts/web" - "encoding/json" - "fmt" - "html/template" - "io" - "net/http" - "os" - "path" - "strings" ) -type CODE struct { - web.WEB -} - -// yac := m.Sess("tags", m.Sess("yac").Cmd("scan")) -// yac.Cmd("train", "void", "void", "[\t ]+") -// yac.Cmd("train", "other", "other", "[^\n]+") -// yac.Cmd("train", "key", "key", "[A-Za-z_][A-Za-z_0-9]*") -// yac.Cmd("train", "code", "def", "def", "key", "(", "other") -// yac.Cmd("train", "code", "def", "class", "key", "other") -// yac.Cmd("train", "code", "struct", "struct", "key", "\\{") -// yac.Cmd("train", "code", "struct", "\\}", "key", ";") -// yac.Cmd("train", "code", "struct", "typedef", "struct", "key", "key", ";") -// yac.Cmd("train", "code", "function", "key", "\\*", "key", "(", "other") -// yac.Cmd("train", "code", "function", "key", "key", "(", "other") -// yac.Cmd("train", "code", "variable", "struct", "key", "key", "other") -// yac.Cmd("train", "code", "define", "#define", "key", "other") -// - var Index = &ctx.Context{Name: "code", Help: "代码中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{ - "library_dir": &ctx.Config{Name: "library_dir", Value: "usr", Help: "通用模板路径"}, - "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template/", Help: "通用模板路径"}, - "common_tmpl": &ctx.Config{Name: "common_tmpl", Value: "common/*.html", Help: "通用模板路径"}, - "common_main": &ctx.Config{Name: "common_main", Value: "main.html", Help: "通用模板框架"}, - "upload_tmpl": &ctx.Config{Name: "upload_tmpl", Value: "upload.html", Help: "上传文件模板"}, - "upload_main": &ctx.Config{Name: "upload_main", Value: "main.html", Help: "上传文件框架"}, - "travel_tmpl": &ctx.Config{Name: "travel_tmpl", Value: "travel.html", Help: "浏览模块模板"}, - "travel_main": &ctx.Config{Name: "travel_main", Value: "main.html", Help: "浏览模块框架"}, - - "check": &ctx.Config{Name: "check", Value: map[string]interface{}{ + "web_site": &ctx.Config{Name: "web_site", Value: []interface{}{ + map[string]interface{}{"_name": "MDN", "site": "https://developer.mozilla.org"}, + map[string]interface{}{"_name": "github", "site": "https://github.com"}, + }, Help: "web_site"}, + "componet_command": &ctx.Config{Name: "component_command", Value: "pwd", Help: "默认命令"}, + "componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"}, + "componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{ "login": []interface{}{ - map[string]interface{}{ - "session": "aaa", - "module": "aaa", "command": "login", - "variable": []interface{}{"$sessid"}, - "template": "login", "title": "login", + map[string]interface{}{"name": "head", "template": "head"}, + map[string]interface{}{"name": "userinfo", "help": "userinfo", + "context": "aaa", "command": "userinfo", "arguments": []interface{}{"@sessid"}, }, - map[string]interface{}{ - "module": "aaa", "command": "login", - "variable": []interface{}{"$username", "$password"}, - "template": "login", "title": "login", + map[string]interface{}{"name": "login", "help": "login", "template": "componet", + "context": "aaa", "command": "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", "label": "login"}, + }, + "display_append": "", "display_result": "", "result_reload": "10", }, + map[string]interface{}{"name": "tail", "template": "tail"}, }, - "right": []interface{}{ - map[string]interface{}{ - "module": "web", "command": "right", - "variable": []interface{}{"$username", "check", "command", "/index", "dir", "$dir"}, - "template": "notice", "title": "notice", + "index": []interface{}{ + map[string]interface{}{"name": "head", "template": "head"}, + map[string]interface{}{"name": "clipbaord", "help": "clipbaord", "template": "clipboard"}, + map[string]interface{}{"name": "buffer", "help": "buffer", "template": "componet", + "context": "cli", "command": "tmux", "arguments": []interface{}{"buffer"}, "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "limit", "label": "limit", "value": "3"}, + map[string]interface{}{"type": "text", "name": "index", "label": "index"}, + map[string]interface{}{"type": "button", "label": "refresh"}, + }, + "pre_run": true, }, - map[string]interface{}{ - "module": "aaa", "command": "login", - "variable": []interface{}{"username", "password"}, - "template": "login", "title": "login", + map[string]interface{}{"name": "command", "help": "command", "template": "componet", + "context": "cli.shell1", "command": "source", "arguments": []interface{}{"@cmd"}, + "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "cmd", "value": "", + "class": "cmd", "clipstack": "clistack", + }, + }, }, + map[string]interface{}{"name": "time", "help": "time", "template": "componet", + "context": "cli", "command": "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", "label": "refresh"}, + }, + }, + map[string]interface{}{"name": "json", "help": "json", "template": "componet", + "context": "nfs", "command": "json", "arguments": []interface{}{"@string"}, + "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "string", "label": "string"}, + map[string]interface{}{"type": "button", "label": "refresh"}, + }, + }, + map[string]interface{}{"name": "upload", "help": "upload", "template": "componet", + "form_type": "upload", + "inputs": []interface{}{ + map[string]interface{}{"type": "file", "name": "upload"}, + map[string]interface{}{"type": "submit", "value": "submit"}, + }, + "display_result": "", + }, + map[string]interface{}{"name": "dir", "help": "dir", "template": "componet", + "context": "nfs", "command": "dir", "arguments": []interface{}{"@dir", + "dir_deep", "no", "dir_name", "name", "dir_info", "", + "dir_link", "%s", + }, + "pre_run": true, + "inputs": []interface{}{ + map[string]interface{}{"type": "choice", "name": "dir_type", + "label": "dir_type", "value": "both", "choice": []interface{}{ + map[string]interface{}{"name": "both", "value": "both"}, + map[string]interface{}{"name": "file", "value": "file"}, + map[string]interface{}{"name": "dir", "value": "dir"}, + }, + }, + map[string]interface{}{"type": "choice", "name": "sort_field", + "label": "sort_field", "value": "time", "choice": []interface{}{ + map[string]interface{}{"name": "filename", "value": "filename"}, + map[string]interface{}{"name": "is_dir", "value": "is_dir"}, + map[string]interface{}{"name": "line", "value": "line"}, + map[string]interface{}{"name": "size", "value": "size"}, + map[string]interface{}{"name": "time", "value": "time"}, + }, + }, + map[string]interface{}{"type": "choice", "name": "sort_order", + "label": "sort_order", "value": "time_r", "choice": []interface{}{ + map[string]interface{}{"name": "str", "value": "str"}, + map[string]interface{}{"name": "str_r", "value": "str_r"}, + map[string]interface{}{"name": "int", "value": "int"}, + map[string]interface{}{"name": "int_r", "value": "int_r"}, + map[string]interface{}{"name": "time", "value": "time"}, + map[string]interface{}{"name": "time_r", "value": "time_r"}, + }, + }, + map[string]interface{}{"type": "text", "name": "dir", "label": "dir"}, + }, + }, + map[string]interface{}{"name": "web_site", "help": "web_site", "template": "componet", + "context": "web", "command": "config", "arguments": []interface{}{ + "web_site", "format_field", "site", "%s", + }, + "display_result": "", + }, + map[string]interface{}{"name": "prompt", "help": "prompt", "template": "componet", + "context": "nfs.stdio", "command": "prompt", "arguments": []interface{}{"@string"}, + "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "string", "label": "string"}, + map[string]interface{}{"type": "button", "label": "refresh"}, + }, + }, + map[string]interface{}{"name": "exec", "help": "exec", "template": "componet", + "context": "nfs.stdio", "command": "exec", "arguments": []interface{}{"@string"}, + "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "string"}, + }, + }, + map[string]interface{}{"name": "show", "help": "show", "template": "componet", + "context": "nfs.stdio", "command": "show", "arguments": []interface{}{"\n", "@string", "\n"}, + "inputs": []interface{}{ + map[string]interface{}{"type": "text", "name": "string", "label": "string"}, + map[string]interface{}{"type": "button", "label": "refresh"}, + }, + }, + map[string]interface{}{"name": "tail", "template": "tail"}, }, - }, Help: "执行条件"}, - "auto_create": &ctx.Config{Name: "auto_create(true/false)", Value: "true", Help: "路由数量"}, - "refresh_time": &ctx.Config{Name: "refresh_time(ms)", Value: "1000", Help: "路由数量"}, - "define": &ctx.Config{Name: "define", Value: map[string]interface{}{ - "ngx_command_t": map[string]interface{}{ - "position": []interface{}{map[string]interface{}{ - "file": "nginx-1.15.2/src/core/ngx_core.h", - "line": "22", - }}, - }, - "ngx_command_s": map[string]interface{}{ - "position": map[string]interface{}{ - "file": "nginx-1.15.2/src/core/ngx_conf_file.h", - "line": "77", - }, - }, - }, Help: "路由数量"}, - "index": &ctx.Config{Name: "index", Value: map[string]interface{}{ - "duyu": []interface{}{ - map[string]interface{}{ - "template": "userinfo", "title": "userinfo", - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "aaa", "command": "lark", - "argument": []interface{}{}, - "template": "append", "title": "lark_friend", - }, - map[string]interface{}{ - "module": "aaa", "detail": []interface{}{"lark"}, - "template": "detail", "title": "send_lark", - "option": map[string]interface{}{"ninput": 2}, - }, - map[string]interface{}{ - "module": "aaa", "command": "lark", - "argument": []interface{}{"duyu"}, - "template": "append", "title": "lark", - }, - map[string]interface{}{ - "module": "nfs", "command": "dir", - "argument": []interface{}{"dir_type", "all", "dir_deep", "false", "dir_field", "time size line filename", "sort_field", "time", "sort_order", "time_r"}, - "template": "append", "title": "", - }, - }, - "shy": []interface{}{ - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "template": "userinfo", "title": "userinfo", - }, - //文件服务 - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "nfs", "command": "dir", - "argument": []interface{}{"dir_type", "all", "dir_deep", "false", "dir_field", "time size line filename", "sort_field", "time", "sort_order", "time_r"}, - "template": "append", "title": "", - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "template": "upload", "title": "upload", - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "template": "create", "title": "create", - }, - //会话服务 - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "cli", "command": "system", - "argument": []interface{}{"tmux", "show-buffer"}, - "template": "result", "title": "buffer", - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "cli", "command": "system", - "argument": []interface{}{"tmux", "list-clients"}, - "template": "result", "title": "client", - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "cli", "command": "system", - "argument": []interface{}{"tmux", "list-sessions"}, - "template": "result", "title": "session", - }, - //格式转换 - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "cli", "detail": []interface{}{"time"}, - "template": "detail", "title": "time", - "option": map[string]interface{}{"refresh": true, "ninput": 1}, - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "nfs", "detail": []interface{}{"json"}, - "template": "detail", "title": "json", - "option": map[string]interface{}{"ninput": 1}, - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "nfs", "detail": []interface{}{"pwd"}, - "template": "detail", "title": "pwd", - "option": map[string]interface{}{"refresh": true}, - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "nfs", "command": "git", - "argument": []interface{}{}, - "template": "result", "title": "git", - }, - map[string]interface{}{ - "from": "root", "to": []interface{}{}, - "module": "web", "command": "/share", - "argument": []interface{}{}, - "template": "share", "title": "share", - }, - }, - "notice": []interface{}{ - map[string]interface{}{ - "template": "userinfo", "title": "userinfo", - }, - map[string]interface{}{ - "template": "notice", "title": "notice", - }, - }, - "login": []interface{}{ - map[string]interface{}{ - "template": "login", "title": "login", - }, - }, - "wiki": []interface{}{ - map[string]interface{}{ - "template": "wiki_head", "title": "wiki_head", - }, - map[string]interface{}{ - "template": "wiki_menu", "title": "wiki_menu", - }, - map[string]interface{}{ - "module": "web", "command": "/wiki_list", - "template": "wiki_list", "title": "wiki_list", - }, - map[string]interface{}{ - "module": "web", "command": "/wiki_body", - "template": "wiki_body", "title": "wiki_body", - }, - }, - }, Help: "资源列表"}, - }, - Commands: map[string]*ctx.Command{ - "/demo": &ctx.Command{Name: "/demo", Help: "demo", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Echo("demo") - }}, - "/render": &ctx.Command{Name: "/render index", Help: "模板响应, main: 模板入口, tmpl: 附加模板", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - w := m.Optionv("response").(http.ResponseWriter) - w.Header().Add("Content-Type", "text/html") - m.Optioni("ninput", 0) - - tpl := template.New("render").Funcs(ctx.CGI) - tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("common_tmpl")))) - tpl = template.Must(tpl.ParseGlob(path.Join(m.Conf("template_dir"), m.Conf("upload_tmpl")))) - - replace := [][]byte{ - []byte{27, 91, 51, 50, 109}, []byte(""), - []byte{27, 91, 51, 49, 109}, []byte(""), - []byte{27, 91, 109}, []byte(""), - } - - if m.Confv("index", arg[0]) == nil { - arg[0] = "notice" - } - - m.Assert(tpl.ExecuteTemplate(w, "head", m)) - for _, v := range m.Confv("index", arg[0]).([]interface{}) { - if v == nil { - continue - } - val := v.(map[string]interface{}) - //命令模板 - if detail, ok := val["detail"].([]interface{}); ok { - msg := m.Spawn().Add("detail", detail[0].(string), detail[1:]) - msg.Option("module", val["module"]) - msg.Option("title", val["title"]) - if option, ok := val["option"].(map[string]interface{}); ok { - for k, v := range option { - msg.Option(k, v) - } - } - - m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg)) - continue - } - - //执行命令 - if _, ok := val["command"]; ok { - msg := m.Find(val["module"].(string)).Cmd(val["command"], val["argument"]) - for i, v := range msg.Meta["result"] { - b := []byte(v) - for i := 0; i < len(replace)-1; i += 2 { - b = bytes.Replace(b, replace[i], replace[i+1], -1) - } - msg.Meta["result"][i] = string(b) - } - if msg.Option("title", val["title"]) == "" { - msg.Option("title", m.Option("dir")) - } - m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), msg)) - continue - } - - //解析模板 - if _, ok := val["template"]; ok { - m.Assert(tpl.ExecuteTemplate(w, val["template"].(string), m)) - } - } - m.Assert(tpl.ExecuteTemplate(w, "tail", m)) - }}, - - "/check": &ctx.Command{Name: "/check arg...", Help: "权限检查, cache|config|command: 接口类型, name: 接口名称, args: 其它参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if login := m.Spawn().Cmd("/login"); login.Has("template") { - m.Echo("no").Copy(login, "append") - return - } - - if msg := m.Spawn().Cmd("right", m.Append("username"), "check", arg); !msg.Results(0) { - m.Echo("no").Append("message", "no right, please contact manager") - return - } - - m.Echo("ok") - - }}, - "/login": &ctx.Command{Name: "/login", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if m.Options("sessid") { - if aaa := m.Sess("aaa").Cmd("login", m.Option("sessid")); aaa.Results(0) { - m.Append("redirect", m.Option("referer")) - m.Append("username", aaa.Result(0)) - return - } - } - - w := m.Optionv("response").(http.ResponseWriter) - if m.Options("username") && m.Options("password") { - if aaa := m.Sess("aaa").Cmd("login", m.Option("username"), m.Option("password")); aaa.Results(0) { - http.SetCookie(w, &http.Cookie{Name: "sessid", Value: aaa.Result(0)}) - m.Append("redirect", m.Option("referer")) - m.Append("username", m.Option("username")) - return - } - } - - w.WriteHeader(http.StatusUnauthorized) - m.Append("template", "login") - - }}, - "/lookup": &ctx.Command{Name: "user", Help: "应用示例", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if len(arg) > 0 { - m.Option("service", arg[0]) - } - msg := m.Sess("cli").Cmd("system", "sd", "lookup", m.Option("service")) - - rs := strings.Split(msg.Result(0), "\n") - i := 0 - for ; i < len(rs); i++ { - if len(rs[i]) == 0 { - break - } - fields := strings.SplitN(rs[i], ": ", 2) - m.Append(fields[0], fields[1]) - } - - lists := []interface{}{} - for i += 2; i < len(rs); i++ { - fields := strings.SplitN(rs[i], " ", 3) - if len(fields) < 3 { - break - } - lists = append(lists, map[string]interface{}{ - "ip": fields[0], - "port": fields[1], - "tags": fields[2], - }) - } - - m.Appendv("lists", lists) - m.Log("log", "%v", lists) - }}, - "upload": &ctx.Command{Name: "upload file", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - msg := m.Spawn(m.Target()) - msg.Cmd("get", "/upload", "method", "POST", "file", "file", arg[0]) - m.Copy(msg, "result") - - }}, - "/travel": &ctx.Command{Name: "/travel", Help: "文件上传", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - // r := m.Optionv("request").(*http.Request) - // w := m.Optionv("response").(http.ResponseWriter) - - if !m.Options("dir") { - m.Option("dir", "ctx") - } - - check := m.Spawn().Cmd("/share", "/travel", "dir", m.Option("dir")) - if !check.Results(0) { - m.Copy(check, "append") - return - } - - // 权限检查 - if m.Option("method") == "POST" { - if m.Options("domain") { - msg := m.Find("ssh", true) - msg.Detail(0, "send", "domain", m.Option("domain"), "context", "find", m.Option("dir")) - if m.Option("name") != "" { - msg.Add("detail", m.Option("name")) - } - if m.Options("value") { - value := []string{} - json.Unmarshal([]byte(m.Option("value")), &value) - if len(value) > 0 { - msg.Add("detail", value[0], value[1:]) - } - } - - msg.CallBack(true, func(sub *ctx.Message) *ctx.Message { - m.Copy(sub, "result").Copy(sub, "append") - return nil - }) - return - } - - msg := m.Find(m.Option("dir"), true) - if msg == nil { - return - } - - switch m.Option("ccc") { - case "cache": - m.Echo(msg.Cap(m.Option("name"))) - case "config": - if m.Has("value") { - m.Echo(msg.Conf(m.Option("name"), m.Option("value"))) - } else { - m.Echo(msg.Conf(m.Option("name"))) - } - case "command": - msg = msg.Spawn(msg.Target()) - msg.Detail(0, m.Option("name")) - if m.Options("value") { - value := []string{} - json.Unmarshal([]byte(m.Option("value")), &value) - if len(value) > 0 { - msg.Add("detail", value[0], value[1:]) - } - } - - msg.Cmd() - m.Copy(msg, "result").Copy(msg, "append") - } - return - } - - // 解析模板 - m.Set("append", "tmpl", "userinfo", "share") - msg := m - for _, v := range []string{"cache", "config", "command", "module", "domain"} { - if m.Options("domain") { - msg = m.Find("ssh", true) - msg.Detail(0, "send", "domain", m.Option("domain"), "context", "find", m.Option("dir"), "list", v) - msg.CallBack(true, func(sub *ctx.Message) *ctx.Message { - msg.Copy(sub, "result").Copy(sub, "append") - return nil - }) - } else { - msg = m.Spawn() - msg.Cmd("context", "find", msg.Option("dir"), "list", v) - } - - if len(msg.Meta["append"]) > 0 { - msg.Option("current_module", m.Option("dir")) - msg.Option("current_domain", m.Option("domain")) - m.Add("option", "tmpl", v) - m.Sess(v, msg) - } - } - m.Append("template", m.Conf("travel_main"), m.Conf("travel_tmpl")) - - }}, - "/index/": &ctx.Command{Name: "/index", Help: "网页门户", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - r := m.Optionv("request").(*http.Request) - w := m.Optionv("response").(http.ResponseWriter) - - if login := m.Spawn().Cmd("/login"); login.Has("template") { - m.Echo("no").Copy(login, "append") - return - } - m.Option("username", m.Append("username")) - - //权限检查 - dir := m.Option("dir", path.Join(m.Cap("directory"), "local", m.Option("username"), m.Option("dir", strings.TrimPrefix(m.Option("path"), "/index")))) - // if check := m.Spawn(c).Cmd("/check", "command", "/index/", "dir", dir); !check.Results(0) { - // m.Copy(check, "append") - // return - // } - - //执行命令 - if m.Has("details") { - if m.Confs("check_right") { - if check := m.Spawn().Cmd("/check", "target", m.Option("module"), "command", m.Option("details")); !check.Results(0) { - m.Copy(check, "append") - return - } - } - - msg := m.Find(m.Option("module")).Cmd(m.Optionv("details")) - m.Copy(msg, "result").Copy(msg, "append") - return - } - - //下载文件 - if s, e := os.Stat(dir); e == nil && !s.IsDir() { - http.ServeFile(w, r, dir) - return - } - - if !m.Options("module") { - m.Option("module", "web") - } - //浏览目录 - m.Append("template", m.Append("username")) - m.Option("page_title", "index") - - }}, - "/create": &ctx.Command{Name: "/create", Help: "创建目录或文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - // if check := m.Spawn().Cmd("/share", "/upload", "dir", m.Option("dir")); !check.Results(0) { - // m.Copy(check, "append") - // return - // } - - r := m.Optionv("request").(*http.Request) - if m.Option("method") == "POST" { - if m.Options("filename") { //添加文件或目录 - name := path.Join(m.Option("dir"), m.Option("filename")) - if _, e := os.Stat(name); e != nil { - if m.Options("content") { - f, e := os.Create(name) - m.Assert(e) - defer f.Close() - - _, e = f.WriteString(m.Option("content")) - m.Assert(e) - } else { - e = os.Mkdir(name, 0766) - m.Assert(e) - } - m.Append("message", name, " create success!") - } else { - m.Append("message", name, " already exist!") - } - } else { //上传文件 - file, header, e := r.FormFile("file") - m.Assert(e) - - name := path.Join(m.Option("dir"), header.Filename) - - if _, e := os.Stat(name); e != nil { - f, e := os.Create(name) - m.Assert(e) - defer f.Close() - - _, e = io.Copy(f, file) - m.Assert(e) - m.Append("message", name, " upload success!") - } else { - m.Append("message", name, " already exist!") - } - } - } - m.Append("redirect", m.Option("referer")) - - }}, - "/share": &ctx.Command{Name: "/share arg...", Help: "资源共享", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if check := m.Spawn().Cmd("/check", "target", m.Option("module"), m.Optionv("share")); !check.Results(0) { - m.Copy(check, "append") - return - } - m.Option("username", m.Append("username")) - - // if m.Options("friend") && m.Options("module") { - // m.Copy(m.Appendv("aaa").(*ctx.Message).Find(m.Option("module")).Cmd("right", m.Option("friend"), m.Option("action"), m.Optionv("share")), "result") - // if m.Confv("index", m.Option("friend")) == nil { - // m.Confv("index", m.Option("friend"), m.Confv("index", m.Append("username"))) - // } - // return - // } - // - // msg := m.Spawn().Cmd("right", "target", m.Option("module"), m.Append("username"), "show", "context") - // m.Copy(msg, "append") - if m.Options("friend") && m.Options("template") && m.Options("title") { - for i, v := range m.Confv("index", m.Option("username")).([]interface{}) { - if v == nil { - continue - } - val := v.(map[string]interface{}) - if val["template"].(string) == m.Option("template") && val["title"].(string) == m.Option("title") { - if m.Option("action") == "del" { - friends := m.Confv("index", strings.Join([]string{m.Option("username"), fmt.Sprintf("%d", i), "to"}, ".")).([]interface{}) - for j, x := range friends { - if x.(string) == m.Option("friend") { - m.Confv("index", strings.Join([]string{m.Option("username"), fmt.Sprintf("%d", i), "to", fmt.Sprintf("%d", j)}, "."), nil) - } - } - - temps := m.Confv("index", strings.Join([]string{m.Option("friend")}, ".")).([]interface{}) - for j, x := range temps { - if x == nil { - continue - } - val = x.(map[string]interface{}) - if val["template"].(string) == m.Option("template") && val["title"].(string) == m.Option("title") { - m.Confv("index", strings.Join([]string{m.Option("friend"), fmt.Sprintf("%d", j)}, "."), nil) - } - } - - break - } - - if m.Confv("index", m.Option("friend")) == nil && !m.Confs("auto_create") { - break - } - m.Confv("index", strings.Join([]string{m.Option("username"), fmt.Sprintf("%d", i), "to", "-2"}, "."), m.Option("friend")) - - item := map[string]interface{}{ - "template": val["template"], - "title": val["title"], - "from": m.Option("username"), - } - if val["command"] != nil { - item["module"] = val["module"] - item["command"] = val["command"] - item["argument"] = val["argument"] - } else if val["detail"] != nil { - item["module"] = val["module"] - item["detail"] = val["detail"] - item["option"] = val["option"] - } - - m.Confv("index", strings.Join([]string{m.Option("friend"), fmt.Sprintf("%d", -2)}, "."), item) - m.Appendv("aaa").(*ctx.Message).Spawn(c).Cmd("right", m.Option("friend"), "add", "command", "/index/", "dir", m.Cap("directory")) - os.Mkdir(path.Join(m.Cap("directory"), m.Option("friend")), 0666) - break - } - } - return - } - for _, v := range m.Confv("index", m.Option("username")).([]interface{}) { - val := v.(map[string]interface{}) - m.Add("append", "template", val["template"]) - m.Add("append", "titles", val["title"]) - m.Add("append", "from", val["from"]) - m.Add("append", "to", "") - if val["to"] == nil { - continue - } - for _, u := range val["to"].([]interface{}) { - m.Add("append", "template", val["template"]) - m.Add("append", "titles", val["title"]) - m.Add("append", "from", val["from"]) - m.Add("append", "to", u) - } - } - - }}, + }, Help: "组件列表"}, }, + Commands: map[string]*ctx.Command{}, } func init() { - code := &CODE{} + code := &web.WEB{} code.Context = Index web.Index.Register(Index, code) } diff --git a/src/examples/wiki/wiki.go b/src/examples/wiki/wiki.go index ed5772bc..2b753531 100644 --- a/src/examples/wiki/wiki.go +++ b/src/examples/wiki/wiki.go @@ -1,48 +1,119 @@ package wiki import ( - "os/exec" - "time" - "bufio" "bytes" "contexts/ctx" "contexts/web" - "encoding/json" "encoding/xml" "fmt" "github.com/gomarkdown/markdown" - "io" "io/ioutil" - "mime/multipart" "net/http" "os" "path" - "path/filepath" "strings" ) -type WIKI struct { - web.WEB -} - var Index = &ctx.Context{Name: "wiki", Help: "文档中心", Caches: map[string]*ctx.Cache{}, Configs: map[string]*ctx.Config{ - "which": &ctx.Config{Name: "which", Value: "redis.note", Help: "路由数量"}, - "wiki_dir": &ctx.Config{Name: "wiki_dir", Value: "usr/wiki", Help: "路由数量"}, + "wiki_dir": &ctx.Config{Name: "wiki_dir", Value: "usr/wiki", Help: "路由数量"}, + "wiki_favor": &ctx.Config{Name: "wiki_favor", Value: "lamp.md", Help: "路由数量"}, + "wiki_list": &ctx.Config{Name: "wiki_list", Value: []interface{}{}, Help: "路由数量"}, + "wiki_list_show": &ctx.Config{Name: "wiki_list_show", Value: map[string]interface{}{ "md": true, }, Help: "路由数量"}, + + "componet_group": &ctx.Config{Name: "component_group", Value: "index", Help: "默认组件"}, + "componet": &ctx.Config{Name: "componet", Value: map[string]interface{}{ + "index": []interface{}{ + map[string]interface{}{"name": "head", "template": "head"}, + map[string]interface{}{"name": "header", "template": "header"}, + map[string]interface{}{"name": "list", "template": "list", + "context": "web.wiki", "command": "wiki_list", "arguments": []interface{}{"h2", "int_r"}, + "pre_run": true, + }, + map[string]interface{}{"name": "text", "template": "text", + "context": "web.wiki", "command": "wiki_body", "arguments": []interface{}{"@wiki_favor"}, + "pre_run": true, + }, + map[string]interface{}{"name": "footer", "template": "footer"}, + map[string]interface{}{"name": "tail", "template": "tail"}, + }, + }, Help: "组件列表"}, }, Commands: map[string]*ctx.Command{ - "/blog": &ctx.Command{Name: "/blog", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if m.Has("title") && m.Has("content") { + "wiki_list": &ctx.Command{Name: "wiki_list sort_field sort_order", Help: "wiki_list", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + sort_field, sort_order := "h2", "int_r" + if len(arg) > 0 { + sort_field, arg = arg[0], arg[1:] + } + if len(arg) > 0 { + sort_order, arg = arg[0], arg[1:] } - m.Echo("blog service") + md, e := ioutil.ReadDir(m.Conf("wiki_dir")) + m.Assert(e) + for _, v := range md { + if strings.HasSuffix(v.Name(), ".md") { + f, e := os.Open(path.Join(m.Conf("wiki_dir"), v.Name())) + m.Assert(e) + defer f.Close() + + title := "" + nline, ncode := 0, 0 + h2, h3, h4 := 0, 0, 0 + for bio := bufio.NewScanner(f); bio.Scan(); { + line := bio.Text() + nline++ + + if strings.HasPrefix(line, "## ") { + h2++ + if title == "" { + title = line[3:] + } + } else if strings.HasPrefix(line, "### ") { + h3++ + } else if strings.HasPrefix(line, "#### ") { + h4++ + } else if strings.HasPrefix(line, "```") { + ncode++ + } + } + + m.Add("append", "time", v.ModTime().Format("2006/01/02")) + m.Add("append", "file", v.Name()) + m.Add("append", "size", v.Size()) + + m.Add("append", "line", nline) + m.Add("append", "code", ncode/2) + m.Add("append", "h4", h4) + m.Add("append", "h3", h3) + m.Add("append", "h2", h2) + m.Add("append", "title", title) + } + } + m.Sort(sort_field, sort_order).Table() + + m.Target().Configs["wiki_list"].Value = []interface{}{} + m.Table(func(maps map[string]string, list []string, line int) bool { + if line > 0 { + m.Confv("wiki_list", -2, maps) + } + return true + }) }}, + "wiki_body": &ctx.Command{Name: "wiki_body", Help: "wiki_body", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + which := path.Join(m.Conf("wiki_dir"), m.Confx("wiki_favor", arg, 0)) + if ls, e := ioutil.ReadFile(which); e == nil { + ls = markdown.ToHTML(ls, nil, nil) + m.Echo(string(ls)) + } + }}, + "/wiki_tags": &ctx.Command{Name: "/wiki_tags ", Help: "博客", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if len(arg) > 0 { m.Option("dir", arg[0]) @@ -347,269 +418,11 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心", m.Echo(string(b)) } }}, - "old_get": &ctx.Command{ - Name: "get [method GET|POST] [file name filename] url arg...", - Help: "访问服务, method: 请求方法, file: 发送文件, url: 请求地址, arg: 请求参数", - Form: map[string]int{"method": 1, "content_type": 1, "headers": 2, "file": 2, "body_type": 1, "body": 1, "fields": 1, "value": 1, "json_route": 1, "json_key": 1}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - if web, ok := m.Target().Server.(*web.WEB); m.Assert(ok) { - if web.Client == nil { - web.Client = &http.Client{} - } - - if m.Has("value") { - args := strings.Split(m.Option("value"), " ") - values := []interface{}{} - for _, v := range args { - if len(v) > 1 && v[0] == '$' { - values = append(values, m.Cap(v[1:])) - } else { - values = append(values, v) - } - } - arg[0] = fmt.Sprintf(arg[0], values...) - } - - method := m.Confx("method") - uri := web.Merge(m, arg[0], arg[1:]...) - m.Log("info", "%s %s", method, uri) - m.Echo("%s: %s\n", method, uri) - - var body io.Reader - index := strings.Index(uri, "?") - content_type := "" - - switch method { - case "POST": - if m.Options("file") { - file, e := os.Open(m.Meta["file"][1]) - m.Assert(e) - defer file.Close() - - if m.Option("body_type") == "json" { - content_type = "application/json" - body = file - break - } - buf := &bytes.Buffer{} - writer := multipart.NewWriter(buf) - - part, e := writer.CreateFormFile(m.Option("file"), filepath.Base(m.Meta["file"][1])) - m.Assert(e) - io.Copy(part, file) - - for i := 0; i < len(arg)-1; i += 2 { - value := arg[i+1] - if len(arg[i+1]) > 1 { - switch arg[i+1][0] { - case '$': - value = m.Cap(arg[i+1][1:]) - case '@': - value = m.Conf(arg[i+1][1:]) - } - } - writer.WriteField(arg[i], value) - } - - content_type = writer.FormDataContentType() - body = buf - writer.Close() - } else if m.Option("body_type") == "json" { - if m.Options("body") { - data := []interface{}{} - for _, v := range arg[1:] { - if len(v) > 1 && v[0] == '$' { - v = m.Cap(v[1:]) - } - data = append(data, v) - } - body = strings.NewReader(fmt.Sprintf(m.Option("body"), data...)) - } else { - data := map[string]interface{}{} - for i := 1; i < len(arg)-1; i += 2 { - switch arg[i+1] { - case "false": - data[arg[i]] = false - case "true": - data[arg[i]] = true - default: - if len(arg[i+1]) > 1 && arg[i+1][0] == '$' { - data[arg[i]] = m.Cap(arg[i+1][1:]) - } else { - data[arg[i]] = arg[i+1] - } - } - } - - b, e := json.Marshal(data) - m.Assert(e) - body = bytes.NewReader(b) - } - - content_type = "application/json" - if index > -1 { - uri = uri[:index] - } - - } else if index > 0 { - content_type = "application/x-www-form-urlencoded" - body = strings.NewReader(uri[index+1:]) - uri = uri[:index] - } - } - - req, e := http.NewRequest(method, uri, body) - m.Assert(e) - for i := 0; i < len(m.Meta["headers"]); i += 2 { - req.Header.Set(m.Meta["headers"][i], m.Meta["headers"][i+1]) - } - - if len(content_type) > 0 { - req.Header.Set("Content-Type", content_type) - m.Log("info", "content-type: %s", content_type) - } - - for _, v := range m.Confv("cookie").(map[string]interface{}) { - req.AddCookie(v.(*http.Cookie)) - } - - res, e := web.Client.Do(req) - m.Assert(e) - - for _, v := range res.Cookies() { - m.Confv("cookie", v.Name, v) - m.Log("info", "set-cookie %s: %v", v.Name, v.Value) - } - - if m.Confs("logheaders") { - for k, v := range res.Header { - m.Log("info", "%s: %v", k, v) - } - } - - if m.Confs("output") { - if _, e := os.Stat(m.Conf("output")); e == nil { - name := path.Join(m.Conf("output"), fmt.Sprintf("%d", time.Now().Unix())) - f, e := os.Create(name) - m.Assert(e) - io.Copy(f, res.Body) - if m.Confs("editor") { - cmd := exec.Command(m.Conf("editor"), name) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Run() - } else { - m.Echo("write to %s\n", name) - } - return - } - } - - buf, e := ioutil.ReadAll(res.Body) - m.Assert(e) - - ct := res.Header.Get("Content-Type") - if len(ct) >= 16 && ct[:16] == "application/json" { - var result interface{} - json.Unmarshal(buf, &result) - m.Option("response_json", result) - if m.Has("json_route") { - routes := strings.Split(m.Option("json_route"), ".") - for _, k := range routes { - if len(k) > 0 && k[0] == '$' { - k = m.Cap(k[1:]) - } - switch r := result.(type) { - case map[string]interface{}: - result = r[k] - } - } - } - - fields := map[string]bool{} - for _, k := range strings.Split(m.Option("fields"), " ") { - if k == "" { - continue - } - if fields[k] = true; len(fields) == 1 { - m.Meta["append"] = append(m.Meta["append"], "index") - } - m.Meta["append"] = append(m.Meta["append"], k) - } - - if len(fields) > 0 { - - switch ret := result.(type) { - case map[string]interface{}: - m.Append("index", "0") - for k, v := range ret { - switch value := v.(type) { - case string: - m.Append(k, strings.Replace(value, "\n", " ", -1)) - case float64: - m.Append(k, fmt.Sprintf("%d", int(value))) - default: - if _, ok := fields[k]; ok { - m.Append(k, fmt.Sprintf("%v", value)) - } - } - } - case []interface{}: - for i, r := range ret { - m.Add("append", "index", i) - if rr, ok := r.(map[string]interface{}); ok { - for k, v := range rr { - switch value := v.(type) { - case string: - if _, ok := fields[k]; len(fields) == 0 || ok { - m.Add("append", k, strings.Replace(value, "\n", " ", -1)) - } - case float64: - if _, ok := fields[k]; len(fields) == 0 || ok { - m.Add("append", k, fmt.Sprintf("%d", int64(value))) - } - case bool: - if _, ok := fields[k]; len(fields) == 0 || ok { - m.Add("append", k, fmt.Sprintf("%v", value)) - } - case map[string]interface{}: - for kk, vv := range value { - key := k + "." + kk - if _, ok := fields[key]; len(fields) == 0 || ok { - m.Add("append", key, strings.Replace(fmt.Sprintf("%v", vv), "\n", " ", -1)) - } - } - default: - if _, ok := fields[k]; ok { - m.Add("append", k, fmt.Sprintf("%v", value)) - } - } - } - } - } - - if m.Has("json_key") { - m.Sort(m.Option("json_key")) - } - m.Meta["index"] = nil - for i, _ := range ret { - m.Add("append", "index", i) - } - } - } - } - - if m.Table(); len(m.Meta["append"]) == 0 { - m.Echo("%s", string(buf)) - } - } - }}, }, } func init() { - wiki := &WIKI{} + wiki := &web.WEB{} wiki.Context = Index web.Index.Register(Index, wiki) } diff --git a/usr/library/base.js b/usr/librarys/code.js similarity index 94% rename from usr/library/base.js rename to usr/librarys/code.js index 902fbaec..b244c2ff 100644 --- a/usr/library/base.js +++ b/usr/librarys/code.js @@ -1,20 +1,3 @@ -function insert_child(parent, element, html, position) { - var elm = document.createElement(element) - html && (elm.innerHTML = html) - return parent.insertBefore(elm, position || parent.firstElementChild) -} -function append_child(parent, element, html) { - var elm = document.createElement(element) - html && (elm.innerHTML = html) - parent.append(elm) - return elm -} -function insert_before(self, element, html) { - var elm = document.createElement(element) - html && (elm.innerHTML = html) - return self.parentElement.insertBefore(elm, self) -} - function copy_to_clipboard(text) { var clipboard = document.querySelector(".clipboard") clipboard.value = text diff --git a/usr/library/context.js b/usr/librarys/context.js similarity index 85% rename from usr/library/context.js rename to usr/librarys/context.js index 186ee7ea..a2e52208 100644 --- a/usr/library/context.js +++ b/usr/librarys/context.js @@ -126,3 +126,23 @@ context = { xhr.send(); }, } + +context.isMobile = navigator.userAgent.indexOf("Mobile") > -1 + +function insert_child(parent, element, html, position) { + var elm = document.createElement(element) + html && (elm.innerHTML = html) + return parent.insertBefore(elm, position || parent.firstElementChild) +} +function append_child(parent, element, html) { + var elm = document.createElement(element) + html && (elm.innerHTML = html) + parent.append(elm) + return elm +} +function insert_before(self, element, html) { + var elm = document.createElement(element) + html && (elm.innerHTML = html) + return self.parentElement.insertBefore(elm, self) +} + diff --git a/usr/librarys/wiki.js b/usr/librarys/wiki.js new file mode 100644 index 00000000..ea44d98b --- /dev/null +++ b/usr/librarys/wiki.js @@ -0,0 +1,154 @@ +function action(event, cmd) { + switch (cmd) { + case "toggle_nav": + var nav = document.querySelector("nav") + nav.hidden = !nav.hidden + var article = document.querySelector("article") + if (!context.isMobile) { + article.style.width = nav.hidden? "80%": "calc(100% - 250px)" + } + break + case "toggle_list": + var list = document.querySelector(".list") + list.hidden = !list.hidden + break + case "toggle_menu": + var menu = document.querySelector(".menu") + menu.hidden = !menu.hidden + break + case "toggle_link": + var link = document.querySelector(".link") + link.hidden = !link.hidden + break + } +} + +function init_menu() { + var max = 0; + var min = 1000; + var list = []; + var hs = ["h2", "h3", "h4"]; + for (var i = 0; i < hs.length; i++) { + var head = document.getElementsByTagName(hs[i]); + for (var j = 0; j < head.length; j++) { + head[j].id = "head"+head[j].offsetTop; + head[j].onclick = function(event) {} + list.push({"level": hs[i], "position": head[j].offsetTop, "title": head[j].innerText, "hash": head[j].id}) + if (head[j].offsetTop > max) { + max = head[j].offsetTop; + } + if (head[j].offsetTop < min) { + min = head[j].offsetTop; + } + } + } + + max = max - min; + for (var i = 0; i < list.length-1; i++) { + for (var j = i+1; j < list.length; j++) { + if (list[j].position < list[i].position) { + var a = list[i]; + list[i] = list[j]; + list[j] = a; + } + } + } + + var index = [-1, 0, 0] + for (var i = 0; i < list.length; i++) { + if (list[i].level == "h2") { + index[0]++; + index[1]=0; + index[2]=0; + } else if (list[i].level == "h3") { + index[1]++; + index[2]=0; + } else { + index[2]++; + } + + list[i].index4 = index[2]; + list[i].index3 = index[1]; + list[i].index2 = index[0]; + } + + var m = document.getElementsByClassName("menu"); + for (var i = 0; i < m.length; i++) { + for (var j = 0; j < list.length; j++) { + var text = list[j].index2+"." + if (list[j].level == "h3") { + text += list[j].index3 + } else if (list[j].level == "h4") { + text += list[j].index3+"."+list[j].index4 + } + + text += " " + text += list[j].title; + + var h = document.getElementById(list[j].hash) + h.innerText = text + + var one = append_child(m[i], "li") + var a = append_child(one, "a") + a.href = "#"+list[j].hash; + a.innerText = text+" ("+parseInt((list[j].position-min)/max*100)+"%)"; + + one.className = list[j].level; + } + } +} + +function init_link() { + var link = []; + var a = document.querySelectorAll(".text a"); + for (var i = 0; i < a.length; i++) { + link.push({href: a[i].href, title: a[i].innerText}); + } + var m = document.getElementsByClassName("link"); + for (var i = 0; i < m.length; i++) { + var one = append_child(m[i], "li") + var a = one.appendChild(document.createTextNode("相关链接: ")); + + for (var j = 0; j < link.length; j++) { + var one = append_child(m[i], "li") + var a = one.appendChild(document.createTextNode(link[j].title+": ")); + var a = append_child(one, "a"); + a.href = link[j].href + a.innerText = a.href + } + } +} + +function init_code() { + var m = document.getElementsByTagName("pre"); + for (var i = 0; i < m.length; i++) { + var line = (m[i].clientHeight-10)/15 + // if (line < 3) { + // continue + // } + console.log(m[i].clientHeight) + var nu = m[i].parentElement.insertBefore(document.createElement("div"), m[i]); + nu.className = "number1" + + for (var j = 1; j <= line; j++) { + console.log(j) + var li = nu.appendChild(document.createElement("div")); + li.appendChild(document.createTextNode(""+j)); + } + } +} + +window.onload = function() { + init_menu() + init_link() + init_code() + var article = document.querySelector("article") + var mav = document.querySelector("nav") + alert(context.isMobile) + if (context.isMobile) { + article.style.width = "100%" + } else { + article.style.maxHeight = "calc(100% - 80px)" + mav.style.maxHeight = "calc(100% - 80px)" + } +} diff --git a/usr/template/code/code.tmpl b/usr/template/code/code.tmpl new file mode 100644 index 00000000..a38a513e --- /dev/null +++ b/usr/template/code/code.tmpl @@ -0,0 +1,198 @@ +{{define "head"}} + + + + +{{option .Meta "page_title"}} + + + + + +{{end}} + +{{define "void"}}{{end}} + +{{define "detail"}}{{detail .}}{{end}} +{{define "option"}}{{option .}}{{end}} +{{define "append"}}{{append .}}{{end}} +{{define "result"}}{{result .}}{{end}} + +{{define "clipboard"}} +
clipboard + + + +
+{{end}} + +{{define "componet"}} +
{{option .Meta "help"}}({{option .Meta "context"}}.{{option .Meta "command"}}) + {{$form_type := option . "form_type"|meta}} + + {{if eq $form_type "upload"}} + {{end}} +
+ + {{range $index, $input := option . "inputs"}} +
+ {{$type := index $input "type"}} + {{if index $input "label"}} + + {{end}} + {{if eq $type "button"}} + + {{else if eq $type "submit"}} + + {{else if eq $type "file"}} + + {{else if eq $type "choice"}} + {{$default_value := index $input "value"}} + + {{else}} + + {{end}} +
+ {{end}} +
+
+ {{if eq $form_type "upload"}} + {{end}} + + {{if index .Meta "display_append"}} + {{option .Meta "display_append"}} + {{else}} + + {{$msg := .}} + {{range $field := append .}}{{end}} + {{range $line := table .}} + {{range $field := append $msg}}{{end}} + {{end}} +
{{$field}}
{{index $line $field|unescape}}
+ {{end}} + + {{if index .Meta "display_result"}} + {{option .Meta "display_result"}} + {{else}} +
{{result .Meta}}
+ {{end}} +
+{{end}} + +{{define "tail"}} + + + +{{end}} diff --git a/usr/template/common/base.tmpl b/usr/template/web/web.tmpl similarity index 100% rename from usr/template/common/base.tmpl rename to usr/template/web/web.tmpl diff --git a/usr/template/wiki/wiki.tmpl b/usr/template/wiki/wiki.tmpl new file mode 100644 index 00000000..b93155fb --- /dev/null +++ b/usr/template/wiki/wiki.tmpl @@ -0,0 +1,148 @@ +{{define "head"}} + + + + +{{option .Meta "page_title"}} + + + +{{end}} + +{{define "header"}} +
+
+ +
shylinux
+
+
+
+ + +
{{result .|meta|unescape}}
+
+{{end}} + +{{define "footer"}} + +{{end}} + +{{define "tail"}} + + + +{{end}}