diff --git a/conf/user.go b/conf/user.go index e0a5a3c..86f3863 100644 --- a/conf/user.go +++ b/conf/user.go @@ -59,6 +59,7 @@ type User struct { Workspace string // the GOPATH of this user (maybe contain several paths splitted by os.PathListSeparator) Locale string GoFormat string + GoBuildArgs string FontFamily string FontSize string Theme string @@ -91,7 +92,7 @@ func NewUser(username, password, email, workspace string) *User { now := time.Now().UnixNano() return &User{Name: username, Password: password, Salt: salt, Email: email, Gravatar: gravatar, Workspace: workspace, - Locale: Wide.Locale, GoFormat: "gofmt", FontFamily: "Helvetica", FontSize: "13px", Theme: "default", + Locale: Wide.Locale, GoFormat: "gofmt", GoBuildArgs: "-i", FontFamily: "Helvetica", FontSize: "13px", Theme: "default", Keymap: "wide", Created: now, Updated: now, Lived: now, Editor: &editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px", diff --git a/conf/users/admin.json b/conf/users/admin.json index fe526ac..fe6beb8 100644 --- a/conf/users/admin.json +++ b/conf/users/admin.json @@ -7,6 +7,7 @@ "Workspace": "${GOPATH}", "Locale": "en_US", "GoFormat": "gofmt", + "GoBuildArgs": "-i", "FontFamily": "Helvetica", "FontSize": "13px", "Theme": "default", @@ -18,20 +19,15 @@ "FontFamily": "Consolas, 'Courier New', monospace", "FontSize": "13px", "LineHeight": "17px", - "Theme": "lesser-dark", + "Theme": "wide", "TabSize": "4" }, "LatestSessionContent": { "fileTree": [ - "/Users/Vanessa/Work/GoGoGo/src", - "/Users/Vanessa/Work/GoGoGo/src/github.com", - "/Users/Vanessa/Work/GoGoGo/src/github.com/b3log", - "/Users/Vanessa/Work/GoGoGo/src/github.com/b3log/wide" ], "files": [ - "/Users/Vanessa/Work/GoGoGo/src/github.com/b3log/wide/.gitignore" ], - "currentFile": "/Users/Vanessa/Work/GoGoGo/src/github.com/b3log/wide/.gitignore", + "currentFile": "", "layout": { "side": { "state": "normal", diff --git a/conf/wide.go b/conf/wide.go index 9f063c4..77896bb 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -137,6 +137,11 @@ func initUsers() { user.Keymap = "wide" } + // Compatibility upgrade (1.5.3): https://github.com/b3log/wide/issues/308 + if "" == user.GoBuildArgs { + user.GoBuildArgs = "-i" + } + Users = append(Users, user) } diff --git a/output/build.go b/output/build.go index cb752bb..6ad40f4 100644 --- a/output/build.go +++ b/output/build.go @@ -18,8 +18,6 @@ import ( "bufio" "encoding/json" "io" - "io/ioutil" - "math/rand" "net/http" "os" "os/exec" @@ -45,7 +43,8 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { return } username := httpSession.Values["username"].(string) - locale := conf.GetUser(username).Locale + user := conf.GetUser(username) + locale := user.Locale var args map[string]interface{} @@ -93,7 +92,11 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { suffix = ".exe" } - cmd := exec.Command("go", "build") + goBuildArgs := []string{} + goBuildArgs = append(goBuildArgs, "build") + goBuildArgs = append(goBuildArgs, strings.Split(user.GoBuildArgs, " ")...) + + cmd := exec.Command("go", goBuildArgs...) cmd.Dir = curDir setCmdEnv(cmd, username) @@ -126,7 +129,10 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { if nil != session.OutputWS[sid] { // display "START [go build]" in front-end browser - channelRet["output"] = "" + i18n.Get(locale, "start-build").(string) + "\n" + msg := i18n.Get(locale, "start-build").(string) + msg = strings.Replace(msg, "build]", "build "+user.GoBuildArgs+"]", 1) + + channelRet["output"] = "" + msg + "\n" channelRet["cmd"] = "start-build" wsChannel := session.OutputWS[sid] @@ -140,8 +146,6 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { wsChannel.Refresh() } - reader := bufio.NewReader(io.MultiReader(stdout, stderr)) - if err := cmd.Start(); nil != err { logger.Error(err) result.Succ = false @@ -149,114 +153,160 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) { return } - go func(runningId int) { + // logger.Debugf("User [%s, %s] is building [id=%d, dir=%s]", username, sid, runningId, curDir) + + channelRet["cmd"] = "build" + channelRet["executable"] = executable + + outReader := bufio.NewReader(stdout) + + ///////// + go func() { defer util.Recover() - defer cmd.Wait() - - // logger.Debugf("User [%s, %s] is building [id=%d, dir=%s]", username, sid, runningId, curDir) - - // read all - buf, _ := ioutil.ReadAll(reader) - - channelRet := map[string]interface{}{} - channelRet["cmd"] = "build" - channelRet["executable"] = executable - - if 0 == len(buf) { // build success - channelRet["nextCmd"] = args["nextCmd"] - channelRet["output"] = "" + i18n.Get(locale, "build-succ").(string) + "\n" - - go func() { // go install, for subsequent gocode lib-path - defer util.Recover() - - cmd := exec.Command("go", "install") - cmd.Dir = curDir - - setCmdEnv(cmd, username) - - out, _ := cmd.CombinedOutput() - if len(out) > 0 { - logger.Warn(string(out)) - } - }() - } else { // build error - // build gutter lint - - errOut := string(buf) - lines := strings.Split(errOut, "\n") - - // path process - var errOutWithPath string - for _, line := range lines { - errOutWithPath += parsePath(curDir, line) + "\n" - } - - channelRet["output"] = "" + i18n.Get(locale, "build-error").(string) + "\n" + - "" + errOutWithPath + "" - - // lint process - - if lines[0][0] == '#' { - lines = lines[1:] // skip the first line - } - - lints := []*Lint{} - - for _, line := range lines { - if len(line) < 1 { - continue - } - - if line[0] == '\t' { - // append to the last lint - last := len(lints) - msg := lints[last-1].Msg - msg += line - - lints[last-1].Msg = msg - - continue - } - - file := line[:strings.Index(line, ":")] - left := line[strings.Index(line, ":")+1:] - index := strings.Index(left, ":") - lineNo := 0 - msg := left - if index >= 0 { - lineNo, err = strconv.Atoi(left[:index]) - - if nil != err { - continue - } - - msg = left[index+2:] - } - - lint := &Lint{ - File: filepath.Join(curDir, file), - LineNo: lineNo - 1, - Severity: lintSeverityError, - Msg: msg, - } - - lints = append(lints, lint) - } - - channelRet["lints"] = lints - } - - if nil != session.OutputWS[sid] { - // logger.Debugf("User [%s, %s] 's build [id=%d, dir=%s] has done", username, sid, runningId, curDir) + for { wsChannel := session.OutputWS[sid] - err := wsChannel.WriteJSON(&channelRet) + if nil == wsChannel { + break + } + + line, err := outReader.ReadString('\n') + if io.EOF == err { + break + } + if nil != err { logger.Warn(err) + + break + } + + channelRet["output"] = line + + err = wsChannel.WriteJSON(&channelRet) + if nil != err { + logger.Warn(err) + break } wsChannel.Refresh() } + }() - }(rand.Int()) + errReader := bufio.NewReader(stderr) + lines := []string{} + for { + wsChannel := session.OutputWS[sid] + if nil == wsChannel { + break + } + + line, err := errReader.ReadString('\n') + if io.EOF == err { + break + } + + lines = append(lines, line) + + if nil != err { + logger.Warn(err) + + break + } + + // path process + errOutWithPath := parsePath(curDir, line) + channelRet["output"] = "" + errOutWithPath + "" + + err = wsChannel.WriteJSON(&channelRet) + if nil != err { + logger.Warn(err) + break + } + + wsChannel.Refresh() + } + + if nil == cmd.Wait() { + channelRet["nextCmd"] = args["nextCmd"] + channelRet["output"] = "" + i18n.Get(locale, "build-succ").(string) + "\n" + + go func() { // go install, for subsequent gocode lib-path + defer util.Recover() + + cmd := exec.Command("go", "install") + cmd.Dir = curDir + + setCmdEnv(cmd, username) + + out, _ := cmd.CombinedOutput() + if len(out) > 0 { + logger.Warn(string(out)) + } + }() + } else { + channelRet["output"] = "" + i18n.Get(locale, "build-error").(string) + "\n" + + logger.Info(lines) + // lint process + if lines[0][0] == '#' { + lines = lines[1:] // skip the first line + } + + lints := []*Lint{} + + for _, line := range lines { + if len(line) < 1 || !strings.Contains(line, ":") { + continue + } + + if line[0] == '\t' { + // append to the last lint + last := len(lints) + msg := lints[last-1].Msg + msg += line + + lints[last-1].Msg = msg + + continue + } + + file := line[:strings.Index(line, ":")] + left := line[strings.Index(line, ":")+1:] + index := strings.Index(left, ":") + lineNo := 0 + msg := left + if index >= 0 { + lineNo, err = strconv.Atoi(left[:index]) + + if nil != err { + continue + } + + msg = left[index+2:] + } + + lint := &Lint{ + File: filepath.ToSlash(filepath.Join(curDir, file)), + LineNo: lineNo - 1, + Severity: lintSeverityError, + Msg: msg, + } + + lints = append(lints, lint) + } + + channelRet["lints"] = lints + } + + wsChannel := session.OutputWS[sid] + if nil == wsChannel { + return + } + err = wsChannel.WriteJSON(&channelRet) + if nil != err { + logger.Warn(err) + } + + wsChannel.Refresh() } diff --git a/output/outputs.go b/output/outputs.go index 16aa93f..f41993f 100644 --- a/output/outputs.go +++ b/output/outputs.go @@ -93,7 +93,7 @@ func parsePath(curDir, outputLine string) string { column = parts[2] } - tagStart := `` text := file + ":" + line if hasColumn { diff --git a/session/users.go b/session/users.go index 7532203..1add20a 100644 --- a/session/users.go +++ b/session/users.go @@ -95,6 +95,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) { FontFamily string FontSize string GoFmt string + GoBuildArgs string Keymap string Workspace string Username string @@ -119,6 +120,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) { user.FontFamily = args.FontFamily user.FontSize = args.FontSize user.GoFormat = args.GoFmt + user.GoBuildArgs = args.GoBuildArgs user.Keymap = args.Keymap // XXX: disallow change workspace at present // user.Workspace = args.Workspace diff --git a/static/js/bottomGroup.js b/static/js/bottomGroup.js index 996a77a..8c2876f 100644 --- a/static/js/bottomGroup.js +++ b/static/js/bottomGroup.js @@ -19,7 +19,7 @@ * * @author Liyuan Li * @author Liang Ding - * @version 1.1.0.1, Dec 8, 2015 + * @version 1.1.1.1, Mar 15, 2017 */ var bottomGroup = { tabs: undefined, @@ -82,6 +82,7 @@ var bottomGroup = { fillOutput: function (data) { var $output = $('.bottom-window-group .output'); + data = data.replace(/\r/g, ''); data = data.replace(/\n/g, '
'); if (-1 !== data.indexOf("
")) { diff --git a/static/js/menu.js b/static/js/menu.js index dd75c3d..455c841 100644 --- a/static/js/menu.js +++ b/static/js/menu.js @@ -19,7 +19,7 @@ * * @author Liyuan Li * @author Liang Ding - * @version 1.0.0.1, Dec 8, 2015 + * @version 1.0.1.1, Mar 15, 2017 */ var menu = { init: function () { @@ -313,10 +313,11 @@ var menu = { dataType: "json", beforeSend: function () { bottomGroup.resetOutput(); - }, - success: function (result) { + $("#buildRun").addClass("ico-stop") .removeClass("ico-buildrun").attr("title", config.label.stop); + }, + success: function (result) { } }); }, @@ -424,6 +425,7 @@ var menu = { $fontFamily = $dialogPreference.find("input[name=fontFamily]"), $fontSize = $dialogPreference.find("input[name=fontSize]"), $goFmt = $dialogPreference.find("select[name=goFmt]"), + $goBuildArgs = $dialogPreference.find("input[name=goBuildArgs]"), $workspace = $dialogPreference.find("input[name=workspace]"), $password = $dialogPreference.find("input[name=password]"), $email = $dialogPreference.find("input[name=email]"), @@ -440,6 +442,7 @@ var menu = { "fontFamily": $fontFamily.val(), "fontSize": $fontSize.val(), "goFmt": $goFmt.val(), + "goBuildArgs": $goBuildArgs.val(), "workspace": $workspace.val(), "password": $password.val(), "email": $email.val(), @@ -469,6 +472,7 @@ var menu = { $fontFamily.data("value", $fontFamily.val()); $fontSize.data("value", $fontSize.val()); $goFmt.data("value", $goFmt.val()); + $goBuildArgs.data("value", $goBuildArgs.val()); $workspace.data("value", $workspace.val()); $password.data("value", $password.val()); $email.data("value", $email.val()); diff --git a/views/preference.html b/views/preference.html index 9615906..8f24297 100644 --- a/views/preference.html +++ b/views/preference.html @@ -70,6 +70,10 @@ {{end}} +