package ctx import ( "text/template" "bytes" "io" "path" "strings" "toolkit" ) func index(name string, arg ...interface{}) interface{} { if len(arg) == 0 { return "" } switch m := arg[0].(type) { case *Message: if len(arg) == 1 { return m.Meta[name] } switch value := arg[1].(type) { case int: if 0 <= value && value < len(m.Meta[name]) { return m.Meta[name][value] } case string: if len(arg) == 2 { return m.Optionv(value) } switch val := arg[2].(type) { case int: switch list := m.Optionv(value).(type) { case []string: if 0 <= val && val < len(list) { return list[val] } case []interface{}: if 0 <= val && val < len(list) { return list[val] } } } } case map[string][]string: if len(arg) == 1 { return m[name] } switch value := arg[1].(type) { case int: return m[name][value] case string: if len(arg) == 2 { return m[value] } switch val := arg[2].(type) { case int: return m[value][val] } } case []string: if len(arg) == 1 { return m } switch value := arg[1].(type) { case int: return m[value] } default: return m } return "" } var CGI = template.FuncMap{ "options": func(arg ...interface{}) string { switch value := index("option", arg...).(type) { case string: return value case []string: return strings.Join(value, "") } return "" }, "option": func(arg ...interface{}) interface{} { return index("option", arg...) }, "conf": func(arg ...interface{}) interface{} { switch m := arg[0].(type) { case *Message: switch c := arg[1].(type) { case string: if len(arg) == 2 { return m.Confv(c) } if len(arg) == 3 { return m.Confv(c, arg[2]) } } } return nil }, "cmd": func(arg ...interface{}) interface{} { switch m := arg[0].(type) { case *Message: switch c := arg[1].(type) { case string: return m.Cmd(c, arg[2:]) } } return nil }, "append": func(arg ...interface{}) interface{} { switch m := arg[0].(type) { case *Message: if len(arg) == 1 { return m.Meta["append"] } if len(arg) > 1 { switch c := arg[1].(type) { case string: if len(arg) > 2 { switch i := arg[2].(type) { case int: return kit.Select("", m.Meta[c], i) } } return m.Meta[c] } } } return nil }, "result": func(arg ...interface{}) interface{} { switch m := arg[0].(type) { case *Message: return m.Meta["result"] } return nil }, "results": func(arg ...interface{}) interface{} { switch m := arg[0].(type) { case *Message: return strings.Join(m.Meta["result"], "") } return nil }, } func LocalCGI(m *Message, c *Context) *template.FuncMap { cgi := template.FuncMap{ "table": func(arg ...interface{}) interface{} { if len(arg) == 0 { return "" } switch msg := arg[0].(type) { case *Message: res := []map[string]string{} msg.Table(func(index int, value map[string]string) { res = append(res, value) }) return res case string: sub := m.Spawn() head := []string{} for i, l := range strings.Split(strings.TrimSpace(msg), "\n") { if i == 0 { head = kit.Split(l, ' ', 100) continue } for j, v := range strings.Split(l, " ") { sub.Push(head[j], v) } } return sub } return nil }, "format": func(arg ...interface{}) interface{} { switch msg := arg[0].(type) { case *Message: buffer := bytes.NewBuffer([]byte{}) tmpl := m.Optionv("tmpl").(*template.Template) m.Assert(tmpl.ExecuteTemplate(buffer, kit.Select("table", arg, 1), msg)) return string(buffer.Bytes()) } return nil }, } for k, v := range c.Commands { if strings.HasPrefix(k, "/") || strings.HasPrefix(k, "_") { continue } func(k string, v *Command) { cgi[k] = func(arg ...interface{}) interface{} { msg := m.Spawn() v.Hand(msg, c, k, kit.Trans(arg)...) buffer := bytes.NewBuffer([]byte{}) tmpl := m.Optionv("tmpl").(*template.Template) m.Assert(tmpl.ExecuteTemplate(buffer, kit.Select("code", "table", len(msg.Meta["append"]) > 0), msg)) return string(buffer.Bytes()) } }(k, v) } for k, v := range CGI { cgi[k] = v } return &cgi } func ExecuteFile(m *Message, w io.Writer, p string) error { tmpl := template.New("render").Funcs(CGI) tmpl.ParseGlob(p) return tmpl.ExecuteTemplate(w, path.Base(p), m) } func ExecuteStr(m *Message, w io.Writer, p string) error { tmpl := template.New("render").Funcs(CGI) tmpl, _ = tmpl.Parse(p) return tmpl.Execute(w, m) }