Merge remote-tracking branch 'refs/remotes/origin/1.5.3-dev'

This commit is contained in:
Liang Ding 2017-03-15 23:27:06 +08:00
commit 4a4788be85
9 changed files with 183 additions and 120 deletions

View File

@ -59,6 +59,7 @@ type User struct {
Workspace string // the GOPATH of this user (maybe contain several paths splitted by os.PathListSeparator) Workspace string // the GOPATH of this user (maybe contain several paths splitted by os.PathListSeparator)
Locale string Locale string
GoFormat string GoFormat string
GoBuildArgs string
FontFamily string FontFamily string
FontSize string FontSize string
Theme string Theme string
@ -91,7 +92,7 @@ func NewUser(username, password, email, workspace string) *User {
now := time.Now().UnixNano() now := time.Now().UnixNano()
return &User{Name: username, Password: password, Salt: salt, Email: email, Gravatar: gravatar, Workspace: workspace, 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", Keymap: "wide",
Created: now, Updated: now, Lived: now, Created: now, Updated: now, Lived: now,
Editor: &editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px", Editor: &editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit", LineHeight: "17px",

View File

@ -7,6 +7,7 @@
"Workspace": "${GOPATH}", "Workspace": "${GOPATH}",
"Locale": "en_US", "Locale": "en_US",
"GoFormat": "gofmt", "GoFormat": "gofmt",
"GoBuildArgs": "-i",
"FontFamily": "Helvetica", "FontFamily": "Helvetica",
"FontSize": "13px", "FontSize": "13px",
"Theme": "default", "Theme": "default",
@ -18,20 +19,15 @@
"FontFamily": "Consolas, 'Courier New', monospace", "FontFamily": "Consolas, 'Courier New', monospace",
"FontSize": "13px", "FontSize": "13px",
"LineHeight": "17px", "LineHeight": "17px",
"Theme": "lesser-dark", "Theme": "wide",
"TabSize": "4" "TabSize": "4"
}, },
"LatestSessionContent": { "LatestSessionContent": {
"fileTree": [ "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": [ "files": [
"/Users/Vanessa/Work/GoGoGo/src/github.com/b3log/wide/.gitignore"
], ],
"currentFile": "/Users/Vanessa/Work/GoGoGo/src/github.com/b3log/wide/.gitignore", "currentFile": "",
"layout": { "layout": {
"side": { "side": {
"state": "normal", "state": "normal",

View File

@ -137,6 +137,11 @@ func initUsers() {
user.Keymap = "wide" 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) Users = append(Users, user)
} }

View File

@ -18,8 +18,6 @@ import (
"bufio" "bufio"
"encoding/json" "encoding/json"
"io" "io"
"io/ioutil"
"math/rand"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
@ -45,7 +43,8 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
username := httpSession.Values["username"].(string) username := httpSession.Values["username"].(string)
locale := conf.GetUser(username).Locale user := conf.GetUser(username)
locale := user.Locale
var args map[string]interface{} var args map[string]interface{}
@ -93,7 +92,11 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
suffix = ".exe" 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 cmd.Dir = curDir
setCmdEnv(cmd, username) setCmdEnv(cmd, username)
@ -126,7 +129,10 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
if nil != session.OutputWS[sid] { if nil != session.OutputWS[sid] {
// display "START [go build]" in front-end browser // display "START [go build]" in front-end browser
channelRet["output"] = "<span class='start-build'>" + i18n.Get(locale, "start-build").(string) + "</span>\n" msg := i18n.Get(locale, "start-build").(string)
msg = strings.Replace(msg, "build]", "build "+user.GoBuildArgs+"]", 1)
channelRet["output"] = "<span class='start-build'>" + msg + "</span>\n"
channelRet["cmd"] = "start-build" channelRet["cmd"] = "start-build"
wsChannel := session.OutputWS[sid] wsChannel := session.OutputWS[sid]
@ -140,8 +146,6 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
wsChannel.Refresh() wsChannel.Refresh()
} }
reader := bufio.NewReader(io.MultiReader(stdout, stderr))
if err := cmd.Start(); nil != err { if err := cmd.Start(); nil != err {
logger.Error(err) logger.Error(err)
result.Succ = false result.Succ = false
@ -149,114 +153,160 @@ func BuildHandler(w http.ResponseWriter, r *http.Request) {
return 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 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"] = "<span class='build-succ'>" + i18n.Get(locale, "build-succ").(string) + "</span>\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"] = "<span class='build-error'>" + i18n.Get(locale, "build-error").(string) + "</span>\n" +
"<span class='stderr'>" + errOutWithPath + "</span>"
// 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] 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 { if nil != err {
logger.Warn(err) logger.Warn(err)
break
}
channelRet["output"] = line
err = wsChannel.WriteJSON(&channelRet)
if nil != err {
logger.Warn(err)
break
} }
wsChannel.Refresh() 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"] = "<span class='stderr'>" + errOutWithPath + "</span>"
err = wsChannel.WriteJSON(&channelRet)
if nil != err {
logger.Warn(err)
break
}
wsChannel.Refresh()
}
if nil == cmd.Wait() {
channelRet["nextCmd"] = args["nextCmd"]
channelRet["output"] = "<span class='build-succ'>" + i18n.Get(locale, "build-succ").(string) + "</span>\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"] = "<span class='build-error'>" + i18n.Get(locale, "build-error").(string) + "</span>\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()
} }

View File

@ -93,7 +93,7 @@ func parsePath(curDir, outputLine string) string {
column = parts[2] column = parts[2]
} }
tagStart := `<span class="path" data-path="` + filepath.Join(curDir, file) + `" data-line="` + line + tagStart := `<span class="path" data-path="` + filepath.ToSlash(filepath.Join(curDir, file)) + `" data-line="` + line +
`" data-column="` + column + `">` `" data-column="` + column + `">`
text := file + ":" + line text := file + ":" + line
if hasColumn { if hasColumn {

View File

@ -95,6 +95,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
FontFamily string FontFamily string
FontSize string FontSize string
GoFmt string GoFmt string
GoBuildArgs string
Keymap string Keymap string
Workspace string Workspace string
Username string Username string
@ -119,6 +120,7 @@ func PreferenceHandler(w http.ResponseWriter, r *http.Request) {
user.FontFamily = args.FontFamily user.FontFamily = args.FontFamily
user.FontSize = args.FontSize user.FontSize = args.FontSize
user.GoFormat = args.GoFmt user.GoFormat = args.GoFmt
user.GoBuildArgs = args.GoBuildArgs
user.Keymap = args.Keymap user.Keymap = args.Keymap
// XXX: disallow change workspace at present // XXX: disallow change workspace at present
// user.Workspace = args.Workspace // user.Workspace = args.Workspace

View File

@ -19,7 +19,7 @@
* *
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a> * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.1.0.1, Dec 8, 2015 * @version 1.1.1.1, Mar 15, 2017
*/ */
var bottomGroup = { var bottomGroup = {
tabs: undefined, tabs: undefined,
@ -82,6 +82,7 @@ var bottomGroup = {
fillOutput: function (data) { fillOutput: function (data) {
var $output = $('.bottom-window-group .output'); var $output = $('.bottom-window-group .output');
data = data.replace(/\r/g, '');
data = data.replace(/\n/g, '<br/>'); data = data.replace(/\n/g, '<br/>');
if (-1 !== data.indexOf("<br/>")) { if (-1 !== data.indexOf("<br/>")) {

View File

@ -19,7 +19,7 @@
* *
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a> * @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
* @author <a href="http://88250.b3log.org">Liang Ding</a> * @author <a href="http://88250.b3log.org">Liang Ding</a>
* @version 1.0.0.1, Dec 8, 2015 * @version 1.0.1.1, Mar 15, 2017
*/ */
var menu = { var menu = {
init: function () { init: function () {
@ -313,10 +313,11 @@ var menu = {
dataType: "json", dataType: "json",
beforeSend: function () { beforeSend: function () {
bottomGroup.resetOutput(); bottomGroup.resetOutput();
},
success: function (result) {
$("#buildRun").addClass("ico-stop") $("#buildRun").addClass("ico-stop")
.removeClass("ico-buildrun").attr("title", config.label.stop); .removeClass("ico-buildrun").attr("title", config.label.stop);
},
success: function (result) {
} }
}); });
}, },
@ -424,6 +425,7 @@ var menu = {
$fontFamily = $dialogPreference.find("input[name=fontFamily]"), $fontFamily = $dialogPreference.find("input[name=fontFamily]"),
$fontSize = $dialogPreference.find("input[name=fontSize]"), $fontSize = $dialogPreference.find("input[name=fontSize]"),
$goFmt = $dialogPreference.find("select[name=goFmt]"), $goFmt = $dialogPreference.find("select[name=goFmt]"),
$goBuildArgs = $dialogPreference.find("input[name=goBuildArgs]"),
$workspace = $dialogPreference.find("input[name=workspace]"), $workspace = $dialogPreference.find("input[name=workspace]"),
$password = $dialogPreference.find("input[name=password]"), $password = $dialogPreference.find("input[name=password]"),
$email = $dialogPreference.find("input[name=email]"), $email = $dialogPreference.find("input[name=email]"),
@ -440,6 +442,7 @@ var menu = {
"fontFamily": $fontFamily.val(), "fontFamily": $fontFamily.val(),
"fontSize": $fontSize.val(), "fontSize": $fontSize.val(),
"goFmt": $goFmt.val(), "goFmt": $goFmt.val(),
"goBuildArgs": $goBuildArgs.val(),
"workspace": $workspace.val(), "workspace": $workspace.val(),
"password": $password.val(), "password": $password.val(),
"email": $email.val(), "email": $email.val(),
@ -469,6 +472,7 @@ var menu = {
$fontFamily.data("value", $fontFamily.val()); $fontFamily.data("value", $fontFamily.val());
$fontSize.data("value", $fontSize.val()); $fontSize.data("value", $fontSize.val());
$goFmt.data("value", $goFmt.val()); $goFmt.data("value", $goFmt.val());
$goBuildArgs.data("value", $goBuildArgs.val());
$workspace.data("value", $workspace.val()); $workspace.data("value", $workspace.val());
$password.data("value", $password.val()); $password.data("value", $password.val());
$email.data("value", $email.val()); $email.data("value", $email.val());

View File

@ -70,6 +70,10 @@
{{end}} {{end}}
</select> </select>
</label> </label>
<label>
Go Build Args{{.i18n.colon}}
<input data-value="{{.user.GoBuildArgs}}" value="{{.user.GoBuildArgs}}" name="goBuildArgs"/>
</label>
</div> </div>
<div class="fn-none" data-index="keymap"> <div class="fn-none" data-index="keymap">
<label> <label>