commit
7fc41ca5fb
85
conf/wide.go
85
conf/wide.go
|
@ -36,6 +36,7 @@ type User struct {
|
|||
Password string
|
||||
Workspace string // 该用户的工作空间 GOPATH 路径
|
||||
Locale string
|
||||
GoFormat string
|
||||
LatestSessionContent *LatestSessionContent
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,7 @@ func FixedTimeCheckEnv() {
|
|||
os.Exit(-1)
|
||||
}
|
||||
|
||||
gocode := Wide.GetGocode()
|
||||
gocode := Wide.GetExecutableInGOBIN("gocode")
|
||||
cmd := exec.Command(gocode, "close")
|
||||
_, err := cmd.Output()
|
||||
if nil != err {
|
||||
|
@ -91,7 +92,7 @@ func FixedTimeCheckEnv() {
|
|||
glog.Warningf("Not found gocode [%s]", gocode)
|
||||
}
|
||||
|
||||
ide_stub := Wide.GetIDEStub()
|
||||
ide_stub := Wide.GetExecutableInGOBIN("ide_stub")
|
||||
cmd = exec.Command(ide_stub, "version")
|
||||
_, err = cmd.Output()
|
||||
if nil != err {
|
||||
|
@ -131,11 +132,23 @@ func (c *conf) GetWorkspace() string {
|
|||
return filepath.FromSlash(strings.Replace(c.Workspace, "{pwd}", c.Pwd, 1))
|
||||
}
|
||||
|
||||
// 获取 user 的工作空间路径.
|
||||
func (user *User) getWorkspace() string {
|
||||
ret := strings.Replace(user.Workspace, "{pwd}", Wide.Pwd, 1)
|
||||
// 获取 username 指定的用户的 Go 源码格式化工具路径,查找不到时返回 "gofmt".
|
||||
func (c *conf) GetGoFmt(username string) string {
|
||||
for _, user := range c.Users {
|
||||
if user.Name == username {
|
||||
switch user.GoFormat {
|
||||
case "gofmt":
|
||||
return "gofmt"
|
||||
case "goimports":
|
||||
return c.GetExecutableInGOBIN("goimports")
|
||||
default:
|
||||
glog.Errorf("Unsupported Go Format tool [%s]", user.GoFormat)
|
||||
return "gofmt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filepath.FromSlash(ret)
|
||||
return "gofmt"
|
||||
}
|
||||
|
||||
// 获取 username 指定的用户配置.
|
||||
|
@ -149,40 +162,40 @@ func (*conf) GetUser(username string) *User {
|
|||
return nil
|
||||
}
|
||||
|
||||
// 获取 gocode 路径.
|
||||
func (*conf) GetGocode() string {
|
||||
return getGOBIN() + "gocode"
|
||||
}
|
||||
|
||||
// 获取 ide_stub 路径.
|
||||
func (*conf) GetIDEStub() string {
|
||||
return getGOBIN() + "ide_stub"
|
||||
}
|
||||
|
||||
// 获取 GOBIN 路径,末尾带路径分隔符.
|
||||
func getGOBIN() string {
|
||||
// $GOBIN/
|
||||
ret := os.Getenv("GOBIN")
|
||||
if "" != ret {
|
||||
return ret + PathSeparator
|
||||
// 获取 GOBIN 中 executable 指定的文件路径.
|
||||
//
|
||||
// 函数内部会判断操作系统,如果是 Windows 则在 executable 实参后加入 .exe 后缀.
|
||||
func (*conf) GetExecutableInGOBIN(executable string) string {
|
||||
if util.OS.IsWindows() {
|
||||
executable += ".exe"
|
||||
}
|
||||
|
||||
// $GOPATH/bin/$GOOS_$GOARCH/
|
||||
ret = os.Getenv("GOPATH") + PathSeparator + "bin" + PathSeparator +
|
||||
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH")
|
||||
if isExist(ret) {
|
||||
return ret + PathSeparator
|
||||
gopaths := strings.Split(os.Getenv("GOPATH"), PathListSeparator)
|
||||
|
||||
for _, gopath := range gopaths {
|
||||
// $GOPATH/bin/$GOOS_$GOARCH/executable
|
||||
ret := gopath + PathSeparator + "bin" + PathSeparator +
|
||||
os.Getenv("GOOS") + "_" + os.Getenv("GOARCH") + PathSeparator + executable
|
||||
if isExist(ret) {
|
||||
return ret
|
||||
}
|
||||
|
||||
// $GOPATH/bin/{runtime.GOOS}_{runtime.GOARCH}/executable
|
||||
ret = gopath + PathSeparator + "bin" + PathSeparator +
|
||||
runtime.GOOS + "_" + runtime.GOARCH + PathSeparator + executable
|
||||
if isExist(ret) {
|
||||
return ret
|
||||
}
|
||||
|
||||
// $GOPATH/bin/executable
|
||||
ret = gopath + PathSeparator + "bin" + PathSeparator + executable
|
||||
if isExist(ret) {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
// $GOPATH/bin/{runtime.GOOS}_{runtime.GOARCH}/
|
||||
ret = os.Getenv("GOPATH") + PathSeparator + "bin" + PathSeparator +
|
||||
runtime.GOOS + "_" + runtime.GOARCH
|
||||
if isExist(ret) {
|
||||
return ret + PathSeparator
|
||||
}
|
||||
|
||||
// $GOPATH/bin/
|
||||
return os.Getenv("GOPATH") + PathSeparator + "bin" + PathSeparator
|
||||
// $GOBIN/executable
|
||||
return os.Getenv("GOBIN") + PathSeparator + executable
|
||||
}
|
||||
|
||||
// 保存 Wide 配置.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"Password": "admin",
|
||||
"Workspace": "{pwd}/data/user_workspaces/admin",
|
||||
"Locale": "zh_CN",
|
||||
"GoFormat": "gofmt",
|
||||
"LatestSessionContent": {
|
||||
"FileTree": [],
|
||||
"Files": [],
|
||||
|
|
|
@ -56,7 +56,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// glog.Infof("offset: %d", offset)
|
||||
|
||||
gocode := conf.Wide.GetGocode()
|
||||
gocode := conf.Wide.GetExecutableInGOBIN("gocode")
|
||||
argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)}
|
||||
|
||||
var output bytes.Buffer
|
||||
|
@ -124,16 +124,18 @@ func AutocompleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// glog.Infof("offset: %d", offset)
|
||||
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
workspaces := strings.Split(userWorkspace, conf.PathListSeparator)
|
||||
libPath := ""
|
||||
for _, workspace := range workspaces {
|
||||
userLib := workspace + conf.PathSeparator + "pkg" + conf.PathSeparator +
|
||||
runtime.GOOS + "_" + runtime.GOARCH
|
||||
libPath += userLib + conf.PathListSeparator
|
||||
}
|
||||
|
||||
//glog.Infof("User [%s] workspace [%s]", username, userWorkspace)
|
||||
userLib := userWorkspace + conf.PathSeparator + "pkg" + conf.PathSeparator +
|
||||
runtime.GOOS + "_" + runtime.GOARCH
|
||||
|
||||
libPath := userLib
|
||||
//glog.Infof("gocode set lib-path %s", libPath)
|
||||
glog.V(5).Infof("gocode set lib-path %s", libPath)
|
||||
|
||||
// FIXME: 使用 gocode set lib-path 在多工作空间环境下肯定是有问题的,需要考虑其他实现方式
|
||||
gocode := conf.Wide.GetGocode()
|
||||
gocode := conf.Wide.GetExecutableInGOBIN("gocode")
|
||||
argv := []string{"set", "lib-path", libPath}
|
||||
exec.Command(gocode, argv...).Run()
|
||||
|
||||
|
@ -205,7 +207,7 @@ func GetExprInfoHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// glog.Infof("offset [%d]", offset)
|
||||
|
||||
// TODO: 目前是调用 liteide_stub 工具来查找声明,后续需要重新实现
|
||||
ide_stub := conf.Wide.GetIDEStub()
|
||||
ide_stub := conf.Wide.GetExecutableInGOBIN("ide_stub")
|
||||
argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-info", "."}
|
||||
cmd := exec.Command(ide_stub, argv...)
|
||||
cmd.Dir = curDir
|
||||
|
@ -279,7 +281,7 @@ func FindDeclarationHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// glog.Infof("offset [%d]", offset)
|
||||
|
||||
// TODO: 目前是调用 liteide_stub 工具来查找声明,后续需要重新实现
|
||||
ide_stub := conf.Wide.GetIDEStub()
|
||||
ide_stub := conf.Wide.GetExecutableInGOBIN("ide_stub")
|
||||
argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-def", "."}
|
||||
cmd := exec.Command(ide_stub, argv...)
|
||||
cmd.Dir = curDir
|
||||
|
@ -361,7 +363,7 @@ func FindUsagesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// glog.Infof("offset [%d]", offset)
|
||||
|
||||
// TODO: 目前是调用 liteide_stub 工具来查找使用,后续需要重新实现
|
||||
ide_stub := conf.Wide.GetIDEStub()
|
||||
ide_stub := conf.Wide.GetExecutableInGOBIN("ide_stub")
|
||||
argv := []string{"type", "-cursor", filename + ":" + strconv.Itoa(offset), "-use", "."}
|
||||
cmd := exec.Command(ide_stub, argv...)
|
||||
cmd.Dir = curDir
|
||||
|
|
|
@ -5,24 +5,30 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/88250/gohtml"
|
||||
"github.com/b3log/wide/conf"
|
||||
"github.com/b3log/wide/session"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// TODO: 加入 goimports 格式化 Go 源码文件
|
||||
|
||||
// gofmt 格式化 Go 源码文件.
|
||||
// 格式化 Go 源码文件.
|
||||
// 根据用户的 GoFormat 配置选择格式化工具:
|
||||
// 1. gofmt
|
||||
// 2. goimports
|
||||
func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
|
||||
data := map[string]interface{}{"succ": true}
|
||||
defer util.RetJSON(w, r, data)
|
||||
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
session, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
username := session.Values["username"].(string)
|
||||
|
||||
var args map[string]interface{}
|
||||
|
||||
if err := decoder.Decode(&args); err != nil {
|
||||
if err := json.NewDecoder(r.Body).Decode(&args); err != nil {
|
||||
glog.Error(err)
|
||||
data["succ"] = false
|
||||
|
||||
|
@ -31,6 +37,12 @@ func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
filePath := args["file"].(string)
|
||||
|
||||
apiPath := runtime.GOROOT() + conf.PathSeparator + "src" + conf.PathSeparator + "pkg"
|
||||
if strings.HasPrefix(filePath, apiPath) { // 如果是 Go API 源码文件
|
||||
// 忽略修改
|
||||
return
|
||||
}
|
||||
|
||||
fout, err := os.Create(filePath)
|
||||
|
||||
if nil != err {
|
||||
|
@ -50,8 +62,10 @@ func GoFmtHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
fmt := conf.Wide.GetGoFmt(username)
|
||||
|
||||
argv := []string{filePath}
|
||||
cmd := exec.Command("gofmt", argv...)
|
||||
cmd := exec.Command(fmt, argv...)
|
||||
|
||||
bytes, _ := cmd.Output()
|
||||
output := string(bytes)
|
||||
|
|
|
@ -45,9 +45,24 @@ func GetFiles(w http.ResponseWriter, r *http.Request) {
|
|||
session, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
username := session.Values["username"].(string)
|
||||
userSrc := conf.Wide.GetUserWorkspace(username) + conf.PathSeparator + "src"
|
||||
userWorkspace := conf.Wide.GetUserWorkspace(username)
|
||||
workspaces := strings.Split(userWorkspace, conf.PathListSeparator)
|
||||
|
||||
root := FileNode{Name: "projects", Path: userSrc, IconSkin: "ico-ztree-dir ", Type: "d", FileNodes: []*FileNode{}}
|
||||
root := FileNode{Name: "root", Path: "", IconSkin: "ico-ztree-dir ", Type: "d", FileNodes: []*FileNode{}}
|
||||
|
||||
// 工作空间节点处理
|
||||
for _, workspace := range workspaces {
|
||||
workspacePath := workspace + conf.PathSeparator + "src"
|
||||
|
||||
workspaceNode := FileNode{Name: workspace[strings.LastIndex(workspace, conf.PathSeparator)+1:] + " (" +
|
||||
workspace + ")",
|
||||
Path: workspacePath, IconSkin: "ico-ztree-dir ", Type: "d", FileNodes: []*FileNode{}}
|
||||
|
||||
walk(workspacePath, &workspaceNode)
|
||||
|
||||
// 添加工作空间节点
|
||||
root.FileNodes = append(root.FileNodes, &workspaceNode)
|
||||
}
|
||||
|
||||
// 构造 Go API 节点
|
||||
apiPath := runtime.GOROOT() + conf.PathSeparator + "src" + conf.PathSeparator + "pkg"
|
||||
|
@ -65,9 +80,6 @@ func GetFiles(w http.ResponseWriter, r *http.Request) {
|
|||
close(goapiBuildOKSignal)
|
||||
}()
|
||||
|
||||
// 构造用户工作空间文件树
|
||||
walk(userSrc, &root)
|
||||
|
||||
// 等待放行
|
||||
<-goapiBuildOKSignal
|
||||
|
||||
|
@ -381,28 +393,30 @@ func createFile(path, fileType string) bool {
|
|||
case "f":
|
||||
file, err := os.OpenFile(path, os.O_CREATE, 0664)
|
||||
if nil != err {
|
||||
glog.Info(err)
|
||||
glog.Error(err)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
glog.Infof("Created file [%s]", path)
|
||||
glog.V(5).Infof("Created file [%s]", path)
|
||||
|
||||
return true
|
||||
case "d":
|
||||
err := os.Mkdir(path, 0775)
|
||||
|
||||
if nil != err {
|
||||
glog.Info(err)
|
||||
glog.Error(err)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
glog.Infof("Created directory [%s]", path)
|
||||
glog.V(5).Infof("Created directory [%s]", path)
|
||||
|
||||
return true
|
||||
default:
|
||||
glog.Infof("Unsupported file type [%s]", fileType)
|
||||
glog.Errorf("Unsupported file type [%s]", fileType)
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
21
main.go
21
main.go
|
@ -53,8 +53,6 @@ func init() {
|
|||
|
||||
// 登录.
|
||||
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
if "GET" == r.Method {
|
||||
// 展示登录页面
|
||||
|
||||
|
@ -126,8 +124,6 @@ func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Wide 首页.
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
if httpSession.IsNew {
|
||||
|
@ -175,8 +171,6 @@ func serveSingle(pattern string, filename string) {
|
|||
|
||||
// 起始页请求处理.
|
||||
func startHandler(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
if httpSession.IsNew {
|
||||
|
@ -209,8 +203,6 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// 键盘快捷键页请求处理.
|
||||
func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
if httpSession.IsNew {
|
||||
|
@ -241,8 +233,6 @@ func keyboardShortcutsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// 关于页请求处理.
|
||||
func aboutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
if httpSession.IsNew {
|
||||
|
@ -356,10 +346,21 @@ func main() {
|
|||
func handlerWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
handler := panicRecover(f)
|
||||
handler = stopwatch(handler)
|
||||
handler = i18nLoad(handler)
|
||||
|
||||
return handler
|
||||
}
|
||||
|
||||
// 国际化处理包装.
|
||||
func i18nLoad(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
// Handler 处理
|
||||
handler(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler 包装请求计时.
|
||||
func stopwatch(handler func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -225,7 +225,7 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
suffix := ""
|
||||
if "windows" == runtime.GOOS {
|
||||
if util.OS.IsWindows() {
|
||||
suffix = ".exe"
|
||||
}
|
||||
executable := "main" + suffix
|
||||
|
|
|
@ -25,8 +25,6 @@ var ShellWS = map[string]*util.WSChannel{}
|
|||
|
||||
// Shell 首页.
|
||||
func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
i18n.Load()
|
||||
|
||||
httpSession, _ := session.HTTPSession.Get(r, "wide-session")
|
||||
|
||||
if httpSession.IsNew {
|
||||
|
|
|
@ -509,6 +509,10 @@ var wide = {
|
|||
wide.run();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wide.curProcessId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var request = newWideRequest();
|
||||
request.pid = wide.curProcessId;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type myos struct{}
|
||||
|
||||
// 操作系统工具.
|
||||
var OS = myos{}
|
||||
|
||||
// 判断是否是 Windows 操作系统.
|
||||
func (*myos) IsWindows() bool {
|
||||
return "windows" == runtime.GOOS
|
||||
}
|
Loading…
Reference in New Issue