├── LICENSE ├── README.md ├── certs ├── gencert.bash └── openssl.cnf ├── conf.go ├── golab ├── gosrc │ ├── deps.go │ ├── godoc.go │ ├── godoc.html │ ├── gosrc.go │ ├── info.go │ ├── install.go │ ├── package.html │ ├── pkg.go │ ├── report.go │ └── scan.go ├── htmod │ ├── actions.go │ ├── content.go │ ├── htmod.go │ ├── otdocs.go │ └── static.go ├── http.go ├── main.go └── static │ ├── app.js │ ├── base.js │ ├── conn.js │ ├── golab.png │ ├── lib │ ├── completion.css │ ├── completion.js │ ├── paths.js │ ├── sot.js │ └── sotdoc.js │ ├── main.css │ ├── main.js │ ├── main.manifest │ ├── test.html │ ├── test.js │ ├── tile.js │ └── view │ ├── ace.js │ ├── docs.js │ ├── editor.js │ ├── file.js │ ├── folder.js │ ├── godoc.js │ ├── modes.js │ └── report.js ├── hub ├── conn.go └── hub.go ├── lab.go ├── ot ├── doc.go ├── doc_test.go ├── ops.go └── ops_test.go ├── screenshot.png └── ws ├── ctrl.go ├── res.go ├── util.go ├── watcher_linux.go ├── ws.go └── ws_test.go /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Martin Schnabel. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 13 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 14 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 15 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 16 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 17 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 18 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | golab 2 | ===== 3 | golab was a Go IDE for Linux. 4 | 5 | This project is no longer maintained and might not build due to chganges in dependency projects. 6 | 7 | The author (mb0) does use neovim and is quite happy with it, while missing the convenient auto install and test facilities. 8 | The ot (operation transformation) package is worth a look and a good start for any collaborative text editing project, there is also a utf-8 based version with js client that can be shared. 9 | 10 | 11 | ![golab screenshot][screenshot] 12 | 13 | Install 14 | ------- 15 | Requires Linux and Go 1.1. 16 | 17 | go get github.com/mb0/lab/golab 18 | echo 'yay! magic!' 19 | 20 | Basic Usage 21 | ----------- 22 | `golab` watches all files under your goroot and gopath (`go help gopath`). 23 | It automatically installs and tests a list of packages specified by the `-work` flag and prints colored reports to stdout. 24 | 25 | Flag `-work` specifies a path list to the packages you are working on. 26 | Multiple paths can be seperated by a colon `:`. 27 | The default `./...` uses the current directory and all it child packages. 28 | 29 | Example: 30 | 31 | cd $GOPATH/src/github.com/mb0 32 | golab -work=../garyburd/go-websocket/websocket:./lab/... 33 | 34 | Html5 UI 35 | -------- 36 | `golab -http` starts a web interface for reports and collaborative editing of text files. 37 | 38 | Flag `-addr=localhost:8910` specifies the http address. 39 | 40 | Example: 41 | 42 | cd $GOPATH/src 43 | golab -http -addr=:80 -work=github.com/mb0/lab/... 44 | 45 | Features: 46 | * Report view for go errors and test failures with links to sources. 47 | * Ace editor with gentle highlights and error markers for go, js and css. 48 | * Document collaboration with operational transformation. 49 | * External filesystem changes to open documents are merged. 50 | * godoc Ctrl+Alt+Click on imports in go source files opens the doc view. 51 | * gofmt Ctrl+Shift+F changes the document (does not save to disk) 52 | * gocode Ctrl+Space shows gocode completion proposals if installed. 53 | 54 | I recommend using the Chrome browser, because the visual feedback seems faster than other browsers. 55 | 56 | Feedback 57 | -------- 58 | Yes please! 59 | * https://github.com/mb0/lab/issues 60 | * http://godoc.org/github.com/mb0/lab 61 | 62 | License 63 | ------- 64 | golab is BSD licensed, Copyright (c) 2013 Martin Schnabel 65 | 66 | Server code attributions 67 | * Go (c) The Go Authors (BSD License) 68 | * go-websocket (c) Gary Burd (Apache License 2.0) 69 | 70 | Client code and asset attributions 71 | * require.js (c) The Dojo Foundation (BSD/MIT License) 72 | * json2.js by Douglas Crockford (public domain) 73 | * Underscore (c) Jeremy Ashkenas (MIT License) 74 | * Zepto (c) Thomas Fuchs (MIT License) 75 | * Backbone (c) Jeremy Ashkenas (MIT License) 76 | * Ace (c) Ajax.org B.V. (BSD License) 77 | * Font Awesome by Dave Gandy (SIL, MIT and CC BY 3.0 License) 78 | * Qunit (c) jQuery Foundation and others (MIT License) 79 | 80 | Recycled code attribution // was easier than adapting to golab 81 | * ot.js (c) Tim Baumann (MIT License) 82 | 83 | [screenshot]: https://raw.github.com/mb0/lab/master/screenshot.png 84 | -------------------------------------------------------------------------------- /certs/gencert.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cdir=$( cd "$( dirname "$0" )" && pwd ) 4 | conf="$cdir/openssl.cnf" 5 | 6 | home=$( getent passwd "$USER" | cut -d: -f6 ) 7 | out="$home/.golab" 8 | mkdir -p $out || exit 1 9 | 10 | ca="$out/ca" 11 | serial="$out/serial" 12 | 13 | case $1 in 14 | ca) 15 | echo 'certificate authority' 16 | openssl req -x509 -newkey rsa:2048 -keyout $ca.key -out $ca.crt -config $conf -extensions v3_ca \ 17 | && chmod 400 $ca.key 18 | ;; 19 | server) 20 | echo 'server certificate' 21 | echo "if the server has more than one valid domain or IP, specify these in 'subjectAltName' in $conf" 22 | echo "by default 'subjectAltName' is set to 'IP:127.0.0.1,DNS:localhost' for local testing" 23 | read -p 'Enter primary server domain or IP: ' domain 24 | srv="$out/server" 25 | subj=$( openssl x509 -in $ca.crt -noout -subject | sed 's/subject=\s*//' ) 26 | openssl req -new -newkey rsa:2048 -nodes -keyout $srv.key -out $srv.csr -config $conf -subj "$subj/CN=$domain" \ 27 | && chmod 400 $srv.key \ 28 | && openssl x509 -req -in $srv.csr -out $srv.crt -extfile $conf -extensions v3_srv \ 29 | -CA $ca.crt -CAkey $ca.key -CAserial $serial -CAcreateserial \ 30 | && rm $srv.csr 31 | ;; 32 | client) 33 | echo 'client certificate' 34 | read -p 'Enter user name: ' username 35 | cli="$out/$username" 36 | subj=$( openssl x509 -in $ca.crt -noout -subject | sed 's/subject=\s*//' ) 37 | openssl req -new -newkey rsa:2048 -nodes -keyout $cli.key -out $cli.csr -config $conf -subj "$subj/CN=$username" \ 38 | && chmod 400 $cli.key \ 39 | && openssl x509 -req -in $cli.csr -out $cli.crt -extfile $conf -extensions v3_cli \ 40 | -CA $ca.crt -CAkey $ca.key -CAserial $serial -CAcreateserial \ 41 | && rm $cli.csr \ 42 | && openssl pkcs12 -export -in $cli.crt -inkey $cli.key -certfile $ca.crt -out $cli.p12 \ 43 | && chmod 400 $cli.p12 44 | ;; 45 | *) 46 | echo "usage: $0 command" 47 | echo "command can be:" 48 | echo " ca - generate a certificate authority key and crt file" 49 | echo " server - generate a server certificate key and crt file" 50 | echo " client - generate a client certificate key, crt and p12 file" 51 | exit 1 52 | ;; 53 | esac 54 | 55 | -------------------------------------------------------------------------------- /certs/openssl.cnf: -------------------------------------------------------------------------------- 1 | # openssl config file for golab. 2 | 3 | HOME = . 4 | RANDFILE = $ENV::HOME/.rnd 5 | 6 | [ req ] 7 | default_days = 365 8 | distinguished_name = req_distinguished_name 9 | string_mask = utf8only 10 | 11 | [ req_distinguished_name ] 12 | countryName = country code (2 letters) 13 | countryName_min = 2 14 | countryName_max = 2 15 | 0.organizationName = organization 16 | 17 | [ v3_ca ] 18 | subjectKeyIdentifier = hash 19 | authorityKeyIdentifier = keyid:always,issuer 20 | basicConstraints = CA:TRUE 21 | 22 | [ v3_srv ] 23 | basicConstraints = CA:FALSE 24 | keyUsage = digitalSignature, keyEncipherment 25 | extendedKeyUsage = serverAuth 26 | subjectAltName = IP:127.0.0.1,DNS:localhost 27 | 28 | [ v3_cli ] 29 | basicConstraints = CA:FALSE 30 | keyUsage = digitalSignature, keyEncipherment 31 | extendedKeyUsage = clientAuth 32 | 33 | -------------------------------------------------------------------------------- /conf.go: -------------------------------------------------------------------------------- 1 | package lab 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | "os/user" 10 | "path/filepath" 11 | "runtime" 12 | "sync" 13 | ) 14 | 15 | // Conf is special flag set that can be loaded via LoadConf in three passes. 16 | var Conf = flag.NewFlagSet("config", flag.ContinueOnError) 17 | 18 | // LoadConf loads the Conf flag set values in three passes on first invocation. 19 | // The first pass will parse the arguments to populate the -conf flag. 20 | // The second pass loads the file specified by the -conf flag. 21 | // The third pass overrides all flags specifed by program arguments. 22 | func LoadConf() { 23 | loadOnce.Do(loadConf) 24 | } 25 | 26 | var loadOnce sync.Once 27 | var confFile = Conf.String("conf", "~/.golab/flags.conf", "flags config file") 28 | var maxprocs = Conf.Int("maxprocs", 0, "GOMAXPROCS") 29 | 30 | func loadConf() { 31 | flag.Usage = func() { 32 | fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) 33 | flag.PrintDefaults() 34 | Conf.PrintDefaults() 35 | } 36 | err := Conf.Parse(os.Args[1:]) 37 | if err != nil { 38 | os.Exit(2) 39 | } 40 | if *confFile != "" { 41 | loadConfFile() 42 | } 43 | err = Conf.Parse(os.Args[1:]) 44 | if err != nil { 45 | log.Println("parsing config args", err) 46 | } 47 | maxprocs := *maxprocs 48 | if maxprocs < 0 { 49 | maxprocs = runtime.NumCPU() 50 | } 51 | if maxprocs > 0 { 52 | runtime.GOMAXPROCS(maxprocs) 53 | } 54 | } 55 | 56 | func loadConfFile() { 57 | path := *confFile 58 | if len(path) > 1 && path[0] == '~' && path[1] == '/' { 59 | usr, err := user.Current() 60 | if err != nil { 61 | log.Println("expanding home dir for config path", err) 62 | return 63 | } 64 | path = filepath.Join(usr.HomeDir, path[2:]) 65 | } 66 | f, err := os.Open(path) 67 | if err != nil { 68 | if !os.IsNotExist(err) { 69 | log.Println("opening config file", err) 70 | } 71 | return 72 | } 73 | defer f.Close() 74 | data, err := ioutil.ReadAll(f) 75 | if err != nil { 76 | log.Println("reading config file", err) 77 | } 78 | var toks []string 79 | var start int 80 | for i := 0; i < len(data); i++ { 81 | switch data[i] { 82 | case ' ', '\t', '\n', '\r', '\f': 83 | if start < i { 84 | toks = append(toks, string(data[start:i])) 85 | } 86 | start = i + 1 87 | case '#': 88 | for j := i; j < len(data); j++ { 89 | if data[j] == '\n' { 90 | i = j 91 | start = i + 1 92 | break 93 | } 94 | } 95 | default: 96 | } 97 | } 98 | if start < len(data)-1 { 99 | toks = append(toks, string(data[start:])) 100 | } 101 | err = Conf.Parse(toks) 102 | if err != nil { 103 | log.Println("parsing config file", err) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /golab/gosrc/deps.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Martin Schnabel. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gosrc 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "time" 11 | ) 12 | 13 | func Deps(src *Src, pkg *Pkg) *Result { 14 | if pkg.Src.Info == nil { 15 | // not scanned 16 | return nil 17 | } 18 | 19 | retry := pkg.Flag&MissingDeps != 0 20 | missing := make(map[string]struct{}, 100) 21 | deps(src, pkg, missing) 22 | if len(missing) == 0 { 23 | // all deps found 24 | pkg.Flag &^= MissingDeps 25 | return nil 26 | } 27 | if !retry { 28 | // flag missing dependencies and retry later 29 | pkg.Flag |= MissingDeps 30 | return nil 31 | } 32 | var buf bytes.Buffer 33 | for pkgpath := range missing { 34 | fmt.Fprintf(&buf, "\t%s\n", pkgpath) 35 | } 36 | return &Result{ 37 | Mode: "deps", 38 | Time: time.Now().Unix(), 39 | Errmsg: "missing dependencies", 40 | Stdout: buf.String(), 41 | } 42 | } 43 | 44 | func deps(src *Src, pkg *Pkg, missing map[string]struct{}) { 45 | info := pkg.Src.Info 46 | if info == nil { 47 | return 48 | } 49 | for i := range info.Imports { 50 | imprt := &info.Imports[i] 51 | p := src.lookup[imprt.Path] 52 | if p == nil || p.Path == "" { 53 | missing[imprt.Path] = struct{}{} 54 | continue 55 | } 56 | imprt.Id = p.Id 57 | p.AddUse(pkg.Id) 58 | if p.Flag&Watching == 0 { 59 | p.Flag |= Watching 60 | } 61 | if p.Src.Info == nil { 62 | Scan(p) 63 | } 64 | deps(src, p, missing) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /golab/gosrc/godoc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Martin Schnabel. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gosrc 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "go/build" 11 | "io" 12 | "os" 13 | "os/exec" 14 | "path/filepath" 15 | "runtime" 16 | ) 17 | 18 | var godoctool, godoctmpl string 19 | 20 | func init() { 21 | path := filepath.Join(runtime.GOROOT(), "bin/godoc") 22 | _, err := os.Stat(path) 23 | if err != nil { 24 | path, err = exec.LookPath("godoc") 25 | if err != nil { 26 | fmt.Println("could not find godoc") 27 | path = "" 28 | } 29 | } 30 | godoctool = path 31 | tmpl := findTemplate() 32 | if tmpl != "" { 33 | godoctmpl = "-templates=" + tmpl 34 | } 35 | } 36 | 37 | var snips = [][]byte{ 38 | []byte(`