This commit is contained in:
Liang Ding 2014-09-15 13:03:44 +08:00
parent 28ca0b2f94
commit 172f7f3b4f
4 changed files with 159 additions and 9 deletions

View File

@ -7,6 +7,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
_ "github.com/b3log/wide/i18n" _ "github.com/b3log/wide/i18n"
@ -37,7 +38,7 @@ var Wide conf
var rawWide conf var rawWide conf
// 获取 username 指定的用户的工作空间路径. // 获取 username 指定的用户的工作空间路径.
func (this *conf) GetUserWorkspace(username string) string { func (*conf) GetUserWorkspace(username string) string {
for _, user := range Wide.Users { for _, user := range Wide.Users {
if user.Name == username { if user.Name == username {
ret := strings.Replace(user.Workspace, "{Pwd}", Wide.Pwd, 1) ret := strings.Replace(user.Workspace, "{Pwd}", Wide.Pwd, 1)
@ -48,6 +49,28 @@ func (this *conf) GetUserWorkspace(username string) string {
return "" 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 { func Save() bool {
// 只有 Users 是可以通过界面修改的,其他属性只能手工维护 wide.json 配置文件 // 只有 Users 是可以通过界面修改的,其他属性只能手工维护 wide.json 配置文件
rawWide.Users = Wide.Users rawWide.Users = Wide.Users

View File

@ -62,8 +62,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
// glog.Infof("offset: %d", offset) // glog.Infof("offset: %d", offset)
gocode := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + gocode := conf.Wide.GetGocode()
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "gocode"
argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)} argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)}
var output bytes.Buffer var output bytes.Buffer
@ -122,8 +121,7 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
//glog.Infof("gocode set lib-path %s", libPath) //glog.Infof("gocode set lib-path %s", libPath)
// FIXME: 使用 gocode set lib-path 在多工作空间环境下肯定是有问题的,需要考虑其他实现方式 // FIXME: 使用 gocode set lib-path 在多工作空间环境下肯定是有问题的,需要考虑其他实现方式
gocode := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + gocode := conf.Wide.GetGocode()
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "gocode"
argv := []string{"set", "lib-path", libPath} argv := []string{"set", "lib-path", libPath}
cmd := exec.Command(gocode, argv...) cmd := exec.Command(gocode, argv...)
cmd.Start() cmd.Start()
@ -200,8 +198,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
// glog.Infof("offset [%d]", offset) // glog.Infof("offset [%d]", offset)
// TODO: 目前是调用 liteide_stub 工具来查找声明,后续需要重新实现 // TODO: 目前是调用 liteide_stub 工具来查找声明,后续需要重新实现
ide_stub := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + ide_stub := conf.Wide.GetIDEStub()
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "ide_stub"
argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-def", "."} argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-def", "."}
cmd := exec.Command(ide_stub, argv...) cmd := exec.Command(ide_stub, argv...)
cmd.Dir = curDir cmd.Dir = curDir
@ -282,8 +279,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
offset := getCursorOffset(code, line, ch) offset := getCursorOffset(code, line, ch)
// TODO: 目前是调用 liteide_stub 工具来查找使用,后续需要重新实现 // TODO: 目前是调用 liteide_stub 工具来查找使用,后续需要重新实现
ide_stub := os.Getenv("GOPATH") + string(os.PathSeparator) + "bin" + string(os.PathSeparator) + ide_stub := conf.Wide.GetIDEStub()
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + string(os.PathSeparator) + "ide_stub"
argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-use", "."} argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-use", "."}
cmd := exec.Command(ide_stub, argv...) cmd := exec.Command(ide_stub, argv...)
cmd.Dir = curDir cmd.Dir = curDir

8
notification/events.go Normal file
View File

@ -0,0 +1,8 @@
package notification
const (
EvtGOPATHNotFound = iota // 事件:找不到环境变量 $GOPATH
EvtGOROOTNotFound // 事件:找不到环境变量 $GOROOT
EvtGocodeNotFount // 事件:找不到 gocode
EvtIDEStubNotFound // 事件:找不到 IDE stub
)

View File

@ -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
}