0
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

The only case when you don't want a buffer included is when

  • options.listed is truthy and
  • is_listed is 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.

\$\endgroup\$
1
  • \$\begingroup\$ Many thanks for such an elaborate answer! :) \$\endgroup\$ Sep 24 '21 at 23:54

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.