mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 09:44:31 +00:00 
			
		
		
		
	feat(lua): use callable table as iterator in vim.iter (#23957)
A table passed to `vim.iter` can be a class instance with a `__call` implementation for the iterator protocol.
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							b302da9ad2
						
					
				
				
					commit
					302d3cfb96
				
			@@ -2999,6 +2999,8 @@ pipeline depend on the type passed to this function:
 | 
			
		||||
• Non-list tables pass both the key and value of each element
 | 
			
		||||
• Function iterators pass all of the values returned by their respective
 | 
			
		||||
  function
 | 
			
		||||
• Tables with a metatable implementing __call are treated as function
 | 
			
		||||
  iterators
 | 
			
		||||
 | 
			
		||||
Examples: >lua
 | 
			
		||||
 | 
			
		||||
@@ -3032,6 +3034,12 @@ Examples: >lua
 | 
			
		||||
   end)
 | 
			
		||||
   -- true
 | 
			
		||||
 | 
			
		||||
   local rb = vim.ringbuf(3)
 | 
			
		||||
   rb:push("a")
 | 
			
		||||
   rb:push("b")
 | 
			
		||||
   vim.iter(rb):totable()
 | 
			
		||||
   -- { "a", "b" }
 | 
			
		||||
 | 
			
		||||
<
 | 
			
		||||
 | 
			
		||||
In addition to the |vim.iter()| function, the |vim.iter| module provides
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@
 | 
			
		||||
--- - Non-list tables pass both the key and value of each element
 | 
			
		||||
--- - Function iterators pass all of the values returned by their respective
 | 
			
		||||
---   function
 | 
			
		||||
--- - Tables with a metatable implementing __call are treated as function
 | 
			
		||||
---   iterators
 | 
			
		||||
---
 | 
			
		||||
--- Examples:
 | 
			
		||||
--- <pre>lua
 | 
			
		||||
@@ -46,6 +48,12 @@
 | 
			
		||||
---     return k == 'z'
 | 
			
		||||
---   end)
 | 
			
		||||
---   -- true
 | 
			
		||||
---
 | 
			
		||||
---   local rb = vim.ringbuf(3)
 | 
			
		||||
---   rb:push("a")
 | 
			
		||||
---   rb:push("b")
 | 
			
		||||
---   vim.iter(rb):totable()
 | 
			
		||||
---   -- { "a", "b" }
 | 
			
		||||
--- </pre>
 | 
			
		||||
---
 | 
			
		||||
--- In addition to the |vim.iter()| function, the |vim.iter| module provides
 | 
			
		||||
@@ -889,6 +897,17 @@ end
 | 
			
		||||
function Iter.new(src, ...)
 | 
			
		||||
  local it = {}
 | 
			
		||||
  if type(src) == 'table' then
 | 
			
		||||
    local mt = getmetatable(src)
 | 
			
		||||
    if mt and type(mt.__call) == 'function' then
 | 
			
		||||
      ---@private
 | 
			
		||||
      function it.next()
 | 
			
		||||
        return src()
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      setmetatable(it, Iter)
 | 
			
		||||
      return it
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    local t = {}
 | 
			
		||||
 | 
			
		||||
    -- Check if source table can be treated like a list (indices are consecutive integers
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,15 @@ local matches = helpers.matches
 | 
			
		||||
local pcall_err = helpers.pcall_err
 | 
			
		||||
 | 
			
		||||
describe('vim.iter', function()
 | 
			
		||||
  it('new() on iterable class instance', function()
 | 
			
		||||
    local rb = vim.ringbuf(3)
 | 
			
		||||
    rb:push("a")
 | 
			
		||||
    rb:push("b")
 | 
			
		||||
 | 
			
		||||
    local it = vim.iter(rb)
 | 
			
		||||
    eq({"a", "b"}, it:totable())
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('filter()', function()
 | 
			
		||||
    local function odd(v)
 | 
			
		||||
      return v % 2 ~= 0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user