diff --git a/internal/action/actions.go b/internal/action/actions.go index cac954a1..304f0c9a 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -1835,17 +1835,30 @@ func (h *BufPane) SemanticInfo() bool { // AutoFormat automatically formats the document using LSP func (h *BufPane) AutoFormat() bool { - edits, err := h.Buf.Server.DocumentFormat(h.Buf.AbsPath, protocol.FormattingOptions{ - InsertSpaces: h.Buf.Settings["tabstospaces"].(bool), - TabSize: h.Buf.Settings["tabsize"].(float64), - }) + var err error + var edits []protocol.TextEdit + + if h.Cursor.HasSelection() { + edits, err = h.Buf.Server.DocumentRangeFormat(h.Buf.AbsPath, protocol.Range{ + Start: lsp.Position(h.Cursor.CurSelection[0].X, h.Cursor.CurSelection[0].Y), + End: lsp.Position(h.Cursor.CurSelection[1].X, h.Cursor.CurSelection[1].Y), + }, protocol.FormattingOptions{ + InsertSpaces: h.Buf.Settings["tabstospaces"].(bool), + TabSize: h.Buf.Settings["tabsize"].(float64), + }) + } else { + edits, err = h.Buf.Server.DocumentFormat(h.Buf.AbsPath, protocol.FormattingOptions{ + InsertSpaces: h.Buf.Settings["tabstospaces"].(bool), + TabSize: h.Buf.Settings["tabsize"].(float64), + }) + } + if err != nil { InfoBar.Error(err) return false } h.Buf.ApplyEdits(edits) - return true } diff --git a/internal/lsp/requests.go b/internal/lsp/requests.go index d8b52507..92e1e579 100644 --- a/internal/lsp/requests.go +++ b/internal/lsp/requests.go @@ -2,11 +2,14 @@ package lsp import ( "encoding/json" + "errors" lsp "go.lsp.dev/protocol" "go.lsp.dev/uri" ) +var ErrNotSupported = errors.New("Operation not supported by language server") + type RPCCompletion struct { RPCVersion string `json:"jsonrpc"` ID int `json:"id"` @@ -54,6 +57,9 @@ func Position(x, y int) lsp.Position { } func (s *Server) DocumentFormat(filename string, options lsp.FormattingOptions) ([]lsp.TextEdit, error) { + if !s.capabilities.DocumentFormattingProvider { + return nil, ErrNotSupported + } doc := lsp.TextDocumentIdentifier{ URI: uri.File(filename), } @@ -77,11 +83,40 @@ func (s *Server) DocumentFormat(filename string, options lsp.FormattingOptions) return r.Result, nil } -func (s *Server) DocumentRangeFormat() { +func (s *Server) DocumentRangeFormat(filename string, r lsp.Range, options lsp.FormattingOptions) ([]lsp.TextEdit, error) { + if !s.capabilities.DocumentRangeFormattingProvider { + return nil, ErrNotSupported + } + doc := lsp.TextDocumentIdentifier{ + URI: uri.File(filename), + } + + params := lsp.DocumentRangeFormattingParams{ + Options: options, + Range: r, + TextDocument: doc, + } + + resp, err := s.sendRequest(lsp.MethodTextDocumentFormatting, params) + if err != nil { + return nil, err + } + + var rpc RPCFormat + err = json.Unmarshal(resp, &rpc) + if err != nil { + return nil, err + } + + return rpc.Result, nil } func (s *Server) Completion(filename string, pos lsp.Position) ([]lsp.CompletionItem, error) { + if s.capabilities.CompletionProvider == nil { + return nil, ErrNotSupported + } + cc := lsp.CompletionContext{ TriggerKind: lsp.Invoked, } @@ -120,6 +155,10 @@ func (s *Server) CompletionResolve() { } func (s *Server) Hover(filename string, pos lsp.Position) (string, error) { + if !s.capabilities.HoverProvider { + return "", ErrNotSupported + } + params := lsp.TextDocumentPositionParams{ TextDocument: lsp.TextDocumentIdentifier{ URI: uri.File(filename), @@ -148,8 +187,11 @@ func (s *Server) Hover(filename string, pos lsp.Position) (string, error) { switch t := c.(type) { case string: return t, nil - case map[string]string: - return t["value"], nil + case map[string]interface{}: + s, ok := t["value"].(string) + if ok { + return s, nil + } } } return "", nil diff --git a/internal/lsp/server.go b/internal/lsp/server.go index da22dd68..907bb71d 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -172,8 +172,13 @@ func (s *Server) Initialize(directory string) { func (s *Server) receive() { for s.Active { resp, err := s.receiveMessage() + if err == io.EOF { + log.Println("Received EOF, shutting down") + s.Active = false + return + } if err != nil { - log.Println("[micro-lsp]", err) + log.Println("[micro-lsp,error]", err) continue } log.Println("[micro-lsp] <<<", string(resp))