Window-local stack-based buffer management for vim and neovim.
This plugin maintains a separate buffer list per window. Buffers can be switched navigated in two ways:
- Based on a positional list of buffers (Previous/Next).
- Based on most-recently-used order within the window.
This plugin was originally inspired by how I used buffers in emacs:
- Buffers can be buried, i.e. unlisted from the window without closing them.
- Unless only one file is listed in the window, there is always an alternate buffer.
- More generally, buffers are kept in a positional list and additionally remembered in a most-recently-used order. Navigating to most-recently-used order can be done in larger steps, e.g. "open the third-most-recently used buffer." This is similar to ALT-TAB and CTRL-TAB shortcuts in window managers and tab-based applications.
Design goals:
- When opening a file and closing it again, the list of buffers is restored to its previous state, both regarding positional list and most-recently-used order.
- There is no limit to how many buffers are opened and closed to restore the consistent state. It does not matter if one, 3, or 15 buffers are opened and then closed again.
When opening a buffer not in the current window's list:
- Regarding positional list of buffers: The new buffer is inserted as the Next in the current window. The previously focused buffer will be the new Previous buffer in the list. Buffers that were Next to the previously focused buffer will be Next to the newly opened buffer.
- In the most-recently-used list: The previously focused buffer will be added to the top.
Note how for that moment, the top most-recently-used and the Previous buffer will be the same.
E.g. given a window's buffer list, where B is the focused buffer:
-----------------
| A ||B|| C | D |
-----------------
When opening a buffer X, the new positional list will become:
---------------------
| A | B ||X|| C | D |
---------------------
When immediately closing the buffer again (see :BsDelete and :BsBury below)
the resulting list will be the same:
-----------------
| A ||B|| C | D |
-----------------
Similarly, unless other buffers were navigated to in between, the most-recently-used list will be the same, too.
When a new window is opened, its buffer list is inherited from the previously focused window. This affects both positional and most-recently-used lists. After this, each window's list is separate and updated without affecting other windows.
- Commands:
:BsPrevious:BsNext - Normal-mode mapping:
<Plug>(bufstack-previous)<Plug>(bufstack-next)
Move to the Previous/Next buffer in the window's positional buffer list. The currently focused buffer will become the new most-recently-used buffer.
With a count, navigate to the N'th Previous/Next buffer.
If out of range with :BsPrevious, go to the first buffer.
If out of range with :BsNext, extend the list with buffers from arglist (see
:h arglist) that have not been opened yet; if there are none, go to the last
buffer in the list. This allows navigating to each file passed via command line
once with :BsNext.
If the buffer is already the focused one, print an error. Use :silent to
suppress this.
- Command:
:BsAlternate - Normal-mode mapping:
<Plug>(bufstack-alt)
Open the previous most-recently-used buffer in the current window. The currently focused buffer will become the new most-recently-used buffer.
With a count, move to the N'th most-recently-used buffer. If count is larger than the list, move to the least most-recently-used buffer.
The positional list of Previous/Next buffers is unchanged.
If there are no other buffers in the current window's list, print an error. Use
:silent to suppress this.
When using other commands (e.g. :buffer) to open a buffer, and the buffer is
in the window's list, the most-recently-used list is updated as if it had been
opened with :BsPrevious, :BsNext, or :BsAlternate. If the buffer was not
in the window's list, it follows the behavior described in Opening/Closing
buffers.
- Command:
:BsDelete - Normal-mode mapping:
<Plug>(bufstack-delete)
When deleting a buffer, it is removed from all window lists without closing any windows.
Each window currently showing the buffer will move to its most-recently-used buffer; or a new empty buffer, if it was the only buffer.
Contrast this with the native :bdelete, which would would close each window
showing the buffer.
E.g. given a window's buffer list, where B is the focused buffer:
-----------------
| A ||B|| C | D |
-----------------
If C was the most-recently-used buffer, running :BsDelete will result in:
-------------
| A ||C|| D |
-------------
In windows where B was not the current buffer, the buffer is simply removed
from the positional and most-recently-used lists.
- Command:
:BsBury - Normal-mode mapping:
<Plug>(bufstack-bury)
When burying a buffer, it is removed from the current window's buffer list
without affecting other windows. To open the buffer in the current window
again, it has to be opened explicitly, e.g. with :buffer N.
The current window will move to the most-recently-used buffer; or a new empty buffer, if it was the only buffer in the list.
If the buffer is not shown in any other windows, it will become hidden. Enable
'hidden' to allow navigating without saving files.
The effect on the current window's buffer list is the same as :BsDelete, but
other windows will not be affected.
- Command:
:BsOnly - Normal-mode mapping:
<Plug>(bufstack-only)
Removes all buffers except the currently focused from the current window's list. Does not affect other windows.
With a count, keep the N most-recently-used buffers. Sort the positional list the same as most-recently-used list, with the current buffer at the top, the most-recently-used as Previous buffer, and so on.
| behavior | :bwipe | :bdelete | :BsDelete | :BsBury |
|---|---|---|---|---|
| removes from current window | yes | yes | yes | yes |
| removes from other windows' lists | yes | yes | yes | no |
| deletes the buffer | yes | yes | yes | no |
| closes windows showing the buffer | yes | yes | no | no |
wipes the buffer (see :h :bwipe) |
yes | no | no | no |