[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/eglot 147f3b0 16/49: Close #411: offer shortcut command
From: |
Stefan Monnier |
Subject: |
[elpa] externals/eglot 147f3b0 16/49: Close #411: offer shortcut commands to commonly invoked code actions |
Date: |
Wed, 17 Mar 2021 18:41:44 -0400 (EDT) |
branch: externals/eglot
commit 147f3b0c10048d90315f9e43f3ddaf3718d3bc29
Author: Andrii Kolomoiets <andreyk.mad@gmail.com>
Commit: GitHub <noreply@github.com>
Close #411: offer shortcut commands to commonly invoked code actions
See also #598.
Make eglot-code-actions accept a new action-kind argument. If there
is only one action of that kind, apply it. This allows us to create
actions shortcuts like eglot-code-action-organize-imports, etc.
* eglot.el (eglot-code-actions): Accept new argument action-kind.
(eglot--code-action): New function-defining helper macro.
(eglot-code-action-organize-imports)
(eglot-code-action-extract)
(eglot-code-action-inline)
(eglot-code-action-rewrite)
(eglot-code-action-quickfix): New commands.
* README.md: Mention new feature.
* NEWS.md: Mention new feature.
Co-authored-by: João Távora <joaotavora@gmail.com>
---
NEWS.md | 20 +++++++++++++++-
README.md | 10 ++++----
eglot.el | 79 ++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 77 insertions(+), 32 deletions(-)
diff --git a/NEWS.md b/NEWS.md
index cb72ba3..1b373bc 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,4 +1,17 @@
-# 1.7 (upcoming)
+# (upcoming)
+
+##### Code action shortcuts ([#411][github#411])
+
+`M-x eglot-code-actions` accepts an optional `action-kind` argument,
+specified interactively with `C-u`. Other shortcuts call specific
+actions directly (`eglot-code-action-inline`,
+`eglot-code-action-extract`, `eglot-code-action-rewrite`,
+`eglot-code-action-organize-imports` and
+`eglot-code-action-quickfix`). One can create own shortcuts for code
+actions with specific a kind by calling `eglot-code-actions` from
+elisp.
+
+# 1.7 (16/12/2020)
##### Support hierarchical symbols in Imenu ([#303][github#303])
@@ -232,3 +245,8 @@ and now said bunch of references-->
[github#324]: https://github.com/joaotavora/eglot/issues/324
[github#326]: https://github.com/joaotavora/eglot/issues/326
[github#361]: https://github.com/joaotavora/eglot/issues/361
+[github#411]: https://github.com/joaotavora/eglot/issues/411
+[github#439]: https://github.com/joaotavora/eglot/issues/439
+[github#454]: https://github.com/joaotavora/eglot/issues/454
+[github#481]: https://github.com/joaotavora/eglot/issues/481
+[github#494]: https://github.com/joaotavora/eglot/issues/494
diff --git a/README.md b/README.md
index 7194241..d42eefc 100644
--- a/README.md
+++ b/README.md
@@ -217,10 +217,9 @@ Here's a summary of available commands:
- `M-x eglot-format` asks the server to format buffer or the active
region;
-- `M-x eglot-code-actions` asks the server for any code actions at
- point. These may tipically be simple fixes, like deleting an unused
- variable, or fixing an import. Left click on diagnostics to check if
- there are any there;
+- `M-x eglot-code-actions` asks the server for any "code actions" at
+ point. Can also be invoked by `mouse-1`-clicking some diagnostics.
+ Also `M-x eglot-code-action-<TAB>` for shortcuts to specific actions.
- `M-x eldoc` asks the Eldoc system for help at point (this command
isn't specific to Eglot, by the way, it works in other contexts).
@@ -241,9 +240,10 @@ in `eglot-mode-map`, which is active as long as Eglot is
managing a
file in your project. The commands don't need to be Eglot-specific,
either:
-```
+```lisp
(define-key eglot-mode-map (kbd "C-c h") 'eglot-help-at-point)
(define-key eglot-mode-map (kbd "<f6>") 'xref-find-definitions)
+(define-key eglot-mode-map (kbd "C-c o") 'eglot-code-action-organize-imports)
```
<a name="customization"></a>
diff --git a/eglot.el b/eglot.el
index 8cfe991..276cd1a 100644
--- a/eglot.el
+++ b/eglot.el
@@ -2523,14 +2523,21 @@ is not active."
:newName ,newname))
current-prefix-arg))
-
-(defun eglot-code-actions (beg &optional end)
- "Offer to execute code actions between BEG and END.
-Interactively, if a region is active, BEG and END are its bounds,
-else BEG is point and END is nil, which results in a request for
-code actions at point"
+(defun eglot--region-bounds () "Region bounds if active, else point and nil."
+ (if (use-region-p) `(,(region-beginning) ,(region-end)) `(,(point) nil)))
+
+(defun eglot-code-actions (beg &optional end action-kind)
+ "Offer to execute actions of ACTION-KIND between BEG and END.
+If ACTION-KIND is nil, consider all kinds of actions.
+Interactively, default BEG and END to region's bounds else BEG is
+point and END is nil, which results in a request for code actions
+at point. With prefix argument, prompt for ACTION-KIND."
(interactive
- (if (region-active-p) `(,(region-beginning) ,(region-end)) `(,(point) nil)))
+ `(,@(eglot--region-bounds)
+ ,(and current-prefix-arg
+ (completing-read "[eglot] Action kind: "
+ '("quickfix" "refactor.extract" "refactor.inline"
+ "refactor.rewrite" "source.organizeImports")))))
(unless (eglot--server-capable :codeActionProvider)
(eglot--error "Server can't execute code actions!"))
(let* ((server (eglot--current-server-or-lose))
@@ -2544,27 +2551,35 @@ code actions at point"
:context
`(:diagnostics
[,@(cl-loop for diag in (flymake-diagnostics beg end)
- when (cdr (assoc 'eglot-lsp-diag
(eglot--diag-data diag)))
- collect it)]))))
+ when (cdr (assoc 'eglot-lsp-diag
+ (eglot--diag-data diag)))
+ collect it)]
+ ,@(when action-kind `(:only ,action-kind))))))
(menu-items
- (or (mapcar (jsonrpc-lambda (&rest all &key title &allow-other-keys)
- (cons title all))
- actions)
- (eglot--error "No code actions here")))
+ (or (cl-loop for action across actions
+ ;; Do filtering ourselves, in case the `:only'
+ ;; didn't go through.
+ when (or (not action-kind)
+ (equal action-kind (plist-get action :kind)))
+ collect (cons (plist-get action :title) action))
+ (apply #'eglot--error
+ (if action-kind `("No \"%s\" code actions here"
,action-kind)
+ `("No code actions here")))))
(preferred-action (cl-find-if
- (jsonrpc-lambda (&key isPreferred
&allow-other-keys)
- isPreferred)
- actions))
- (menu `("Eglot code actions:" ("dummy" ,@menu-items)))
- (action (if (listp last-nonmenu-event)
- (x-popup-menu last-nonmenu-event menu)
- (cdr (assoc (completing-read "[eglot] Pick an action: "
- menu-items nil t
- nil nil (or (plist-get
- preferred-action
- :title)
- (car menu-items)))
- menu-items)))))
+ (lambda (menu-item)
+ (plist-get (cdr menu-item) :isPreferred))
+ menu-items))
+ (default-action (car (or preferred-action (car menu-items))))
+ (action (if (and action-kind (null (cadr menu-items)))
+ (cdr (car menu-items))
+ (if (listp last-nonmenu-event)
+ (x-popup-menu last-nonmenu-event `("Eglot code actions:"
+ ("dummy"
,@menu-items)))
+ (cdr (assoc (completing-read
+ (format "[eglot] Pick an action (default
%s): "
+ default-action)
+ menu-items nil t nil nil default-action)
+ menu-items))))))
(eglot--dcase action
(((Command) command arguments)
(eglot-execute-command server (intern command) arguments))
@@ -2574,6 +2589,18 @@ code actions at point"
(eglot--dbind ((Command) command arguments) command
(eglot-execute-command server (intern command) arguments)))))))
+(defmacro eglot--code-action (name kind)
+ "Define NAME to execute KIND code action."
+ `(defun ,name (beg &optional end)
+ ,(format "Execute '%s' code actions between BEG and END." kind)
+ (interactive (eglot--region-bounds))
+ (eglot-code-actions beg end ,kind)))
+
+(eglot--code-action eglot-code-action-organize-imports
"source.organizeImports")
+(eglot--code-action eglot-code-action-extract "refactor.extract")
+(eglot--code-action eglot-code-action-inline "refactor.inline")
+(eglot--code-action eglot-code-action-rewrite "refactor.rewrite")
+(eglot--code-action eglot-code-action-quickfix "quickfix")
;;; Dynamic registration
- [elpa] externals/eglot 133c25e 24/49: Close #613: explicitly require seq.el, (continued)
- [elpa] externals/eglot 133c25e 24/49: Close #613: explicitly require seq.el, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot a43289e 25/49: Fix #616: also override global flymake-diagnostic-functions, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot fc4c324 29/49: Fix #567: update elixir-ls link in README.md, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 7918fac 43/49: Close #637: Add TRAMP support, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 33e83ba 44/49: Fix #638: convert colon to hex in URI, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot bf4a7aa 31/49: Fix #406: mention eglot-stay-out-of in README.md, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 65aadca 46/49: Fix #620: simplify eglot--apply-workspace-edit, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 97ed4ca 49/49: Close #643: add new command eglot-shutdown-all, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot f9df418 06/49: Fix #584: Define a face for symbol highlight, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot cb58b72 15/49: Close #603: add fortls for Fotran (f90-mode), Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 147f3b0 16/49: Close #411: offer shortcut commands to commonly invoked code actions,
Stefan Monnier <=
- [elpa] externals/eglot 99f8d7b 17/49: Per #604: mention common installation pitfalls in README.md, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 2879b83 19/49: * README.md: Mention Google Open Source Peer Bonus, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot d5b840b 20/49: Fix #606, #Fix 608: fix bug in eglot-code-actions, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot eac5264 21/49: Fix #609: flush pending changes to server before code actions request, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot f68f829 26/49: Close #566: prefer typescript-language-server for JS&TS, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot c73f5ed 27/49: Fix #612: remove duplicate entry for "Registration" LSP type, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 4ae5a44 28/49: Fix #568: update gopls URL in README.md, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 8d00f8b 32/49: Per #602: speed up glob matching 2x, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot e57be55 36/49: Fix #502: silence messages while formatting markup, Stefan Monnier, 2021/03/17
- [elpa] externals/eglot 398b81e 35/49: Per #602: simplify dir-watching strategy of w/didChangeWatchedFiles, Stefan Monnier, 2021/03/17