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

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

[elpa] externals/eglot 9e9c740d0b 1/3: Close #899: Implement on-type-for


From: ELPA Syncer
Subject: [elpa] externals/eglot 9e9c740d0b 1/3: Close #899: Implement on-type-formatting support
Date: Tue, 29 Mar 2022 05:57:28 -0400 (EDT)

branch: externals/eglot
commit 9e9c740d0bf9c14559c651ebc8748400e24424a9
Author: Felicián Németh <felician.nemeth@gmail.com>
Commit: João Távora <joaotavora@gmail.com>

    Close #899: Implement on-type-formatting support
    
    * eglot.el (eglot-format): Add new optional argument `on-type-format'
    to request :textDocument/onTypeFormatting, and ...
    (eglot--post-self-insert-hook): ... call it from here when necessary.
    
    * eglot-tests.el (eglot--simulate-key-event): New helper defun.
    (rust-on-type-formatting): New test.
    
    * NEWS.md: mention feature.
---
 NEWS.md        |  3 +++
 eglot-tests.el | 27 +++++++++++++++++++++++++++
 eglot.el       | 27 +++++++++++++++++++++++----
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index ad087134be..4cbd17f91b 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,7 @@
 # (upcoming)
 
+##### Support on-type-formatting ([#899][github#899])
+
 ##### Provide basic workspace-folders support ([#893][github#893])
 Eglot now advertises `project-root` and `project-external-roots` as
 workspace-folders.  (Configuring `tags-table-list` sets the external
@@ -355,3 +357,4 @@ and now said bunch of references-->
 [github#810]: https://github.com/joaotavora/eglot/issues/810
 [github#813]: https://github.com/joaotavora/eglot/issues/813
 [github#893]: https://github.com/joaotavora/eglot/issues/893
+[github#899]: https://github.com/joaotavora/eglot/issues/899
diff --git a/eglot-tests.el b/eglot-tests.el
index 55967a4977..1432de6dd1 100644
--- a/eglot-tests.el
+++ b/eglot-tests.el
@@ -262,6 +262,13 @@ Pass TIMEOUT to `eglot--with-timeout'."
          (eglot-connect-timeout timeout))
     (apply #'eglot--connect (eglot--guess-contact))))
 
+(defun eglot--simulate-key-event (char)
+  "Like (execute-kbd-macro (vector char)), but with `call-interactively'."
+  ;; Also, this is a bit similar to what electric-tests.el does.
+  (setq last-input-event char)
+  (setq last-command-event char)
+  (call-interactively (key-binding (vector char))))
+
 
 ;;; Unit tests
 
@@ -670,6 +677,26 @@ pyls prefers autopep over yafp, despite its README stating 
the contrary."
       (should
        (string= (buffer-string) "def a():\n    pass\n\n\ndef b():\n    
pass\n")))))
 
+(ert-deftest rust-on-type-formatting ()
+  "Test textDocument/onTypeFormatting agains rust-analyzer."
+  (skip-unless (executable-find "rust-analyzer"))
+  (skip-unless (executable-find "cargo"))
+  (eglot--with-fixture
+      '(("on-type-formatting-project" .
+         (("main.rs" .
+           "fn main() -> () {\n  foo\n    .bar()\n  "))))
+    (with-current-buffer
+        (eglot--find-file-noselect "on-type-formatting-project/main.rs")
+      (let ((eglot-server-programs '((rust-mode . ("rust-analyzer")))))
+        (should (zerop (shell-command "cargo init")))
+        (eglot--sniffing (:server-notifications s-notifs)
+          (should (eglot--tests-connect))
+          (eglot--wait-for (s-notifs 10) (&key method &allow-other-keys)
+             (string= method "textDocument/publishDiagnostics")))
+        (goto-char (point-max))
+        (eglot--simulate-key-event ?.)
+        (should (looking-back "^    \\."))))))
+
 (ert-deftest javascript-basic ()
   "Test basic autocompletion in a JavaScript LSP."
   (skip-unless (executable-find "typescript-language-server"))
diff --git a/eglot.el b/eglot.el
index 58ad4588ae..1cf0b7ae63 100644
--- a/eglot.el
+++ b/eglot.el
@@ -1974,8 +1974,18 @@ THINGS are either registrations or unregisterations 
(sic)."
   "If non-nil, value of the last inserted character in buffer.")
 
 (defun eglot--post-self-insert-hook ()
-  "Set `eglot--last-inserted-char'."
-  (setq eglot--last-inserted-char last-input-event))
+  "Set `eglot--last-inserted-char', call on-type-formatting if necessary."
+  (setq eglot--last-inserted-char last-input-event)
+  (when (or (eq last-input-event
+                (elt (eglot--server-capable
+                      :documentOnTypeFormattingProvider
+                      :firstTriggerCharacter)
+                     0))
+            (seq-find (lambda (elt) (eq last-input-event (elt elt 0)))
+                      (eglot--server-capable
+                         :documentOnTypeFormattingProvider
+                         :moreTriggerCharacter)))
+    (eglot-format (point) nil (string last-input-event))))
 
 (defun eglot--pre-command-hook ()
   "Reset `eglot--last-inserted-char'."
@@ -2357,14 +2367,23 @@ Try to visit the target file for a richer summary line."
   (interactive)
   (eglot-format nil nil))
 
-(defun eglot-format (&optional beg end)
+(defun eglot-format (&optional beg end on-type-format)
   "Format region BEG END.
 If either BEG or END is nil, format entire buffer.
 Interactively, format active region, or entire buffer if region
-is not active."
+is not active.
+
+If ON-TYPE-FORMAT is non-nil, request on-type-formatting from the
+server.  The argument should be a one-character-long string that
+has just been inserted at BEG."
   (interactive (and (region-active-p) (list (region-beginning) (region-end))))
   (pcase-let ((`(,method ,cap ,args)
                (cond
+                ((and beg on-type-format)
+                 `(:textDocument/onTypeFormatting
+                   :documentOnTypeFormattingProvider
+                   ,`(:position ,(eglot--pos-to-lsp-position beg)
+                      :ch ,on-type-format)))
                 ((and beg end)
                  `(:textDocument/rangeFormatting
                    :documentRangeFormattingProvider



reply via email to

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