19

Using vim editor, a common task is to browse buffers. I now use standard commands like :ls or a :bnext. In fact I set in my .vimrc:

"move amongs buffers with CTRL
map <C-J> :bnext<CR>
map <C-K> :bprev<CR>

I would like to browse buffers as list in quickfix window, in the simple (=excellent) way MRU plugin implements.

Is there a plugin as simple as MRU but acting on buffers ?

OK, a possible solution could be to use :CtrlpBuffers command, part of Ctrlp plugin but I'm not a big fan of Ctrlp, because sometime have strange beahviours I do not fully understand (the fuzzy-mode selections...); so I'm look for something really simple as MRU plugin.

BTW, I joked with :cexpr {expr} command, trying populate the quickfix windows with content of :buffers list, without success (maybe because my ignorance programming vimscripts)

Any suggestion ?

6
  • Did you mean :bnext instead of :cnext?
    – tommcdo
    Feb 23, 2015 at 10:51
  • Do you specifically need it to be the quickfix window? Or do you just want to be able to see the open buffers in a window? (Because there's several plugins to do the latter).
    – Rich
    Feb 23, 2015 at 11:01
  • I want to be able to browse open buffers in a window. Indeed quickfix is not reuired Feb 23, 2015 at 11:31
  • @tommcdo: yes sorry, my usual typos. I mean :bnext and I updated the question Feb 23, 2015 at 11:49

4 Answers 4

25

You can populate the quickfix list with each buffer like this:

:call setqflist(map(filter(range(1, bufnr('$')), 'buflisted(v:val)'), '{"bufnr": v:val}'))
  • setqflist() takes a List of Dictionary items describing each error (filename, line number, position, etc.). In this case we're specifying a minimal set of information: the buffer number
  • map() takes a List and an expression (a string) and returns a new List of the expression applied to each item of the input List. Here, we're taking a List of listed buffer numbers and formatting them for use in setqflist() ('{"bufnr": v:val}', where v:val is the value of the item in the list)
  • filter() filters a List, removing elements that don't satisfy a given expression. Here the expression is buflisted(v:val), meaning the buffer number exists and is listed, i.e. appears in :ls output
  • range(a, b) generates a List of numbers from a to b
  • bufnr() returns the number of a given buffer name. If the argument is '$', it returns the highest buffer number

That's a lot to type, and not very memorable, so you can wrap it in a command in your vimrc:

command! Qbuffers call setqflist(map(filter(range(1, bufnr('$')), 'buflisted(v:val)'), '{"bufnr":v:val}'))

Now you can just use :Qbuffers to populate the quickfix list.


If you want this to be updated automatically as new buffers are added, you can do something like this:

autocmd BufAdd * Qbuffers

I wouldn't recommend this, however, as it will render the quickfix list pretty unusable for things like :make or :grep.

1
  • 1
    thanks for explanations, tommcdo. Qbuffers is beautiful! Maybe i'd add a :copen at last of your call to immediately open the quickfix window and maybe it could be useful to report cursor position. I have to study a bit of vimscript :-) Feb 23, 2015 at 11:46
10

You should try this mapping:

nnoremap gb :ls<CR>:b<Space>

At the prompt, type the desired buffer number and hit Enter.

gb

3
  • the qustion where about listing buffers in the quickfind window.
    – VeXii
    Jan 7, 2016 at 11:38
  • Yes, and my answer provides a lightweight alternative.
    – romainl
    Jan 7, 2016 at 13:15
  • 2
    OP states he knows about the bufferlist but like to have it in the quickfix window. and you're solution is just to use the bufferlist?
    – VeXii
    Jan 7, 2016 at 20:21
1

Have a look at the bufexplorer plugin. It opens a browsable list of all buffers in a sidebar, similar to the mentioned MRU plugin. Also, there are several more such plugins on vim.org.

PS: You've asked the same question on Stack Overflow; please don't submit the identical question to multiple sites in parallel!

2
  • tks Ingo, I tested a bit bufexplorer and I like it. I posted also here because a stackoverflow suggested to do Feb 23, 2015 at 11:33
  • 1
    Yes, I saw that. I would have preferred you had then deleted the original SO post, or at least linked to the cross-posting. Feb 23, 2015 at 12:48
1

If you are using a fairly recent version of Vim, you can use the following script. This script displays only the buffer name in the quickfix window, reuses the same quickfix list for listing the buffers (avoids polluting the quickfix stack with too many quickfix lists), sorts the buffers by their last used timestamp and refreshes the quickfix window only if it is open.

Modified: Updated to handle the strict buffer checking added recently to Vim.

func s:QfBufferName(info)
  let items = getqflist(#{id: a:info.id, items: v:true}).items
  return items->map('bufname(v:val.bufnr)')
endfunc

let s:qfID = 0
let s:qbuflistNeedUpdate = v:false

func s:qbuffer(update) abort
  let s:qbuflistNeedUpdate = v:false
  let bufs = getbufinfo(#{buflisted: v:true})
  let bufs = bufs->sort({a, b -> a.lastused < b.lastused})
  let bufs = bufs->filter('v:val.name != ""')
  let items = map(bufs, '{"bufnr": v:val.bufnr}')

  let s:qfID = getqflist(#{id: s:qfID}).id
  let d = #{items: items, quickfixtextfunc: 's:QfBufferName'}
  if s:qfID != 0
    let d['id'] = s:qfID
  endif
  call setqflist([], 'r', d)
  if !a:update
    copen
  endif
endfunc

command! Qbuffers call s:qbuffer(v:false)
augroup Qbuffer
  au!
  au BufEnter * let s:qbuflistNeedUpdate = v:true
  au SafeState * if s:qbuflistNeedUpdate | call <SID>qbuffer(v:true) | endif
augroup END
3
  • Thx. I inserted the code in my .vimrc. When I run vi file1.txt file2.txt file3.txt and afterward :Qbuffers, visually apperars the quickfix windows listing the files. perfect! But when I select a line and I tener <ENTER>I got E925: Current quickfix list was changed and the file doesn't change in the main window. Apr 9, 2022 at 17:25
  • Due to recent changes to Vim (to handle quickfix content changes from an autocmd), you are seeing this error. I have updated the code to use the SafeState autocmd to update the quickfix list. Apr 9, 2022 at 20:42
  • 1
    I have created a repository for the above script (github.com/yegappan/bufpicker). Apr 9, 2022 at 21:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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