diff --git a/etc/init.shy b/etc/init.shy
index 5bfdb1e3..a95b3d83 100644
--- a/etc/init.shy
+++ b/etc/init.shy
@@ -1,14 +1,2 @@
-~aaa
- # login load var/login.txt
-~file1
- history load var/history.txt
-
source etc/local.shy
-~shell1
- alias import nfs
- alias send send
- alias open open
- alias dial dial
- alias pwd pwd
-
diff --git a/src/contexts/aaa/aaa.go b/src/contexts/aaa/aaa.go
index cce25fb9..224742e0 100644
--- a/src/contexts/aaa/aaa.go
+++ b/src/contexts/aaa/aaa.go
@@ -69,7 +69,9 @@ func (aaa *AAA) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
return time.Unix(int64(n), 0).Format("15:03:04")
}},
}
- c.Configs = map[string]*ctx.Config{}
+ c.Configs = map[string]*ctx.Config{
+ "right": &ctx.Config{Name: "right", Value: map[string]interface{}{}, Help: "用户权限"},
+ }
s := new(AAA)
s.Context = c
@@ -153,6 +155,7 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
}
return true
}, c)
+
if m.Results(0) {
return
}
@@ -173,18 +176,26 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
}
return true
}, c)
+
if m.Results(0) {
+ m.Append("sessid", m.Result(0))
+ return
+ }
+ if arg[0] == "" {
return
}
m.Start(fmt.Sprintf("user%d", m.Capi("nuser", 1)), "密码登录", "password", arg[0])
m.Cap("password", "password", aaa.Password(arg[1]), "密码登录")
+ m.Append("sessid", m.Cap("sessid"))
m.Echo(m.Cap("sessid"))
return
case 1:
+ m.Sess("login", nil)
m.Travel(func(m *ctx.Message, n int) bool {
if n > 0 && m.Cap("sessid") == arg[0] {
if int64(m.Capi("expire_time")) > time.Now().Unix() {
+ m.Sess("login", m.Target().Message())
m.Echo(m.Cap("stream"))
} else {
m.Target().Close(m)
@@ -205,6 +216,92 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
}
}
}},
+ "right": &ctx.Command{Name: "right [user [check|owner|share group [order] [add|del]]]", Form: map[string]int{"from": 1}, Help: "权限管理", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
+ m.Travel(func(m *ctx.Message, n int) bool {
+ if n == 0 {
+ return true
+ }
+ if len(arg) == 0 {
+ m.Add("append", "user", m.Cap("stream"))
+ m.Add("append", "right", m.Confv("right"))
+ return true
+ }
+ if m.Cap("stream") == arg[0] {
+ if len(arg) == 1 { //查看所有权
+ for k, v := range m.Confv("right").(map[string]interface{}) {
+ m.Add("append", "group", k)
+ m.Add("append", "right", v)
+ }
+ return true
+ }
+ if arg[1] == "check" { //权限检查
+ if from := m.Confv("right", []interface{}{"right", "role"}); from != nil && from.(string) == "root" {
+ m.Echo("root")
+ }
+ if len(arg) == 2 {
+ return false
+ }
+ if from := m.Confv("right", []interface{}{arg[2], "right", "role"}); from != nil && from.(string) == "owner" {
+ m.Echo("owner")
+ }
+ if len(arg) == 3 {
+ return false
+ }
+ if from := m.Confv("right", []interface{}{arg[2], arg[3], "right", "role"}); from != nil && from.(string) == "share" {
+ m.Echo("share")
+ }
+ return false
+ }
+ if len(arg) == 2 { //分配人事权
+ if m.Option("from") != "root" {
+ return false
+ }
+ switch arg[1] {
+ case "add":
+ m.Confv("right", []interface{}{"right", "role"}, "root")
+ m.Confv("right", []interface{}{"right", "from"}, m.Option("from"))
+ case "del":
+ m.Confv("right", []interface{}{"right", "role"}, "")
+ }
+ return true
+ }
+ if len(arg) == 3 { //查看使用权
+ for k, v := range m.Confv("right", arg[2]).(map[string]interface{}) {
+ m.Add("append", "order", k)
+ m.Add("append", "right", v)
+ }
+ return true
+ }
+ switch arg[1] {
+ case "owner": //分配所有权
+ if m.Cmd("right", m.Option("from"), "check").Result(0) == "" {
+ return false
+ }
+ switch arg[3] {
+ case "add":
+ m.Confv("right", []interface{}{arg[2], "right", "role"}, "owner")
+ m.Confv("right", []interface{}{arg[2], "right", "from"}, m.Option("from"))
+ case "del":
+ m.Confv("right", []interface{}{arg[2], "right", "role"}, "")
+ }
+ case "share": //分配使用权
+ if m.Cmd("right", m.Option("from"), "check", arg[2]).Result(0) == "" {
+ return false
+ }
+ switch arg[4] {
+ case "add":
+ m.Confv("right", []interface{}{arg[2], arg[3], "right", "role"}, "share")
+ m.Confv("right", []interface{}{arg[2], arg[3], "right", "from"}, m.Option("from"))
+ case "del":
+ m.Confv("right", []interface{}{arg[2], arg[3], "right", "role"}, "")
+ }
+ }
+ return false
+ }
+ return true
+ }, c)
+ m.Table()
+ }},
"cert": &ctx.Command{Name: "cert [filename]", Help: "导出证书", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if aaa, ok := m.Target().Server.(*AAA); m.Assert(ok) && aaa.certificate != nil {
certificate := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: aaa.certificate.Raw}))
diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go
index 09596344..5420c38d 100644
--- a/src/contexts/cli/cli.go
+++ b/src/contexts/cli/cli.go
@@ -1,20 +1,16 @@
-package cli // {{{
-// }}}
-import ( // {{{
- "contexts/ctx"
+package cli
+import (
+ "contexts/ctx"
"fmt"
+ "os"
+ "os/exec"
"regexp"
"strconv"
"strings"
-
- "os"
- "os/exec"
"time"
)
-// }}}
-
type Frame struct {
key string
run bool
@@ -22,7 +18,6 @@ type Frame struct {
index int
list []string
}
-
type CLI struct {
alias map[string][]string
label map[string]string
@@ -33,7 +28,7 @@ type CLI struct {
*ctx.Context
}
-func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
+func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
c.Caches = map[string]*ctx.Cache{
"level": &ctx.Cache{Name: "level", Value: "0", Help: "嵌套层级"},
"parse": &ctx.Cache{Name: "parse(true/false)", Value: "true", Help: "命令解析"},
@@ -43,15 +38,15 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
}
c.Configs = map[string]*ctx.Config{
"ps_time": &ctx.Config{Name: "ps_time", Value: "[15:04:05]", Help: "当前时间", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
- if len(arg) > 0 { // {{{
+ if len(arg) > 0 {
return arg[0]
}
return time.Now().Format(x.Value.(string))
- // }}}
+
}},
"ps_end": &ctx.Config{Name: "ps_end", Value: "> ", Help: "命令行提示符结尾"},
"prompt": &ctx.Config{Name: "prompt(ps_count/ps_time/ps_target/ps_end/...)", Value: "ps_count ps_time ps_target ps_end", Help: "命令行提示符, 以空格分隔, 依次显示缓存或配置信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
- if len(arg) > 0 { // {{{
+ if len(arg) > 0 {
return arg[0]
}
@@ -64,7 +59,7 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
}
}
return strings.Join(ps, "")
- // }}}
+
}},
}
@@ -83,15 +78,11 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
return s
}
-
-// }}}
-func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
+func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
cli.Message = m
return cli
}
-
-// }}}
-func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
+func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
cli.Message = m
m.Sess("cli", m)
yac := m.Sess("yac")
@@ -178,9 +169,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
}
return false
}
-
-// }}}
-func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{
+func (cli *CLI) Close(m *ctx.Message, arg ...string) bool {
switch cli.Context {
case m.Target():
case m.Source():
@@ -188,8 +177,6 @@ func (cli *CLI) Close(m *ctx.Message, arg ...string) bool { // {{{
return true
}
-// }}}
-
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "cli", Help: "管理中心",
Caches: map[string]*ctx.Cache{
@@ -199,11 +186,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"init.shy": &ctx.Config{Name: "init.shy", Value: "etc/init.shy", Help: "启动脚本"},
"exit.shy": &ctx.Config{Name: "exit.shy", Value: "etc/exit.shy", Help: "启动脚本"},
"cli_name": &ctx.Config{Name: "cli_name", Value: "shell", Help: "模块命名", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
- if len(arg) > 0 { // {{{
+ if len(arg) > 0 {
return arg[0]
}
return fmt.Sprintf("%s%d", x.Value, m.Capi("nshell", 1))
- // }}}
+
}},
"cli_help": &ctx.Config{Name: "cli_help", Value: "shell", Help: "模块文档"},
"cmd_timeout": &ctx.Config{Name: "cmd_timeout", Value: "60s", Help: "系统命令超时"},
@@ -239,28 +226,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
}},
"label": &ctx.Command{Name: "label name", Help: "记录当前脚本的位置, name: 位置名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if cli.label == nil {
cli.label = map[string]string{}
}
cli.label[arg[1]] = m.Option("file_pos")
- } // }}}
+ }
}},
"goto": &ctx.Command{Name: "goto label [exp] condition", Help: "向上跳转到指定位置, label: 跳转位置, condition: 跳转条件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if pos, ok := cli.label[arg[1]]; ok {
if !ctx.Right(arg[len(arg)-1]) {
return
}
m.Append("file_pos0", pos)
}
- } // }}}
+ }
}},
"return": &ctx.Command{Name: "return result...", Help: "结束脚本, result: 返回值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Add("append", "return", arg[1:])
}},
"target": &ctx.Command{Name: "target module", Help: "设置当前模块, module: 模块全名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if len(arg) == 0 {
m.Echo("%s", m.Cap("ps_target"))
return
@@ -269,13 +256,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
cli.target = msg.Target()
m.Cap("ps_target", cli.target.Name)
}
- } // }}}
+ }
}},
"alias": &ctx.Command{
Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]",
Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名, import导入模块所有命令",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
switch len(arg) {
case 0:
for k, v := range cli.alias {
@@ -318,21 +305,21 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Log("info", "%s: %v", arg[0], cli.alias[arg[0]])
}
}
- } // }}}
+ }
}},
"sleep": &ctx.Command{Name: "sleep time", Help: "睡眠, time(ns/us/ms/s/m/h): 时间值(纳秒/微秒/毫秒/秒/分钟/小时)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if d, e := time.ParseDuration(arg[0]); m.Assert(e) { // {{{
+ if d, e := time.ParseDuration(arg[0]); m.Assert(e) {
m.Log("info", "sleep %v", d)
time.Sleep(d)
m.Log("info", "sleep %v done", d)
- } // }}}
+ }
}},
"time": &ctx.Command{
Name: "time [time_format format] [parse when] when [begin|end|yestoday|tommorow|monday|sunday|first|last|origin|last]",
Form: map[string]int{"time_format": 1, "parse": 1, "time_interval": 1},
Help: "查看时间, time_format: 输出或解析的时间格式, parse: 输入的时间字符串, when: 输入的时间戳, 其它是时间偏移",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- t := time.Now() // {{{
+ t := time.Now()
if m.Options("parse") {
n, e := time.ParseInLocation(m.Confx("time_format"), m.Option("parse"), time.Local)
m.Assert(e)
@@ -341,7 +328,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
if len(arg) > 0 {
if i, e := strconv.ParseInt(arg[0], 10, 64); e == nil {
- m.Option("time_format", m.Conf("time_format"))
t = time.Unix(int64(i/int64(m.Confi("time_unit"))), 0)
arg = arg[1:]
} else if n, e := time.ParseInLocation(m.Confx("time_format"), arg[0], time.Local); e == nil {
@@ -405,7 +391,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
} else {
m.Echo(t.Format(m.Confx("time_format")))
}
- // }}}
+
}},
"echo": &ctx.Command{Name: "echo arg...", Help: "函数调用, name: 函数名, arg: 参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Echo("%s", strings.Join(arg, ""))
@@ -415,7 +401,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Echo(arg[0][1 : len(arg[0])-1])
}},
"exe": &ctx.Command{Name: "exe $ ( cmd )", Help: "解析嵌套命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
switch len(arg) {
case 1:
m.Echo(arg[0])
@@ -438,7 +424,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
} //}}}
}},
"val": &ctx.Command{Name: "val exp", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- result := "false" // {{{
+ result := "false"
switch len(arg) {
case 0:
result = ""
@@ -567,7 +553,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
}
m.Echo(result)
- // }}}
+
}},
"exp": &ctx.Command{Name: "exp word", Help: "表达式运算", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if len(arg) > 0 && arg[0] == "{" {
@@ -585,7 +571,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
return
}
- pre := map[string]int{ // {{{
+ pre := map[string]int{
"=": 1,
"+": 2, "-": 2,
"*": 3, "/": 3, "%": 3,
@@ -609,10 +595,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
m.Echo("%s", num[0])
- // }}}
+
}},
"var": &ctx.Command{Name: "var a [= exp]", Help: "定义变量, a: 变量名, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 { // {{{
+ if m.Cap(arg[1], arg[1], "", "临时变量"); len(arg) > 1 {
switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
@@ -621,28 +607,28 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
}
m.Echo(m.Cap(arg[1]))
- // }}}
+
}},
"let": &ctx.Command{Name: "let a = exp", Help: "设置变量, a: 变量名, exp: 表达式(a {+|-|*|/|%} b)", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- switch arg[2] { // {{{
+ switch arg[2] {
case "=":
m.Cap(arg[1], arg[3])
case "<-":
m.Cap(arg[1], m.Cap("last_msg"))
}
m.Echo(m.Cap(arg[1]))
- // }}}
+
}},
"if": &ctx.Command{Name: "if exp", Help: "条件语句, exp: 表达式", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
run := m.Caps("parse") && ctx.Right(arg[1])
cli.stack = append(cli.stack, &Frame{pos: m.Optioni("file_pos"), key: key, run: run})
m.Capi("level", 1)
m.Caps("parse", run)
- } // }}}
+ }
}},
"else": &ctx.Command{Name: "else", Help: "条件语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if !m.Caps("parse") {
m.Caps("parse", true)
} else {
@@ -653,10 +639,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Caps("parse", !frame.run)
}
}
- } // }}}
+ }
}},
"end": &ctx.Command{Name: "end", Help: "结束语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
if frame := cli.stack[len(cli.stack)-1]; frame.key == "for" && frame.run {
m.Append("file_pos0", frame.pos)
return
@@ -667,13 +653,13 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
} else {
m.Caps("parse", true)
}
- } // }}}
+ }
}},
"for": &ctx.Command{
Name: "for [[express ;] condition]|[index message meta value]",
Help: "循环语句, express: 每次循环运行的表达式, condition: 循环条件, index: 索引消息, message: 消息编号, meta: value: ",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
run := m.Caps("parse")
defer func() { m.Caps("parse", run) }()
@@ -726,10 +712,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
m.Cap(arg[3], arg[3], frame.list[0], "临时变量")
}
- } // }}}
+ }
}},
"cmd": &ctx.Command{Name: "cmd word", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) { // {{{
+ if cli, ok := m.Target().Server.(*CLI); m.Assert(ok) {
detail := []string{}
if a, ok := cli.alias[arg[0]]; ok {
detail = append(detail, a...)
@@ -774,14 +760,14 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Capi("last_msg", 0, msg.Code())
m.Capi("ps_count", 1)
}
- // }}}
+
}},
"system": &ctx.Command{
Name: "system [cmd_combine true|false] [cmd_timeout time] word...",
Help: "调用系统命令, cmd_combine: 非交互式命令, cmd_timeout: 命令超时, word: 命令",
Form: map[string]int{"cmd_combine": 1, "cmd_timeout": 1},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- system := map[string]bool{"vi": true} // {{{
+ system := map[string]bool{"vi": true}
ui, ok := system[arg[0]]
if ui = ok && ui; m.Option("cmd_combine") != "" {
ui = !m.Options("cmd_combine")
@@ -816,7 +802,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
case <-wait:
}
}
- // }}}
+
}},
"login": &ctx.Command{Name: "login username password", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Sess("aaa", false).Cmd("login", arg[0], arg[1])
@@ -827,6 +813,27 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"tmux": &ctx.Command{Name: "tmux", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Copy(m.Spawn().Cmd("system", "tmux", arg), "result")
}},
+ "buffer": &ctx.Command{Name: "buffer", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
+ bufs := strings.Split(m.Spawn().Cmd("system", "tmux", "list-buffers").Result(0), "\n")
+
+ n := 3
+ if m.Option("limit") != "" {
+ n = m.Optioni("limit")
+ }
+
+ for i, b := range bufs {
+ if i >= n {
+ break
+ }
+ bs := strings.SplitN(b, ": ", 3)
+ if len(bs) > 1 {
+ m.Add("append", "buffer", bs[0][:len(bs[0])])
+ m.Add("append", "length", bs[1][:len(bs[1])-6])
+ m.Add("append", "string", bs[2][1:len(bs[2])-1])
+ }
+ }
+ m.Echo(m.Append("string"))
+ }},
},
Index: map[string]*ctx.Context{
"void": &ctx.Context{Caches: map[string]*ctx.Cache{"nshell": &ctx.Cache{}}},
diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go
index 2544921a..b5abe2ca 100644
--- a/src/contexts/ctx/ctx.go
+++ b/src/contexts/ctx/ctx.go
@@ -709,7 +709,14 @@ func (m *Message) Search(key string, root ...bool) []*Message {
}
func (m *Message) Sess(key string, arg ...interface{}) *Message {
spawn := true
- if _, ok := m.Sessions[key]; !ok && len(arg) > 0 {
+ if len(arg) > 0 {
+ switch v := arg[0].(type) {
+ case bool:
+ spawn, arg = v, arg[1:]
+ }
+ }
+
+ if len(arg) > 0 {
if m.Sessions == nil {
m.Sessions = make(map[string]*Message)
}
@@ -747,13 +754,9 @@ func (m *Message) Sess(key string, arg ...interface{}) *Message {
m.Sessions[key] = m.Search(value, root)[0]
}
return m.Sessions[key]
- }
- }
-
- if len(arg) > 0 {
- switch v := arg[0].(type) {
- case bool:
- spawn = v
+ case nil:
+ m.Sessions[key] = nil
+ return nil
}
}
@@ -1077,6 +1080,14 @@ func (m *Message) Sort(key string, arg ...string) *Message {
for j := i + 1; j < len(table); j++ {
result := false
switch cmp {
+ case "str":
+ if table[i][key] > table[j][key] {
+ result = true
+ }
+ case "str_r":
+ if table[i][key] < table[j][key] {
+ result = true
+ }
case "int":
a, e := strconv.Atoi(table[i][key])
m.Assert(e)
@@ -1093,14 +1104,6 @@ func (m *Message) Sort(key string, arg ...string) *Message {
if a < b {
result = true
}
- case "string":
- if table[i][key] > table[j][key] {
- result = true
- }
- case "string_r":
- if table[i][key] < table[j][key] {
- result = true
- }
case "time":
ti, e := time.ParseInLocation(m.Confx("time_layout"), table[i][key], time.Local)
m.Assert(e)
@@ -1964,16 +1967,18 @@ var CGI = template.FuncMap{
m.Assert(e)
index = i
}
+
if len(arg) == 2 {
return m.Detail(index)
}
+
return m.Detail(index, arg[2])
case map[string][]string:
return strings.Join(m["detail"], "")
case []string:
return strings.Join(m, "")
default:
- return fmt.Sprintf("%v", arg[0])
+ return m
}
return ""
},
@@ -2016,7 +2021,7 @@ var CGI = template.FuncMap{
case []string:
return strings.Join(m, "")
default:
- return fmt.Sprintf("%v", arg[0])
+ return m
}
return ""
},
@@ -2040,16 +2045,18 @@ var CGI = template.FuncMap{
m.Assert(e)
index = i
}
+
if len(arg) == 2 {
return m.Result(index)
}
+
return m.Result(index, arg[2])
case map[string][]string:
return strings.Join(m["result"], "")
case []string:
return strings.Join(m, "")
default:
- return fmt.Sprintf("%v", arg[0])
+ return m
}
return ""
},
@@ -2092,11 +2099,55 @@ var CGI = template.FuncMap{
case []string:
return strings.Join(m, "")
default:
- return fmt.Sprintf("%v", arg[0])
+ return m
}
return ""
},
- "unscaped": func(str string) interface{} {
+ "table": func(arg ...interface{}) []interface{} {
+ if len(arg) == 0 {
+ return []interface{}{}
+ }
+
+ switch m := arg[0].(type) {
+ case *Message:
+ if len(m.Meta["append"]) == 0 {
+ return []interface{}{}
+ }
+ if len(arg) == 1 {
+ data := []interface{}{}
+ nrow := len(m.Meta[m.Meta["append"][0]])
+ for i := 0; i < nrow; i++ {
+ line := map[string]string{}
+ for _, k := range m.Meta["append"] {
+ line[k] = m.Meta[k][i]
+ if len(m.Meta[k]) != i {
+ continue
+ }
+ }
+ data = append(data, line)
+ }
+
+ return data
+ }
+ case map[string][]string:
+ if len(arg) == 1 {
+ data := []interface{}{}
+ nrow := len(m[m["append"][0]])
+
+ for i := 0; i < nrow; i++ {
+ line := map[string]string{}
+ for _, k := range m["append"] {
+ line[k] = m[k][i]
+ }
+ data = append(data, line)
+ }
+
+ return data
+ }
+ }
+ return []interface{}{}
+ },
+ "unescape": func(str string) interface{} {
return template.HTML(str)
},
@@ -2978,7 +3029,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
"where_field": 1, "where_value": 1,
"sort_field": 1, "sort_order": 1,
"page_limit": 1, "page_offset": 1,
- "select": 3,
+ "format_field": 2,
+ "select": 3,
},
Hand: func(m *Message, c *Context, key string, arg ...string) {
offset, e := strconv.Atoi(m.Confx("page_offset"))
@@ -3022,6 +3074,12 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
de.Decode(&save)
}
+ format_field := m.Option("format_field")
+ format_str := "%s"
+ if format_field != "" {
+ format_str = m.Meta["format_field"][1]
+ }
+
// sort_field := m.Option("sort_field")
// sort_order := m.Option("sort_order")
m.BackTrace(func(m *Message) bool {
@@ -3113,7 +3171,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
m.Add("append", "index", "0")
for k, v := range val {
if len(fields) == 0 || fields[k] {
- m.Add("append", k, v)
+ if k == format_field {
+ m.Add("append", k, fmt.Sprintf(format_str, v))
+ } else {
+ m.Add("append", k, v)
+ }
}
}
case []interface{}:
@@ -3134,7 +3196,11 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
m.Add("append", "index", i)
for k, v := range val {
if len(fields) == 0 || fields[k] {
- m.Add("append", k, v)
+ if k == format_field {
+ m.Add("append", k, fmt.Sprintf(format_str, v, v))
+ } else {
+ m.Add("append", k, v)
+ }
}
}
}
@@ -3142,11 +3208,18 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
case []string:
for i, v := range val {
m.Add("append", "index", i)
- m.Add("append", "value", v)
+ if k == format_field {
+ m.Add("append", k, fmt.Sprintf(format_str, v, v))
+ } else {
+ m.Add("append", k, v)
+ }
}
default:
m.Echo("%v", Trans(val)[0])
}
+ case 3:
+ m.Echo("%v", m.Confv(arg[0], strings.Split(arg[1], "."), arg[2]))
+
default:
m.Echo("%v", m.Confv(arg[0], arg[1:]))
return false
diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go
index c864bc6f..7904ec3e 100644
--- a/src/contexts/nfs/nfs.go
+++ b/src/contexts/nfs/nfs.go
@@ -68,8 +68,8 @@ func dir(m *ctx.Message, name string, level int, deep bool, fields []string) {
switch k {
case "filename":
m.Add("append", "filename", "..")
- case "dir":
- m.Add("append", "dir", "true")
+ case "is_dir":
+ m.Add("append", "is_dir", "true")
case "size":
m.Add("append", "size", 0)
case "line":
@@ -130,8 +130,8 @@ func dir(m *ctx.Message, name string, level int, deep bool, fields []string) {
switch k {
case "filename":
m.Add("append", "filename", filename)
- case "dir":
- m.Add("append", "dir", f.IsDir())
+ case "is_dir":
+ m.Add("append", "is_dir", f.IsDir())
case "size":
m.Add("append", "size", f.Size())
case "line":
@@ -803,11 +803,12 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"buf_size": &ctx.Config{Name: "buf_size", Value: "1024", Help: "读取文件的缓存区的大小"},
"qr_size": &ctx.Config{Name: "qr_size", Value: "256", Help: "生成二维码的图片的大小"},
- "dir_name": &ctx.Config{Name: "dir_name(name/tree/path/full)", Value: "name", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"},
- "dir_info": &ctx.Config{Name: "dir_info(sizes/lines/files/dirs)", Value: "sizes lines files dirs", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"},
+ "dir_root": &ctx.Config{Name: "dir_root", Value: "usr", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"},
"dir_deep": &ctx.Config{Name: "dir_deep(yes/no)", Value: "yes", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"},
"dir_type": &ctx.Config{Name: "dir_type(file/dir)", Value: "file", Help: "dir命令输出的文件类型, file: 只输出普通文件, dir: 只输出目录文件, 否则输出所有文件"},
- "dir_field": &ctx.Config{Name: "dir_field", Value: "filename line size time", Help: "表格排序字段"},
+ "dir_name": &ctx.Config{Name: "dir_name(name/tree/path/full)", Value: "name", Help: "dir命令输出文件名的类型, name: 文件名, tree: 带缩进的文件名, path: 相对路径, full: 绝对路径"},
+ "dir_info": &ctx.Config{Name: "dir_info(sizes/lines/files/dirs)", Value: "sizes lines files dirs", Help: "dir命令输出目录的统计信息, info: 输出统计信息, 否则输出"},
+ "dir_field": &ctx.Config{Name: "dir_field", Value: "filename is_dir line size time", Help: "表格排序字段"},
"sort_field": &ctx.Config{Name: "sort_field", Value: "line", Help: "表格排序字段"},
"sort_order": &ctx.Config{Name: "sort_order(int/int_r/string/string_r/time/time_r)", Value: "int", Help: "表格排序类型"},
@@ -1078,13 +1079,16 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
if len(arg) == 1 {
var data interface{}
e := json.Unmarshal([]byte(arg[0]), &data)
+ if e != nil {
+ return
+ }
m.Assert(e)
buf, e := json.MarshalIndent(data, "", " ")
m.Assert(e)
- m.Echo("'")
+ // m.Echo("'")
m.Echo(string(buf))
- m.Echo("'")
+ // m.Echo("'")
return
}
@@ -1122,10 +1126,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
"pwd": &ctx.Command{Name: "pwd", Help: "查看当前路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if m.Options("dir") {
m.Echo(m.Option("dir"))
- m.Add("append", "hi", "hello")
- m.Add("append", "he", "hello")
- m.Add("append", "hi", "world")
- m.Add("append", "he", "world")
return
}
if len(arg) > 0 {
@@ -1134,20 +1134,31 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
wd, e := os.Getwd()
m.Assert(e)
m.Echo(wd)
- m.Append("hi", "hello")
}},
"dir": &ctx.Command{
- Name: "dir dir [dir_deep yes|no] [dir_info info] [dir_name name|tree|path|full] [dir_type file|dir] [sort_field name] [sort_order type]",
+ Name: "dir dir [dir_deep yes|no] [dir_info info] [dir_name name|tree|path|full] [dir_type both|file|dir] [sort_field name] [sort_order type]",
Help: "查看目录, dir: 目录名, dir_info: 显示统计信息, dir_name: 文件名类型, dir_type: 文件类型, sort_field: 排序字段, sort_order: 排序类型",
- Form: map[string]int{"dir_field": 1, "dir_deep": 1, "dir_info": 1, "dir_name": 1, "dir_type": 1, "sort_field": 1, "sort_order": 1},
+ Form: map[string]int{
+ "dir_root": 1,
+ "dir_deep": 1,
+ "dir_type": 1,
+ "dir_name": 1,
+ "dir_info": 1,
+ "dir_link": 1,
+ "dir_field": 1,
+ "sort_field": 1,
+ "sort_order": 1,
+ },
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- d := "./" + m.Option("dir")
if len(arg) > 0 {
- d = arg[0]
+ m.Option("dir", arg[0])
}
+ m.Option("dir", path.Clean(m.Option("dir")))
+ d := path.Join(m.Confx("dir_root"), m.Option("dir"))
if s, e := os.Stat(d); m.Assert(e) && !s.IsDir() {
d = path.Dir(d)
}
+
fields := strings.Split(m.Confx("dir_field"), " ")
trip := 0
@@ -1170,22 +1181,30 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
key := m.Meta["append"][i]
switch key {
case "filename":
+ v = maps[key]
if line > -1 && trip > 0 && trip <= len(v) {
v = v[trip:]
- m.Meta["filename"][line] = v
+ if m.Options("dir_link") {
+ m.Meta["filename"][line] = fmt.Sprintf(m.Option("dir_link"), maps["is_dir"], v)
+ } else {
+ m.Meta["filename"][line] = v
+ }
+ }
+ if line > -1 {
+ if m.Options("dir_link") {
+ m.Meta["filename"][line] = fmt.Sprintf(m.Option("dir_link"), maps["is_dir"], v)
+ }
}
- case "dir":
- continue
}
- m.Echo("%s\t", v)
}
- m.Echo("\n")
return true
})
+ if !m.Options("dir_link") {
+ m.Table()
+ }
for _, v := range info {
m.Echo("%s: %s\n", v, m.Option(v))
}
-
}},
"git": &ctx.Command{
Name: "git branch|status|diff|log|info arg... [dir path]...",
diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go
index 4d9c22d7..4536944f 100644
--- a/src/contexts/web/web.go
+++ b/src/contexts/web/web.go
@@ -27,8 +27,8 @@ type MUX interface {
type WEB struct {
*http.Client
*http.ServeMux
- *http.Server
- *template.Template
+ server *http.Server
+ template *template.Template
*ctx.Context
}
@@ -80,7 +80,9 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) {
m.TryCatch(m.Spawn(), true, func(msg *ctx.Message) {
msg.Add("option", "method", r.Method).Add("option", "path", r.URL.Path)
+ msg.Option("remote_addr", r.RemoteAddr)
msg.Option("referer", r.Header.Get("Referer"))
+ msg.Option("accept", r.Header.Get("Accept"))
if r.ParseForm(); len(r.PostForm) > 0 {
for k, v := range r.PostForm {
@@ -101,11 +103,11 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) {
switch {
case msg.Has("redirect"):
- http.Redirect(w, r, msg.Append("redirect"), http.StatusFound)
+ http.Redirect(w, r, msg.Append("redirect"), http.StatusTemporaryRedirect)
case msg.Has("directory"):
http.ServeFile(w, r, msg.Append("directory"))
- case msg.Has("template"):
- msg.Spawn().Cmd("/render", msg.Meta["template"])
+ case msg.Has("componet"):
+ msg.Spawn().Add("option", "componet_group", msg.Meta["componet"]).Cmd("/render")
case msg.Has("append"):
meta := map[string]interface{}{}
if len(msg.Meta["result"]) > 0 {
@@ -208,16 +210,16 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool {
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
}
@@ -244,16 +246,192 @@ 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: "路由数量"},
- "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", Help: "路由数量"},
- "template_file": &ctx.Config{Name: "template_file", Value: "usr/template", Help: "路由数量"},
- "template": &ctx.Config{Name: "template", Value: map[string]interface{}{
- "index": []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"},
+ "template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template", 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": "message", "title": "message",
- "context": "nfs", "command": "pwd",
+ "template": "head", "name": "head", "help": "head",
+ "context": "", "command": "", "arguments": []interface{}{},
+ },
+ map[string]interface{}{
+ "template": "componet", "name": "login", "help": "login",
+ "context": "aaa", "command": "login", "arguments": []interface{}{"@username", "@password"},
+ "inputs": []interface{}{
+ map[string]interface{}{
+ "type": "text", "name": "username",
+ "label": "username", "value": "",
+ },
+ map[string]interface{}{
+ "type": "password", "name": "password",
+ "label": "password", "value": "",
+ },
+ map[string]interface{}{
+ "type": "button", "name": "string",
+ "label": "string", "value": "login",
+ },
+ },
+ "display_append": "",
+ "display_result": "",
+ "result_reload": "10",
+ },
+ map[string]interface{}{
+ "template": "tail", "name": "tail", "help": "tail",
+ "context": "", "command": "", "arguments": []interface{}{},
},
},
- }, Help: "路由数量"},
+ "index": []interface{}{
+ map[string]interface{}{
+ "template": "head", "name": "head", "help": "head",
+ "context": "", "command": "", "arguments": []interface{}{},
+ },
+ map[string]interface{}{
+ "template": "clipboard", "name": "clipbaord", "help": "clipbaord",
+ "context": "", "command": "", "arguments": []interface{}{},
+ },
+ map[string]interface{}{
+ "template": "componet", "name": "message", "help": "message",
+ "context": "cli", "command": "buffer", "arguments": []interface{}{},
+ "inputs": []interface{}{
+ map[string]interface{}{
+ "type": "text", "name": "limit",
+ "label": "limit", "value": "3",
+ },
+ map[string]interface{}{
+ "type": "button", "name": "string",
+ "label": "string", "value": "refresh",
+ },
+ },
+ },
+ map[string]interface{}{
+ "template": "componet", "name": "time", "help": "time",
+ "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", "value": "",
+ },
+ map[string]interface{}{
+ "type": "button", "name": "button",
+ "label": "string", "value": "refresh",
+ },
+ },
+ },
+ map[string]interface{}{
+ "template": "componet", "name": "json", "help": "json",
+ "context": "nfs", "command": "json",
+ "arguments": []interface{}{"@string"},
+ "inputs": []interface{}{
+ map[string]interface{}{
+ "type": "text", "name": "string",
+ "label": "string", "value": "",
+ },
+ map[string]interface{}{
+ "type": "button", "name": "button",
+ "label": "string", "value": "refresh",
+ },
+ },
+ },
+ map[string]interface{}{
+ "template": "componet", "name": "dir", "help": "dir",
+ "context": "nfs", "command": "dir",
+ "arguments": []interface{}{"@dir",
+ "dir_deep", "no",
+ "dir_name", "name",
+ "dir_link", "%s",
+ "dir_info", "",
+ },
+ "inputs": []interface{}{
+ map[string]interface{}{
+ "type": "text", "name": "dir",
+ "label": "dir", "value": "",
+ },
+ 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": "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",
+ "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{}{
+ "template": "componet", "name": "web_site", "help": "web_site",
+ "context": "web", "command": "config",
+ "arguments": []interface{}{
+ "web_site",
+ "format_field", "site", "%s",
+ },
+ "display_result": "",
+ },
+ map[string]interface{}{
+ "template": "tail", "name": "tail", "help": "tail",
+ "context": "", "command": "", "arguments": []interface{}{},
+ },
+ },
+ }, Help: "组件列表"},
},
Commands: map[string]*ctx.Command{
"client": &ctx.Command{Name: "client address [output [editor]]", Help: "添加浏览器配置, address: 默认地址, output: 输出路径, editor: 编辑器", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
@@ -517,55 +695,248 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
}
}
}},
- "/demo": &ctx.Command{Name: "/demo template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- m.Append("template", "index")
- }},
- "template": &ctx.Command{Name: "template [file directory]|[name content]", Help: "添加模块, content: 模板内容, directory: 模板目录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
+ "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 {
- buf := bytes.NewBuffer(make([]byte, 1024))
- tmpl, e := web.Template.Clone()
+ tmpl, e := web.template.Clone()
m.Assert(e)
+ tmpl.Funcs(ctx.CGI)
+
+ buf := bytes.NewBuffer(make([]byte, 1024))
tmpl.ExecuteTemplate(buf, arg[0], m)
m.Echo(string(buf.Bytes()))
}
}
}
}},
- "/render": &ctx.Command{Name: "/render template", Help: "渲染模板, template: 模板名称", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
- if web, ok := m.Target().Server.(*WEB); m.Assert(ok) {
- w := m.Optionv("response").(http.ResponseWriter)
- w.Header().Add("Content-Type", "text/html")
- tmpl, e := web.Template.Clone()
- m.Assert(e)
-
- for _, v := range m.Confv("template", arg[0]).([]interface{}) {
- //执行命令
- val := v.(map[string]interface{})
- if _, ok := val["command"]; ok {
- msg := m.Find(val["context"].(string)).Cmd(val["command"], val["argument"])
- msg.Option("title", val["title"])
- m.Assert(tmpl.ExecuteTemplate(w, val["name"].(string), msg))
+ "componet": &ctx.Command{Name: "componet [group [order [arg...]]]", Help: "添加组件, group: 组件分组, arg...: 组件参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
+ switch len(arg) {
+ case 0:
+ for k, v := range m.Confv("componet").(map[string]interface{}) {
+ for i, val := range v.([]interface{}) {
+ value := val.(map[string]interface{})
+ m.Add("append", "group", k)
+ m.Add("append", "order", i)
+ m.Add("append", "name", value["name"])
+ m.Add("append", "help", value["help"])
+ m.Add("append", "context", value["context"])
+ m.Add("append", "command", value["command"])
}
}
+ m.Sort("group").Table()
+ case 1:
+ for i, val := range m.Confv("componet", arg[0]).([]interface{}) {
+ value := val.(map[string]interface{})
+ m.Add("append", "order", i)
+ m.Add("append", "name", value["name"])
+ m.Add("append", "help", value["help"])
+ m.Add("append", "context", value["context"])
+ m.Add("append", "command", value["command"])
+ }
+ m.Table()
+ case 2:
+ value := m.Confv("componet", []interface{}{arg[0], arg[1]}).(map[string]interface{})
+ for k, v := range value {
+ m.Add("append", k, v)
+ }
+ m.Table()
+ default:
+ if com, ok := m.Confv("componet", []interface{}{arg[0], arg[1]}).(map[string]interface{}); ok {
+ for i := 2; i < len(arg)-1; i += 2 {
+ com[arg[i]] = arg[i+1]
+ }
+ } else {
+ m.Confv("componet", []interface{}{arg[0], arg[1]}, map[string]interface{}{
+ "name": arg[2], "help": arg[3],
+ "context": m.Confx("componet_context", arg, 4),
+ "command": m.Confx("componet_command", arg, 5),
+ })
+ break
+ }
+ }
+ }},
+ "session": &ctx.Command{Name: "session", Help: "用户登录", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
+ sessid := m.Option("sessid")
+ if sessid == "" && m.Options("username") && m.Options("password") {
+ sessid = m.Sess("aaa").Cmd("login", m.Option("username"), m.Option("password")).Result(0)
+ }
+ if sessid == "" && m.Options("remote_addr") {
+ sessid = m.Sess("aaa").Cmd("login", "ip", m.Option("remote_addr")).Result(0)
+ }
+
+ login := m.Sess("aaa").Cmd("login", sessid).Sess("login", false)
+ m.Appendv("login", login)
+ m.Echo(sessid)
+ }},
+ "/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) {
+ accept_json := strings.HasPrefix(m.Option("accept"), "application/json")
+ list := []interface{}{}
+
+ // tmpl, e := web.template.Clone()
+ // m.Assert(e)
+ // tmpl.Funcs(ctx.CGI)
+ //
+
+ tmpl := template.New("render").Funcs(ctx.CGI)
+ tmpl.ParseGlob("/Users/shaoying/context/usr/template/common/base.tmpl")
+
+ w := m.Optionv("response").(http.ResponseWriter)
+ if accept_json {
+ w.Header().Add("Content-Type", "application/json")
+ } else {
+ w.Header().Add("Content-Type", "text/html")
+ }
+
+ if m.Option("componet_group") == "" {
+ m.Option("componet_group", m.Conf("componet_group"))
+ }
+ group := m.Option("componet_group")
+
+ right := false
+ if group == "login" {
+ right = true
+ }
+
+ login := m
+ login = nil
+
+ for count := 0; count == 0; {
+ order := -1
+ if m.Option("componet_order") != "" {
+ order = m.Optioni("componet_order")
+ }
+
+ if !right {
+ login = m.Spawn().Cmd("session").Appendv("login").(*ctx.Message)
+ }
+ if !right && login != nil {
+ if role := login.Confv("right", []interface{}{"right", "role"}); role != nil && role.(string) == "root" {
+ right = true
+ }
+ }
+ if !right && login != nil {
+ if role := login.Confv("right", []interface{}{group, "right", "role"}); role != nil && role.(string) == "owner" {
+ right = true
+ }
+ }
+
+ for i, v := range m.Confv("componet", group).([]interface{}) {
+ if order != -1 && i != order {
+ continue
+ }
+
+ val := v.(map[string]interface{})
+
+ order_right := right
+ if !order_right && login != nil {
+ if role := login.Confv("right", []interface{}{group, val["name"], "right", "role"}); role != nil && role.(string) == "share" {
+ order_right = true
+ }
+ }
+ if !order_right {
+ continue
+ }
+
+ msg := m.Find(val["context"].(string))
+ if msg == nil {
+ if !accept_json {
+ m.Assert(tmpl.ExecuteTemplate(w, val["template"].(string), m))
+ }
+ continue
+ }
+ count++
+
+ msg.Option("componet_order", i)
+
+ for k, v := range val {
+ if msg.Option(k) != "" {
+ continue
+ }
+ switch value := v.(type) {
+ case []string:
+ msg.Add("option", k, value)
+ case string:
+ msg.Add("option", k, value)
+ default:
+ msg.Put("option", k, value)
+ }
+ }
+
+ args := []string{}
+ if val["arguments"] != nil {
+ for _, v := range val["arguments"].([]interface{}) {
+ switch value := v.(type) {
+ case string:
+ if len(value) > 1 && value[0] == '$' {
+ args = append(args, msg.Cap(value[1:]))
+ } else if len(value) > 1 && value[0] == '@' {
+ args = append(args, msg.Confx(value[1:]))
+ } else {
+ args = append(args, value)
+ }
+ }
+ }
+ }
+ if val["inputs"] != nil {
+ for _, v := range val["inputs"].([]interface{}) {
+ value := v.(map[string]interface{})
+ if msg.Option(value["name"].(string)) == "" {
+ msg.Add("option", value["name"].(string), value["value"])
+ }
+ }
+ }
+
+ if msg.Cmd(val["command"], args); accept_json {
+ list = append(list, msg.Meta)
+ } else {
+ m.Assert(tmpl.ExecuteTemplate(w, val["template"].(string), msg))
+ }
+
+ if msg.Appends("sessid") {
+ http.SetCookie(w, &http.Cookie{Name: "sessid", Value: msg.Append("sessid")})
+ m.Append("page_redirect", fmt.Sprintf("/render?componet_group=%s&componet_order=%s",
+ m.Option("componet_group", m.Option("last_componet_group")),
+ m.Option("componet_order", m.Option("last_componet_order"))))
+ return
+ }
+ }
+
+ if count == 0 {
+ m.Option("last_componet_group", m.Option("componet_group"))
+ m.Option("last_componet_order", m.Option("componet_order"))
+ m.Option("componet_group", "login")
+ m.Option("componet_order", "-1")
+ group = m.Option("componet_group")
+ order = -1
+ right = true
+ }
+ }
+
+ if accept_json {
+ en := json.NewEncoder(w)
+ en.SetIndent("", " ")
+ en.Encode(list)
+ }
}
}},
},
diff --git a/usr/library/base.js b/usr/library/base.js
index 6ab18a33..e4281724 100644
--- a/usr/library/base.js
+++ b/usr/library/base.js
@@ -1,59 +1,194 @@
-
-function update(event, module, details, key) {
- if (event) {
- window[key+"timer"] = !window[key+"timer"];
- }
- if (!window[key+"timer"]) {
- return
- }
- console.log("update "+key)
- setTimeout(function() {
- action(event, module, details, key);
- update(null, module, details, key);
- }, refresh_time);
+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 input(event, module, details, key) {
- if (event.code == "Enter") {
- action(event, module, details, key);
- }
+function copy_to_clipboard(text) {
+ var clipboard = document.querySelector("#clipboard")
+ clipboard.value = text
+ clipboard.select()
+ document.execCommand("copy")
+ clipboard.blur()
+
+ var clipstack = document.querySelector("#clipstack")
+ insert_child(clipstack, "option").value = clipboard.value
+ clipstack.childElementCount > 3 && clipstack.removeChild(clipstack.lastElementChild)
}
-function action(event, module, details, key) {
- var input = document.getElementsByClassName(key+"_input");
- for (var i = 0; i < input.length; i++ ){
- if (input[i].value != "") {
- details.push(input[i].value)
- }
- }
- ctx.POST("", {module:module, details:details}, function(msg) {
- if (msg && msg.result) {
- var result = document.getElementsByClassName(key+"_result")[0];
- result.innerHTML = msg.result;
- }
- if (!msg || !msg.append || msg.append.length < 1) {
- return
- }
+function send_command(form, cb) {
+ var data = {}
+ for (var key in form.dataset) {
+ data[key] = form.dataset[key]
+ }
+ for (var i = 0; i < form.length; i++) {
+ data[form[i].name] = form[i].value
+ }
- var append = document.getElementsByClassName(key+"_append")[0];
- if (append.rows.length == msg[msg.append[0]].length+1) {
- return
- }
- append.innerHTML = '';
- var tr = append.insertRow(0);
- for (var i in msg.append) {
- var th = tr.appendChild(document.createElement("th"));
- th.appendChild(document.createTextNode(msg.append[i]));
- }
+ context.GET("", data, function(msg) {
+ msg = msg[0]
- for (var i = 0; i < msg[msg.append[0]].length; i++) {
- var tr = append.insertRow(1);
- for (var j in msg.append) {
- var td = tr.appendChild(document.createElement("td"));
- td.appendChild(document.createTextNode(msg[msg.append[j]][i]));
- }
- }
- var div = append.parent;
+ var result = document.querySelector("code.result."+data["componet_name"]+" pre")
+ result && (result.innerHTML = (msg.result || []).join(""))
- })
- return false;
+ var append = document.querySelector("table.append."+data["componet_name"])
+ append && (append.innerHTML = "")
+
+ if (append && msg.append) {
+ var tr = append_child(append, "tr")
+ for (var i in msg.append) {
+ append_child(tr, "th", msg.append[i])
+ }
+
+ var ncol = msg.append.length
+ var nrow = msg[msg.append[0]].length
+ for (var i = 0; i < nrow; i ++) {
+ var tr = append_child(append, "tr")
+ for (var k in msg.append) {
+ append_child(tr, "td", msg[msg.append[k]][i])
+ }
+ }
+ }
+
+ typeof(cb) == "function" && cb(msg)
+ })
+}
+function onaction(event, action) {
+ switch (action) {
+ case "command":
+ send_command(event.target.form)
+ break
+ case "input":
+ switch (event.key) {
+ case "Enter":
+ var form = event.target.form
+ for (var i = 0; i < form.length; i++) {
+ if (form[i] == event.target) {
+ continue
+ }
+ (i == form.length-1)? send_command(form): form[i+1].focus()
+ }
+ break
+ case "Escape":
+ event.target.value = ""
+ event.target.blur()
+ break
+ }
+ break
+ case "keymap":
+ switch (event.key) {
+ case "g":
+ document.querySelectorAll("form.option label.keymap").forEach(function(item) {
+ item.className = (item.className == "keymap show")? "keymap hide": "keymap show"
+ })
+ break
+ default:
+ if (inputs[event.key]) {
+ inputs[event.key].focus()
+ }
+ break
+ }
+ break
+ case "copy":
+ copy_to_clipboard(event.target.innerText)
+ break
+ }
+}
+var inputs = {}
+var ninput = 0
+var keymap = ['a', 'b', 'c']
+function init_option() {
+ inputs = {}
+ ninput = 0
+ keymap =[]
+ for (var i = 97; i < 123; i++) {
+ if (i == 103) {
+ continue
+ }
+ keymap.push(String.fromCharCode(i))
+ }
+
+ document.querySelectorAll("form.option input").forEach(function(input) {
+ if (ninput < keymap.length && input.style.display != "none") {
+ input.title = "keymap: "+keymap[ninput]
+ input.dataset["keymap"] = keymap[ninput]
+ insert_before(input, "label", "("+keymap[ninput]+")").className = "keymap"
+ inputs[keymap[ninput++]] = input
+ }
+ })
+}
+function init_append(event) {
+ var append = document.querySelectorAll("table.append").forEach(function(item) {
+ item.onclick = function(event) {
+ if (event.target.tagName == "TD") {
+ copy_to_clipboard(event.target.innerText)
+ }
+ }
+ })
+}
+function init_result(event) {
+ var result = document.querySelectorAll("code.result pre").forEach(function(item) {
+ item.onclick = function(event) {
+ copy_to_clipboard(event.target.innerText)
+ }
+ })
+}
+function init_download(event) {
+ var option = document.querySelector("form.option.dir")
+ if (!option) {
+ return
+ }
+ option["dir"].value && send_command(option)
+
+ var append = document.querySelector("table.append.dir")
+ append.onclick = function(event) {
+ if (event.target.tagName == "A") {
+ if (event.target.dataset.type != "true") {
+ location.href = option["dir"].value+"/"+event.target.innerText
+ return
+ }
+
+ option["dir"].value = option["dir"].value+"/"+event.target.innerText
+ send_command(option, function(msg) {
+ option["dir"].value = msg.dir.join("")
+ })
+ } else if (event.target.tagName == "TD") {
+ copy_to_clipboard(event.target.innerText)
+ } else if (event.target.tagName == "TH") {
+ option["sort_field"].value = event.target.innerText
+
+ var sort_order = option["sort_order"]
+ switch (event.target.innerText) {
+ case "filename":
+ sort_order.value = (sort_order.value == "str")? "str_r": "str"
+ break
+ case "line":
+ case "size":
+ sort_order.value = (sort_order.value == "int")? "int_r": "int"
+ break
+ case "time":
+ sort_order.value = (sort_order.value == "time")? "time_r": "time"
+ break
+ }
+
+ send_command(option)
+ }
+ }
+}
+
+window.onload = function() {
+ init_option()
+ init_append()
+ init_result()
+ init_download()
}
diff --git a/usr/library/context.js b/usr/library/context.js
index d53f55e8..3c2de56c 100644
--- a/usr/library/context.js
+++ b/usr/library/context.js
@@ -1,202 +1,47 @@
-ctx = {
- Cookie: function(key, value) {//{{{
- if (value == undefined) {
- var pattern = new RegExp(key+"=([^;]*);?");
- var result = pattern.exec(document.cookie);
- if (result && result.length > 0) {
- return result[1];
- }
- return "";
- }
+context = {
+ GET: function(url, form, cb) {
+ form = form || {}
- document.cookie = key+"="+value;
- return this.Cookie(key);
- },//}}}
- Search: function(key, value) {//{{{
- var args = {};
- var search = location.search.split("?");
- if (search.length > 1) {
- var searchs = search[1].split("&");
- for (var i = 0; i < searchs.length; i++) {
- var keys = searchs[i].split("=");
- args[keys[0]] = decodeURIComponent(keys[1]);
- }
- }
-
- if (typeof key == "object") {
- for (var k in key) {
- if (key[k] != undefined) {
- args[k] = key[k];
- }
- }
- } else if (value == undefined) {
- return args[key] || "";
- } else {
- args[key] = value;
- }
-
- var arg = [];
- for (var k in args) {
- arg.push(k+"="+encodeURIComponent(args[k]));
- }
- location.search = arg.join("&");
- },//}}}
- GET: function(url, form, cb) {//{{{
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function() {
- switch (xhr.readyState) {
- case 4:
- switch (xhr.status) {
- case 200:
- try {
- var msg = JSON.parse(xhr.responseText||'{"result":[]}');
- } catch (e) {
- msg = {"result": [xhr.responseText]}
- }
-
- msg && console.log(msg)
- msg.result && console.log(msg.result.join(""));
- typeof cb == "function" && cb(msg)
- }
- break;
- }
- }
-
- form = form || {}
- form["dir"] = form["dir"] || this.Search("dir") || undefined
- form["module"] = form["module"] || this.Search("module") || undefined
- form["domain"] = form["domain"] || this.Search("domain") || undefined
-
- var args = [];
- for (k in form) {
- if (form[k] instanceof Array) {
- for (i in form[k]) {
- args.push(k+"="+encodeURIComponent(form[k][i]));
- }
- } else if (form[k] != undefined) {
- args.push(k+"="+encodeURIComponent(form[k]));
- }
- }
-
- var arg = args.join("&");
- if (arg) {
- url += "?"+arg
+ var args = [];
+ for (var k in form) {
+ if (form[k] instanceof Array) {
+ for (i in form[k]) {
+ args.push(k+"="+encodeURIComponent(form[k][i]));
+ }
+ } else if (form[k] != undefined) {
+ args.push(k+"="+encodeURIComponent(form[k]));
+ }
}
- xhr.open("GET", url);
- console.log("GET: "+url+"?"+arg);
- xhr.send();
- },//}}}
- POST: function(url, form, cb) {//{{{
- var xhr = new XMLHttpRequest();
- xhr.onreadystatechange = function() {
- switch (xhr.readyState) {
- case 4:
- switch (xhr.status) {
- case 200:
- try {
- var msg = JSON.parse(xhr.responseText||'{"result":[]}');
- } catch (e) {
- msg = {"result": [xhr.responseText]}
- }
+ var arg = args.join("&");
+ arg && (url += ((url.indexOf("?")>-1)? "&": "?") + arg)
+ console.log("GET: "+url);
- msg && console.log(msg)
- msg.result && console.log(msg.result.join(""));
- typeof cb == "function" && cb(msg)
- }
- break;
- }
- }
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.setRequestHeader("Accept", "application/json")
- xhr.open("POST", url);
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState != 4) {
+ return
+ }
+ if (xhr.status != 200) {
+ return
+ }
+ try {
+ var msg = JSON.parse(xhr.responseText||'{"result":[]}');
+ } catch (e) {
+ var msg = {"result": [xhr.responseText]}
+ }
- form = form || {}
- form["dir"] = form["dir"] || this.Search("dir") || undefined
- form["module"] = form["module"] || this.Search("module") || undefined
- form["domain"] = form["domain"] || this.Search("domain") || undefined
-
- var args = [];
- for (k in form) {
- if (form[k] instanceof Array) {
- for (i in form[k]) {
- args.push(k+"="+encodeURIComponent(form[k][i]));
- }
- } else if (form[k] != undefined) {
- args.push(k+"="+encodeURIComponent(form[k]));
- }
- }
-
- var arg = args.join("&");
- console.log("POST: "+url+"?"+arg);
- xhr.send(arg);
- },//}}}
- Refresh: function() {//{{{
- location.assign(location.href);
- },//}}}
-
- Cap: function(cap, cb) {//{{{
- if (typeof cap == "function") {
- cb = cap;
- cap = undefined;
- }
-
- var args = {ccc:"cache"};
- if (cap != undefined) {
- args.name = cap;
- }
-
- this.POST("", args, function(msg) {
- var value = msg.result.join("");
- typeof cb == "function" && cb(value);
- });
- },//}}}
- Conf: function(name, value, cb) {//{{{
- if (typeof name == "function") {
- value = name;
- name = undefined;
- }
- if (typeof value == "function") {
- cb = value;
- value = undefined;
- }
-
- var args = {ccc:"config"};
- if (name != undefined) {
- args.name = name
- }
- if (value != undefined) {
- args.value = value
- }
-
- this.POST("", args, function(msg) {
- var value = msg.result.join("");
- typeof cb == "function" && cb(value);
- });
- },//}}}
- Cmd: function(cmd, value, cb) {//{{{
- if (typeof cmd == "function") {
- value = cmd;
- cmd = undefined;
- }
- if (typeof value == "function") {
- cb = value;
- value = undefined;
- }
-
- var args = {ccc:"command"};
- if (cmd != undefined) {
- args.name = cmd
- }
- if (value != undefined) {
- args.value = JSON.stringify(value)
- }
-
- this.POST("", args, cb);
- },//}}}
- Module: function(module, domain) {//{{{
- this.Search({module:module, domain:domain})
- },//}}}
-};
-
+ console.log(msg)
+ msg.result && console.log(msg.result.join(""));
+ if (msg.page_redirect) {
+ location.href = msg.page_redirect.join("")
+ }
+ typeof cb == "function" && cb(msg)
+ }
+ xhr.send();
+ },
+}
diff --git a/usr/library/wiki.js b/usr/library/wiki.js
deleted file mode 100644
index 8d4eb8a9..00000000
--- a/usr/library/wiki.js
+++ /dev/null
@@ -1,211 +0,0 @@
-function jumpto(url) {
- if (url == "..") {
- var ps = locaiton.href.split();
- }
- location.href=url;
-}
-
-function keyup(event) {
- console.log(event);
- if (typeof window.control == "function") {
- control(event);
- }
- if (event.key == "z") {
- var input = document.getElementsByClassName("query_input")[0];
- if (!window.query_show) {
- window.query_show = true;
- var query = document.getElementsByClassName("query_menu")[0];
- var input = query.getElementsByTagName("input")[0];
- input.style.visibility = "visible";
- input.style.width = "80px";
- input.focus();
- }
- return true
- }
- return true
-}
-
-document.onkeyup = keyup;
-function toggle(side) {
- if (side == "left") {
- window.left_list_hide = !window.left_list_hide;
- var list = document.getElementsByClassName("list")[0];
- var content = document.getElementsByClassName("content")[0];
- if (left_list_hide) {
- list.style.visibility = "hidden";
- list.style.width="0px";
- list.style.height="0px";
- list.style["min-width"]="0px";
- content.style.width="100%";
- } else {
- list.style.visibility = "visible";
- list.style.width="15%";
- list.style.height="100%";
- list.style["min-width"]="180px";
- content.style.width="85%";
- }
- }
-}
-
-function 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;
-
- var link = [];
- var a = document.getElementsByTagName("a");
- for (var i = 0; i < a.length; i++) {
- link.push({href: a[i].href, title: a[i].innerText});
- }
-
- 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 = m[i].appendChild(document.createElement("div"));
- var a = one.appendChild(document.createElement("a"));
- a.href = "#"+list[j].hash;
- a.innerText = text+" ("+parseInt((list[j].position-min)/max*100)+"%)";
-
- one.className = list[j].level;
- }
- }
-
- var m = document.getElementsByClassName("link");
- for (var i = 0; i < m.length; i++) {
- var one = m[i].appendChild(document.createElement("div"));
- var a = one.appendChild(document.createTextNode("相关链接: "));
-
- for (var j = 0; j < link.length; j++) {
- var one = m[i].appendChild(document.createElement("div"));
- var a = one.appendChild(document.createTextNode(link[j].title+": "));
- var a = one.appendChild(document.createElement("a"));
- a.href = link[j].href
- a.innerText = a.href
- }
- }
-
- 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));
- }
- }
-}
-
-function query(event) {
- if (event) {
- if (event.code == "Enter") {
- jumpto("/wiki/?query="+encodeURIComponent(event.target.value));
- }
- console.log("what")
- return true
- }
- window.query_show = !window.query_show;
- var query = document.getElementsByClassName("query_menu")[0];
- var input = query.getElementsByTagName("input")[0];
- if (window.query_show) {
- input.style.visibility = "visible";
- input.style.width = "80px";
-
- } else {
- input.style.visibility = "hidden";
- input.style.width = "0px";
- }
-}
-
-var tags_list = {};
-ctx.GET("/wiki/define.json", undefined, function(msg){
- tags_list = msg["define"];
-})
-
-function tags(event) {
- console.log(event);
-
- if (event.srcElement.tagName == "CODE") {
- var tag = document.getSelection().toString();
- console.log(tag);
- if (tag && tag.length > 0 && tags_list[tag]) {
- var position = tags_list[tag].position;
- if (position.length == 1) {
- jumpto("/wiki/src/"+position[0].file+"#hash_"+position[0].line);
- } else {
- jumpto("/wiki/?query="+encodeURIComponent(tag));
- }
- }
- }
-}
-
-document.onmouseup = tags;
-window.onload = function() {
- toggle();
- if (location.href.endsWith(".md")) {
- menu();
- }
-}
diff --git a/usr/template/common/base.html b/usr/template/common/base.html
deleted file mode 100644
index d14b78a9..00000000
--- a/usr/template/common/base.html
+++ /dev/null
@@ -1,145 +0,0 @@
-{{define "head"}}
-
-
-
-
-{{option .Meta "page_title"}}
-
-
-
-
-
-{{end}}
-
-{{define "code"}}
-{{.}}
-{{end}}
-
-{{define "notice"}}
-
-
-{{end}}
-
-{{define "detail"}}
-{{$msg := .}}
-{{$key := append . "title"|meta}}
-
-
-{{end}}
-
-{{define "result"}}
-
-{{end}}
-
-{{define "append_link"}}
-{{.}}
-
-{{end}}
-
-{{define "append"}}
-
-
-{{end}}
-
-{{define "main"}}
-welcome to context world!
-{{end}}
-
-{{define "tail"}}
-
-{{end}}
diff --git a/usr/template/common/base.tmpl b/usr/template/common/base.tmpl
new file mode 100644
index 00000000..a6771bc7
--- /dev/null
+++ b/usr/template/common/base.tmpl
@@ -0,0 +1,138 @@
+{{define "head"}}
+
+
+
+
+{{option .Meta "page_title"}}
+
+
+
+
+
+{{end}}
+
+{{define "detail"}}{{detail .}}{{end}}
+{{define "option"}}{{option .}}{{end}}
+{{define "append"}}{{append .}}{{end}}
+{{define "result"}}{{result .}}{{end}}
+
+{{define "clipboard"}}
+
+{{end}}
+
+{{define "componet"}}
+
+{{end}}
+
+{{define "tail"}}
+
+
+
+{{end}}
diff --git a/usr/template/common/login.html b/usr/template/common/login.html
deleted file mode 100644
index 472887a7..00000000
--- a/usr/template/common/login.html
+++ /dev/null
@@ -1,94 +0,0 @@
-{{define "login"}}
-
-{{end}}
-
-{{define "userinfo"}}
-
-
-
-{{end}}
-
-{{define "share"}}
-
-
-{{end}}
-
-{{$msg := .}}
-{{$meta := .Meta}}
-
-{{template "head" $meta}}
-{{if meta $meta.notice}}
- {{template "notice" $meta}}
-{{end}}
-{{template "login" $meta}}
-{{template "tail" $meta}}
diff --git a/usr/template/common/main.html b/usr/template/common/main.html
deleted file mode 100644
index ce3e2dc1..00000000
--- a/usr/template/common/main.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{{$msg := .}}
-{{$meta := .Meta}}
-
-{{template "head" $meta}}
-{{if meta $meta.message}}
- {{template "message" $meta}}
-{{end}}
-{{template "main" $msg}}
-{{template "tail" $meta}}
diff --git a/usr/template/common/wiki.html b/usr/template/common/wiki.html
deleted file mode 100644
index 835fe9ab..00000000
--- a/usr/template/common/wiki.html
+++ /dev/null
@@ -1,222 +0,0 @@
-{{define "wiki_head"}}
-{{end}}
-
-{{define "wiki_menu"}}
-{{end}}
-
-{{define "wiki_list"}}
-
-
-
-
- {{$msg := .}}
- {{$ncol := append . |len}}
- {{$nrow := append . 0|append .|len}}
-
-
-{{end}}
-
-{{define "wiki_body"}}
-
-
-
-
- {{if option . "modify_time"|meta}}
-
上次修订时间: {{option . "modify_time"|meta}} 修订次数: {{option . "modify_count"|meta}}
- {{end}}
-
上次阅读时间: {{option . "last_record_time"|meta}} 总访问量: {{option . "record_count"|meta}}
-
-
-
-
- {{range option . "nline"|meta|list}}
-
{{.}}
- {{end}}
-
- {{$msg := .}}
- {{if append . "name"}}
- {{$l := append . "name"|len}}
- {{if eq $l 1}}
-
- {{else}}
-
- {{range $i, $v := append . "name"}}
- -
-
-
- {{end}}
-
- {{end}}
- {{else if append . "code"|meta}}
-
{{append . "code"|meta}}
- {{else}}
-
{{append . "body"|meta|unscaped}}
- {{end}}
-
-
-
-
-
-{{end}}
diff --git a/usr/template/travel.html b/usr/template/travel.html
deleted file mode 100644
index b66bb94d..00000000
--- a/usr/template/travel.html
+++ /dev/null
@@ -1,431 +0,0 @@
-{{define "head"}}
-
-
-
-
-
-
-{{end}}
-
-{{define "cache"}}
-{{$meta := .}}
-
-
-{{end}}
-
-{{define "config"}}
-
-
-{{end}}
-
-{{define "command2"}}
-{{$meta := .}}
-
-
-
-{{end}}
-
-{{define "command"}}
-
-
-
-{{end}}
-
-{{define "module"}}
-
-{{end}}
-
-{{define "domain"}}
-
-{{end}}
-
-{{define "tail"}}
-
-
-
-{{end}}
-
-{{define "main"}}
-{{$msg := .}}
-{{$meta := .Meta}}
-{{$sess := $msg.Sessions}}
-{{range .Meta.tmpl}}
- {{if eq . "login"}}
- {{template "login" $meta}}
- {{else if eq . "userinfo"}}
- {{template "userinfo" $msg}}
- {{else if eq . "share"}}
- {{template "share" $sess.share}}
- {{else if eq . "cache"}}
- {{template "cache" $sess.cache.Meta}}
- {{else if eq . "config"}}
- {{template "config" $sess.config.Meta}}
- {{else if eq . "command"}}
- {{template "command" $sess.command.Meta}}
- {{template "command2" $sess.command.Meta}}
- {{else if eq . "module"}}
- {{template "module" $sess.module.Meta}}
- {{else if eq . "domain"}}
- {{template "domain" $sess.domain.Meta}}
- {{end}}
-{{end}}
-{{end}}
diff --git a/usr/template/upload.html b/usr/template/upload.html
deleted file mode 100644
index cc19746e..00000000
--- a/usr/template/upload.html
+++ /dev/null
@@ -1,163 +0,0 @@
-{{define "list"}}
-
-
-
-{{end}}
-
-{{define "git"}}
-
-
-{{end}}
-
-{{define "tmux"}}
-{{$meta := .}}
-{{range $index, $value := index $meta "append"}}
-
-{{end}}
-{{end}}
-
-{{define "upload"}}
-
-{{end}}
-
-{{define "create"}}
-
-{{end}}
-
-{{define "main"}}
-{{$msg := .}}
-{{$meta := .Meta}}
-{{$sess := .Sessions}}
-{{range .Meta.tmpl}}
- {{$tmpl := index $sess .}}
-
- {{if eq . "login"}}
- {{template "login" $meta}}
- {{else if eq . "userinfo"}}
- {{template "userinfo" $msg}}
- {{else if eq . "share"}}
- {{template "share" $sess.share}}
- {{else if eq . "list"}}
- {{template "list" $msg.Sessions.list.Meta}}
- {{else if eq . "tmux"}}
- {{template "tmux" $msg.Sessions.tmux.Meta}}
- {{else if eq . "git"}}
- {{if $msg.Sessions.git}}
- {{template "git" $msg.Sessions.git.Meta}}
- {{end}}
- {{else if eq . "upload"}}
- {{template "upload" $msg}}
- {{else if eq . "create"}}
- {{template "create" $msg}}
- {{else}}
- {{end}}
-{{end}}
-{{end}}
-