[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