Skip to main content
Added help links and tried to improve the clarity.
Source Link
B Layer
  • 20.1k
  • 2
  • 32
  • 59

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:

  1. 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 to filter() now...
  2. 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.
  3. {v -> len(v:val['windows'])} : For each buffer-associated Dictionary retrieved from getbufinfo() we now want to keep only those that have at least one value in the windows 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 each windows 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 from getbufinfo() we want to determine how many elements are in the windows 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 function len() 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.

Interesting question. I was wondering how to do this without parsing :ls a since it's not really meant for that. This seems to do the trick, though it's a bit involved...

Per :h active-buffer, active means the buffer is displayed in a window. If that information is easily available anywhere then it's probably from the function that is a one-stop shop for all your buffer info needs: getbufinfo().

Specifically, I have in mind the windows field which is a list of all the windows a buffer currently appears in. If it's in a window then it's active, right?

So this should display the list of buffers appearing in windows/active:

  1. 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 to filter() now...
  2. 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.
  3. {v -> len(v:val['windows'])} : For each buffer-associated Dictionary retrieved from getbufinfo() we now want to keep only those that have at least one value in the windows 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 each windows list. Those that have zero length get pruned from the list.

Here's an example of its use. You can replace the echo call with whatever work you want to do on 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.

Interesting question. I had to think about how to do this as I wanted to avoid using :ls a. (Parsing :ls output isn't ideal in much the same way that parsing the output of the shell command ls is non-ideal.) I've got it down to a single Ex command line, though one that could use a bit of explanation depending on your familiarity with Vim.

Per :h active-buffer, an active buffer is one that is currently being displayed in a Vim window. I figured that if that is an easily obtainable piece of information then it's likely that it would be provided by the function that is a one-stop shop for all your buffer info needs: getbufinfo().

Specifically, I have in mind the windows property that is included in getbufinfo() output. This property contains a list of all the windows the associated buffer currently appears in. If it's in a window then it's active, right?

Cutting to the chase here's the command that displays the buffers appearing in windows, i.e. the active buffers:

  • 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 from getbufinfo() we want to determine how many elements are in the windows 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 function len() 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 use of the command. You can replace the echo call with whatever work you want to do against 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.

Source Link
B Layer
  • 20.1k
  • 2
  • 32
  • 59

Interesting question. I was wondering how to do this without parsing :ls a since it's not really meant for that. This seems to do the trick, though it's a bit involved...

Per :h active-buffer, active means the buffer is displayed in a window. If that information is easily available anywhere then it's probably from the function that is a one-stop shop for all your buffer info needs: getbufinfo().

Specifically, I have in mind the windows field which is a list of all the windows a buffer currently appears in. If it's in a window then it's active, right?

So this should display the list of buffers appearing in windows/active:

:echo filter(getbufinfo({'bufloaded':1}), {v -> len(v:val['windows'])})

Breaking it down:

  1. 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 to filter() now...
  2. 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.
  3. {v -> len(v:val['windows'])} : For each buffer-associated Dictionary retrieved from getbufinfo() we now want to keep only those that have at least one value in the windows 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 each windows list. Those that have zero length get pruned from the list.

Here's an example of its use. You can replace the echo call with whatever work you want to do on 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.

for buf in filter(getbufinfo({'bufloaded':1}), {v -> len(v:val['windows'])})
    echo buf.bufnr buf.name
endfor