15

How can I iterate over the current open buffers and say, load the buffer numbers into an array in vimscript?

I know there exists arrays or similar data structures in vimscript.
I know that every buffer gets assigned a unique number.
My goal is to put each of those numbers into an array of the same length as the number of buffers i.e for i in number of open buffers: array[i] = #buffer
I would like to let array be a variable in my vimscript file.

4
  • 1
    Have you tried something so far? Have you read the doc (:h :ls, :h buffer-list, :h :bnext, :h buffers)? What are you trying to actually do? I think you question would benefit from a bit more of details.
    – statox
    Commented Dec 2, 2016 at 10:37
  • @statox iterating with :bnext is an extremely cumbersome solution -- see my answer. Otherwise, indeed, as usual with vim one has to read the doc as (almost) everything in present in it. However in this case, several elements are to be combined. We need to be familiar with a dozen entries from :h functions and with :h List. Commented Dec 2, 2016 at 11:03
  • @statox I don't know vimscript and I was hoping for a quick answer. I don't know how it could be more clear what I was trying to do. Did you downvote my question because it wasn't clear enough? I will edit it for you.
    – lsund
    Commented Dec 2, 2016 at 11:03
  • 3
    @LucHermitte I agree that the :bnext isn't the way to go and that the solution is not exactly straight forward. I was just pointing out that it is often a good idea to show a minimum of research in a question: this way answerers feel like they're helping and not only doing some work because OP was to lazy to do it. @lsund: I did not downvoted you (I tend to avoid downvoting new users's questions without a very good reason) I was just inviting you to provide more details about what you already researched :-)
    – statox
    Commented Dec 2, 2016 at 11:09

2 Answers 2

23

You can iterate over buffers if you use :bnext and all. I highly advice against this method. It'll trigger autocommands, and you'll have to remember where you were. In other words, it can be damn slow, and with plenty side effects. Stay away if you can.

Until now my preferred approach was to use filter() on range(1, bufnr('$')) to keep the buffers I'm interested in (bufloaded(), bufexists() or buflisted()). Which gives:

:let buffers = filter(range(1, bufnr('$')), 'bufexists(v:val)')

We can even go further and use other ways to filter the buffer list: according to their name, or buffer-variables (.e.g getbufvar(v:val, 'foo', sentinelvalue) =~ "regex for b:foo")).

As you see, there are plenty options. The entry points are filter() and functions with buf in their name -> :h *buf*()^D (^D as in hit ctrl+D to see the list of functions)

Note also that recent versions of vim provide a new getbufinfo() function that'll return a list dictionaries: each dictionary is filled with plenty information for each existing buffer. Another way to obtain existing buffers is with:

:let buffers = map(copy(getbufinfo()), 'v:val.bufnr')

Or listed buffers with

:let buffers = map(filter(copy(getbufinfo()), 'v:val.listed'), 'v:val.bufnr')
6
  • I guess that E117: Unknown function: getbufinfo means my vim doesn't have this, correct?
    – qneill
    Commented Mar 8, 2018 at 20:35
  • 1
    @qneill. Indeed, you'll have to revert to older functions, or to upgrade your version of vim. Commented Mar 9, 2018 at 0:04
  • I see some weird behavior, these maps/filters don't give same results. The last one in your description seems accurate, it returns the buffers I as a user am aware of, and matches result of command :buffers, and able to open with :b <number> to find some information in. Rest all the commands give varying degrees of extra buffer numbers.
    – codepoet
    Commented Jan 27, 2021 at 3:56
  • @reportaman The buffers can be in various states whether they are displayed, unloaded, wiped out, and so on. Some commands already filter out the useless ones. Commented Jan 27, 2021 at 10:24
  • Not sure if it was implemented from start (i.e. when answr was written), but getbufinfo also accept a filter e.g: getbufinfo({'buflisted': 1}) - so map(getbufinfo({'buflisted': 1}), 'v:val.bufnr') - as in no need for filter() Commented Oct 2, 2021 at 4:09
7

On neovim additionally to getbufinfo() one can also use

let buffers = nvim_list_bufs()

nvim_list_bufs

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.