From 172f7f3b4fcc4fcb1379b54171dcca220822e480 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Mon, 15 Sep 2014 13:03:44 +0800 Subject: [PATCH] . --- conf/wide.go | 25 ++++++- editor/editors.go | 12 ++-- notification/events.go | 8 +++ notification/notifications.go | 123 ++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 notification/events.go create mode 100644 notification/notifications.go diff --git a/conf/wide.go b/conf/wide.go index 641fa12..12440f3 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strings" _ "github.com/b3log/wide/i18n" @@ -37,7 +38,7 @@ var Wide conf var rawWide conf // 获取 username 指定的用户的工作空间路径. -func (this *conf) GetUserWorkspace(username string) string { +func (*conf) GetUserWorkspace(username string) string { for _, user := range Wide.Users { if user.Name == username { ret := strings.Replace(user.Workspace, "{Pwd}", Wide.Pwd, 1) @@ -48,6 +49,28 @@ func (this *conf) GetUserWorkspace(username string) string { return "" } +// 获取 gocode 路径. +func (*conf) GetGocode() string { + if "" != os.Getenv("GOARCH") { + return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + + runtime.GOOS + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "gocode" + } else { + return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + + "gocode" + } +} + +// 获取 ide_stub 路径. +func (*conf) GetIDEStub() string { + if "" != os.Getenv("GOARCH") { + return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + + runtime.GOOS + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "ide_stub" + } else { + return os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + + "ide_stub" + } +} + func Save() bool { // 只有 Users 是可以通过界面修改的,其他属性只能手工维护 wide.json 配置文件 rawWide.Users = Wide.Users diff --git a/editor/editors.go b/editor/editors.go index a22392e..675cde8 100644 --- a/editor/editors.go +++ b/editor/editors.go @@ -62,8 +62,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) { // glog.Infof("offset: %d", offset) - gocode := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "gocode" + gocode := conf.Wide.GetGocode() argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)} var output bytes.Buffer @@ -122,8 +121,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) { //glog.Infof("gocode set lib-path %s", libPath) // FIXME: 使用 gocode set lib-path 在多工作空间环境下肯定是有问题的,需要考虑其他实现方式 - gocode := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "gocode" + gocode := conf.Wide.GetGocode() argv := []string{"set", "lib-path", libPath} cmd := exec.Command(gocode, argv...) cmd.Start() @@ -200,8 +198,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) { // glog.Infof("offset [%d]", offset) // TODO: 目前是调用 liteide_stub 工具来查找声明,后续需要重新实现 - ide_stub := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "ide_stub" + ide_stub := conf.Wide.GetIDEStub() argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-def", "."} cmd := exec.Command(ide_stub, argv...) cmd.Dir = curDir @@ -282,8 +279,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) { offset := getCursorOffset(code, line, ch) // TODO: 目前是调用 liteide_stub 工具来查找使用,后续需要重新实现 - ide_stub := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + - os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "ide_stub" + ide_stub := conf.Wide.GetIDEStub() argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-use", "."} cmd := exec.Command(ide_stub, argv...) cmd.Dir = curDir diff --git a/notification/events.go b/notification/events.go new file mode 100644 index 0000000..37b60c4 --- /dev/null +++ b/notification/events.go @@ -0,0 +1,8 @@ +package notification + +const ( + EvtGOPATHNotFound = iota // 事件:找不到环境变量 $GOPATH + EvtGOROOTNotFound // 事件:找不到环境变量 $GOROOT + EvtGocodeNotFount // 事件:找不到 gocode + EvtIDEStubNotFound // 事件:找不到 IDE stub +) diff --git a/notification/notifications.go b/notification/notifications.go new file mode 100644 index 0000000..16d09df --- /dev/null +++ b/notification/notifications.go @@ -0,0 +1,123 @@ +// 通知. +package notifications + +import ( + "net/http" + "os" + "os/exec" + "runtime" + "strings" + + "github.com/b3log/wide/conf" + "github.com/b3log/wide/user" + "github.com/golang/glog" + "github.com/gorilla/websocket" +) + +// 通知结构. +type Notification struct { + Event int + Type string + Severity string // ERROR/WARN/INFO + Message string +} + +var notificationWS = map[string]*websocket.Conn{} + +func WSHandler(w http.ResponseWriter, r *http.Request) { + session, _ := user.Session.Get(r, "wide-session") + username := session.Values["username"].(string) + sid := session.Values["id"].(string) + + notificationWS[sid], _ = websocket.Upgrade(w, r, nil, 1024, 1024) + + ret := map[string]interface{}{"output": "Notification initialized", "cmd": "init-notification"} + notificationWS[sid].WriteJSON(&ret) + + glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(notificationWS)) + + input := map[string]interface{}{} + + for { + if err := notificationWS[sid].ReadJSON(&input); err != nil { + if err.Error() == "EOF" { + return + } + + if err.Error() == "unexpected EOF" { + return + } + + glog.Error("Shell WS ERROR: " + err.Error()) + return + } + + inputCmd := input["cmd"].(string) + + cmds := strings.Split(inputCmd, "|") + commands := []*exec.Cmd{} + for _, cmdWithArgs := range cmds { + cmdWithArgs = strings.TrimSpace(cmdWithArgs) + cmdWithArgs := strings.Split(cmdWithArgs, " ") + args := []string{} + if len(cmdWithArgs) > 1 { + args = cmdWithArgs[1:] + } + + cmd := exec.Command(cmdWithArgs[0], args...) + commands = append(commands, cmd) + } + + output := "" + if !strings.Contains(inputCmd, "clear") { + output = pipeCommands(username, commands...) + } + + ret = map[string]interface{}{"output": output, "cmd": "shell-output"} + + if err := notificationWS[sid].WriteJSON(&ret); err != nil { + glog.Error("Shell WS ERROR: " + err.Error()) + return + } + } +} + +func pipeCommands(username string, commands ...*exec.Cmd) string { + for i, command := range commands[:len(commands)-1] { + setCmdEnv(command, username) + + stdout, err := command.StdoutPipe() + if nil != err { + return err.Error() + } + + command.Start() + + commands[i+1].Stdin = stdout + } + + last := commands[len(commands)-1] + setCmdEnv(last, username) + + out, err := last.CombinedOutput() + + if err != nil { + return err.Error() + } + + return string(out) +} + +func setCmdEnv(cmd *exec.Cmd, username string) { + userWorkspace := conf.Wide.GetUserWorkspace(username) + + cmd.Env = append(cmd.Env, + "TERM="+os.Getenv("TERM"), + "GOPATH="+userWorkspace, + "GOOS="+runtime.GOOS, + "GOARCH="+runtime.GOARCH, + "GOROOT="+runtime.GOROOT(), + "PATH="+os.Getenv("PATH")) + + cmd.Dir = userWorkspace +}