((lua-mode lua-ts-mode) . ,(eglot-alternatives
'("lua-language-server" "lua-lsp")))
(yang-mode . ("yang-language-server"))
- (zig-mode . ("zls"))
+ ((zig-mode zig-ts-mode) . ("zls"))
((css-mode css-ts-mode)
. ,(eglot-alternatives '(("vscode-css-language-server" "--stdio")
("css-languageserver" "--stdio"))))
(:detail :deprecated :children))
(TextDocumentEdit (:textDocument :edits) ())
(TextEdit (:range :newText))
+ (InsertReplaceEdit (:newText :insert :replace))
(VersionedTextDocumentIdentifier (:uri :version) ())
(WorkDoneProgress (:kind) (:title :message :percentage :cancellable))
(WorkspaceEdit () (:changes :documentChanges))
["documentation"
"details"
"additionalTextEdits"])
- :tagSupport (:valueSet [1]))
+ :tagSupport (:valueSet [1])
+ :insertReplaceSupport t)
:contextSupport t)
:hover (list :dynamicRegistration :json-false
:contentFormat (eglot--accepted-formats))
;; insertion to potentially cancel an essential
;; resolution request (github#1474).
'dont-cancel-on-input)
- (let ((snippet-fn (and (eql insertTextFormat 2)
- (eglot--snippet-expansion-fn))))
+ (let* ((snippet-fn (and (eql insertTextFormat 2)
+ (eglot--snippet-expansion-fn)))
+ (apply-edit
+ (lambda (range text)
+ (pcase-let ((`(,beg . ,end)
+ (eglot-range-region range)))
+ (delete-region beg end)
+ (goto-char beg)
+ (funcall (or snippet-fn #'insert) text)))))
(cond (textEdit
;; Revert buffer back to state when the edit
;; was obtained from server. If a `proxy'
;; state, _not_ the current "foo.bar".
(delete-region orig-pos (point))
(insert (substring bounds-string (- orig-pos (car bounds))))
- (eglot--dbind ((TextEdit) range newText) textEdit
- (pcase-let ((`(,beg . ,end)
- (eglot-range-region range)))
- (delete-region beg end)
- (goto-char beg)
- (funcall (or snippet-fn #'insert) newText))))
+ (eglot--dcase textEdit
+ (((TextEdit) range newText)
+ (funcall apply-edit range newText))
+ (((InsertReplaceEdit) newText replace)
+ (funcall apply-edit replace newText))))
(snippet-fn
;; A snippet should be inserted, but using plain
;; `insertText'. This requires us to delete the
(replace-buffer-contents temp)))
(when reporter
(eglot--reporter-update reporter (cl-incf done))))))))
- (mapcar (eglot--lambda ((TextEdit) range newText)
- (cons newText (eglot-range-region range 'markers)))
+ (mapcar (lambda (edit)
+ (eglot--dcase edit
+ (((TextEdit) range newText)
+ (cons newText (eglot-range-region range 'markers)))
+ (((InsertReplaceEdit) newText replace)
+ (cons newText (eglot-range-region replace 'markers)))))
(reverse edits)))
(undo-amalgamate-change-group change-group)
(when reporter
"fn test() -> i32 { let v: usize = 1; v.count_ones.1234567890;")
(buffer-string))))))
+(ert-deftest eglot-test-zig-insert-replace-completion ()
+ "Test zls's use of 'InsertReplaceEdit'."
+ (skip-unless (functionp 'zig-ts-mode))
+ (eglot--with-fixture
+ `(("project" .
+ (("main.zig" .
+ ,(concat "const Foo = struct {correct_name: u32,\n};\n"
+ "fn example(foo: Foo) u32 {return foo.correc_name; }")))))
+ (with-current-buffer
+ (eglot--find-file-noselect "project/main.zig")
+ (should (eglot--tests-connect))
+ (search-forward "foo.correc")
+ (completion-at-point)
+ (should (looking-back "correct_name")))))
+
(ert-deftest eglot-test-basic-xref ()
"Test basic xref functionality in a clangd LSP."
(skip-unless (executable-find "clangd"))