[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#63372: [PATCH] Add variable: eglot-apply-text-edits-function
From: |
Felician Nemeth |
Subject: |
bug#63372: [PATCH] Add variable: eglot-apply-text-edits-function |
Date: |
Mon, 08 May 2023 16:54:38 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) |
Felician Nemeth <felician.nemeth@gmail.com> writes:
> I've attached a patch with my first attempt at this. João, what do you
> think of this approach?
I forgot to add that alternatively SnippetTextEdit support can be added
to Eglot as well. The patch without the boring parts would look like
the following.
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index eb79a8d2d3..0a4738b3b9 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -3350,14 +3350,13 @@ eglot-imenu
(cl-defun eglot--apply-text-edits (edits &optional version)
"Apply EDITS for current buffer if at VERSION, or if it's nil."
+ ;; This is quite rust-analyzer specific. It assumes there is at
+ ;; most one meaningful SnippetTextEdit and that can be identified by
+ ;; searching for "$0".
(unless edits (cl-return-from eglot--apply-text-edits))
(unless (or (not version) (equal version eglot--versioned-identifier))
(jsonrpc-error "Edits on `%s' require version %d, you have %d"
(current-buffer) version eglot--versioned-identifier))
(atomic-change-group
(let* ((change-group (prepare-change-group))
(howmany (length edits))
@@ -3366,7 +3365,7 @@ eglot--apply-lsp-text-edits
howmany (current-buffer))
0 howmany))
- (done 0))
- (mapc (pcase-lambda (`(,newText ,beg . ,end))
+ (done 0)
+ snippet snippet-beg snippet-end)
+ (mapc (pcase-lambda (`(,newText ,insertTextFormat (,beg . ,end)))
(let ((source (current-buffer)))
(with-temp-buffer
(insert newText)
@@ -3375,11 +3374,30 @@ eglot--apply-lsp-text-edits
(save-excursion
(save-restriction
(narrow-to-region beg end)
- (replace-buffer-contents temp)))
+ (replace-buffer-contents temp))
+ (when (and (eql
insertTextFormat 2)
+ (string-match "\\$\\(0\\|{0[^}]*}\\)"
+ newText))
+ ;; "At the moment, rust-analyzer
+ ;; guarantees that only a single edit will
+ ;; have InsertTextFormat.Snippet.", but:
+ ;;
https://github.com/rust-analyzer/rust-analyzer/issues/11006
+ ;; Every one of them has insertTextFormat
+ ;; = 2, and there's no easy, reliable way
+ ;; to tell, which one contains a real
+ ;; snippet. RA's own .ts implementation
+ ;; uses the regexp above.
+ (setq snippet newText)
+ (setq snippet-beg (point-min-marker))
+ (setq snippet-end (point-max-marker))))
(eglot--reporter-update reporter (cl-incf done)))))))
- (mapcar (eglot--lambda ((TextEdit) range newText)
- (cons newText (eglot--range-region range 'markers)))
+ (mapcar (eglot--lambda ((SnippetTextEdit) range newText
insertTextFormat)
+ (list newText insertTextFormat (eglot--range-region
range 'markers)))
(reverse edits)))
+ (when snippet
+ (goto-char snippet-beg)
+ (delete-region snippet-beg snippet-end)
+ (funcall (eglot--snippet-expansion-fn) snippet))
(undo-amalgamate-change-group change-group)
(progress-reporter-done reporter))))