Subject: bug#63372: [PATCH] Add variable: eglot-apply-text-edits-function

From: Felician Nemeth <[email-masked]>
Date: Mon, 08 May 2023 16:28:56 +0200

In https://lists.gnu.org/archive/html/emacs-devel/2023-05/msg00173.html
Eli Zaretskii <[email-masked]> writes:

>> From: Felician Nemeth <[email-masked]>
>> Cc: [email-masked],  [email-masked]
>> Date: Sat, 06 May 2023 17:17:14 +0200
>> 
>> 3. Eglot uses the eglot--apply-text-edits defun to apply server
>>    initiated edits.  There is an extension that allows the server to
>>    send the edits in a different format (snippet-text-edits).
>> 
>>    Eglot-x puts an advise on eglot--apply-text-edits to check the format
>>    of the edits and act accordingly.
>> 
>>    I don't know how to avoid this advice.
>
> Some hook or function variable, perhaps?  If they don't exist, perhaps
> they could be added?

I've attached a patch with my first attempt at this.  João, what do you
think of this approach?

(Independently of this issue, maybe a configurable
apply-workspace-edit-function would be useful as well.  One alternative
implementation of the current eglot--apply-workspace-edit could be to
apply all edits without asking for confirmation and then show a
`vc-diff'-like interface allowing the user to revert/accept all of the
changes with a single keystroke.)

Thank you.

>From 1a5c534a291a9ee247cb142a4816b75a9cff3ff1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felici=C3=A1n=20N=C3=A9meth?= <[email-masked]>
Date: Mon, 8 May 2023 15:57:56 +0200
Subject: [PATCH] Add variable: eglot-apply-text-edits-function

This allows third parties to experiment with UI, or implement the
SnippetTextEdits LSP extension.

* lisp/progmodes/eglot.el (eglot-apply-text-edits-function): New
defvar defaulting to eglot--apply-lsp-text-edits.
(eglot--apply-text-edits): Delegate the editing task to
eglot-apply-text-edits-function.
(eglot--apply-lsp-text-edits): New defun containing most of the
old eglot--apply-text-edits.
---
 lisp/progmodes/eglot.el | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 95a5b325fb..eb79a8d2d3 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -895,6 +895,11 @@ eglot--language-ids
 (cl-defmethod initialize-instance :before ((_server eglot-lsp-server) &optional args)
   (cl-remf args :initializationOptions))
 
+(defvar eglot-apply-text-edits-function #'eglot--apply-lsp-text-edits
+  "Function to call to apply text edits to the current buffer.
+The fuction must have a single argument holding the \"edits\"
+value of a TextDocumentEdit LSP object, i.e., a TextEdit or an
+AnnotatedTextEdit LSP object.")
 
 ;;; Process management
 (defvar eglot--servers-by-project (make-hash-table :test #'equal)
@@ -3349,6 +3354,10 @@ 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))
+  (funcall eglot-apply-text-edits-function edits))
+
+(cl-defun eglot--apply-lsp-text-edits (edits)
+  "Apply EDITS for current buffer."
   (atomic-change-group
     (let* ((change-group (prepare-change-group))
            (howmany (length edits))
-- 
2.30.2