1

Is there a way to view a list of open buffers and close several buffers without leaving that list?

The best I know of for closing multiple buffers is using :ls to get a list of buffers, memorizing the numbers of the buffers you want to close, and then using :bdelete/:bd with a prefix to close those buffers, e.g. :3,5bd. Sometimes I'll have several buffers open and I want to close a buffer (or at least mark a buffer to be closed) while still looking for more buffers to close. With :ls and :bd, this is very inconvenient because I have to enter :ls again and again between closing buffers rather than closing several buffers and then signaling that I'm done.

3

There is a popular mapping that will show the :ls result above a prompt:

:nnoremap <leader>ls :ls<cr>:b<space>

Instead of showing :b, as in that mapping, we'll show :bd instead:

:nnoremap <leader>lsd :ls<cr>:bd<space>

(If you prefer a different mapping than lsd, heh, feel free to change it.)

Append whatever buffer numbers you want to delete, space separated, and hit Enter.

If you'd rather enter ranges of buffer numbers, like :2,5bd this variation will put the cursor at the beginning, before bd:

:nnoremap <leader>lsd :ls<cr>:bd<home>

But you have to pick one or the other or use two mappings. Personally I use the first mapping and hit Home if I want to enter a range.

Bonus Update: Wanted to stretch my vimscript muscles so came up with this...

" Displays buffer list, prompts for buffer numbers and ranges and deletes
" associated buffers. Example input: 2 5,9 12
" Hit Enter alone to exit. 
function! InteractiveBufDelete()
    let l:prompt = "Specify buffers to delete: "

    ls | let bufnums = input(l:prompt)
    while strlen(bufnums)
        echo "\n"
        let buflist = split(bufnums)
        for bufitem in buflist
            if match(bufitem, '^\d\+,\d\+$') >= 0
                exec ':' . bufitem . 'bd'
            elseif match(bufitem, '^\d\+$') >= 0
                exec ':bd ' . bufitem
            else
                echohl ErrorMsg | echo 'Not a number or range: ' . bufitem | echohl None
            endif 
        endfor
        ls | let bufnums = input(l:prompt)
    endwhile 

endfunction

Put in your vimrc file along with a mapping like this...

nnoremap <silent> <leader>bd :call InteractiveBufDelete()<CR>

Now if you hit \bd in Normal mode you'll see the buffer listing and a prompt. Enter space-separated numbers or ranges, such as 2 5,8 11, and hit Enter and all associated buffers will be deleted. The process will repeat until you hit Enter alone.

(I'll leave it to you to add any additional validation or error checking beyond what I have.)

  • Can this close multiple buffers? This doesn't work with the "3,5" style. – Praxeolitic Jan 17 '18 at 7:33
  • As it says space separated. – B Layer Jan 17 '18 at 7:34
  • Oops, so I can give multiple buffers, which is pretty good, but can I give a range? – Praxeolitic Jan 17 '18 at 7:36
  • Hmm, that's unfortunate. This is a good answer so +1, but it doesn't fulfill all my hopes and dreams. I suspect this is the best there is in vim-land at the moment so I'll hold out hope for an answer with deeper enlightenment for a day or so but after that I'll accept this ;-P. – Praxeolitic Jan 17 '18 at 7:43
  • 1
    Thus the last line of my answer, "I'll leave it to you...". It's usually beyond the scope of here to have full blown solutions with validation and what not...decreases the signal-to-noise ratio too much. – B Layer Jan 21 '18 at 9:44

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.