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    |
|              |              |
|              |              |
*--------------*--------------*
5
  • 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
    Commented Oct 18, 2019 at 1:09
  • 1
    What happens when you add i to the feedkeys mode? Like :au BufEnter <buffer> :call feedkeys('ahola', 'ni') .
    – Ralf
    Commented Oct 18, 2019 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). Commented Oct 18, 2019 at 6:57
  • @ChristianBrabandt Would you have a look at the lower part of my answer?
    – Ralf
    Commented Oct 18, 2019 at 8:39
  • @ChristianBrabandt Because of this bug with norm in a terminal mode. Commented Oct 18, 2019 at 10:02

1 Answer 1

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. .

5
  • 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
    Commented Oct 18, 2019 at 8:02
  • @dedowsdi Got it - thank you. Updated answer.
    – Ralf
    Commented Oct 18, 2019 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 :/ Commented Oct 18, 2019 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. Commented Oct 18, 2019 at 9:15
  • 3
    BTW: I proposed a doc patch Commented Oct 18, 2019 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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