Skip to content

Commit

Permalink
More mess, change jsonrpc to simple rpc (uses gob).
Browse files Browse the repository at this point in the history
  • Loading branch information
nsf committed Jul 9, 2010
1 parent 6379b17 commit 94b7b01
Show file tree
Hide file tree
Showing 6 changed files with 436 additions and 99 deletions.
8 changes: 7 additions & 1 deletion Makefile
Original file line number Original file line Diff line number Diff line change
@@ -1,6 +1,12 @@
include $(GOROOT)/src/Make.$(GOARCH) include $(GOROOT)/src/Make.$(GOARCH)


TARG=gocode TARG=gocode
GOFILES=gocode.go gocodelib.go gocodeserver.go GOFILES=gocode.go gocodelib.go gocodeserver.go gorpc.go


include $(GOROOT)/src/Make.cmd include $(GOROOT)/src/Make.cmd

gorpc.go: gocodeserver.go goremote/goremote
./goremote/goremote gocodeserver.go > gorpc.go

goremote/goremote: goremote/goremote.go
cd goremote && make
98 changes: 55 additions & 43 deletions gocode.go
Original file line number Original file line Diff line number Diff line change
@@ -1,41 +1,80 @@
package main package main


import ( import (
// "os" "io/ioutil"
// "io/ioutil"
// "strings"
"rpc" "rpc"
"rpc/jsonrpc"
"flag" "flag"
"fmt" "fmt"
"os" "os"
) )


var ( var (
server = flag.Bool("s", false, "run a server instead of a client") server = flag.Bool("s", false, "run a server instead of a client")
format = flag.String("f", "vim", "output format (currently only 'vim' is valid)")
) )


func getSocketFilename() string {
user := os.Getenv("USER")
if user == "" {
user = "all"
}
return fmt.Sprintf("%s/acrserver.%s", os.TempDir(), user)
}

func serverFunc() { func serverFunc() {
acrRPC := new(ACR) socketfname := getSocketFilename()
rpc.Register(acrRPC) daemon = NewAutoCompletionDaemon(socketfname)
acrRPC.acr = NewACRServer("/tmp/acrserver") defer os.Remove(socketfname)
defer os.Remove("/tmp/acrserver")
acrRPC.acr.Loop() rpcremote := new(RPCRemote)
rpc.Register(rpcremote)

daemon.acr.Loop()
}

func Cmd_AutoComplete(c *rpc.Client) {
file, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err.String())
}
apropos := flag.Args()[1]
abbrs, words := Client_AutoComplete(c, file, apropos)
if len(words) != len(abbrs) {
panic("Lengths should match!")
}

fmt.Printf("[")
for i := 0; i < len(words); i++ {
fmt.Printf("{'word': '%s', 'abbr': '%s'}", words[i], abbrs[i])
if i != len(words)-1 {
fmt.Printf(", ")
}
}
fmt.Printf("]")
}

func Cmd_Close(c *rpc.Client) {
Client_Close(c, 0)
}

var cmds = map[string]func(*rpc.Client) {
"autocomplete": Cmd_AutoComplete,
"close": Cmd_Close,
} }


func clientFunc() { func clientFunc() {
// client // client
var args, reply int


client, err := jsonrpc.Dial("unix", "/tmp/acrserver") client, err := rpc.Dial("unix", getSocketFilename())
if err != nil { if err != nil {
panic(err.String()) fmt.Printf("Failed to connect to the ACR server\n%s\n", err.String())
return
} }
err = client.Call("ACR.Shutdown", &args, &reply) defer client.Close()
if err != nil {
panic(err.String()) if len(flag.Args()) > 0 {
cmds[flag.Args()[0]](client)
} }
fmt.Printf("close request send\n")
} }


func main() { func main() {
Expand All @@ -45,31 +84,4 @@ func main() {
} else { } else {
clientFunc() clientFunc()
} }
/*
if len(os.Args) != 2 {
panic("usage: ./gocode <apropos request>")
}
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic("Bad stdin")
}
ctx := NewAutoCompleteContext()
ctx.processData(data)
request := os.Args[1]
parts := strings.Split(request, ".", 2)
res := ""
switch len(parts) {
case 1:
for _, decl := range ctx.m[ctx.cfns[request]] {
prettyPrintDecl(os.Stdout, decl, "")
}
case 2:
for _, decl := range ctx.m[ctx.cfns[parts[0]]] {
prettyPrintDecl(os.Stdout, decl, parts[1])
}
}
print(res)
*/
} }
96 changes: 92 additions & 4 deletions gocodelib.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ func processExport(s string) (string, string) {
} }


func (self *AutoCompleteContext) processPackage(filename string, uniquename string, pkgname string) { func (self *AutoCompleteContext) processPackage(filename string, uniquename string, pkgname string) {
if self.cache[filename] {
return
}
self.cache[filename] = true
data, err := ioutil.ReadFile(filename) data, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
panic("Failed to open archive file") panic("Failed to open archive file")
Expand Down Expand Up @@ -347,6 +351,9 @@ func prettyPrintTypeExpr(out io.Writer, e ast.Expr) {
prettyPrintTypeExpr(out, t.Value) prettyPrintTypeExpr(out, t.Value)
case *ast.InterfaceType: case *ast.InterfaceType:
fmt.Fprintf(out, "interface{}") fmt.Fprintf(out, "interface{}")
case *ast.Ellipsis:
fmt.Fprintf(out, "...")
prettyPrintTypeExpr(out, t.Elt)
default: default:
fmt.Fprintf(out, "\n[!!] unknown type: %s\n", ty.String()) fmt.Fprintf(out, "\n[!!] unknown type: %s\n", ty.String())
} }
Expand Down Expand Up @@ -383,6 +390,13 @@ func prettyPrintFuncFieldList(out io.Writer, f *ast.FieldList) int {
return count return count
} }


func startsWith(s, prefix string) bool {
if len(s) >= len(prefix) && s[0:len(prefix)] == prefix {
return true
}
return false
}

func prettyPrintDecl(out io.Writer, d ast.Decl, p string) { func prettyPrintDecl(out io.Writer, d ast.Decl, p string) {
switch t := d.(type) { switch t := d.(type) {
case *ast.GenDecl: case *ast.GenDecl:
Expand All @@ -391,7 +405,7 @@ func prettyPrintDecl(out io.Writer, d ast.Decl, p string) {
for _, spec := range t.Specs { for _, spec := range t.Specs {
c := spec.(*ast.ValueSpec) c := spec.(*ast.ValueSpec)
for _, name := range c.Names { for _, name := range c.Names {
if len(name.Name()) < len(p) || (p != "" && name.Name()[0:len(p)] != p) { if p != "" && !startsWith(name.Name(), p) {
continue continue
} }
fmt.Fprintf(out, "const %s\n", name.Name()) fmt.Fprintf(out, "const %s\n", name.Name())
Expand All @@ -400,7 +414,7 @@ func prettyPrintDecl(out io.Writer, d ast.Decl, p string) {
case token.TYPE: case token.TYPE:
for _, spec := range t.Specs { for _, spec := range t.Specs {
t := spec.(*ast.TypeSpec) t := spec.(*ast.TypeSpec)
if len(t.Name.Name()) < len(p) || (p != "" && t.Name.Name()[0:len(p)] != p) { if p != "" && !startsWith(t.Name.Name(), p) {
continue continue
} }
fmt.Fprintf(out, "type %s\n", t.Name.Name()) fmt.Fprintf(out, "type %s\n", t.Name.Name())
Expand All @@ -409,7 +423,7 @@ func prettyPrintDecl(out io.Writer, d ast.Decl, p string) {
for _, spec := range t.Specs { for _, spec := range t.Specs {
v := spec.(*ast.ValueSpec) v := spec.(*ast.ValueSpec)
for _, name := range v.Names { for _, name := range v.Names {
if len(name.Name()) < len(p) || (p != "" && name.Name()[0:len(p)] != p) { if p != "" && !startsWith(name.Name(), p) {
continue continue
} }
fmt.Fprintf(out, "var %s\n", name.Name()) fmt.Fprintf(out, "var %s\n", name.Name())
Expand All @@ -423,7 +437,7 @@ func prettyPrintDecl(out io.Writer, d ast.Decl, p string) {
//XXX: skip method, temporary //XXX: skip method, temporary
break break
} }
if len(t.Name.Name()) < len(p) || (p != "" && t.Name.Name()[0:len(p)] != p) { if p != "" && !startsWith(t.Name.Name(), p) {
break break
} }
fmt.Fprintf(out, "func %s(", t.Name.Name()) fmt.Fprintf(out, "func %s(", t.Name.Name())
Expand All @@ -443,6 +457,53 @@ func prettyPrintDecl(out io.Writer, d ast.Decl, p string) {
} }
} }


func autoCompleteDecl(out io.Writer, d ast.Decl, p string) {
switch t := d.(type) {
case *ast.GenDecl:
switch t.Tok {
case token.CONST:
for _, spec := range t.Specs {
c := spec.(*ast.ValueSpec)
for _, name := range c.Names {
if p != "" && !startsWith(name.Name(), p) {
continue
}
fmt.Fprintf(out, "%s\n", name.Name()[len(p):])
}
}
case token.TYPE:
for _, spec := range t.Specs {
t := spec.(*ast.TypeSpec)
if p != "" && !startsWith(t.Name.Name(), p) {
continue
}
fmt.Fprintf(out, "%s\n", t.Name.Name()[len(p):])
}
case token.VAR:
for _, spec := range t.Specs {
v := spec.(*ast.ValueSpec)
for _, name := range v.Names {
if p != "" && !startsWith(name.Name(), p) {
continue
}
fmt.Fprintf(out, "%s\n", name.Name()[len(p):])
}
}
default:
fmt.Fprintf(out, "[!!] STUB\n")
}
case *ast.FuncDecl:
if t.Recv != nil {
//XXX: skip method, temporary
break
}
if p != "" && !startsWith(t.Name.Name(), p) {
break
}
fmt.Fprintf(out, "%s(\n", t.Name.Name()[len(p):])
}
}

func findFile(imp string) string { func findFile(imp string) string {
goroot := os.Getenv("GOROOT") goroot := os.Getenv("GOROOT")
goarch := os.Getenv("GOARCH") goarch := os.Getenv("GOARCH")
Expand Down Expand Up @@ -489,13 +550,15 @@ type AutoCompleteContext struct {
// alias name -> // alias name ->
// unique package name // unique package name
cfns map[string]string cfns map[string]string
cache map[string]bool
debuglog io.Writer debuglog io.Writer
} }


func NewAutoCompleteContext() *AutoCompleteContext { func NewAutoCompleteContext() *AutoCompleteContext {
self := new(AutoCompleteContext) self := new(AutoCompleteContext)
self.m = make(map[string][]ast.Decl) self.m = make(map[string][]ast.Decl)
self.cfns = make(map[string]string) self.cfns = make(map[string]string)
self.cache = make(map[string]bool)
return self return self
} }


Expand All @@ -506,3 +569,28 @@ func (self *AutoCompleteContext) Add(globalname string, decls []ast.Decl) {
func (self *AutoCompleteContext) AddAlias(alias string, globalname string) { func (self *AutoCompleteContext) AddAlias(alias string, globalname string) {
self.cfns[alias] = globalname self.cfns[alias] = globalname
} }

func (self *AutoCompleteContext) Apropos(file []byte, apropos string) ([]string, []string) {
self.processData(file)

buf := bytes.NewBuffer(make([]byte, 0, 4096))
buf2 := bytes.NewBuffer(make([]byte, 0, 4096))

parts := strings.Split(apropos, ".", 2)
switch len(parts) {
case 1:
for _, decl := range self.m[self.cfns[apropos]] {
prettyPrintDecl(buf, decl, "")
autoCompleteDecl(buf2, decl, "")
}
case 2:
for _, decl := range self.m[self.cfns[parts[0]]] {
prettyPrintDecl(buf, decl, parts[1])
autoCompleteDecl(buf2, decl, parts[1])
}
}

result := strings.Split(buf.String(), "\n", -1)
result2 := strings.Split(buf2.String(), "\n", -1)
return result, result2
}
Loading

0 comments on commit 94b7b01

Please sign in to comment.