diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..56dbf4da --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ + +BENCH=src/example/bench.go + +install: + go install $(BENCH) + +build: + go build $(BENCH) diff --git a/etc/init.shy b/etc/init.shy index 6cd987a1..cb6565d9 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,2 +1,5 @@ ~aaa login root root -source etc/local.shy + +~web serve ./ ":9090" +# source etc/local.shy + diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 20fdeebd..4b73599a 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -102,7 +102,7 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ yac.Cmd("train", "num", "num", "mul{", "[1-9][0-9]*", "0[0-9]+", "0x[0-9]+", "}") yac.Cmd("train", "str", "str", "mul{", "\"[^\"]*\"", "'[^']*'", "}") - yac.Cmd("train", "tran", "tran", "mul{", "@", "$", "}", "opt{", "[a-zA-Z0-9]+", "}") + yac.Cmd("train", "tran", "tran", "mul{", "@", "$", "}", "opt{", "$", "[a-zA-Z0-9]+", "}") yac.Cmd("train", "word", "word", "mul{", "~", "!", "tran", "str", "[a-zA-Z0-9_/.]+", "}") yac.Cmd("train", "op1", "op1", "mul{", "$", "@", "}") diff --git a/src/contexts/mdb/mdb.go b/src/contexts/mdb/mdb.go index 693df84c..15cecf3c 100644 --- a/src/contexts/mdb/mdb.go +++ b/src/contexts/mdb/mdb.go @@ -1,7 +1,9 @@ -package mdb - -import ( +package mdb // {{{ +// }}} +import ( // {{{ "contexts" + "strconv" + "strings" "database/sql" _ "github.com/go-sql-driver/mysql" @@ -9,12 +11,19 @@ import ( "fmt" ) +// }}} + type MDB struct { *sql.DB + + list map[string][]string + list_key []string + + table []string *ctx.Context } -func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { +func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ c.Caches = map[string]*ctx.Cache{ "source": &ctx.Cache{Name: "数据库参数", Value: "", Help: "数据库参数"}, "driver": &ctx.Cache{Name: "数据库驱动", Value: "", Help: "数据库驱动"}, @@ -26,14 +35,17 @@ func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } -func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { +// }}} +func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ + mdb.Context.Master(nil) if mdb.Context == Index { Pulse = m } return mdb } -func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { +// }}} +func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{ if len(arg) > 0 { m.Cap("source", arg[0]) } @@ -54,7 +66,8 @@ func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { return false } -func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { +// }}} +func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { // {{{ switch mdb.Context { case m.Target(): if mdb.DB != nil { @@ -67,9 +80,12 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { return true } +// }}} + var Pulse *ctx.Message var Index = &ctx.Context{Name: "mdb", Help: "数据中心", Caches: map[string]*ctx.Cache{ + "count": &ctx.Cache{Name: "count", Value: "0", Help: "主机协议"}, "nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"}, }, Configs: map[string]*ctx.Config{ @@ -77,15 +93,16 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", }, Commands: map[string]*ctx.Command{ "open": &ctx.Command{Name: "open source [driver]", Help: "打开数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Assert(len(arg) > 0, "缺少参数") + m.Assert(len(arg) > 0, "缺少参数") // {{{ m.Start(fmt.Sprintf("db%d", Pulse.Capi("nsource", 1)), "数据存储", arg...) Pulse.Cap("stream", Pulse.Cap("nsource")) m.Echo(m.Target().Name) + // }}} }}, "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库", Appends: map[string]string{"last": "最后插入元组的标识", "nrow": "修改元组的数量"}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - mdb, ok := m.Target().Server.(*MDB) + mdb, ok := m.Target().Server.(*MDB) // {{{ m.Assert(ok, "目标模块类型错误") m.Assert(len(arg) > 0, "缺少参数") m.Assert(mdb.DB != nil, "数据库未打开") @@ -106,9 +123,10 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", m.Add("append", "last", fmt.Sprintf("%d", id)) m.Add("append", "nrow", fmt.Sprintf("%d", n)) m.Log("info", nil, "last(%d) nrow(%d)", id, n) + // }}} }}, "query": &ctx.Command{Name: "query sql [arg]", Help: "执行查询语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - mdb, ok := m.Target().Server.(*MDB) + mdb, ok := m.Target().Server.(*MDB) // {{{ m.Assert(ok, "目标模块类型错误") m.Assert(len(arg) > 0, "缺少参数") m.Assert(mdb.DB != nil, "数据库未打开") @@ -151,6 +169,91 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心", } else { m.Log("info", nil, "rows(0) cols(0)") } + // }}} + }}, + "table": &ctx.Command{Name: "table", Help: "执行查询语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + mdb, ok := m.Target().Server.(*MDB) // {{{ + m.Assert(ok) + msg := m.Spawn(m.Target()) + if len(arg) > 0 { + table := arg[0] + index, e := strconv.Atoi(arg[0]) + if e == nil && index < len(mdb.table) { + table = mdb.table[index] + } + msg.Cmd("query", fmt.Sprintf("desc %s", table)) + + if len(arg) > 1 { + for i, v := range msg.Meta[msg.Meta["append"][0]] { + if v == arg[1] { + for _, k := range msg.Meta["append"] { + m.Echo("%s: %s\n", k, msg.Meta[k][i]) + } + } + } + } else { + for _, v := range msg.Meta[msg.Meta["append"][0]] { + m.Echo("%s\n", v) + } + } + } else { + msg.Cmd("query", "show tables") + mdb.table = []string{} + for i, v := range msg.Meta[msg.Meta["append"][0]] { + mdb.table = append(mdb.table, v) + m.Echo("%d: %s\n", i, v) + } + } + // }}} + }}, + "list": &ctx.Command{Name: "list add table field", Help: "执行查询语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + mdb, ok := m.Target().Server.(*MDB) // {{{ + m.Assert(ok) + if len(arg) == 0 { + for _, k := range mdb.list_key { + m.Echo("%s: %v\n", k, mdb.list[k]) + } + return + } + + switch arg[0] { + case "add": + if mdb.list == nil { + mdb.list = make(map[string][]string) + } + mdb.list[m.Cap("count")] = arg[1:] + mdb.list_key = append(mdb.list_key, m.Cap("count")) + m.Capi("count", 1) + case "set": + mdb.list[arg[1]] = arg[2:] + default: + if table, ok := mdb.list[arg[0]]; ok { + msg := m.Spawn(m.Target()) + + fields := strings.Join(table[1:], ",") + condition := "" + if len(arg) > 1 && len(arg[1]) > 0 { + condition = fmt.Sprintf("where %s", arg[1]) + } + other := "" + if len(arg) > 2 { + other = strings.Join(arg[2:], " ") + } + + msg.Cmd("query", fmt.Sprintf("select %s from %s %s %s", fields, table[0], condition, other)) + for _, k := range msg.Meta["append"] { + m.Echo("\t%s", k) + } + m.Echo("\n") + for i := 0; i < len(msg.Meta[msg.Meta["append"][0]]); i++ { + for _, k := range msg.Meta["append"] { + m.Echo("\t%s", msg.Meta[k][i]) + } + m.Echo("\n") + } + } + } + // }}} }}, }, Index: map[string]*ctx.Context{ diff --git a/src/contexts/web/web.go b/src/contexts/web/web.go index d2b6f856..9ba99e64 100644 --- a/src/contexts/web/web.go +++ b/src/contexts/web/web.go @@ -32,15 +32,18 @@ type WEB struct { *http.ServeMux *http.Server - list map[string]string + client *http.Client + cookie map[string]*http.Cookie + + list map[string][]string list_key []string *ctx.Message *ctx.Context } -func (web *WEB) generate(m *ctx.Message, arg string) string { // {{{ - add, e := url.Parse(arg) +func (web *WEB) generate(m *ctx.Message, uri string, arg ...string) string { // {{{ + add, e := url.Parse(uri) m.Assert(e) adds := []string{} @@ -76,12 +79,31 @@ func (web *WEB) generate(m *ctx.Message, arg string) string { // {{{ } } + args := []string{} + for i := 0; i < len(arg)-1; i += 2 { + args = append(args, arg[i]+"="+arg[i+1]) + } + p := strings.Join(args, "&") + if add.RawQuery != "" { adds = append(adds, "?") adds = append(adds, add.RawQuery) + if p != "" { + adds = append(adds, "&") + adds = append(adds, p) + } } else if m.Confs("query") { adds = append(adds, "?") adds = append(adds, m.Conf("query")) + if p != "" { + adds = append(adds, "&") + adds = append(adds, p) + } + } else { + if p != "" { + adds = append(adds, "?") + adds = append(adds, p) + } } return strings.Join(adds, "") @@ -147,22 +169,23 @@ func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.C // }}} func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) { // {{{ + web.Log("fuck", nil, "why") if web.Message != nil { log.Println() web.Log("cmd", nil, "%v %s %s", r.RemoteAddr, r.Method, r.URL) if web.Conf("logheaders") == "yes" { for k, v := range r.Header { - log.Printf("%s: %v", k, v) + web.Log("info", nil, "%s: %v", k, v) } - log.Println() + web.Log("info", nil, "") } if r.ParseForm(); len(r.PostForm) > 0 { for k, v := range r.PostForm { - log.Printf("%s: %v", k, v) + web.Log("info", nil, "%s: %v", k, v) } - log.Println() + web.Log("info", nil, "") } } @@ -170,9 +193,9 @@ func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) { // {{{ if web.Message != nil && web.Conf("logheaders") == "yes" { for k, v := range w.Header() { - log.Printf("%s: %v", k, v) + web.Log("info", nil, "%s: %v", k, v) } - log.Println() + web.Log("info", nil, "") } } @@ -207,7 +230,7 @@ func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ } } - web.list = map[string]string{} + web.list = map[string][]string{} return web } @@ -348,45 +371,112 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", }) } // }}} }}, - "get": &ctx.Command{Name: "get url", Help: "访问URL", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "cookie": &ctx.Command{Name: "cookie add|del arg...", Help: "访问URL", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { web, ok := m.Target().Server.(*WEB) // {{{ m.Assert(ok) - uri := web.generate(m, arg[0]) - m.Log("info", nil, "GET %s", uri) - - res, e := http.Get(uri) - m.Assert(e) - - for k, v := range res.Header { - m.Log("info", nil, "%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", name) - } - return + switch len(arg) { + case 0: + for k, v := range web.cookie { + m.Echo("%s: %v\n", k, v.Value) + } + case 1: + if v, ok := web.cookie[arg[0]]; ok { + m.Echo("%s", v.Value) + } + default: + if web.cookie == nil { + web.cookie = make(map[string]*http.Cookie) + } + if v, ok := web.cookie[arg[0]]; ok { + v.Value = arg[1] + } else { + web.cookie[arg[0]] = &http.Cookie{Name: arg[0], Value: arg[1]} } } - - buf, e := ioutil.ReadAll(res.Body) - m.Assert(e) - m.Echo(string(buf)) // }}} }}, - "list": &ctx.Command{Name: "list [index|add|del [url]]", Help: "查看、访问、添加url", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + "get": &ctx.Command{Name: "get [method GET|POST] [file filename] arg...", Help: "访问URL", + Formats: map[string]int{"method": 1, "file": 1}, + Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + web, ok := m.Target().Server.(*WEB) // {{{ + m.Assert(ok) + + uri := web.generate(m, arg[0], arg[1:]...) + m.Log("info", nil, "GET %s", uri) + + if web.client == nil { + web.client = &http.Client{} + } + + method := "GET" + if m.Options("method") { + method = m.Option("method") + } + + var body io.Reader + index := strings.Index(uri, "?") + switch method { + case "POST": + if index > 0 { + body = strings.NewReader(uri[index+1:]) + uri = uri[:index] + } + } + + req, e := http.NewRequest(method, uri, body) + m.Assert(e) + + switch method { + case "POST": + if index > 0 { + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + } + } + + for _, v := range web.cookie { + req.AddCookie(v) + } + + res, e := web.client.Do(req) + m.Assert(e) + + if web.cookie == nil { + web.cookie = make(map[string]*http.Cookie) + } + for _, v := range res.Cookies() { + web.cookie[v.Name] = v + } + + for k, v := range res.Header { + m.Log("info", nil, "%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", name) + } + return + } + } + + buf, e := ioutil.ReadAll(res.Body) + m.Assert(e) + m.Echo(string(buf)) + // }}} + }}, + "list": &ctx.Command{Name: "list [set|add|del [url]]", Help: "查看、访问、添加url", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { web, ok := m.Target().Server.(*WEB) // {{{ m.Assert(ok) @@ -400,16 +490,33 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心", case 1: msg := m.Spawn(m.Target()).Cmd("get", web.list[arg[0]]) m.Copy(msg, "result") - case 2: + default: switch arg[0] { case "add": - m.Capi("count", 1) - web.list[m.Cap("count")] = arg[1] + web.list[m.Cap("count")] = arg[1:] web.list_key = append(web.list_key, m.Cap("count")) + m.Capi("count", 1) case "del": delete(web.list, arg[1]) + case "set": + web.list[arg[1]] = arg[2:] default: - web.list[arg[0]] = arg[1] + list := []string{} + j := 1 + for _, v := range web.list[arg[0]] { + if v == "_" && j < len(arg) { + list = append(list, arg[j]) + j++ + } else { + list = append(list, v) + } + } + for ; j < len(arg); j++ { + list = append(list, arg[j]) + } + + msg := m.Spawn(m.Target()).Cmd("get", list) + m.Copy(msg, "result") } } // }}} }},