Closed thinkiny closed 7 months ago
Yes, it would be great to support eglot. However, I am not quite sure how this can work with eglot at the moment due to my insufficient knowledge to eglot.
eglot is going to merge to master. Is there any plan to support eglot like sideline-lsp?
It doesn't already support it? Eglot uses flymake to display the errors in the buffer, so sideline-flymake already covers that.
I think he is referring to the code action from eglot
since sideline-lsp
provides it.
There was a discussion https://github.com/joaotavora/eglot/discussions/1070 on Eglot repo with some code snippets.
The implementation looks interesting, but I don't know how to apply the action
working. 🤔
(defun sideline-eglot-code-actions (command)
"Sideline backend for Eglot code actions."
(cl-case command
(`candidates
(cons :async
(lambda (callback &rest _)
(funcall callback (mapcar (lambda (x) (concat (substring x 0 (min (length x) 50)) " "))
(eglot-code-actions (point)))))))
(`action (lambda (candidate &rest _) ; optional
(message "Execute command for `%s`!" candidate))))) ; How to resolve the code action depends on selected candidate?
@joaotavora Can you help us here? 😕
Sorry, I don't have time to learn about this sideline API right now. Nothing is the code looks fishy, but then I don't understand what candidates
and action
mean. "how to apply the action
working" is not something I can understand. What is the type of the variable candidate
?
In the latest master version pushed just now (to Emacs's upstream, not here) I offer a new eglot-execute
API function that can be used to ask a server (which you can get with the existing eglot-current-server
) to execute one of the items returned by the existing eglot-code-actions
.
Sorry, I don't have time to learn about this sideline API right now.
The design is the same as company-mode, and it seems like you know company-mode very well. 🤔
Nothing is the code looks fishy, but then I don't understand what
candidates
andaction
mean. "how to apply theaction
working" is not something I can understand. What is the type of the variablecandidate
?
candidate
is just a string you displayed by the sideline, therefore:
(defun my-backend (command)
"Example backend."
(cl-case command
(`candidates '("info 1" "info 2")) ; this returns the candidates
(`action (lambda (candidate &rest _) ; candidate is the string got clicked! In this case, it will either be `info 1` or `info 2`.
(message "Execute command for `%s`!" candidate))))) ; we expect to execute the corresponding code action here
So we need a way to use the string as an ID (I normally use hash-table) to find the right code action to execute.
The design is the same as company-mode, and it seems like you know company-mode very well. thinking
Company mode is a completely different thing. I don't appreciate or remember much about its API. And what I knew back then is not what I know now. I think you may as well believe me when I tell you i don't know how this APi works (no documentation was shown to me until now) and you should believe me when I tell you I don't have time to learn it. No need for "thinking" emoji.
You should solve this problem, not me. I've provided eglot-execute
. Use text properties or something.
Thanks for the response! I will check into it when I have time for this! ;)
Something like this seems to work, but I'm having trouble with eglot timing out when using the mouse.
(defvar-local sideline-eglot--async-candidates-timer nil)
(defvar-local sideline-eglot--ht-candidates nil)
(defun sideline-eglot--async-candidates (callback &rest _)
(when sideline-eglot--async-candidates-timer
(cancel-timer sideline-eglot--async-candidates-timer)
(setq sideline-eglot--async-candidates-timer nil))
(let ((p (point)))
(setq sideline-eglot--async-candidates-timer
(run-with-idle-timer
0.3 nil
(lambda ()
(setq sideline-eglot--ht-candidates (ht-create))
(dolist (row (eglot-code-actions p))
(ht-set! sideline-eglot--ht-candidates (getf row :title) row))
(funcall callback (ht-keys sideline-eglot--ht-candidates)))))))
(defun sideline-eglot (command)
"Eglot backend for sideline."
(cl-case command
(`candidates
(cons :async #'sideline-eglot--async-candidates))
(`action
(lambda (candidate &rest _)
(let ((matching-code-action (ht-get sideline-eglot--ht-candidates candidate)))
(unless matching-code-action
(error "Failed to find candidate: %s" candidate))
(let ((command (getf matching-code-action :command))
(server (eglot-current-server)))
(unless server
(error "Server disappeared"))
(eglot-execute-command server
(getf command :command)
(getf command :arguments))))))))
Any updates on this @jcs090218 ? Would be really awesome to have a sideline mode for eglot that works out of the box.
I've created the package sideline-eglot. It's currently only on JCS-ELPA.
Thank you!
eglot is going to merge to master. Is there any plan to support eglot like sideline-lsp?