github.com/jmigpin/editor@v1.6.0/plugins/gotodefinition_godef/gotodefinition_godef.go (about)

     1  /*
     2  Build with:
     3  $ go build -buildmode=plugin gotodefinition_godef.go
     4  */
     5  
     6  package main
     7  
     8  import (
     9  	"bytes"
    10  	"context"
    11  	"path"
    12  	"path/filepath"
    13  	"strconv"
    14  	"time"
    15  
    16  	"github.com/jmigpin/editor/core"
    17  	"github.com/jmigpin/editor/util/osutil"
    18  	"github.com/jmigpin/editor/util/parseutil/reslocparser"
    19  )
    20  
    21  func OnLoad(ed *core.Editor) {
    22  	// default contentcmds at: github.com/jmigpin/editor/core/contentcmds/init.go
    23  	core.ContentCmds.Remove("gotodefinition") // remove default
    24  	core.ContentCmds.Prepend("gotodefinition_godef", goToDefinition)
    25  }
    26  
    27  func goToDefinition(ctx0 context.Context, erow *core.ERow, index int) (err error, handled bool) {
    28  	if erow.Info.IsDir() {
    29  		return nil, false
    30  	}
    31  	if path.Ext(erow.Info.Name()) != ".go" {
    32  		return nil, false
    33  	}
    34  
    35  	// timeout for the cmd to run
    36  	timeout := 8000 * time.Millisecond
    37  	ctx, cancel := context.WithTimeout(ctx0, timeout)
    38  	defer cancel()
    39  
    40  	// it's a go file, return true from here
    41  
    42  	// godef args
    43  	args := []string{osutil.ExecName("godef"), "-i", "-f", erow.Info.Name(), "-o", strconv.Itoa(index)}
    44  
    45  	// godef can read from stdin: use textarea bytes
    46  	bin, err := erow.Row.TextArea.Bytes()
    47  	if err != nil {
    48  		return err, true
    49  	}
    50  	in := bytes.NewBuffer(bin)
    51  
    52  	// execute external cmd
    53  	dir := filepath.Dir(erow.Info.Name())
    54  	out, err := core.ExecCmdStdin(ctx, dir, in, args...)
    55  	if err != nil {
    56  		return err, true
    57  	}
    58  
    59  	// parse external cmd output
    60  	filePos, err := reslocparser.ParseFilePos(out, 0)
    61  	if err != nil {
    62  		return err, true
    63  	}
    64  
    65  	erow.Ed.UI.RunOnUIGoRoutine(func() {
    66  		// place under the calling row
    67  		rowPos := erow.Row.PosBelow() // needs ui goroutine
    68  
    69  		conf := &core.OpenFileERowConfig{
    70  			FilePos:               filePos,
    71  			RowPos:                rowPos,
    72  			FlashVisibleOffsets:   true,
    73  			NewIfNotExistent:      true,
    74  			NewIfOffsetNotVisible: true,
    75  		}
    76  		core.OpenFileERow(erow.Ed, conf) // needs ui goroutine
    77  	})
    78  
    79  	return nil, true
    80  }