vimtricks.wiki Concise Vim tricks, one at a time.

How do I use Neovim's built-in lazy iterator API to chain filter and map operations over a list?

Answer

vim.iter()

Explanation

vim.iter() (Neovim 0.10+) is a built-in Lua API that wraps any table or iterator in a lazy iterator object, letting you chain operations like :filter(), :map(), :take(), :skip(), and :totable() in a readable, functional style — without loading plugins like Plenary or Underscore.

How it works

  • vim.iter(tbl) wraps a list or iterator
  • :filter(fn) keeps only elements for which fn(val) returns true
  • :map(fn) transforms each element with fn(val) and returns the new value
  • :each(fn) runs fn(val) for side effects without returning a new iterator
  • :totable() collects the final result into a plain Lua table

Example

:lua =vim.iter({1, 2, 3, 4, 5}):filter(function(x) return x % 2 == 0 end):totable()
" → {2, 4}
" Get names of all listed buffers
:lua =vim.iter(vim.api.nvim_list_bufs()):filter(function(b)
    return vim.bo[b].buflisted
end):map(function(b)
    return vim.api.nvim_buf_get_name(b)
end):totable()

Tips

  • Iterators are lazy — no work is done until :totable(), :each(), or a consuming method is called
  • Works with both list-like tables (sequential) and iterator functions (e.g., from ipairs(), pairs())
  • Neovim's own vim.api functions that return lists integrate naturally with vim.iter()
  • Requires Neovim ≥ 0.10; check with vim.fn.has('nvim-0.10')

Next

How do I inspect a Vim register's full details including its type (charwise, linewise, or blockwise) in Vimscript?