diff --git a/main.go b/main.go index 6200af3..7c47b86 100644 --- a/main.go +++ b/main.go @@ -40,6 +40,7 @@ func main() { http.HandleFunc("/", indexHandler) + http.HandleFunc("/build", output.BuildHandler) http.HandleFunc("/run", output.RunHandler) http.HandleFunc("/output/ws", output.WSHandler) diff --git a/output/outputs.go b/output/outputs.go index 47bdf68..b3a2b61 100644 --- a/output/outputs.go +++ b/output/outputs.go @@ -10,6 +10,8 @@ import ( "net/http" "os" "os/exec" + "runtime" + "strings" ) var outputWS = map[string]*websocket.Conn{} @@ -41,31 +43,11 @@ func RunHandler(w http.ResponseWriter, r *http.Request) { return } - filePath := args["file"].(string) + filePath := args["executable"].(string) + curDir := filePath[:strings.LastIndex(filePath, string(os.PathSeparator))] - fout, err := os.Create(filePath) - - if nil != err { - glog.Error(err) - http.Error(w, err.Error(), 500) - - return - } - - code := args["code"].(string) - - fout.WriteString(code) - - if err := fout.Close(); nil != err { - glog.Error(err) - http.Error(w, err.Error(), 500) - - return - } - - argv := []string{"run", filePath} - - cmd := exec.Command("go", argv...) + cmd := exec.Command(filePath) + cmd.Dir = curDir stdout, err := cmd.StdoutPipe() if nil != err { @@ -119,3 +101,104 @@ func RunHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Write(ret) } + +func BuildHandler(w http.ResponseWriter, r *http.Request) { + session, _ := session.Store.Get(r, "wide-session") + sid := session.Values["id"].(string) + + decoder := json.NewDecoder(r.Body) + + var args map[string]interface{} + + if err := decoder.Decode(&args); err != nil { + glog.Error(err) + http.Error(w, err.Error(), 500) + + return + } + + filePath := args["file"].(string) + curDir := filePath[:strings.LastIndex(filePath, string(os.PathSeparator))] + + fout, err := os.Create(filePath) + + if nil != err { + glog.Error(err) + http.Error(w, err.Error(), 500) + + return + } + + code := args["code"].(string) + + fout.WriteString(code) + + if err := fout.Close(); nil != err { + glog.Error(err) + http.Error(w, err.Error(), 500) + + return + } + + suffix := "" + if "windows" == runtime.GOOS { + suffix = ".exe" + } + executable := "main" + suffix + argv := []string{"build", "-o", executable, filePath} + + cmd := exec.Command("go", argv...) + cmd.Dir = curDir + + glog.Info("go build ", filePath) + + stdout, err := cmd.StdoutPipe() + if nil != err { + glog.Error(err) + http.Error(w, err.Error(), 500) + + return + } + + stderr, err := cmd.StderrPipe() + if nil != err { + glog.Error(err) + http.Error(w, err.Error(), 500) + + return + } + + reader := io.MultiReader(stdout, stderr) + + cmd.Start() + + go func(runningId int) { + glog.Infof("Session [%s] is building [id=%d, file=%s]", sid, runningId, filePath) + + // 一次性读取 + buf := make([]byte, 1024*8) + count, _ := reader.Read(buf) + + channelRet := map[string]interface{}{} + + channelRet["output"] = string(buf[:count]) + channelRet["cmd"] = "build" + channelRet["nextCmd"] = "run" + channelRet["executable"] = curDir + string(os.PathSeparator) + executable + + if nil != outputWS[sid] { + glog.Infof("Session [%s] 's build [id=%d, file=%s] has done", sid, runningId, filePath) + + err := outputWS[sid].WriteJSON(&channelRet) + if nil != err { + glog.Error(err) + } + } + + }(rand.Int()) + + ret, _ := json.Marshal(map[string]interface{}{"succ": true}) + + w.Header().Set("Content-Type", "application/json") + w.Write(ret) +} diff --git a/static/css/base.css b/static/css/base.css index 660e6c6..d9b7327 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -74,5 +74,5 @@ ul { } .shellOutput { - height: 125px; + height: 80px; } \ No newline at end of file diff --git a/static/js/wide.js b/static/js/wide.js index 3a6b0f0..1c2df7a 100644 --- a/static/js/wide.js +++ b/static/js/wide.js @@ -5,9 +5,30 @@ outputWS.onopen = function() { outputWS.onmessage = function(e) { console.log('[output onmessage]' + e.data); var data = JSON.parse(e.data); + if ('init-output' !== data.cmd) { $('#output').val($('#output').val() + data.output); - } + } + + if ('build' == data.cmd) { + if ('run' === data.nextCmd) { + var request = { + "executable": data.executable + }; + + $.ajax({ + type: 'POST', + url: '/run', + data: JSON.stringify(request), + dataType: "json", + beforeSend: function(data) { + $('#output').val(''); + }, + success: function(data) { + } + }); + } + } }; outputWS.onclose = function(e) { console.log('[output onclose] disconnected (' + e.code + ')'); @@ -80,16 +101,21 @@ var wide = { "file": wide.curNode.path, "code": wide.curEditor.getValue() }; + $.ajax({ type: 'POST', - url: '/run', + url: '/build', data: JSON.stringify(request), dataType: "json", beforeSend: function(data) { $('#output').val(''); }, success: function(data) { - console.log(data); + executable = data.executable; + + if (data.succ) { + + } } }); }, diff --git a/templates/index.html b/templates/index.html index 67ed9c8..d08e84f 100644 --- a/templates/index.html +++ b/templates/index.html @@ -40,7 +40,7 @@
- +