Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it possible to select server to shut down from eglot-shutdown #73

Closed
wants to merge 1 commit into from
Closed

Make it possible to select server to shut down from eglot-shutdown #73

wants to merge 1 commit into from

Conversation

mkcms
Copy link
Collaborator

@mkcms mkcms commented Aug 12, 2018

This commit makes the command eglot-shutdown ask the user for server to kill when it's called with a prefix argument. I find the current workflow for killing servers a little bit awkward (switch to project, switch to some file managed by the server, kill it). This IMO improves this workflow.

@joaotavora
Copy link
Owner

Leave the prefix argument semantics untouched and always read the server when interactively called and more than one server. Put the current server first when it exists so that single extra RET does what is expected.

We'll have to revisit this when we allow more than one server to manage a buffer, but we'll probably have to revisit a whole bunch of stuff...

BTW the reason you find it akward is probably because you are developing Eglot itself and starting and stopping a lot of servers. You probably wouldn't mind so much of you were just using Eglot regularly.

* eglot.el (eglot-shutdown): Read the server from minibuffer.
(eglot--read-server): New function.
(lambda (server) (cons (jsonrpc-name server) server))
(delq nil
(cons (eglot--current-server)
(apply #'append
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few problems here

  • apply #'append is pathologically slow for large lists because of the variable arglist of append.
    A cl-loop can iterate through hash tables cheaply and append on the go.

  • there's no need to also cons a new alist or use hash-table-values

  • I don't understand the need for delq nil or delete-dups (though we've been forgetting to purge the hash table of empty entries, but that's a different problem).

  • We probably want to error if there are no servers and return the only server without prompting if it exists, or if it is the current server.

I came up with this lightly tested version:

(defun eglot--read-server (prompt &optional dont-if-just-the-one)
  "Read a running Eglot server from minibuffer using PROMPT.
If DONT-IF-JUST-THE-ONE and there's only one server, don't prompt
and just return it."
  (let ((servers (cl-loop for servers
                           being hash-values of eglot--servers-by-project
                           append servers)))
    (cond ((null servers)
           (eglot--error "No servers!"))
          ((or (cdr servers) (not dont-if-just-the-one))
           (let ((read (completing-read
                        prompt (mapcar #'jsonrpc-name servers)
                        nil t
                        (when-let ((current (eglot--current-server)))
                          (jsonrpc-name current)))))
             (cl-find read servers :key #'jsonrpc-name :test #'equal)))
          (t (car servers)))))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply #'append is pathologically slow for large lists because of the variable arglist of append.
A cl-loop can iterate through hash tables cheaply and append on the go.

I didn't think about that, I assumed that even with a large number of servers (I never use more than 3 myself), the delay would be unnoticeable.

I don't understand the need for delq nil or delete-dups (though we've been forgetting to purge the hash table of empty entries, but that's a different problem).

I'm prepending the value of eglot--current-server to the list, then deleting that element if it was nil. completing-read doesn't allow nil values. I'm using delete-dups because when I prepend eglot-current-server, it's still somewhere in the tail of the other list. I don't know if completing-read removes duplicates, but I use ivy, and it didn't delete them.

We probably want to error if there are no servers and return the only server without prompting if it exists, or if it is the current server.

I think it might be a bit unexpected when there is only one server and we kill it. I would have to always check how many servers there are before I call eglot-shutdown to make sure I don't kill the current server if I don't want to.

A cl-loop can iterate through hash tables cheaply and append on the go.

Thanks, I don't know 'cl very well. I will try to rewrite it, or you can push your version as mine will probably be very similar.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't think about that, I assumed that even with a large number of servers (I never use more than 3 myself), the delay would be unnoticeable.

If you (hash-table-count eglot-servers-by-project) the result may surprise you, but that's the bug I was referring to. Anyway, it's good practice in general to avoid applying to things whose lengths we don't control well.

I'm prepending the value of eglot--current-server to the list, then deleting that element if it was nil. completing-read doesn't allow nil values. I'm using delete-dups because when I prepend eglot-current-server, it's still somewhere in the tail of the other list. I don't know if completing-read removes duplicates, but I use ivy, and it didn't delete them.

OK, but it's not needed if you use the initial-value argument to completing-read. (What could be problematic is if you have two projects identically named)

I think it might be a bit unexpected when there is only one server and we kill it. I would have to always check how many servers there are before I call eglot-shutdown to make sure I don't kill the current server if I don't want to.

Then we can just call my version of eglot--read-server with eglot--current-server as the second argument.

Thanks, I don't know 'cl very well. I will try to rewrite it, or you can push your version as mine will probably be very similar.

OK I will push mine and I hope you don't mind the lisp pedancy.

bhankas pushed a commit to bhankas/emacs that referenced this pull request Sep 18, 2022
…tdown

* eglot.el (eglot--read-server): New helper.
(eglot-shutdown): Use it.
bhankas pushed a commit to bhankas/emacs that referenced this pull request Sep 19, 2022
…tdown

* eglot.el (eglot--read-server): New helper.
(eglot-shutdown): Use it.
bhankas pushed a commit to bhankas/emacs that referenced this pull request Sep 19, 2022
* eglot.el (eglot--read-server): New helper.
(eglot-shutdown): Use it.

#73: joaotavora/eglot#73
jollaitbot pushed a commit to sailfishos-mirror/emacs that referenced this pull request Oct 12, 2022
* eglot.el (eglot--read-server): New helper.
(eglot-shutdown): Use it.

GitHub-reference: close joaotavora/eglot#73
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants