How do I close all buffers that aren't shown in a window in vim?

Viewed 9038

I have a horde of buffers open in vim, with only a few of them open in split windows or on other tabs. Is there a way to close all but the ones that are currently visible in one of those splits or tabs?

6 Answers

I know why the second script doesn't work properly.

This is due to the bufloaded() function which must be bufexits() !

Indeed, a buffer to delete is not loaded ! Just remove this condition is okay but it is doing some warning when we are trying to wipe out a buffer not used so we have to use bufexists(b).

The final solution is the following:

function! CloseHiddenBuffers()
    " Tableau pour memoriser la visibilite des buffers                                                                                      
    let visible = {}
    " Pour chaque onglet...
    for t in range(1, tabpagenr('$'))
        " Et pour chacune de ses fenetres...
        for b in tabpagebuflist(t)
            " On indique que le buffer est visible.
            let visible[b] = 1
        endfor
    endfor
    " Pour chaque numero de buffer possible...
    for b in range(1, bufnr('$'))
        " Si b est un numero de buffer valide et qu'il n'est pas visible, on le
        " supprime.
        if bufexists(b) && !has_key(visible, b)
            " On ferme donc tous les buffers qui ne valent pas 1 dans le tableau et qui
            " sont pourtant charges en memoire.
            execute 'bwipeout' b
        endif
    endfor
endfun

Thanks to you.

There's a plugin that does exactly this and a bit more!

Check out close-buffers.vim

If you're using fzf, here's a way to select buffers to delete:

" fzf delete buffers
function! s:list_buffers()
  redir => list
  silent ls
  redir END
  return split(list, "\n")
endfunction
function! s:delete_buffers(lines)
  execute 'bwipeout' join(map(a:lines, {_, line -> split(line)[0]}))
endfunction
command! BD call fzf#run(fzf#wrap({
  \ 'source': s:list_buffers(),
  \ 'sink*': { lines -> s:delete_buffers(lines) },
  \ 'options': '--multi --reverse --bind ctrl-a:select-all+accept'
  \ }))
Related