2

Very often, after days and days of coding, opening vim -S session everytime, I end up with a fair long buffer list that I want to clean.

Therefore I use :ls to list all buffers, and then :bdelete several times, with a range of buffer numbers and or explicitly specifying buffer names.

The weak points in this approach are two:

  1. if I run :bdelete on a single buffer, the lines N buffers deleted and Press ENTER or type command to continue do not appear, and the buffer list closes, so I have to run :ls again, which is very annoying;
  2. I have to run :bdelete several times, which is less a pain but still annoying.

If there's a cleaner way to list non-contiguous buffer names to :bdelete, that would be great, as it would solve 1 and 2; if not, then a way to prevent the closure of the output of :ls would be good enough, as it'd solve 2.

Important edit

I don't want to delete any buffer which is opened on a window in any tab.

4

For my config I wrote this:

~/.vim/autoload/misc.vim

" Wipe all deleted (unloaded & unlisted) or all unloaded buffers
function! misc#bwipeout(listed) abort
    let l:buffers = filter(getbufinfo(), {_, v -> !v.loaded && (!v.listed || a:listed)})
    if !empty(l:buffers)
        execute 'bwipeout' join(map(l:buffers, {_, v -> v.bufnr}))
    endif
endfunction

~/.vim/vimrc

" :Bwipeout[!]
" wipe all deleted/unloaded buffers
command! -bar -bang Bwipeout call misc#bwipeout(<bang>0)

Now do :Bwipeout! to clean the whole mess.

Note: :bwipeout differs from :bdelete in that it actually deletes the buffer, while :bdelete keeps name/number/local bookmarks for later re-use. You can see all "deleted" buffers by the command :ls!.

If you still want to make use of :bdelete you can adapt the code easily:

function s:bdelete() abort
    let l:buffers = filter(getbufinfo(), {_, v -> !v.loaded && v.listed})
    if !empty(l:buffers)
        execute 'bdelete' join(map(l:buffers, {_, v -> v.bufnr}))
    endif
endfunction
command! -bar Bdelete call s:bdelete()
| improve this answer | |
  • :bwipeout's doc says Don't use this unless you know what you are doing. Any comments on this, with respect to your solution? – Enrico Sep 2 at 12:31
  • @EnricoMariaDeAngelis If you wonder what's a (minor) difference between :bdelete and :bwipeout you should read both :h :bd and :h :bw and compare. Personally I like :bw more and use it instead of :bd on those rare occasions I have to use one of them. – Matt Sep 2 at 13:08
  • 1
    @EnricoMariaDeAngelis You might be interested in this q&a about :bwipeout – Rich Sep 2 at 14:33
3

For my config I wrote this:

" kill-all but visible buffers
nnoremap <silent> <M-BS> :call Delete_buffers()<CR>:echo "Non-windowed buffers are deleted"<CR>

"" Delete all(saved) but visible buffers
func! Delete_buffers()
    " all visible buffers in all tabs
    let buflist = []
    for i in range(tabpagenr('$'))
        call extend(buflist, tabpagebuflist(i + 1))
    endfor

    " all existing buffers
    for bnr in range(1, bufnr("$"))
        if index(buflist, bnr) == -1 && buflisted(bnr)
            exe 'bd ' . bnr
        endif
    endfor
endfunc

Then with Alt+Backspace all but buffers currently visible in split windows are deleted.

Very handy to save/update session without bunch of unneeded buffers.

PS, updated to not delete buffers in other tabs.

PPS, thx @matt, better version:

func! Delete_buffers()
    let l:buffers = filter(getbufinfo(), {_, v -> v.hidden})
    if !empty(l:buffers)
        execute 'bwipeout' join(map(l:buffers, {_, v -> v.bufnr}))
    endif
endfunc

| improve this answer | |
  • let l:buffers = filter(getbufinfo(), {_, v -> v.hidden}) will eventually fail for modified hidden buffers. – Matt Sep 2 at 13:31
  • 1
    @Matt, yes I know. I have set confirm and get confirmation requests to save those buffers. – Maxim Kim Sep 2 at 13:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.