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

feat(lsp): redrawstatus on progress notifications #28569

Closed
wants to merge 1 commit into from

Conversation

mfussenegger
Copy link
Member

@mfussenegger mfussenegger commented Apr 29, 2024

Problem:

Currently users can include vim.lsp.status() in their statusline, but
they won't see status changes if the statusline isn't redrawn on progress updates.

The simple solution for that is:

autocmd LspProgress * redrawstatus

But that has the problem that the last message remains stale until
something else triggers a redraw. To fix the stale messages, users would
have to add something like this:

local timer = vim.loop.new_timer()
api.nvim_create_autocmd("LspProgress", {
  group = lsp_group,
  callback = function()
    vim.cmd.redrawstatus()
    if timer then
      timer:stop()
      timer:start(500, 0, vim.schedule_wrap(function()
        timer:stop()
        vim.cmd.redrawstatus()
      end))
    end
  end
})

That's quite complex.

Solution:

Call redrawstatus by default. To avoid redrawstatus() burst the calls
are debounced to 60 FPS.

Problem:

Currently users can include `vim.lsp.status()` in their statusline, but
they won't see status changes without also adding a `LspProgress`
autocmd.

The simple solution for that is:

    autocmd LspProgress * redrawstatus

But that has the problem that the last message remains stale until
something else triggers a redraw. To fix the stale messages, users would
have to add something like this:

    local timer = vim.loop.new_timer()
    api.nvim_create_autocmd("LspProgress", {
      group = lsp_group,
      callback = function()
        vim.cmd.redrawstatus()
        if timer then
          timer:stop()
          timer:start(500, 0, vim.schedule_wrap(function()
            timer:stop()
            vim.cmd.redrawstatus()
          end))
        end
      end
    })

That's quite complex.

Solution:

Call redrawstatus by default. To avoid `redrawstatus()` burst the calls
are debounced to 60 FPS.
Copy link
Member

@justinmk justinmk left a comment

Choose a reason for hiding this comment

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

Do we need a debounce util?

@gpanders gpanders added this to the 0.11 milestone May 6, 2024
@gpanders
Copy link
Member

gpanders commented May 6, 2024

Is redrawstatus "cheap" if the statusline hasn't changed? Otherwise, this could be wasteful if the user doesn't use LSP status messages in their statusline (unless we include that by default too?).

@linrongbin16
Copy link

linrongbin16 commented May 17, 2024

Is redrawstatus a blocking/sync IO operation on editor's statusline?

No matter it's yes or no, I don't think sending LspProgress should always force the editor to redraw statusline.

The real good way (of showing LSP status in your statusline) is:

  1. Listen to the LspProgress event, receive the data and cache (include formatting) it.
  2. Register a background job scheduled with a timer, to flush those formatted string/info to whatever component in a fixed interval (say 200 milliseconds, which fits your eyes).

This solution separates the data consuming and UI rendering, which avoid the performance issue. Because the frequency of LspProgress events are not guaranteed by LSP servers. If too many LspProgress events are been sent in a certain moment, there will be too many UI rendering, which is unnecessary, and leads to UI blocking. People usually just need to know the LSP status is been updated, so a regular fixed interval time (say 200 milliseconds) already meets the requirement. My plugin lsp-progress.nvim does exactly this way.

Besides, some user even don't need to show LSP status in statusline. The plugin fidget.nvim renders the LSP status info in the bottom right corner of the editor, instead of using statusline, which thus never need to redraw the statusline.

@mfussenegger
Copy link
Member Author

I also noticed that this causes cursor flickering in insert mode. So this isn't viable as default.

@mfussenegger mfussenegger deleted the lsp-progress branch May 17, 2024 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants