The function below is written in Lua and returns the list of buffers from the current neovim session, it also allows the option to specify a optional table (object) as a parameter, with a listed property to filter the type of buffer returned by the function (only listed buffers, or every single one).
local function get_buffers(options)
local buffers = {}
for buffer = 1, vim.fn.bufnr('$') do
local is_listed = vim.fn.buflisted(buffer) == 1
if options.listed and is_listed then
table.insert(buffers, buffer)
else
table.insert(buffers, buffer)
end
end
return buffers
end
return get_buffers
The if..else part seems a little bit off for me, I'm not sure if it can be improved, but something tells me that there's some way to make this less repetitive
2 Answers 2
The only case when you don't want a buffer included is when
options.listedis truthy andis_listedis falsy
In every other case you want it included. If my understanding is correct you can simplify the if to a single branch:
...
local is_listed = vim.fn.buflisted(buffer) == 1
if not (options.listed and is_listed) then
table.insert(buffers, buffer)
end
...
That code is still calculating is_listed on every iteration. If you move it inside the conditional and remove the parenthesis, the code will be a bit more efficient (is_listed won't be calculated at all when options.listed is falsy)
...
if not options.listed or vim.fn.buflisted(buffer) ~= 1 then
table.insert(buffers, buffer)
end
...
I think that is good enough. There's some extra perf changes chat can be done. options.listed and vim.fn could be localized into a local variable to make it slightly faster, too. And using table.insert is slower than direct table insertion. Final result:
local function get_buffers(options)
local buffers = {}
local len = 0
local options_listed = options.listed
local vim_fn = vim.fn
local buflisted = vim_fn.buflisted
for buffer = 1, vim_fn.bufnr('$') do
if not options_listed or buflisted(buffer) ~= 1 then
len = len + 1
buffers[len] = buffer
end
end
return buffers
end
There is an API question that is still worth mentioning. In most cases, I try to avoid boolean parameters completely. Instead, consider using two functions: get_all_buffers() (no params) to get all buffers, and get_listed_buffers() (no params) to get only the listed buffers.
The code in your if and else branches is identical.
table.insert(buffers, buffer)
I prefer to use neovim api functions over similar vim functions (bufnr, buflisted).
nvim_list_bufs() gets the current list of buffer handles, and nvim_buf_is_loaded() checks if a buffer is valid and loaded.
Here's an example that returns the buffers that are loaded.
function get_bufs_loaded()
local bufs_loaded = {}
for i, buf_hndl in ipairs(vim.api.nvim_list_bufs()) do
if vim.api.nvim_buf_is_loaded(buf_hndl) then
bufs_loaded[i] = buf_hndl
end
end
return bufs_loaded
end
-
1\$\begingroup\$ I'm not saying this is a bad answer, but you might want to read How do I write a good answer. The more insightful observations you make about the code in the question the better your answer will be. \$\endgroup\$2022年12月26日 22:29:07 +00:00Commented Dec 26, 2022 at 22:29