Interesting question. I was wonderinghad to think about how to do this without parsingas I wanted to avoid using :ls a
since it's not really meant for. (Parsing :ls
output isn't ideal in much the same way that parsing the output of the shell command ls
is non-ideal. This seems) I've got it down to do the tricka single Ex command line, though it'sone that could use a bit involved..of explanation depending on your familiarity with Vim.
Per :h active-buffer
:h active-buffer
, an active means the buffer is one that is currently being displayed in a Vim window. IfI figured that informationif that is an easily available anywhereobtainable piece of information then it's probably fromlikely that it would be provided by the function that is a one-stop shop for all your buffer info needs: getbufinfo()
getbufinfo()
.
Specifically, I have in mind the windows
field whichproperty that is included in getbufinfo()
output. This property contains a list of all the windows athe associated buffer currently appears in. If it's in a window then it's active, right?
So this should displayCutting to the list ofchase here's the command that displays the buffers appearing in windows/active, i.e. the active buffers:
filter(list_or_dict, expr_or_func)
:filter()
takes a List or Dictionary and removes some subset of entries based on some condition. The condition is defined in the second param as either an expression or the result of a function call that is passed elements from the List/Dictionary. Looking at both params tofilter()
now...getbufinfo({'bufloaded':1})
: As mentioned above the big buffer info source. The Dictionary param is telling it to only return buffers that are loaded...active buffers are always loaded. The result is a List of Dictionary objects, one for each loaded buffer.{v -> len(v:val['windows'])}
: For each buffer-associated Dictionary retrieved fromgetbufinfo()
we now want to keep only those that have at least one value in thewindows
attribute (which is itself a List). IOW, buffers that appear in at least one window. It's probably beyond the scope of this answer to describe how exactly it works but this is a lambda type of function call and we're checking for non-zero when checking the length of eachwindows
list. Those that have zero length get pruned from the list.
filter(list_or_dict, condition)
: takes a List or Dictionary and removes some subset of elements from it based on a condition. The condition is specified in the second param as an expression or function which is evaluated for each element. A non-zero result means the element is kept, otherwise it is dropped (filtered out). As for the specific parameters being used...getbufinfo({'bufloaded':1})
: As mentioned above this function provides a bunch of info about a buffer or buffers. The Dictionary we're passing in as a param is telling the function to only return buffers that are loaded. By definition an active buffer is a loaded buffer so this allows us to narrow things down a bit. The returned value is a List of Dictionary objects, one for each loaded buffer.{v -> len(v:val['windows'])}
: For each buffer-associated Dictionary retrieved fromgetbufinfo()
we want to determine how many elements are in thewindows
property (which is itself a List) and drop buffers with none. We need to evaluate to zero for those elements we want dropped and this works out nicely as we just make a call to the length functionlen()
and return whatever it returns.
If you're not familiar with the ->
notation it's basically just a shorthand way of calling a function, in this case one that takes a single parameter. Explaining this "lambda expression" further is probably beyond the scope of this answer but I think it's otherwise pretty clear what's going on here.
Here's an example of its use of the command. You can replace the echo
call with whatever work you want to do onagainst each buffer. The buffer number is available so you can address each buffer by that (among other possibilities). If you want me to get into that a bit further let me know.