148

Vim's multilayered views (Windows, Buffers and Tabs) left me a little confused. Let's say I split the display (:sp) and then select a different buffer to display in each window. Now I want to close one of the buffers, yet I don't want the window to close (After the closing it can display the next buffer on the list or an empty buffer, it doesn't matter). How can I do this?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Mosh
  • 2,458
  • 3
  • 18
  • 19
  • Is there a reason you want to *close* the buffer rather than just not see it there anymore? – rampion Sep 18 '09 at 15:11
  • 12
    I've actually been wondering about this as well. Deleting a buffer and having to subsequently rebuild whatever part of my splits were destroyed in the process is annoying. – brettkelly Sep 18 '09 at 17:09
  • 4
    29 up votes so far. I think this is a pretty common use case. I need this when I am working with a lot of buffers. Sometimes I am using 2 windows and want to close a buffer. I don't want that window to go away. I just want the next buffer to be displayed there. – Wilson Freitas Jan 16 '14 at 20:09
  • possible duplicate of [Vim: Delete buffer without losing the split window](http://stackoverflow.com/questions/4465095/vim-delete-buffer-without-losing-the-split-window) – George Hilliard May 27 '15 at 18:45
  • 1
    [This one `DeleteCurBufferNotCloseWindow()` works well and is quite readable](https://stackoverflow.com/a/44950143/3625404). (Disclaimer: my answer) – qeatzy Jul 06 '17 at 13:33

17 Answers17

174

I messed with this a bit and finally came up with:

:bp | sp | bn | bd

Here's the copy/paste version for key mapping:

:bp<bar>sp<bar>bn<bar>bd<CR>

I've tested it a fair bit and it works consistently in various conditions. When used on the last buffer it will leave you with a new blank buffer.

Throw this in your .vimrc:

map <leader>q :bp<bar>sp<bar>bn<bar>bd<CR>

Restart Vim, or just :source ~/.vimrc for changes to take effect. Next time you want to close a buffer just type: \q (if \ is your leader key)

user3.1415927
  • 367
  • 3
  • 19
Jonah Braun
  • 4,155
  • 7
  • 29
  • 31
  • This is awesome! You can hide annoying error messages with `silent! bp | sp | silent! bn | bd` – ivan Jan 17 '14 at 03:05
  • 16
    For the beginner, throw this in your *.vimrc*: `map q :bpspbnbd`. Restart VIM, next time you want to close a buffer just type: `\q` – EasyCo Sep 08 '14 at 01:03
  • 7
    This will have unexpected outcome if you had a vertically splitted window. In fact, any window splitting configuration other than the standard (created by `sp`). – hitzg Jun 29 '15 at 13:26
  • Yes.. as @hitzg says one gets a crazy creation of windows. I don't completely understand what it's doing, but since it includes `sp` I assume it's because it closes a `vsp` window and opens an `sp` one. – OJFord Jul 13 '15 at 21:08
  • It worked fine for my usual single vertical split setup, but not for anything more complicated. – labyrinth Sep 01 '16 at 19:28
  • 2
    I think the snippet of what to put in .vimrc should not include the period at the end. Other than that, awesome! This should be the accepted answer. – Ernesto Mar 22 '17 at 13:08
  • 3
    this is elegant. as other people have said, if you mostly use vertical splits, switch `sp` with `vsp`. my .vimrc entry looks like this: `cnoremap bd bpvspbnbd` – Connor Dec 17 '18 at 16:08
  • Sometimes I have to use `:bpspbnbd!`. `!` is necessary. – WW00WW Jan 07 '20 at 03:13
57

I searched for this today and came up with

:b#|bd#

which changes the current window to the previously open buffer and deletes/hides the buffer you just switched away from.

This requires at least two known buffers.

If another window but the current shows the same buffer this will still destroy splitting. You can change all windows to the previously open buffer with

:windo b#

I added more detail about the former command discussing a mapping for it (and some pitfalls) in an answer to a similar question.

Community
  • 1
  • 1
valid
  • 1,858
  • 1
  • 18
  • 28
  • Also this can be done... `:#b|#bd` Just interchanging the buffer command & buffer number in the above. – Ashish Jul 30 '15 at 12:35
  • I've used this a bit but I kept getting annoyed that it re-opened a previously closed buffter. – pean Aug 21 '18 at 05:16
  • @pean That's what I mentioned in the linked answer - see "Important notes". Yeah, would be nicer if this switched to another open buffer. – valid Aug 21 '18 at 08:46
  • 7
    You can also do `:bn|bd#` or `:bp|bd#` to instead switch to the previous or next open buffer, respectively, rather than than the buffer you most recently accessed (b#). – pavon Mar 25 '20 at 23:58
35

There's a script on the Vim wiki to do this. I don't think there is a builtin that does what you want.

The latest version of vim-bufkill is on github.

Sardathrion - against SE abuse
  • 17,269
  • 27
  • 101
  • 156
Brian Carper
  • 71,150
  • 28
  • 166
  • 168
  • 5
    Great answer, it led me to the final version of the script on: http://www.vim.org/scripts/script.php?script_id=1147 – Mosh Sep 18 '09 at 20:07
  • 1
    I used [bufkill](https://github.com/qpkorr/vim-bufkill) for years but found its autocmds to maintain a buffer list often threw errors. I evaluated some other plugins that accomplish a similar goal. I preferred the simplicity of [vim-bbye](https://github.com/moll/vim-bbye). The other alternative was [vim-sayonara](https://github.com/mhinz/vim-sayonara) which tries to replace all buffer/window closing commands and Do The Right Thing, but I prefer more manual control. – idbrii Apr 12 '21 at 17:42
15
nmap <leader>d :bprevious<CR>:bdelete #<CR>

Works as it should until one buffer is open in several windows. Good enough unless you want to use the bigger scripts out there.

Edit: this is what i use right now:

function! BufferDelete()
    if &modified
        echohl ErrorMsg
        echomsg "No write since last change. Not closing buffer."
        echohl NONE
    else
        let s:total_nr_buffers = len(filter(range(1, bufnr('$')), 'buflisted(v:val)'))

        if s:total_nr_buffers == 1
            bdelete
            echo "Buffer deleted. Created new buffer."
        else
            bprevious
            bdelete #
            echo "Buffer deleted."
        endif
    endif
endfunction
ggustafsson
  • 603
  • 7
  • 13
  • 2
    I tried this way but it didn't work very well while using multiple split windows. Here is my solution if someone is having the same problem: `nmap d :ene:bd #` – caio Sep 05 '12 at 18:41
7

I think this is what you're looking for

http://www.vim.org/htmldoc/windows.html#window-moving

Try this:

Look ar your buffer id using

:buffers

you will see list of buffers there like

1  a.cpp
2  b.py
3  c.php

if you want to remove b.py from buffer

:2bw

if you want to remove/close all from buffers

:1,3bw
Nope
  • 34,682
  • 42
  • 94
  • 119
  • 1
    I don't want to move the window. I want to close the buffer without touching the window's position, size or existance. – Mosh Sep 18 '09 at 14:21
5

For those who use NERDTree.

I fix this using this plugin https://github.com/jistr/vim-nerdtree-tabs and now I can close the only buff/file/tab without closing the window.

After having the plugin above installed put the following code on my .vimrc:

let g:nerdtree_tabs_autoclose=0

The description for the variable above is: Close current tab if there is only one window in it and it's NERDTree (default 1)

More info here: https://github.com/jistr/vim-nerdtree-tabs#configuration

Lucas Serafim
  • 3,702
  • 6
  • 30
  • 36
4

A simple version I use personally is

:bp|bd#

It goes to the previous buffer and deletes the other buffer (which is actually the original where we jumped from). This does what you would expect in 99% of cases without any complicated scripts.

As a keyboard shortcut I use the following

nnoremap <silent> <Leader>c :bp<BAR>bd#<CR>
Dorian B.
  • 1,101
  • 13
  • 22
3

I don't think there is a one shot way to do this, but you could do :enew or :ls to list your buffers and swap to a different one using :b [number].

Once you've got a different buffer in the window :bd # will delete the previous buffer in the window, and since the current buffer still exists the window won't be closed.

Andrew Khosravian
  • 1,069
  • 6
  • 13
3

Here is a very readable vimscript function, which handles all cases well,

  • behave similar to built-in:bd (if only one window, just invoke it!),
    • issue a warning and do nothing if buffer modifed.
    • if no other buffer, create one, via :enew.
    • if alternate buffer exist and in buffer-list, switch to it, else go next, via:bn.
  • more reasonable behavior for multiple-window layout
    • not closing any window,
    • always stay on the original window.
    • for each window that displays current buffer, do as listed above, then delete old current buffer.
nnoremap <Leader>b :call DeleteCurBufferNotCloseWindow()<CR>

func! DeleteCurBufferNotCloseWindow() abort
    if &modified
        echohl ErrorMsg
        echom "E89: no write since last change"
        echohl None
    elseif winnr('$') == 1
        bd
    else  " multiple window
        let oldbuf = bufnr('%')
        let oldwin = winnr()
        while 1   " all windows that display oldbuf will remain open
            if buflisted(bufnr('#'))
                b#
            else
                bn
                let curbuf = bufnr('%')
                if curbuf == oldbuf
                    enew    " oldbuf is the only buffer, create one
                endif
            endif
            let win = bufwinnr(oldbuf)
            if win == -1
                break
            else        " there are other window that display oldbuf
                exec win 'wincmd w'
            endif
        endwhile
        " delete oldbuf and restore window to oldwin
        exec oldbuf 'bd'
        exec oldwin 'wincmd w'
    endif
endfunc
qeatzy
  • 1,363
  • 14
  • 21
2

I used to use :

:bp<bar>sp<bar>bn<bar>bd<CR>

But I found certain occasions where it closed my window.

Recently I noticed that I always use this when I am working on a project and need to quickly open my .tmux.conf .zshrc before going back to work.

For this usage, I find better to :

  • switch back to the buffer I was previously working on with C-6
  • type :bd# to delete the previous buffer (I have mapped it like this : nnoremap <leader>d :bd#<CR>)

It allows me to control the buffer I'm going back to and feels more natural.

DaftWooly
  • 348
  • 3
  • 7
2

Simply do :new|bd# or Paste this into your vimrc

let mapleader = " "
" CLOSE current Buffer without closing window
nnoremap <silent><leader>d :new<BAR>bd#<CR>
" CLOSE current window
noremap <leader>x <c-w>c

Then hit (space + d) or (space + x)

EDIT: even better with

nnoremap <silent><leader>d :new<BAR>bd#<BAR>bp<CR>
Doftom
  • 31
  • 4
1

Would

:enew

do what you want? it will edit a new, unnamed buffer in the current window leaving the existing file open in any other windows.

mikej
  • 65,295
  • 17
  • 152
  • 131
  • 2
    This will open a new empty buffer. I want to close the current buffer without closing the window. – Mosh Sep 18 '09 at 14:21
1

My favorite solution for this is the bufkill.vim plugin (GitHub). It provides alternate versions of the various :b-prefix commands that work the same as their counterparts, but leave the window open. They display whatever the last visible buffer contained, or an empty/new buffer if there was no prior buffer.

From the documentation:

When you want to unload/delete/wipe a buffer, use:
  :bun/:bd/:bw to close the window as well (vim command), or
  :BUN/:BD/:BW to leave the window(s) intact (this script).
Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
1

To 'close' a view, use :hid[e]. Works if you have managed to split the viewport or opened multiple files. You can't hide the last buffer on display.

1 Further tip that helped me: use :e ./path/to/file.work to open a file in viewport without splitting the window.

P.S. At two days into vim I still have trouble finding the precise help commands. Hopefully this will help someone else keep working until they really get time to understand vim.

Sennekuyl
  • 31
  • 2
1

If you're like me and you came here trying to do the opposite, close the window without closing the buffer, you can do that via:

:close

xdhmoore
  • 8,935
  • 11
  • 47
  • 90
1

I like this answer most, although I prefer

<CTRL-^>:bd#

because it is faster to type and I don't need a keymapping.

The command <CTRL-^> (same as on English keyboard) switches to the alternate file and :bd# deletes the other buffer.

d2weber
  • 163
  • 1
  • 5
-5

use ":bd" as a command.

Silvanus
  • 145
  • 1
  • 5