4

After starting neovim with nvim -u NONE, why do the following commands

:term
:au BufWinEnter,WinEnter <buffer> startinsert
:tabnew

leave me in insert mode in the new tab, and how can I avoid that? The same behaviour happens when replacing <buffer> by term://*, as in the answer provided here.

  • 1
    I removed the neovim and terminal tags because you get the same result in Vim and/or if you remove the first command given. (I left the command, though, because I think it explains why you'd want to do this). Note that the <cr> after startinsert is unnecessary and, in Vim at least, causes an error when the autocommand fires. – Rich Apr 18 '18 at 11:22
  • 1
    You're right, it's obvious that I pressed Enter after each command. I deleted all the <cr>. – Rastapopoulos Apr 18 '18 at 11:30
  • 1
    looks like a bug to me – Christian Brabandt Apr 18 '18 at 11:55
  • 1
    I am not so sure, this is a bug anymore. It kind of is documented below :h WinEnter. See the Note section. That also applies to :tab commands. – Christian Brabandt Apr 19 '18 at 8:58
  • 1
    I don't know, buf in fact it seems that, for my purpose, BufEnter does the trick. Perhaps WinEnter autocommands just can't be linked to buffers? It's not really clear from the documentation what the differences between BufEnter, WinEnter and BufWinEnter are. – Rastapopoulos Apr 19 '18 at 10:47
2

The culprit appears to be the WinEnter autocmd, which is apparently being triggered with the buffer you left and not the one you entered. To demonstrate, you can set up an autocmd like this to print the name of the buffer the WinEnter command was run on, or 'unnamed buffer' if it has no name.

augroup Testingautocmd!
    autocmd WinEnter * echom (empty(expand('<amatch>'))? 'unnamed buffer' : expand('<amatch>'))
augroup END

To see the output when running :tabnew, :new, and :vnew, you'll need to run :messages, as vim annoyingly overwrites the commandline with a blank line for those commands (that's why I used :echom[sg]).

By checking the messages you can see that when :tabnew, :new or :vnew is run we get the name of the last buffer (in your case a terminal code) instead of 'unnamed buffer' like you'd expect, so it appears that vim still thinks it's in the old buffer when it runs the WinEnter command, and so erronously triggers :startinsert on the new file.

As for how to fix it, triggering the autocmd on BufEnter will work most of the time (as you already know), except for the case of switching between two windows both containing the same terminal.

Vim's buffers are it's abstraction of files. Windows are simply areas of the screen that offer a view onto a buffer. All windows showing the same file are views of parts of the same buffer - this includes windows in different tabs, as vim tabs are just collections of windows. So WinLeave and WinEnter completely ignore what's in any buffer and are fired everytime you move between two different windows. The BufLeave and BufEnter completely ignore whether you move windows and are fired only when vim changes the buffer you're currently editing (it calls this the current file and it's the one who's name you can use as % on the commandline, see :h current-file). So typically when switching between two windows which have different files open, both BufLeave/Enter and WinLeave/Enter get called (both of their conditions are satisfied). BufWinLeave/BufWinEnter gets triggered when a window changes the buffer it's viewing. Commands like :e and :b usually trigger this. :e and :b also usually trigger BufLeave/Enter, but not WinLeave/Enter; although the current window hasn't changed, the current file has (BufLeave/Enter) and the file displayed in the current window has (BufWinLeave/Enter). You can look at these commands being executed by getting them to echo messages everytime they are fired (like my example above), to see what happens whereever you're unsure.

Hence by triggering startinsert on BufEnter you get into insert mode whenever the current buffer switches to a terminal, which I assume is almost always what you want. As I mentioned, it breaks when you have to windows both viewing the same terminal buffer and you switch between those; the current file does not change and so BufEnter is never triggered.

  • Thank you! So there is indeed a bug with WinEnter? Would you know of a solution to address the issue you pointed out in your last paragraph? – Rastapopoulos Apr 24 '18 at 9:18
  • 1
    I can't think of a simple way to do it. It's probably possible with a load of complex vimscript, but personally I never have multiple windows showing the same terminal. Arguably it's not really a bug in the behaviour of winenter either, if you look at the note in the documentation for winenter it mentions early triggering (though not the fact it triggers for the wrong buffer). A feature then I guess... – flemingfleming Apr 24 '18 at 19:13

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.