Closed vogelsgesang closed 2 years ago
Ah good point, feel free to update or I'll get to it when I have a chance :ok_hand:
Howdie folks,
I thought I'd give this a try, but I'm a bit stuck
❯ nvim --version
NVIM v0.7.0
I've inserted the following right next where I've but the current snippet from the wiki, but the print()
never happens, even when I can see notifications from the wiki snippet just fine
vim.api.nvim_create_autocmd({ "User" }, {
desc = "show progress as notifications",
callback = function(opts)
print(vim.inspect(opts))
end,
pattern = { "LspProgressUpdate" },
})
If I change the pattern to "*"
then I can see "LspRequest" events coming through, just never "LspProgressUpdate" events
Do I need to do something specific to enable the LspProgressUpdates? I think I'm using a new-enough nvim
, but is this only in nightly or something maybe?
Cheers!
I took a stab at this this morning and got a pretty good solution I think:
local client_notifs = {}
local spinner_frames = { "⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷" } -- spinners
local function update_spinner(notif_data) -- update spinner helper function to defer
if notif_data.spinner then
local new_spinner = (notif_data.spinner + 1) % #spinner_frames
notif_data.spinner = new_spinner
notif_data.notification = vim.notify(nil, nil, {
hide_from_history = true,
icon = spinner_frames[new_spinner],
replace = notif_data.notification,
})
vim.defer_fn(function()
update_spinner(notif_data)
end, 100)
end
end
vim.api.nvim_create_augroup("lsp_notify", { clear = true }) -- create augroup
vim.api.nvim_create_autocmd("User", {
pattern = "LspProgressUpdate", -- LSP Progress Update autocommand
group = "lsp_notify",
desc = "LSP progress notification",
callback = function()
local bufnr = vim.api.nvim_get_current_buf() -- get buffer number
for _, client in pairs(vim.lsp.buf_get_clients()) do -- loop over each client to check notifications
if not client_notifs[bufnr] then -- create buffer specific notification table if not exists
client_notifs[bufnr] = {}
end
if not client_notifs[bufnr][client.id] then -- create buffers client specific notification table if not exists
client_notifs[bufnr][client.id] = {}
end
local notif_data = client_notifs[bufnr][client.id] -- set notif_data variable
local progress = nil
for _, progress_msg in pairs(client.messages.progress) do
progress = true -- expose if a progress exists
if not progress_msg.done then
progress = progress_msg -- get clients first not done progress messages
break
end
end
if type(progress) == "table" and progress.percentage and progress.percentage ~= 0 then -- if there is a progress message
local notify_opts = {} -- define notification options
local new_msg = notif_data.notification == nil -- if it's a new message set different options
if new_msg then -- for new messages set a title, initialize icone and disable timeout
notify_opts = {
title = client.name .. (#progress.title > 0 and ": " .. progress.title or ""),
icon = spinner_frames[1],
timeout = false,
}
else -- for existing messages just update the existing notification
notify_opts = { replace = notif_data.notification }
end
notif_data.notification = vim.notify( -- notify with percentage and message
(progress.percentage and progress.percentage .. "%\t" or "") .. (progress.message or ""),
"info",
notify_opts
)
if new_msg then -- if it's a new message, start the update spinner background job
update_spinner(notif_data)
end
elseif progress and not vim.tbl_isempty(notif_data) then -- if there is finished progress and a notification, complete it
notif_data.notification = vim.notify(
"Complete",
"info",
{ icon = "", replace = notif_data.notification, timeout = 3000 }
)
notif_data = {} -- clear notification data
end
end
end,
})
LTGM, feel free to replace the existing implementation :smile:
I tried it and it looks good, but it seems to struggle mit multiple progress reports like rust-analyzer has.
I've inserted the following right next where I've but the current snippet from the wiki, but the
print()
never happens, even when I can see notifications from the wiki snippet just finevim.api.nvim_create_autocmd({ "User" }, { desc = "show progress as notifications", callback = function(opts) print(vim.inspect(opts)) end, pattern = { "LspProgressUpdate" }, })
If I change the pattern to
"*"
then I can see "LspRequest" events coming through, just never "LspProgressUpdate" eventsDo I need to do something specific to enable the LspProgressUpdates? I think I'm using a new-enough
nvim
, but is this only in nightly or something maybe?Cheers!
@jokeyrhyme Guess you add this without deleting the code snippet from the wiki?
LspProgressUpdate
event is actually triggered in neovim's builtin "$/progress" handler. If you override vim.lsp.handlers["$/progress" ]
, then this event will never be triggered.
@ZenLian ah, yes, you're absolutely right, haha, thanks! <3
@mehalter the spinner isn't spinning, because notif_data.spinner
never gets set to any value and the update_spinner
therefore never actually does something.
I guess, notif_data.spinner = 1
should happen for the first progress notification.
There is also a notif_data.spinner = nil
assignment missing for when the the progress is complete. The notif_data = {}
assignment doesn't help, because the update_spinner
function will continue to use the original object.
I tweaked the implementation a bit to avoid global states, split spinner and LSP logic, and, more importantly, debounce calls to require('notify').notify()
because it's too heavy and we don't need to update the contents of notification window more than, say, 10 times per second :
https://github.com/mitinarseny/dotfiles/blob/4c78f07c0d046d491d086651aea6cf65ea9e6a1a/.config/nvim/after/plugin/lsp.lua#L185-L233
https://github.com/mitinarseny/dotfiles/blob/4c78f07c0d046d491d086651aea6cf65ea9e6a1a/.config/nvim/lua/spinner.lua
@mitinarseny thanks! This works like a charm!
@rcarriga would you like to include the code in the project? It would be nice to have a central place for it where bugs can be fixed and code shared. I feel like the wiki is not a good place to track bug fixes and it is quite a big chunk of code with potentials to break it.
I don't want this code to live in nvim-notify, the repo is relatively simple and I don't want to maintain use cases that I don't use. However if someone wishes to create a repo for them, I'd be happy to link them in the README!
Turns out neovim already has its own $/progress handler. We should probably not override it, but listen to the autocommand. Also see https://github.com/j-hui/fidget.nvim/issues/51
(Not part of the plugin itself, only regarding code in the wiki. Leaving this here for discussion. Maybe I will fix this myself some time later)