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

Beta-testing 'mini.notify' #640

Closed
echasnovski opened this issue Jan 4, 2024 · 22 comments
Closed

Beta-testing 'mini.notify' #640

echasnovski opened this issue Jan 4, 2024 · 22 comments

Comments

@echasnovski
Copy link
Owner

Please leave your feedback about new mini.notify module here. Feel free to either add new comment or positively upvote existing one.

Some things I am interested to find out (obviously, besides bugs):

  • Is configuration intuitive enough?
  • Are default values of settings convenient for you?
  • Is documentation and examples clear enough?

Thanks!

@bassamsdata
Copy link

congratulations on the new module! my first impression is quite positive and favorable. I haven't got the a lot of time to play with it, but I wanted to kindly note some initial observations:

  1. the pomodoro plugin pomo stopped working with an error from Mini.notfiy
Error executing Lua callback: (mini.notify) Only valid values of `vim.log.levels` are supported.
stack traceback:
        [C]: in function 'error'
        ...m/.local/share/sila/lazy/mini.notify/lua/mini/notify.lua:807: in function 'error'
        ...m/.local/share/sila/lazy/mini.notify/lua/mini/notify.lua:280: in function 'notify'
        ...share/sila/lazy/pomo.nvim/lua/pomo/notifiers/default.lua:68: in function '_update'
        ...share/sila/lazy/pomo.nvim/lua/pomo/notifiers/default.lua:99: in function 'start'
        ...ssam/.local/share/sila/lazy/pomo.nvim/lua/pomo/timer.lua:129: in function 'start'
        ...assam/.local/share/sila/lazy/pomo.nvim/lua/pomo/init.lua:36: in function 'start_timer'
        ...re/sila/lazy/pomo.nvim/lua/pomo/commands/timer_start.lua:17: in function <...re/sila/lazy/pomo.nvim/lua/pomo/commands/timer_start.lua:5>

I checked the plugin source code, and actually, it should works. It was working with vanilla neovim, and worked with fidget and nvim-notify.
NOTE: i don't want to take up too much of your time, as it's not a significant issue. i can create a wrapper for the pomo plugin to directly use this module. i was just curious because i assumed that anything functioning with vanilla vim.notify() should seamlessly work with mini.notify.

  1. some errors doesn't show up with mini.notify. (the neovim notification system sucks, I didn't know which function is responsible for those errors). Examples:
    a. the previous error doesn't appear with Mini.notify.
    b. when I get an error after applying a command or module like :lua some_function()

  2. could we get please some more examples in the help file for the content.format. such as if we want to show the notification level word like (Error, Warn).

  3. thank you for adding the highlight MiniNotifyTitle 😄

Screenshot 2024-01-04 at 11 04 20 PM

@echasnovski
Copy link
Owner Author

  1. the pomodoro plugin pomo stopped working with an error from Mini.notfiy

This is indeed because 'epwalsh/pomo.nvim' doesn't use vim.notify() as it is described in its interface. Here is some justification:

There is no error with default vim.notify() because it doesn't enforce the proper level type, which I don't quite agree with.

  1. some errors doesn't show up with mini.notify. (the neovim notification system sucks, I didn't know which function is responsible for those errors). Examples:

'mini.notify' does not (at least at the moment) override anything except LSP progress handler. So Neovim's errors are still expected to be shown using built-in mechanism.

  1. could we get please some more examples in the help file for the content.format. such as if we want to show the notification level word like (Error, Warn).

Well, it takes notification object as input and should return the string to be used as new message. To prepend notification level before message, you can use something like this:

local format = function(notif) return string.format('%s: %s', notif.level, notif.msg) end
require('mini.notify').setup({ content = { format = format } })

@bassamsdata
Copy link

Thank you for the response.

At least have a type of integer or nil.

I wasn't aware that it should only accept an integer or nil. Now I understand why I encountered errors when I routed the print function to it.

By the way, I have a notification function that provides highlights and icons for protected requires in modules. Upon checking, I realized I used the same approach with strings :(. So, I made some modifications, and now whether I write 'ERROR' or 3, it will always output 3 😌. This eliminates the need to remember which number corresponds to which log level, solving the issue.

Here's the function I referred to for reference:
function M.custom_notify(message, level)
	local levels = {
		DEBUG = 1,
		ERROR = 4,
		INFO = 2,
		OFF = 5,
		TRACE = 0,
		WARN = 3,
	}
	local highlight = {
		[levels.ERROR] = "ErrorMsg",
		[levels.WARN] = "WarningMsg",
		[levels.INFO] = "None",
		[levels.DEBUG] = "Comment",
	}
	local style = {
		[levels.ERROR] = "",
		[levels.WARN] = "",
		[levels.INFO] = "",
		[levels.DEBUG] = "",
	}
	-- Check if level is a string or a number
	local levelValue = type(level) == "number" and level or levels[level]
	local icon = style[levelValue] or ""
	local hl = highlight[levelValue] or "None"
	vim.notify(icon .. ": " .. message, levelValue, { highlight = hl })
end
local format = function(notif) return string.format('%s: %s', notif.level, notif.msg) end
require('mini.notify').setup({ content = { format = format } })

this is good, I didn't know that just putting notif.level will show the level. thanks again.

@echasnovski
Copy link
Owner Author

I wasn't aware that it should only accept an integer or nil. Now I understand why I encountered errors when I routed the print function to it.

By the way, I have a notification function that provides highlights and icons for protected requires in modules. Upon checking, I realized I used the same approach with strings :(. So, I made some modifications, and now whether I write 'ERROR' or 3, it will always output 3 😌. This eliminates the need to remember which number corresponds to which log level, solving the issue.

I mean, I don't like this either, but it is the documented and declared function interface. The functions from 'mini.notify' and notification object itself use level names as strings ("ERROR", "WARN", etc.), which for me is more explicit.

@mike325
Copy link

mike325 commented Jan 15, 2024

Hi @echasnovski, Thanks for the work you put into this module!

vim.notify supports {opts} argument and although by default it's not used, it is still being passed.
it could be useful to also pass this table to the format function and allow the it to determine the notification string using any context it may provide.

A use case could be like nvim_notify that uses this table to set the the notification's title.

@echasnovski
Copy link
Owner Author

vim.notify supports {opts} argument and although by default it's not used, it is still being passed. it could be useful to also pass this table to the format function and allow the it to determine the notification string using any context it may provide.

I've thought about incorporating opts somehow, but there wasn't anything reliably useful.

General users of vim.notify() can not know in advance of what opts fields they can provide because there is no documented workflows. Help page says "Optional parameters. Unused by default.". I agree that having something like provider or context field might be useful, but as actual names are not fixed I am hesitant to add it. Mostly because it can be incorporated into custom vim.notify() implementation which itself uses MiniNotify.make_notify().

A use case could be like nvim_notify that uses this table to set the the notification's title.

Unfortunately, this is not really usable with 'mini.notify' because all notifications are shown in a single window (with a single title). The best it can be is a custom prefix.

@mike325
Copy link

mike325 commented Jan 16, 2024

vim.notify supports {opts} argument and although by default it's not used, it is still being passed. it could be useful to also pass this table to the format function and allow the it to determine the notification string using any context it may provide.

I've thought about incorporating opts somehow, but there wasn't anything reliably useful.

General users of vim.notify() can not know in advance of what opts fields they can provide because there is no documented workflows. Help page says "Optional parameters. Unused by default.". I agree that having something like provider or context field might be useful, but as actual names are not fixed I am hesitant to add it. Mostly because it can be incorporated into custom vim.notify() implementation which itself uses MiniNotify.make_notify().

A use case could be like nvim_notify that uses this table to set the the notification's title.

Unfortunately, this is not really usable with 'mini.notify' because all notifications are shown in a single window (with a single title). The best it can be is a custom prefix.

This is exactly what I had in mind, since the default implementation of vim.notify does not have a "title" space but rather the info can be wrap in a prefix "[FOO]: bar" apart, mini does not need to do any validation or something, it would just pass the table directly and let the format function decide on how to use the provided context.

@echasnovski
Copy link
Owner Author

This is exactly what I had in mind, since the default implementation of vim.notify does not have a "title" space but rather the info can be wrap in a prefix "[FOO]: bar" apart, mini does not need to do any validation or something, it would just pass the table directly and let the format function decide on how to use the provided context.

This can be done by user when overriding vim.notify():

local mini_notify = MiniNotify.make_notify()
vim.notify = function(msg, level, opts)
  opts = opts or {}
  if opts.title ~= nil then msg = string.format('[%s]: %s', opts.title, msg) end
  mini_notify(msg, level)
end

@junelva
Copy link

junelva commented Jan 27, 2024

Wow, I love this! I always felt lost waiting for my LS to spin up. No more! :)

I tried to configure the width of the window to be wider so lines wrap less. I find the wrapping jarring. Unfortunately, changing the width property of the window had no effect. I wonder if wrapped lines would be more readable if they were indented one or two spaces below the first line of a message.

Anyway, thanks again, this makes my brain happy as-is.

@echasnovski
Copy link
Owner Author

Thanks for kind words!

I tried to configure the width of the window to be wider so lines wrap less. I find the wrapping jarring. Unfortunately, changing the width property of the window had no effect. I wonder if wrapped lines would be more readable if they were indented one or two spaces below the first line of a message.

First prototype did include empty line between consecutive notifications. But this looked like consuming unnecessarily too much vertical space. Second prototype included prefix before each notification (with notification time and vertical separator) and deemed to be the most usable.

That said, I probably should add an easily set max_width option (which is now 38.2% of whole Neovim instance's width). Right now it can be set but also requires some manual computation to ensure proper height. I'll look into it.

@bassamsdata
Copy link

bassamsdata commented Jan 27, 2024

Hello again, I'm encountering an issue when resize Neovim. I have an autocmd for refresh mini.notfiy when VimResize event occurs.

Firstly, sometimes it doesn't work, and the window remains at its initial position. Secondly, even when it works, it doesn't respect the col option col = vim.o.columns - 2 that I've set to prevent overlap with mini.map (which I have the same autocmd for VimResize and it works) during horizontal resizing, as well as the row option during vertical resizing.

vim.api.nvim_create_autocmd("VimResized", {
		callback = function()
		mini_notify.refresh()
		end,
})
f8583994-31e2-42fc-bd08-9c92af713c2c.mp4

thank you

edit: adding video.

@echasnovski
Copy link
Owner Author

echasnovski commented Jan 27, 2024

First of all, 'mini.notify' should react to VimResized out of the box. Essentially with the autocommand you provided. But it doesn't now because I might have forgotten to add it. Thanks for finding this!

Edit: This autocommand now is on main branch. Thanks again for bringing attention to this!

Firstly, sometimes it doesn't work, and the window remains at its initial position. Secondly, even when it works, it doesn't respect the col option col = vim.o.columns - 2 that I've set to prevent overlap with mini.map (which I have the same autocmd for VimResize and it works) during horizontal resizing, as well as the row option during vertical resizing.

I think I know what the issue here is. Does it properly react to resize with plain require('mini.notify').setup()?

If you have something like require('mini.notify').setup({ window = { config = { col = vim.o.columns - 2, row = vim.o.lines - 2 } } }), then it computes window config once inside setup() and uses it with actually computed number ever since. So after resize it doesn't recompute it. Allowing config.window.config to be callable was done specifically for this reason. So try something like this instead:

require('mini.notify').setup({
  window = {
    config = function()
      -- Use your table here
      return { col = vim.o.columns - 2, row = vim.o.lines - 2 }
    end,
  },
})

@bassamsdata
Copy link

I think I know what the issue here is. Does it properly react to resize with plain require('mini.notify').setup()?

yes it does work properly with resizing.

So after resize it doesn't recompute it. Allowing config.window.config to be callable was done specifically for this reason.

alright, I didn't know that we should do it as a function but this is magically worked. Thank you.
One question though, I have some other settings and functions, should I put them also in the return table because if I did it the normal way for eg window.config.title, it's gonna overwrite the return table, right?

@echasnovski
Copy link
Owner Author

One question though, I have some other settings and functions, should I put them also in the return table because if I did it the normal way for eg window.config.title, it's gonna overwrite the return table, right?

Yes, config.window.config can be either table or callable. If changes are only permanent and do not depend on Neovim state (so title, border, for example), using table is ok. If they depend on Neovim state (col uses vim.o.columns, etc.), the whole table should be returned inside a callable config.window.config.

@gpanders
Copy link
Contributor

👋

I noticed that using mini.notify causes the intro text to disappear.

Steps to reproduce:

mkdir repro
cd repro
git clone https://github.com/echasnovski/mini.nvim
cat >repro.lua <<EOF
vim.o.runtimepath = os.getenv('PWD') .. '/mini.nvim,' .. vim.o.runtimepath
require('mini.notify').setup()
EOF
nvim --clean -u repro.lua

Note that there is no intro text (occasionally I can see it briefly before it disappears).

This is using Nvim v0.10.0-dev-2240+ga060c13f5.

@echasnovski
Copy link
Owner Author

I noticed that using mini.notify causes the intro text to disappear.

Thanks for reporting this!

It seems to be not an issue with 'mini.notify' but a result of neovim/neovim#27266. it manifests in 'mini.notify' because it uses vim.lsp inside vim.schedule.

In the meantime I'd suggest the proper fix to root cause of the problem: use 'mini.starter' 😅

@echasnovski
Copy link
Owner Author

I've pushed an update that implements new config.window.max_width_share option. It defines the maximum width of notification window (in terms of share of all available columns) until lines start to wrap. By default it is 0.382, but can be increased if you usually have wide notifications and don't like them being wrapped.

@jason0x43
Copy link

jason0x43 commented Feb 5, 2024

I sometimes run into an issue when opening a Rust file and then exiting vim shortly after, while the language server is still initializing, where notify generates a seemingly unending stream of error messages, preventing vim from exiting. (Presumably there's an end, but if so it's after hundreds or thousands of messages; I usually just kill the vim process if this happens.)

This only seems to happen for me with the Rust LS, but I'm guessing it's because the Rust LS takes longer to start up and generates many more notifications than any other LS I use, and the issue is related to that.

Aside from this issue, I really like that notify shows updates from the LS while the LS is starting up.

Screenshot 2024-02-05 at 13 03 15

To reproduce the issue, have mini.notify and the Rust LSP configured, open a rust file, then immediately try to quit vim, while the Rust LSP is still initializing, when it looks particularly busy. In some very light testing just now, the issue happened around 3 out of 5 times when I was trying to reproduce it.

@echasnovski
Copy link
Owner Author

To reproduce the issue, have mini.notify and the Rust LSP configured, open a rust file, then immediately try to quit vim, while the Rust LSP is still initializing, when it looks particularly busy. In some very light testing just now, the issue happened around 3 out of 5 times when I was trying to reproduce it.

I tried it just now with 'lua-language-server' which takes one-two seconds to load workspace and could not reproduce it (0 out of 5 times). Also this is a quite weird looking error message.

I'll try tomorrow with 'rust-analyzer'. Any particular open-sourced repository I could try?

@jason0x43
Copy link

jason0x43 commented Feb 5, 2024

I've only ever seen the issue with rust-analyzer, and only when I exit while it's submitting many updates. I don't do that very often, but every now and then I'll open a file by mistake, try to quit, then get stuck with the giant list of errors.

2024-02-05 15 54 51

You can give WezTerm a try. I can reproduce the issue pretty consistently by opening wezterm/src/main.rs, waiting until the LS starts posting updates, and then quitting.

It looks like notifications are being submitted very quickly. Possibly a bunch are being buffered, I quit vim (which presumably destroys the update window), and then the update code has problems because its window disappeared. Maybe.

@echasnovski
Copy link
Owner Author

@jason0x43, yes I indeed could reproduce this in Neovim 0.9.5. In 0.10.0 (current Nightly) there are no errors but there is a slightly annoying lag before closing.

This should be fixed on latest main. Thanks for bringing this up!

echasnovski added a commit to echasnovski/mini.notify that referenced this issue Feb 6, 2024
@echasnovski
Copy link
Owner Author

With the release of 0.12.0, 'mini.notify' is now out of beta-testing. Huge thanks to everyone for participating and giving feedback!

@echasnovski echasnovski unpinned this issue Feb 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants