tags:

views:

222

answers:

4

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?

+4  A: 

Add this to your .vimrc:

function! CloseHiddenBuffers()
  let i = 0
  let n = bufnr('$')
  while i < n
    let i = i + 1
    if bufloaded(i) && bufwinnr(i) < 0
      exe 'bd ' . i
    endif
  endwhile
endfun

Then you can do this to close hidden buffers:

:call CloseHiddenBuffers()

(You'll probably want to bind a key or a command to it.)

Update:

Here's a version updated to support tab pages. (I don't use tab pages myself, so I hadn't realized that bufwinnr only works for windows on the current page).

function! CloseHiddenBuffers()
  " figure out which buffers are visible in any tab
  let visible = {}
  for t in range(1, tabpagenr('$'))
    for b in tabpagebuflist(t)
      let visible[b] = 1
    endfor
  endfor
  " close any buffer that's loaded and not visible
  for b in range(1, bufnr('$'))
    if bufloaded(b) && !has_key(visible, b)
      exe 'bd ' . b
    endif
  endfor
endfun
Laurence Gonsalves
I may have phrased my question incorrectly—I'm trying to clean up the output of `:ls` and this function doesn't seem to do that.
Drew Stephens
Was it the lack of tab-page support, or something else? I've added a version that supports tab-pages, above.
Laurence Gonsalves
This still doesn't work for me.
Drew Stephens
In what way doesn't it work? (Also, what version of vim are you using?)
Laurence Gonsalves
+2  A: 

Here's an alternative solution you can drop in your .vimrc:

function! Wipeout()
  " list of *all* buffer numbers
  let l:buffers = range(1, bufnr('$'))

  " what tab page are we in?
  let l:currentTab = tabpagenr()
  try
    " go through all tab pages
    let l:tab = 0
    while l:tab < tabpagenr('$')
      let l:tab += 1

      " go through all windows
      let l:win = 0
      while l:win < winnr('$')
        let l:win += 1
        " whatever buffer is in this window in this tab, remove it from
        " l:buffers list
        let l:thisbuf = winbufnr(l:win)
        call remove(l:buffers, index(l:buffers, l:thisbuf))
      endwhile
    endwhile

    " if there are any buffers left, delete them
    if len(l:buffers)
      execute 'bwipeout' join(l:buffers)
    endif
  finally
    " go back to our original tab page
    execute 'tabnext' l:currentTab
  endtry
endfunction

Use :call Wipeout().

too much php
A: 

I can confirm that there is still a problem with these scripts.

Wipeout wipe out incorrect buffers and the other one (CloseHiddenBuffers) do not erase any buffer.

I don't see the problem but I'm keep on searching :)

fiofu
+1  A: 

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.

fifou