diff --git a/.version b/.version index e482fe7a5..27fcb2c7b 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -0.2.473 \ No newline at end of file +0.2.474 \ No newline at end of file diff --git a/cmd/templ/lspcmd/pls/main.go b/cmd/templ/lspcmd/pls/main.go index 4fb6b618a..44ea08cbf 100644 --- a/cmd/templ/lspcmd/pls/main.go +++ b/cmd/templ/lspcmd/pls/main.go @@ -7,6 +7,7 @@ import ( "io" "os" "os/exec" + "path" "go.uber.org/zap" ) @@ -29,17 +30,42 @@ func (opts Options) AsArguments() []string { return args } -// NewGopls starts gopls and opens up a jsonrpc2 connection to it. -func NewGopls(ctx context.Context, log *zap.Logger, opts Options) (rwc io.ReadWriteCloser, err error) { +func findGopls() (location string, err error) { _, err = exec.LookPath("gopls") - if errors.Is(err, exec.ErrNotFound) { - err = fmt.Errorf("cannot find gopls on the path (%q), you can install it with `go install golang.org/x/tools/gopls@latest`", os.Getenv("PATH")) - return + if err == nil { + // Found on the path. + return "gopls", nil + } + + // Unexpected error. + if !errors.Is(err, exec.ErrNotFound) { + return "", fmt.Errorf("unexpected error looking for gopls: %w", err) + } + + // Probe standard locations. + locations := []string{ + path.Join(os.Getenv("HOME"), "go", "bin", "gopls"), + path.Join(os.Getenv("HOME"), ".local", "bin", "gopls"), } + for _, location := range locations { + _, err = os.Stat(location) + if err != nil { + continue + } + // Found in a standard location. + return location, nil + } + + return "", fmt.Errorf("cannot find gopls on the path (%q), in $HOME/go/bin or $HOME/.local/bin/gopls. You can install gopls with `go install golang.org/x/tools/gopls@latest`", os.Getenv("PATH")) +} + +// NewGopls starts gopls and opens up a jsonrpc2 connection to it. +func NewGopls(ctx context.Context, log *zap.Logger, opts Options) (rwc io.ReadWriteCloser, err error) { + location, err := findGopls() if err != nil { - return + return nil, err } - cmd := exec.Command("gopls", opts.AsArguments()...) + cmd := exec.Command(location, opts.AsArguments()...) return newProcessReadWriteCloser(log, cmd) }