emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/elpa ea82b4b 57/71: Close #505: ensure completion termi


From: João Távora
Subject: [elpa] externals/elpa ea82b4b 57/71: Close #505: ensure completion terminates in correct buffer
Date: Wed, 16 Dec 2020 11:42:26 -0500 (EST)

branch: externals/elpa
commit ea82b4bb746e45d9d48c738294f8e84598aff502
Author: Andrew Schwartzmeyer <andrew@schwartzmeyer.com>
Commit: João Távora <joaotavora@gmail.com>

    Close #505: ensure completion terminates in correct buffer
    
    To design a completion-in-region-function replacement that leverages
    the elements in completion-at-point-functions, we must ensure that
    their :exit-function parts execute in the correct buffer.  That is the
    buffer where the text to be completed lives, not necessarily the
    buffer being used for user interaction.
    
    Later on, this guarantee should be provided by Emacs itself, perhaps
    by putting the correct with-current-buffer call in completion--done.
    
    Copyright-paperwork-exempt: yes
    Co-authored-by: João Távora <joaotavora@gmail.com>
    
    * eglot.el (eglot-completion-at-point): Ensure :exit-function's
    buffer is where the source is.
---
 eglot.el | 86 +++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 47 insertions(+), 39 deletions(-)

diff --git a/eglot.el b/eglot.el
index c0f3143..0b23337 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2175,45 +2175,53 @@ is not active."
             (line-beginning-position))))
        :exit-function
        (lambda (proxy _status)
-         (eglot--dbind ((CompletionItem) insertTextFormat
-                        insertText textEdit additionalTextEdits label)
-             (funcall
-              resolve-maybe
-              (or (get-text-property 0 'eglot--lsp-item proxy)
-                        ;; When selecting from the *Completions*
-                        ;; buffer, `proxy' won't have any properties.
-                        ;; A lookup should fix that (github#148)
-                        (get-text-property
-                         0 'eglot--lsp-item
-                         (cl-find proxy (funcall proxies) :test #'string=))))
-           (let ((snippet-fn (and (eql insertTextFormat 2)
-                                  (eglot--snippet-expansion-fn))))
-             (cond (textEdit
-                    ;; Undo (yes, undo) the newly inserted completion.
-                    ;; If before completion the buffer was "foo.b" and
-                    ;; now is "foo.bar", `proxy' will be "bar".  We
-                    ;; want to delete only "ar" (`proxy' minus the
-                    ;; symbol whose bounds we've calculated before)
-                    ;; (github#160).
-                    (delete-region (+ (- (point) (length proxy))
-                                      (if bounds (- (cdr bounds) (car bounds)) 
0))
-                                   (point))
-                    (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)))
-                    (when (cl-plusp (length additionalTextEdits))
-                      (eglot--apply-text-edits additionalTextEdits)))
-                   (snippet-fn
-                    ;; A snippet should be inserted, but using plain
-                    ;; `insertText'.  This requires us to delete the
-                    ;; whole completion, since `insertText' is the full
-                    ;; completion's text.
-                    (delete-region (- (point) (length proxy)) (point))
-                    (funcall snippet-fn (or insertText label)))))
-           (eglot--signal-textDocument/didChange)
-           (eldoc)))))))
+         ;; To assist in using this whole `completion-at-point'
+         ;; function inside `completion-in-region', ensure the exit
+         ;; function runs in the buffer where the completion was
+         ;; triggered from.  This should probably be in Emacs itself.
+         ;; (github#505)
+         (with-current-buffer (if (minibufferp)
+                                  (window-buffer (minibuffer-selected-window))
+                                (current-buffer))
+           (eglot--dbind ((CompletionItem) insertTextFormat
+                          insertText textEdit additionalTextEdits label)
+               (funcall
+                resolve-maybe
+                (or (get-text-property 0 'eglot--lsp-item proxy)
+                    ;; When selecting from the *Completions*
+                    ;; buffer, `proxy' won't have any properties.
+                    ;; A lookup should fix that (github#148)
+                    (get-text-property
+                     0 'eglot--lsp-item
+                     (cl-find proxy (funcall proxies) :test #'string=))))
+             (let ((snippet-fn (and (eql insertTextFormat 2)
+                                    (eglot--snippet-expansion-fn))))
+               (cond (textEdit
+                      ;; Undo (yes, undo) the newly inserted completion.
+                      ;; If before completion the buffer was "foo.b" and
+                      ;; now is "foo.bar", `proxy' will be "bar".  We
+                      ;; want to delete only "ar" (`proxy' minus the
+                      ;; symbol whose bounds we've calculated before)
+                      ;; (github#160).
+                      (delete-region (+ (- (point) (length proxy))
+                                        (if bounds (- (cdr bounds) (car 
bounds)) 0))
+                                     (point))
+                      (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)))
+                      (when (cl-plusp (length additionalTextEdits))
+                        (eglot--apply-text-edits additionalTextEdits)))
+                     (snippet-fn
+                      ;; A snippet should be inserted, but using plain
+                      ;; `insertText'.  This requires us to delete the
+                      ;; whole completion, since `insertText' is the full
+                      ;; completion's text.
+                      (delete-region (- (point) (length proxy)) (point))
+                      (funcall snippet-fn (or insertText label)))))
+             (eglot--signal-textDocument/didChange)
+             (eldoc))))))))
 
 (defun eglot--hover-info (contents &optional range)
   (let ((heading (and range (pcase-let ((`(,beg . ,end) (eglot--range-region 
range)))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]