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.

  • 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 Dec 2 '16 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. – Luc Hermitte Dec 2 '16 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 Dec 2 '16 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 Dec 2 '16 at 11:09

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')
| improve this answer | |
  • I guess that E117: Unknown function: getbufinfo means my vim doesn't have this, correct? – qneill Mar 8 '18 at 20:35
  • 1
    @qneill. Indeed, you'll have to revert to older functions, or to upgrade your version of vim. – Luc Hermitte Mar 9 '18 at 0:04

On neovim additionally to getbufinfo() one can also use

let buffers = nvim_list_bufs()


| improve this answer | |

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.