Open discussion: a UI noficiation API

Hello,

Neovim 0.6 is getting a UI module which provides plugin authors with a standardized API that users can override. I want to discuss the idea of a notification API addition.

Motivation

Neovim can run tasks asynchronously and a notification API would allow asynchronous callbacks to send visual feedback to users when something interesting happens, such as when tests are done running or when a language server has indexed a project. Currently plugins can either use the message area, which works fine but is very tiny and crammed, or they can use some fancy visual plugin, but then they have a dependency on an external plugin.

The notification API would default to using the message area by calling the :echo or :echomsg command, maybe wrapped inside :echohl for highlighting. Users can then substitute the default implementation with their own. For example, an implementation on GNU/Linux could shell out to notify-send or even send a raw D-Bus message to make use of the notification facilities of the OS. There could also be a combination of implementations, such as an implementation that both sends the message to the OS and calls our default implementation so the notification gets logged twice.

Proposal

I suggest an API that is close to the XDG Desktop Notifications specification, but adapted to our needs where it makes sense.

--- Display a human-readable notification to the user
---
---@param from string Human-readable identifier for where the message originated
---@param summary string Short title of the notification
---@param body string Full notification message
---@param level string Severity of the notification
function vim.ui.notify(from, summary, body, level)
    -- implementation goes here
end

The summary is a short title like “Tests finished”, the body can contain the full message like the number of failed, skipped and succeeded tests. The level can be used to allow implementations to filter out notifications, similar to how log levels work with levels like debug, info, warning, error,
critical. We probably don’t need as many notification levels. The from parameter lets the notifier identify itself in a human-readable form.

The notification API is fire-and-forget, there is not way of reacting to a notification. If user action is required, then vim.ui.select is the better choice. One thing that would be cool, but I don’t know if it is appropriate for a notification system, would be a progress notification. Language servers like jdt-ls or Metals can report back their progress, so having a sort of progress bar would be neat. But that would require either an asynchronous notification handler, or a way to register an in-progress notification and a way to update it until it is done.

What are your thoughts?

4 Likes

I believe we already have something just like that, see:

https://neovim.io/doc/user/lua.html#vim.notify()

Without a user-defined UI works just like :echo, but with plugins like: GitHub - rcarriga/nvim-notify: A fancy, configurable, notification manager for NeoVim, you can do things like this:

1 Like

Perfect, that is exactly what I had in mind. I guess this discussion can be closed now. How embarassing.

Not embarrassing at all!

IMO you had a great idea, so great that the neovim team agrees with you, they just happened to agree before you proposed it :slight_smile:

Too bad the fields of the opts argument are not specified at all, every implementation of that function is free to take whatever it wants, which kind of defeats the purpose of it. IMO there should be a standard set of options, implementations can then choose whether they want to honor them or not. For example, an implementation could ignore the icon option if it cannot display icons, but callers can at least rely on it beings understood.

You could create a PR that defines more options - if there is a good rationale for them I don’t think there will be much opposition.

Leaving things open was the way to get the ball rolling. Overspecifying everything out right would have blocked it for longer than necessary

Regarding:

Language servers like jdt-ls or Metals can report back their progress, so having a sort of progress bar would be neat.

nvim-jdtls by default re-routes the notifications to the client.messages.progress - so they’re available via vim.lsp.util.get_progress_messages()