I finally understand all the behavior of :split that has been
troubling me!
First of all, :split with no arguments does no loading of buffers, as
has been said. Hence, no BufWinEnter autocmd. My confusion was in
thinking of :split {file} as the same command. These are two very
different commands. In fact, :split {file} is apparently a synonym
with :new {file}. Not only that, but the help for :new (with no
arguments) says the following:
Autocommands are executed in this order:
1. WinLeave for the current window
2. WinEnter for the new window
3. BufLeave for the current buffer
4. BufEnter for the new buffer
This behaves like a ":split" first, and then a ":e" command.
Armed with this knowledge, I can explain all the behavior that
troubled me with :split {file}:
1. WinEnter contains the old buffer name in <amatch>, <afile>, and %
2. E37 when doing :split %
First, :split is done. This will create a new window, with the current
buffer, without loading any buffers. At this point the WinLeave and
WinEnter autocmds fire. Hence, <afile>, <amatch>, and the values of %
and # are unchanged. Problem 1 explained. Then, an :e is done. This
will, if the file is different, behave just like a normal :e command,
and use whatever buffer is currently loaded for that file. If the file
is the same, it still acts like an :e command, which will indeed
reload the buffer from disk. Problem 2 explained.
Knowing that :split {file} is basically a synonym for :split | edit
{file}, the behavior I have been experiencing is shown to be correct
after all, if a little confusing. To clarify things, I think the help
files should be updated in a few locations:
CTRL-W s *CTRL-W_s*
CTRL-W S *CTRL-W_S*
CTRL-W CTRL-S *CTRL-W_CTRL-S*
:[N]sp[lit] [++opt] [+cmd] *:sp* *:split*
Split current window in two. The result is two viewports on
the same file. Make new window N high (default is to use half
the height of the current window). Reduces the current window
height to create room (and others, if the 'equalalways' option
is set, 'eadirection' isn't "hor", and one of them is higher
than the current or the new window). This does not load a
buffer or read a file, so autocmd events like
|BufWinEnter|, |BufEnter|, etc. will not be triggered. But,
see |:split_f|.
Note: CTRL-S does not work on all terminals and might block
further input, use CTRL-Q to get going again.
Also see |++opt| and |+cmd|.
----------------------------------------------------------------------------
:[N]new [++opt] [+cmd] {file}
:[N]sp[lit] [++opt] [+cmd] {file} *:split_f*
Create a new window and start editing file {file} in it.
If [+cmd] is given, execute the command when the file has been
loaded |+cmd|.
Also see |++opt|.
Make new window N high (default is to use half the existing
height). Reduces the current window height to create room
(and others, if the 'equalalways' option is set).
Just like |:new|, this works exactly like :split|edit {file},
which can cause some behavior that might be unexpected, for
example:
- |WinEnter| autocmds will contain the buffer for the current
window in |<amatch>|, |<afile>|, and |:%|. I.e. they will not
contain {file}.
- Doing :split % will _not_ act like |:split| with no
arguments. It will attempt to reload the buffer after the
:split, which will cause |E37| if the buffer is modified.
----------------------------------------------------------------------------
*BufWinEnter*
BufWinEnter After a buffer is loaded into a window. This
can be when the buffer is first loaded (after
processing the modelines), when a hidden
buffer is displayed in a window (and is no
longer hidden), or a buffer already visible in
a window is also displayed in another window
(but note that |:split| with no arguments does
not load a buffer).