rcarriga / nvim-notify

A fancy, configurable, notification manager for NeoVim
MIT License
3k stars 80 forks source link

Command to dismiss current notification #115

Closed felipesere closed 2 years ago

felipesere commented 2 years ago

Sometimes notifications linger a bit more than I want to or I'm on a particularly small screen and the notification covers importants bits of information.

My reflex is to hammer down on ESC to get rid of the notification 😰

Could we add an API or something that I can bind to a key to dismiss all active notifications?

rcarriga commented 2 years ago

There is already a function for this :h notify.dismiss()

rodhash commented 2 years ago

Thank you sir

rodhash commented 2 years ago

In general it works great!

However I noticed something.. if I dismiss them too early while they are still processing / updating its content, I get some errors..

Not sure whether that's expected but other than that it works fine

For instance right after opening a lua file:

Error executing vim.schedule lua callback: ...art/nvim-notify/lua/notify/service/buffer/highlights.lua:142: Invalid buffer id: 5
stack traceback:
        [C]: in function 'nvim_buf_get_option'
        ...art/nvim-notify/lua/notify/service/buffer/highlights.lua:142: in function 'set_opacity'
        ...ker/start/nvim-notify/lua/notify/service/buffer/init.lua:45: in function '_create_highlights'
        ...ker/start/nvim-notify/lua/notify/service/buffer/init.lua:38: in function 'set_notification'
        ...ack/packer/start/nvim-notify/lua/notify/service/init.lua:68: in function 'replace'
        ...m/site/pack/packer/start/nvim-notify/lua/notify/init.lua:207: in function 'notify'
        /home/rodhash/.config/nvim/lua/plug/lsp.lua:845: in function 'update_spinner'
        /home/rodhash/.config/nvim/lua/plug/lsp.lua:852: in function ''
        vim/_editor.lua: in function ''
        vim/_editor.lua: in function <vim/_editor.lua:0>
rcarriga commented 2 years ago

I think this should be the behaviour. There's no "correct" way for nvim-notify to handle this error. The only way to keep the type signature valid is to create a new notification, which I don't believe most people would want. We could change it to return nil but then it will only return nil if you pass a replace argument which I'm not a fan of.

Also either way, if we catch and pass nil back or let the error bubble, users will probably have to handle it (e.g. stop recording progress etc). So I think the best route is just let it error and you can wrap in pcall where necessary. You could also use the on_close argument to gracefully stop when it's dismissed

mnussbaum commented 1 year ago

Are there any examples you could share on how to gracefully dismiss an in-progress notification without raising a stack-trace? As someone who hasn't worked with neovim plugins extensively I'm not sure how to use the on_close argument or pcall wrapping you mentioned to achieve this.

EDIT: I was able to figure it out. Here's an example update_spinner function that doesn't raise an error when the notification is dismissed:

local function update_spinner(client_id, token)
  local notif_data = get_notif_data(client_id, token)

  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()
      pcall(update_spinner, client_id, token)
    end, 100)
  end
end
rcarriga commented 1 year ago

Feel free to update the wiki if there is something that isn't right, it is community maintained :smile: Using pcall is the right way to do this but I'd probably say to wrap vim.notify with the pcall to make it clear what it is that can fail

mnussbaum commented 1 year ago

Hmm, wrapping vim.notify seems to cause issues for me. With code like this:

 notif_data.notification = pcall(vim.notify, nil, nil, {
   hide_from_history = true,
   icon = spinner_frames[new_spinner],
   replace = notif_data.notification,
 })

I get an error:

Invalid notification to replace

Am I wrapping vim.notify wrong?

rcarriga commented 1 year ago

pcall returns two values (or more), a boolean that is false if the call errored and the actual return values of the call.

So it should be

 local success
 success, notif_data.notification = pcall(vim.notify, nil, nil, {
   hide_from_history = true,
   icon = spinner_frames[new_spinner],
   replace = notif_data.notification,
 })
 if not success then
    ... -- Handle error
 end
mnussbaum commented 1 year ago

Ah that's helpful info, thank you! Using the snippet you shared, I unfortunately see an error after message dismissal, Invalid notification to replace.

I wonder if there's something I need to do in the error handling to cancel the "invalid" notification replacement?

rcarriga commented 1 year ago

You shouldn't be calling vim.defer_fn... if an error occurs

mnussbaum commented 1 year ago

I get the same invalid notification error with

 local success
 success, notif_data.notification = pcall(vim.notify, nil, nil, {
   hide_from_history = true,
   icon = spinner_frames[new_spinner],
   replace = notif_data.notification,
 })

 if success then
   vim.defer_fn(function()
     update_spinner(client_id, token)
   end, 100)
 end
rcarriga commented 1 year ago

That notification is triggered if the replace argument is not valid so I'm not sure what would be causing that without a full reproduction. You can try printing the notif_data.notification to see what it is before each call