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)
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",

View File

@ -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",

View File

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

View File

@ -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"] = "<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"
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"] = "<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]
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"] = "<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]
}
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 + `">`
text := file + ":" + line
if hasColumn {

View File

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

View File

@ -19,7 +19,7 @@
*
* @author <a href="http://vanessa.b3log.org">Liyuan Li</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 = {
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, '<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://88250.b3log.org">Liang Ding</a>
* @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());

View File

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