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\$

2 Answers 2

2
\$\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\$
0
1
\$\begingroup\$

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
\$\endgroup\$
1
  • 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\$
    – pacmaninbw
    Dec 26, 2022 at 22:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.