echasnovski / mini.nvim

Library of 40+ independent Lua modules improving overall Neovim (version 0.8 and higher) experience with minimal effort
MIT License
4.74k stars 178 forks source link

[mini.animate] animation interferes with vim-visual-multi #448

Closed farzadmf closed 1 year ago

farzadmf commented 1 year ago

Contributing guidelines

Module(s)

mini.animate

Description

I'm using mini.animate (and I love it), but I have an issue with relatively large files and when using vim-visual-multi.

I do have a bunch of folds in the file, and when entering visual multi mode:

The issues arises when the file, as I mentioned, is a large file. Seems like in this case visual multi mode tries to select the next occurrence while mini.animate is still animating the movement, and this creates an issue causing a random word to be selected as next occurrence.

My config:

local animate = require('mini.animate')
require('mini.animate').setup({
  cursor = {
    timing = animate.gen_timing.linear({ duration = 80, unit = 'total' }),
  },
  resize = {
    timing = animate.gen_timing.linear({ duration = 100, unit = 'total' }),
  },
  scroll = {
    timing = animate.gen_timing.linear({ duration = 150, unit = 'total' }),
  },
})

Neovim version

NVIM v0.9.1

Steps to reproduce

Sorry, didn't try the bug with minimal config; let me know if it's absolutely necessary and I can do that.

  1. Open nvim with a large file (say, 600 lines) that has a bunch of folds
  2. Open a single fold and enter visual multi mode (default ctrl+n) with cursor being on a word that's commonly used in the file (e.g., echo in a bash script file)
  3. Two things can happen:
    • There's either an unnecessary jump/animation in the window because of the folds being opened by vim-visual-multi
    • (the worse case) while a window animation is in progress, vim-visual-multi selects the next word, but that doesn't match the cursor word.

Expected behavior

If I use neoscroll, that animation doesn't happen, and there's no issue.

Actual behavior

I'd love for mini.animate to not do this since I'm very dependent on vim-visual-multi, but this conflict between the two plugins is a bit annoying.

echasnovski commented 1 year ago

Thanks for the issue!

I don't use 'mg979/vim-visual-multi' so didn't notice this myself. I tried steps and did in fact reproduce this.

Your explanation for small jitter does sound plausible. The reason you don't see it with neoscroll is because it animates only on certain mappings (like <C-d>, <C-f>, etc.; which it makes by itself), while 'mini.animate' works based on Neovim WinScrolled event.

So in order to make it work, all actions from 'vim-visual-multi' should not trigger WinScrolled event. I might suggest two courses of action here:

Then call _G.remap_with_ignore_winscrolled('n', '<C-n>'). It seems to fix scrolling for a single call, but after it 'vim-visual-multi' seems to redo its mappings and <C-n> becomes the way it was before manual remap.

I think I'll ask you if this snippet fixes your case (at least for a one time call). If yes, then I'll close this issue as there is nothing much to be done on 'mini.animate' side here.

farzadmf commented 1 year ago

Thank you @echasnovski for the answer. I'm a bit confused as to where I need to put the function and call it.

I'm lazy loading plugins, and this is my vim-visual-multi config:

url = 'https://github.com/mg979/vim-visual-multi',
name = 'vim-visual-multi',
event = { 'VeryLazy' },
keys = {
  -- ... my keys, ctrl+n in normal/visual etc.
},
init = function()
  vim.g.VM_theme = 'iceblue'
  vim.g.VM_set_statusline = 0
  vim.g.VM_show_warnings = false

  _G.remap_with_ignore_winscrolled = function(mode, lhs)
    local rhs = vim.fn.maparg(lhs, mode)
    local new_rhs = table.concat({
      '<cmd>let g:eventignore = &eventignore | set eventignore=WinScrolled<cr>',
      '<Plug>(VM-Find-Under)',
      '<cmd>let &eventignore = g:eventignore<cr>',
    })
    vim.keymap.set(mode, lhs, new_rhs)
  end
  _G.remap_with_ignore_winscrolled('n', '<C-n>')
end,

But, I still see the jitter/scroll once I do Ctrl-n in normal mode

echasnovski commented 1 year ago

But, I still see the jitter/scroll once I do Ctrl-n in normal mode

Before you press Ctrl-n, what does executing :nmap <C-n> show? For proper test it should be something like <Cmd>let g:eventignore... and not just <Plug>(VM-Find-Under).

This function should be executed after 'vim-visual-multi' does its mappings. If you can't pin point the exact moment it happens, you may have luck to wrap custom wrapper in vim.schedule_wrap. So something like this:

_G.remap_with_ignore_winscrolled = vim.schedule_wrap(function(mode, lhs)
...
end)

If it still doesn't work even for one iteration, I'd ask you to call this function interactively once and test, i.e. execute :lua _G.remap_with_ignore_winscrolled('n', '<C-n>') and immediately try to use <C-n> for usual 'vim-visual-multi' stuff.


By the way, I fixed the original code snippet to be actually useful for other lhs.

farzadmf commented 1 year ago

Thank you @echasnovski , doing it in the config function instead of init seems to do the trick (without the need for vim.schedule_wrap) :tada:

I also have an issue with mini.clue and visual-multi, and I guess I'll use the mini.clue beta testing issue for that

Closing this now as my personal issue seems to be solved with your code snippet

One final question: do you think it would be beneficial/feasible to disable mini.animate for specific key combinations? You said you're reacting to the event, so I guess it's not really applicable to disable it for specific key combinations?

Reason I'm saying this: in a large file, if you're near the bottom and you do gg, it might take a while for it to reach the top (or the other way around; top-to-bottom)


UPDATE: well, I think what I said above about "taking a while" is not 100% true. I think the total time of the animation is constant, am I correct?

But my question still stands for my own curiosity :stuck_out_tongue_closed_eyes:

echasnovski commented 1 year ago

One final question: do you think it would be beneficial/feasible to disable mini.animate for specific key combinations? You said you're reacting to the event, so I guess it's not really applicable to disable it for specific key combinations?

Reason I'm saying this: in a large file, if you're near the bottom and you do gg, it might take a while for it to reach the top (or the other way around; top-to-bottom)

UPDATE: well, I think what I said above about "taking a while" is not 100% true. I think the total time of the animation is constant, am I correct?

But my question still stands for my own curiosity 😝

Yes, this is not easily possible specifically because 'mini.animate' reacts on WinScrolled event.

And yes, judging by your setup, total duration of any "scroll" animation should be 150 ms. It might be slightly greater on slow CPU or terminal emulator, but shouldn't be by much.