Skip to content

Indicate active async requests via spinner in mode-line #4742

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.org
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
* Add Roc support
* Add support for environment variables in rust analyzer runnables. Allowing the new ~Update Tests (Expect)~ code lens to work as expected.
* Add support for [[https://github.com/mathworks/MATLAB-language-server][MATLAB language server]] (requires [[https://github.com/MathWorks/Emacs-MATLAB-Mode][matlab-mode]]).
* Add support for [[https://github.com/c3lang/c3c][c3 language]] (requires [[https://github.com/c3lang/c3-ts-mode][c3-ts-mode]] and [[https://github.com/pherrymason/c3-lsp][c3lsp]]).
* Add support for [[https://github.com/c3lang/c3c][c3 language]] (requires [[https://github.com/c3lang/c3-ts-mode][c3-ts-mode]] and [[https://github.com/pherrymason/c3-lsp][c3lsp]]).
* Drop support for emacs 27.1 and 27.2
* Add ~lsp-nix-nixd-server-arguments~ to allow passing arguments to the ~nixd~ LSP.
* Add ~lsp-display-pending-async-request-via-spinner~. If non-nil, indicate we are waiting for async responses via a spinner in the modeline.
* Improve the lsp-ocaml client (see [[https://github.com/emacs-lsp/lsp-mode/issues/4731][#4731]] for the follow-up issue. MRs: [[https://github.com/emacs-lsp/lsp-mode/pull/4741][#4741]], [[https://github.com/emacs-lsp/lsp-mode/pull/4732][#4732]])

** 9.0.0
Expand Down
44 changes: 34 additions & 10 deletions lsp-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,12 @@ Takes a value accepted by `spinner-start'."
,@(mapcar (lambda (c) (list 'const (car c)))
spinner-types)))

(defcustom lsp-display-pending-async-request-via-spinner nil
"If non-nil, indicate we are waiting for async responses via a spinner
in the modeline."
:group 'lsp-mode
:type 'boolean)

(defvar-local lsp-use-workspace-root-for-server-default-directory nil
"Use `lsp-workspace-root' for `default-directory' when starting LSP process.")

Expand Down Expand Up @@ -3236,6 +3242,24 @@ If WORKSPACE is not provided current workspace will be used."
"Remove TOKEN from the WORKSPACE work-done-tokens."
(remhash token (lsp--workspace-work-done-tokens workspace)))

(defun lsp-client-set-async-request (id handler client)
"Set ID to HANDLER for pending async requests for a CLIENT"
(puthash id handler (lsp--client-response-handlers client))
(if (and lsp-display-pending-async-request-via-spinner
(= (hash-table-count (lsp--client-response-handlers client)) 1))
(lsp--spinner-start)))

(defun lsp-client-get-async-request (id client)
"Get the handler for ID from pending async requests for a CLIENT"
(gethash id (lsp--client-response-handlers client))
)

(defun lsp-client-rem-async-request (id client)
"Remove ID from pending async requests for a CLIENT"
(remhash id (lsp--client-response-handlers client))
(if (and lsp-display-pending-async-request-via-spinner
(zerop (hash-table-count (lsp--client-response-handlers client))))
(lsp--spinner-stop)))

(defun lsp--make-notification (method &optional params)
"Create notification body for method METHOD and parameters PARAMS."
Expand Down Expand Up @@ -3681,11 +3705,9 @@ CANCEL-TOKEN is the token that can be used to cancel request."
(plist-get body :params)
'outgoing-req)
workspace))
(puthash id
(lsp-client-set-async-request id
(list callback error-callback method start-time (current-time))
(-> workspace
(lsp--workspace-client)
(lsp--client-response-handlers)))
(lsp--workspace-client workspace))
(lsp--send-no-wait body (lsp--workspace-proc workspace)))
body)
(error "The connected server(s) does not support method %s.
Expand Down Expand Up @@ -5366,7 +5388,7 @@ If EXCLUDE-DECLARATION is non-nil, request the server to include declarations."
(defun lsp--cancel-request (id)
"Cancel request with ID in all workspaces."
(lsp-foreach-workspace
(->> lsp--cur-workspace lsp--workspace-client lsp--client-response-handlers (remhash id))
(->> lsp--cur-workspace lsp--workspace-client (lsp-client-rem-async-request id))
(lsp-notify "$/cancelRequest" `(:id ,id))))

(defvar-local lsp--hover-saved-bounds nil)
Expand Down Expand Up @@ -7112,25 +7134,25 @@ server. WORKSPACE is the active workspace."
(pcase (lsp--get-message-type json-data)
('response
(cl-assert id)
(-let [(callback _ method _ before-send) (gethash id (lsp--client-response-handlers client))]
(-let [(callback _ method _ before-send) (lsp-client-get-async-request id client)]
(when (lsp--log-io-p method)
(lsp--log-entry-new
(lsp--make-log-entry method id data 'incoming-resp
(lsp--ms-since before-send))
workspace))
(when callback
(remhash id (lsp--client-response-handlers client))
(lsp-client-rem-async-request id client)
(funcall callback (lsp:json-response-result json-data)))))
('response-error
(cl-assert id)
(-let [(_ callback method _ before-send) (gethash id (lsp--client-response-handlers client))]
(-let [(_ callback method _ before-send) (lsp-client-get-async-request id client)]
(when (lsp--log-io-p method)
(lsp--log-entry-new
(lsp--make-log-entry method id (lsp:json-response-error-error json-data)
'incoming-resp (lsp--ms-since before-send))
workspace))
(when callback
(remhash id (lsp--client-response-handlers client))
(lsp-client-rem-async-request id client)
(funcall callback (lsp:json-response-error-error json-data)))))
('notification
(lsp--on-notification workspace json-data))
Expand Down Expand Up @@ -9145,7 +9167,9 @@ IGNORE-MULTI-FOLDER to ignore multi folder server."

(defun lsp--spinner-stop ()
"Stop the spinner in case all of the workspaces are started."
(when (--all? (eq (lsp--workspace-status it) 'initialized)
(when (--all? (and (eq (lsp--workspace-status it) 'initialized)
(or (null lsp-display-pending-async-request-via-spinner)
(zerop (hash-table-count (-> it (lsp--workspace-client) (lsp--client-response-handlers))))))
lsp--buffer-workspaces)
(spinner-stop)))

Expand Down