tabLocalBuffer.nvim keeps a per-tab set of buffers so that bnext / bprevious-style navigation cycles only within that tab.
akasataikisiti/tabLocalBuffer.nvim
require("tablocal_buffer").setting(opts) as the official configuration entry pointkeymaps are registered:TabLocalMoveToNewTab:TabLocalDetachBuffer / :TabLocalWriteDetachBuffer / :TabLocalDeleteBufferbufferline.nvim for global order calculation and sorting when availableNeovim's :bnext / :bprevious navigate through a single global buffer list. When working across multiple tabs — each focused on a different context — you end up cycling through unrelated files. tabLocalBuffer.nvim gives each tab its own buffer list so navigation stays scoped to what's relevant.
lazy.nvim:
{
"akasataikisiti/tabLocalBuffer.nvim",
config = function()
require("tablocal_buffer").setting()
end,
}
require("tablocal_buffer").setting({
keymaps = {
bnext = "<S-l>",
bprevious = "<S-h>",
move_to_new_tab = "st",
open_editor = "<M-a>",
},
replace_builtin_bnext = false,
bufferline = {
enabled = true,
auto_sort_on_apply = true,
},
editor = {
keymaps = {
save_and_close = "s",
add_empty_group = "<C-j>",
delete_group = "<C-d>",
dedup_groups = "<C-l>",
},
},
cycle = {
include_terminal = true,
require_buflisted = true,
exclude = {
unnamed = false,
filetypes = { "fugitive", "neo-tree" },
buftypes = { "help", "quickfix", "prompt", "nofile" },
name_patterns = { "^fugitive://" },
predicates = {},
},
},
})
setup(opts) is an alias of setting(opts).
Normal [No Name] buffers are included in the cycle by default. To exclude them, set cycle.exclude.unnamed = true.
commands.enabled — Whether to define user commands. Default: true.replace_builtin_bnext — Whether to replace :bnext / :bprevious with :TabLocalBnext / :TabLocalBprevious. Default: false.editor.width_ratio — Width of the editor UI as a ratio of vim.o.columns. Default: 0.6.editor.height_ratio — Height of the editor UI as a ratio of vim.o.lines. Default: 0.6.editor.border — Border style for the editor UI floating window. Default: "rounded".cycle.include_terminal — Whether to include buftype == "terminal" in the cycle. Default: true.cycle.require_buflisted — Whether to include only buflisted buffers. Default: true.cycle.exclude.unnamed — Whether to exclude [No Name] buffers. Default: false.cycle.exclude.filetypes — List of filetype values to exclude. Default: { "fugitive" }.cycle.exclude.buftypes — List of buftype values to exclude. Default: {}.cycle.exclude.name_patterns — Lua patterns matched against buffer names for exclusion. Default: { "^fugitive://" }.cycle.exclude.predicates — List of function(ctx) predicates. A buffer is excluded when any returns true. Default: {}.ctx fields: bufnr, buflisted, buftype, filetype, bufname, modified.
:TabLocalEditTabBuffers opens a floating buffer in a Lua table format. Closing with q discards changes. Closing with s (or any method other than q, such as :close) applies the contents.
Each element of groups corresponds to one tab's buffer list. unassigned holds buffers that do not belong to any tab and are excluded from bnext / bprevious cycling. Moving a label into groups assigns it to that tab.
return {
groups = {
{ "init.lua", "README.md" },
{ "main.ts", "test.ts" },
},
unassigned = {
"scratch.txt:18",
},
}
The behavior of :q / :wq / :bd is unchanged. Use these commands to detach only the current buffer from its tab assignment:
:TabLocalDetachBuffer — Remove from the current tab's list, leave unassigned.:TabLocalWriteDetachBuffer — Run :write, then remove from the current tab's list.:TabLocalDeleteBuffer — Remove from the current tab's list, then delete the buffer.:TabLocalBnext:TabLocalBprevious:TabLocalEditTabBuffers:TabLocalBufferlineSort:TabLocalMoveToNewTab:TabLocalDetachBuffer:TabLocalWriteDetachBuffer:TabLocalDeleteBuffer:TabLocalDebugStateNo keymaps are registered by default. Specify them via the keymaps option.
keymaps.bnext — Next tab-local buffer.keymaps.bprevious — Previous tab-local buffer.keymaps.move_to_new_tab — Move current buffer to a new tab.keymaps.open_editor — Open the editor UI.editor.keymaps.save_and_close — Apply the editor UI contents and close it. Default: "s". Set to "" to disable. q is reserved for closing without saving.editor.keymaps.add_empty_group — Insert an empty group after the cursor's group in the editor UI. Default: "<C-j>". Set to "" to disable.editor.keymaps.delete_group — Delete the group at the cursor in the editor UI. Default: "<C-d>". Set to "" to disable.editor.keymaps.dedup_groups — Remove duplicate buffer entries across groups, keeping each buffer only in the first group it appears in. Empty groups resulting from deduplication are removed. Default: "<C-l>". Set to "" to disable. Note: <C-l> overrides Neovim's built-in nohlsearch|diffupdate action inside the editor.When bufferline.nvim is installed, tabLocalBuffer.nvim can use its global buffer order for sorting.
bufferline.enabled — Enable bufferline.nvim integration. Default: true.bufferline.auto_sort_on_apply — Automatically sort after applying the editor UI. Default: true.Use :TabLocalBufferlineSort to trigger sorting manually.
Combine name_formatter with tablocal_buffer.get_buf_tabnr() to display the tab number for each buffer in bufferline (e.g. #1 init.lua).
bufferline.setup({
options = {
name_formatter = function(buf)
local ok, tablocal = pcall(require, "tablocal_buffer")
if not ok then return buf.name end
local tnr = tablocal.get_buf_tabnr(buf.bufnr)
if tnr then
return string.format("#%d %s", tnr, buf.name)
end
return buf.name
end,
},
})
MIT License. See LICENSE.