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  }