github.com/jmigpin/editor@v1.6.0/plugins/autocomplete_gocode/autocomplete_gocode.go (about) 1 /* 2 Build with: 3 $ go build -buildmode=plugin autocomplete_gocode.go 4 */ 5 6 package main 7 8 import ( 9 "bytes" 10 "context" 11 "fmt" 12 "path" 13 "path/filepath" 14 "time" 15 16 "github.com/jmigpin/editor/core" 17 "github.com/jmigpin/editor/ui" 18 "github.com/jmigpin/editor/util/osutil" 19 ) 20 21 func AutoComplete(ctx context.Context, ed *core.Editor, cfb *ui.ContextFloatBox) (_ error, handled bool) { 22 ta, ok := cfb.FindTextAreaUnderPointer() 23 if !ok { 24 cfb.Hide() 25 return nil, false 26 } 27 28 erow, ok := ed.NodeERow(ta) 29 if ok { 30 ok = autoCompleteERow(ed, cfb, erow) 31 if ok { 32 return nil, true 33 } 34 } 35 36 cfb.SetRefPointToTextAreaCursor(ta) 37 cfb.TextArea.SetStr("no results") 38 return nil, true 39 } 40 41 func autoCompleteERow(ed *core.Editor, cfb *ui.ContextFloatBox, erow *core.ERow) bool { 42 if erow.Info.IsFileButNotDir() && path.Ext(erow.Info.Name()) == ".go" { 43 autoCompleteERowGolang(ed, cfb, erow) 44 return true 45 } 46 return false 47 } 48 49 //---------- 50 51 func autoCompleteERowGolang(ed *core.Editor, cfb *ui.ContextFloatBox, erow *core.ERow) { 52 // timeout for the cmd to run 53 timeout := 8000 * time.Millisecond 54 ctx, cancel := context.WithTimeout(context.Background(), timeout) 55 defer cancel() 56 57 // gocode args 58 filename := erow.Info.Name() 59 offset := erow.Row.TextArea.CursorIndex() 60 args := []string{osutil.ExecName("gocode"), "autocomplete", fmt.Sprintf("%v", offset)} 61 62 // gocode can read from stdin: use textarea bytes 63 bin, err := erow.Row.TextArea.Bytes() 64 if err != nil { 65 ed.Error(err) 66 return 67 } 68 in := bytes.NewBuffer(bin) 69 70 // execute external cmd 71 dir := filepath.Dir(filename) 72 bout, err := core.ExecCmdStdin(ctx, dir, in, args...) 73 if err != nil { 74 ed.Error(err) 75 return 76 } 77 78 cfb.SetRefPointToTextAreaCursor(erow.Row.TextArea) 79 cfb.TextArea.SetStr(string(bout)) 80 cfb.TextArea.ClearPos() 81 }