2

In neovim, open two different buffers as follows (using :vnew, for example):

*--------------*--------------*
|              |              |
|      1       |       2      |
|              |              |
*--------------*--------------*

In the first, run

:au BufEnter <buffer> :call feedkeys('ahello', 'n') 

In the second, run

:au BufEnter <buffer> :call feedkeys('ahola', 'n') 

Then, with the cursor in the second window, use e.g. :History from fzf.vim and cancel the search with <esc>.

Doing this on my machine, both autocommands are triggered on escaping the fzf window and, even more strange, they are executed in the same pane. Is this a bug, or am I not using autocommands correctly? End result:

*--------------*--------------*
|              |helloahola    |
|              |              |
|              |              |
*--------------*--------------*
  • 2
    feedkeys are queued for processing, it doesn't have to be applied to the buffer that triggered BufEnter. What really weird here is why BufEnter was triggered on 1 while your cursor rest on 2 after you cancel fzf. The problem can be reproduced by quitting any side window that takes full width or height. – dedowsdi Oct 18 at 1:09
  • 1
    What happens when you add i to the feedkeys mode? Like :au BufEnter <buffer> :call feedkeys('ahola', 'ni') . – Ralf Oct 18 at 5:59
  • is there a reason you need to use feedkeys(). In general I wouldn't recommend using this unless you know that you really need it. (as mentioned before, it is queued for processing, so it might not do what you want or when you want it). – Christian Brabandt Oct 18 at 6:57
  • @ChristianBrabandt Would you have a look at the lower part of my answer? – Ralf Oct 18 at 8:39
  • @ChristianBrabandt Because of this bug with norm in a terminal mode. – Rastapopoulos Oct 18 at 10:02
5

I don't use fzf and use Vim instead of neovim. So I couldn't reproduce your scenario. Also I was not able to reproduce what @dedowsdi described in his comment.(See end of answer.)

But some general stuff around autocmd and feedkeys:

Assume we open Vim with three new files in split windows:

vim -O a.txt b.txt c.txt

Vim will open with three windows like this:

+--------------+--------------+--------------+
|      1       |      2       |      3       |
|    a.txt     |    b.txt     |    c.txt     |
|              |              |              |
+--------------+--------------+--------------+

Move to window 2 and execute :au BufEnter <buffer> :call feedkeys('ab.txt', 'n') and to window 3 and execute :au BufEnter <buffer> :call feedkeys('ac.txt', 'n') then back to window 1.

We now want to move to window 3 using two times <C-W>l. To avoid delays with manual input we use:

:normal ^Wl^Wl

(Note: ^W is entered as <C-V><C-W>.)

So the input queue is <C-W>l<C-W>l.

The first <C-W>l is consumed and the second window is activated. The autocmd kicks in and calls feedkeys.

Now the input queue is: <C-W>lab.txt

Now the other <C-W>l is consumed and the third window is activated. Again the autocmd kicks in and calls feedkeys.

Now the input queue is ab.txtac.txt.

This is processed and appends the text b.txtac.txt to the first line and leaves you in insert mode.

Conclusion:

Using feedkeys is tricky. You should exactly know where you are and what is happening around you. Combined with an autocmd this is even more tricky.

While your usage of autocmd is correct from a technical point of view, the combination with feedkeys might result in unexpected behavior.


Now a test based on the comment from @dedowski (using Vim):

Add an autocmd to 1, move to 3, open a help window, in your case, it should take full width. exit help window by q, you should see autocmd of 1 and 3 applied to 3.

Open Vim with three new files:

vim -O a.txt b.txt c.txt

we get:

+--------------+--------------+--------------+
|      1       |      2       |      3       |
|    a.txt     |    b.txt     |    c.txt     |
|              |              |              |
+--------------+--------------+--------------+

Change to the window showing c.txt and then open help with :help and we get:

+--------------+--------------+--------------+
|                   help                     |
|-----------------------------+--------------|
|      1       |      2       |      3       |
|    a.txt     |    b.txt     |    c.txt     |
+--------------+--------------+--------------+

Now execute:

:autocmd BufEnter * echomsg 'BufEnter ' . expand('%')

Then close the help window using :q and Vim will print

BufEnter a.txt
BufEnter c.txt

(You might need :messages to see both echos.)

Well -- that is unexpected. .

  • 2
    Add an autocmd to 1, move to 3, open a help window, in your case, it should take full width. exit help window by <c-w>q, you should see autocmd of 1 and 3 applied to 3. – dedowsdi Oct 18 at 8:02
  • @dedowsdi Got it - thank you. Updated answer. – Ralf Oct 18 at 8:35
  • 3
    regarding the last part: What is happening is, that Vim will try to put the cursor in the same window, after closing the help window. So what it does it closes the help window. The cursor ends up in Buffer a, triggering a BufEnter autocommand. However Vim knows it has been closing a help window, and therefore tries to restore the window layout it was before opening the help window, therefore moving the cursor to window 2, which triggers again a BufEnter autocommand. This seems to happen specifically for help windows and Vim is just trying to be overly smart :/ – Christian Brabandt Oct 18 at 9:06
  • 1
    BTW: depending on your terminal width, you might need to use ´:topleft :help` to make sure the new help window will be at the top of the other windows. – Christian Brabandt Oct 18 at 9:15
  • 3
    BTW: I proposed a doc patch – Christian Brabandt Oct 18 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.