Skip to content

[idea] Smart buffer close command that preserves window layout #141

@stanfish06

Description

@stanfish06

What

A :Bdelete user command (and optional keymap) that deletes the current buffer without closing its window — switching to an alternate buffer instead.

Where

lua/config/options.lua — alongside the existing buffer navigation keymaps (H/L at lines 27–28, bn at line 23).

Why it matters

The native :bd (:bdelete) closes the window when the buffer being deleted is the last one in that window. This destroys carefully arranged splits — for example, closing one buffer in a two-pane diff view collapses the entire layout. With H/L for buffer cycling, :bn for new buffers, and a , terminal split already in the config, the missing ergonomic link is a way to remove a buffer without nuking the window.

This is especially relevant because:

  • The config uses switchbuf = "usetab" which encourages reusing windows.
  • The :Compile + quickfix workflow often opens a buffer in a split; when done, you want to close the buffer but keep the split for the next compile output.

Suggested implementation

-- lua/config/options.lua
local function smart_bdelete()
    local cur = vim.api.nvim_get_current_buf()
    -- find a different valid normal buffer to switch to
    local bufs = vim.tbl_filter(function(b)
        return b ~= cur
            and vim.api.nvim_buf_is_valid(b)
            and vim.bo[b].buflisted
    end, vim.api.nvim_list_bufs())

    if #bufs > 0 then
        -- prefer the alternate buffer (#) if it exists and is in the list
        local alt = vim.fn.bufnr("#")
        local target = (alt > 0 and vim.tbl_contains(bufs, alt)) and alt or bufs[#bufs]
        vim.api.nvim_win_set_buf(0, target)
    else
        -- no other buffer — open a new empty one so the window survives
        vim.cmd("enew")
    end
    pcall(vim.api.nvim_buf_delete, cur, { force = false })
end

vim.api.nvim_create_user_command("Bdelete", smart_bdelete, { desc = "Delete buffer without closing window" })
vim.keymap.set("n", "<leader>bd", smart_bdelete, { desc = "Buffer delete (keep window)" })

The force = false means unsaved changes still prompt — intentionally conservative.

Notes

  • Falls back to :enew (already used at <leader>bn) if no other buffer exists, so the window is never destroyed.
  • Prefers the alternate buffer (#) for a natural Ctrl-^-like undo feeling.
  • <leader>bd fits the existing <leader>b* namespace (bn = new buffer).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions