mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #23303 from gpanders/more-vim-iter
Create iter_spec and vim.iter module
This commit is contained in:
commit
cacc2dc419
@ -1670,26 +1670,6 @@ endswith({s}, {suffix}) *vim.endswith()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(boolean) `true` if `suffix` is a suffix of `s`
|
(boolean) `true` if `suffix` is a suffix of `s`
|
||||||
|
|
||||||
filter({f}, {src}, {...}) *vim.filter()*
|
|
||||||
Filter a table or iterator.
|
|
||||||
|
|
||||||
This is a convenience function that performs: >lua
|
|
||||||
|
|
||||||
vim.iter(src):filter(f):totable()
|
|
||||||
<
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {f} function(...):bool Filter function. Accepts the current
|
|
||||||
iterator or table values as arguments and returns true if those
|
|
||||||
values should be kept in the final table
|
|
||||||
• {src} table|function Table or iterator function to filter
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
(table)
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
• |Iter:filter()|
|
|
||||||
|
|
||||||
gsplit({s}, {sep}, {opts}) *vim.gsplit()*
|
gsplit({s}, {sep}, {opts}) *vim.gsplit()*
|
||||||
Splits a string at each instance of a separator.
|
Splits a string at each instance of a separator.
|
||||||
|
|
||||||
@ -1735,64 +1715,6 @@ is_callable({f}) *vim.is_callable()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(boolean) `true` if `f` is callable, else `false`
|
(boolean) `true` if `f` is callable, else `false`
|
||||||
|
|
||||||
iter({src}, {...}) *vim.iter()*
|
|
||||||
Create an Iter |lua-iter| object from a table or iterator.
|
|
||||||
|
|
||||||
The input value can be a table or a function iterator (see |luaref-in|).
|
|
||||||
|
|
||||||
This function wraps the input value into an interface which allows
|
|
||||||
chaining multiple pipeline stages in an efficient manner. Each pipeline
|
|
||||||
stage receives as input the output values from the prior stage. The values
|
|
||||||
used in the first stage of the pipeline depend on the type passed to this
|
|
||||||
function:
|
|
||||||
|
|
||||||
• List tables pass only the value of each element
|
|
||||||
• Non-list tables pass both the key and value of each element
|
|
||||||
• Function iterators pass all of the values returned by their respective
|
|
||||||
function
|
|
||||||
|
|
||||||
Examples: >lua
|
|
||||||
|
|
||||||
local it = vim.iter({ 1, 2, 3, 4, 5 })
|
|
||||||
it:map(function(v)
|
|
||||||
return v * 3
|
|
||||||
end)
|
|
||||||
it:rev()
|
|
||||||
it:skip(2)
|
|
||||||
it:totable()
|
|
||||||
-- { 9, 6, 3 }
|
|
||||||
|
|
||||||
vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
|
|
||||||
if i > 2 then return v end
|
|
||||||
end):totable()
|
|
||||||
-- { 3, 4, 5 }
|
|
||||||
|
|
||||||
local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
|
|
||||||
it:map(function(s) return tonumber(s) end)
|
|
||||||
for i, d in it:enumerate() do
|
|
||||||
print(string.format("Column %d is %d", i, d))
|
|
||||||
end
|
|
||||||
-- Column 1 is 1
|
|
||||||
-- Column 2 is 2
|
|
||||||
-- Column 3 is 3
|
|
||||||
-- Column 4 is 4
|
|
||||||
-- Column 5 is 5
|
|
||||||
|
|
||||||
vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
|
|
||||||
return k == 'z'
|
|
||||||
end)
|
|
||||||
-- true
|
|
||||||
<
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {src} table|function Table or iterator.
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
Iter |lua-iter|
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
• |lua-iter|
|
|
||||||
|
|
||||||
list_contains({t}, {value}) *vim.list_contains()*
|
list_contains({t}, {value}) *vim.list_contains()*
|
||||||
Checks if a list-like table (integer keys without gaps) contains `value`.
|
Checks if a list-like table (integer keys without gaps) contains `value`.
|
||||||
|
|
||||||
@ -1835,26 +1757,6 @@ list_slice({list}, {start}, {finish}) *vim.list_slice()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(list) Copy of table sliced from start to finish (inclusive)
|
(list) Copy of table sliced from start to finish (inclusive)
|
||||||
|
|
||||||
map({f}, {src}, {...}) *vim.map()*
|
|
||||||
Map and filter a table or iterator.
|
|
||||||
|
|
||||||
This is a convenience function that performs: >lua
|
|
||||||
|
|
||||||
vim.iter(src):map(f):totable()
|
|
||||||
<
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {f} function(...):?any Map function. Accepts the current iterator
|
|
||||||
or table values as arguments and returns one or more new
|
|
||||||
values. Nil values are removed from the final table.
|
|
||||||
• {src} table|function Table or iterator function to filter
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
(table)
|
|
||||||
|
|
||||||
See also: ~
|
|
||||||
• |Iter:map()|
|
|
||||||
|
|
||||||
pesc({s}) *vim.pesc()*
|
pesc({s}) *vim.pesc()*
|
||||||
Escapes magic chars in |lua-patterns|.
|
Escapes magic chars in |lua-patterns|.
|
||||||
|
|
||||||
@ -2116,20 +2018,6 @@ tbl_values({t}) *vim.tbl_values()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(list) List of values
|
(list) List of values
|
||||||
|
|
||||||
totable({f}, {...}) *vim.totable()*
|
|
||||||
Collect an iterator into a table.
|
|
||||||
|
|
||||||
This is a convenience function that performs: >lua
|
|
||||||
|
|
||||||
vim.iter(f):totable()
|
|
||||||
<
|
|
||||||
|
|
||||||
Parameters: ~
|
|
||||||
• {f} (function) Iterator function
|
|
||||||
|
|
||||||
Return: ~
|
|
||||||
(table)
|
|
||||||
|
|
||||||
trim({s}) *vim.trim()*
|
trim({s}) *vim.trim()*
|
||||||
Trim whitespace (Lua pattern "%s") from both sides of a string.
|
Trim whitespace (Lua pattern "%s") from both sides of a string.
|
||||||
|
|
||||||
@ -2950,6 +2838,79 @@ range({spec}) *vim.version.range()*
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
Lua module: iter *lua-iter*
|
Lua module: iter *lua-iter*
|
||||||
|
|
||||||
|
|
||||||
|
The *vim.iter* module provides a generic "iterator" interface over tables
|
||||||
|
and iterator functions.
|
||||||
|
|
||||||
|
*vim.iter()* wraps its table or function argument into an *Iter* object
|
||||||
|
with methods (such as |Iter:filter()| and |Iter:map()|) that transform the
|
||||||
|
underlying source data. These methods can be chained together to create
|
||||||
|
iterator "pipelines". Each pipeline stage receives as input the output
|
||||||
|
values from the prior stage. The values used in the first stage of the
|
||||||
|
pipeline depend on the type passed to this function:
|
||||||
|
|
||||||
|
• List tables pass only the value of each element
|
||||||
|
• Non-list tables pass both the key and value of each element
|
||||||
|
• Function iterators pass all of the values returned by their respective
|
||||||
|
function
|
||||||
|
|
||||||
|
Examples: >lua
|
||||||
|
|
||||||
|
local it = vim.iter({ 1, 2, 3, 4, 5 })
|
||||||
|
it:map(function(v)
|
||||||
|
return v * 3
|
||||||
|
end)
|
||||||
|
it:rev()
|
||||||
|
it:skip(2)
|
||||||
|
it:totable()
|
||||||
|
-- { 9, 6, 3 }
|
||||||
|
|
||||||
|
vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
|
||||||
|
if i > 2 then return v end
|
||||||
|
end):totable()
|
||||||
|
-- { 3, 4, 5 }
|
||||||
|
|
||||||
|
local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
|
||||||
|
it:map(function(s) return tonumber(s) end)
|
||||||
|
for i, d in it:enumerate() do
|
||||||
|
print(string.format("Column %d is %d", i, d))
|
||||||
|
end
|
||||||
|
-- Column 1 is 1
|
||||||
|
-- Column 2 is 2
|
||||||
|
-- Column 3 is 3
|
||||||
|
-- Column 4 is 4
|
||||||
|
-- Column 5 is 5
|
||||||
|
|
||||||
|
vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
|
||||||
|
return k == 'z'
|
||||||
|
end)
|
||||||
|
-- true
|
||||||
|
|
||||||
|
<
|
||||||
|
|
||||||
|
In addition to the |vim.iter()| function, the |vim.iter| module provides
|
||||||
|
convenience functions like |vim.iter.filter()| and |vim.iter.totable()|.
|
||||||
|
|
||||||
|
filter({f}, {src}, {...}) *vim.iter.filter()*
|
||||||
|
Filter a table or iterator.
|
||||||
|
|
||||||
|
This is a convenience function that performs: >lua
|
||||||
|
|
||||||
|
vim.iter(src):filter(f):totable()
|
||||||
|
<
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
• {f} function(...):bool Filter function. Accepts the current
|
||||||
|
iterator or table values as arguments and returns true if those
|
||||||
|
values should be kept in the final table
|
||||||
|
• {src} table|function Table or iterator function to filter
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
(table)
|
||||||
|
|
||||||
|
See also: ~
|
||||||
|
• |Iter:filter()|
|
||||||
|
|
||||||
Iter:all({self}, {pred}) *Iter:all()*
|
Iter:all({self}, {pred}) *Iter:all()*
|
||||||
Return true if all of the items in the iterator match the given predicate.
|
Return true if all of the items in the iterator match the given predicate.
|
||||||
|
|
||||||
@ -2988,9 +2949,7 @@ Iter:enumerate({self}) *Iter:enumerate()*
|
|||||||
vim.iter(ipairs(t))
|
vim.iter(ipairs(t))
|
||||||
<
|
<
|
||||||
|
|
||||||
over
|
over >lua
|
||||||
|
|
||||||
>lua
|
|
||||||
|
|
||||||
vim.iter(t):enumerate()
|
vim.iter(t):enumerate()
|
||||||
<
|
<
|
||||||
@ -3348,16 +3307,38 @@ Iter:totable({self}) *Iter:totable()*
|
|||||||
Return: ~
|
Return: ~
|
||||||
(table)
|
(table)
|
||||||
|
|
||||||
new({src}, {...}) *new()*
|
map({f}, {src}, {...}) *vim.iter.map()*
|
||||||
Create a new Iter object from a table or iterator.
|
Map and filter a table or iterator.
|
||||||
|
|
||||||
|
This is a convenience function that performs: >lua
|
||||||
|
|
||||||
|
vim.iter(src):map(f):totable()
|
||||||
|
<
|
||||||
|
|
||||||
Parameters: ~
|
Parameters: ~
|
||||||
• {src} table|function Table or iterator to drain values from
|
• {f} function(...):?any Map function. Accepts the current iterator
|
||||||
|
or table values as arguments and returns one or more new
|
||||||
|
values. Nil values are removed from the final table.
|
||||||
|
• {src} table|function Table or iterator function to filter
|
||||||
|
|
||||||
Return: ~
|
Return: ~
|
||||||
Iter
|
(table)
|
||||||
|
|
||||||
next() *next()*
|
See also: ~
|
||||||
TODO: Documentation
|
• |Iter:map()|
|
||||||
|
|
||||||
|
totable({f}, {...}) *vim.iter.totable()*
|
||||||
|
Collect an iterator into a table.
|
||||||
|
|
||||||
|
This is a convenience function that performs: >lua
|
||||||
|
|
||||||
|
vim.iter(f):totable()
|
||||||
|
<
|
||||||
|
|
||||||
|
Parameters: ~
|
||||||
|
• {f} (function) Iterator function
|
||||||
|
|
||||||
|
Return: ~
|
||||||
|
(table)
|
||||||
|
|
||||||
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
|
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
|
||||||
|
@ -55,6 +55,7 @@ vim._submodules = {
|
|||||||
inspect = true,
|
inspect = true,
|
||||||
version = true,
|
version = true,
|
||||||
fs = true,
|
fs = true,
|
||||||
|
iter = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- These are for loading runtime modules in the vim namespace lazily.
|
-- These are for loading runtime modules in the vim namespace lazily.
|
||||||
|
@ -1,4 +1,56 @@
|
|||||||
--- Iterator implementation.
|
---@defgroup lua-iter
|
||||||
|
---
|
||||||
|
--- The \*vim.iter\* module provides a generic "iterator" interface over tables and iterator
|
||||||
|
--- functions.
|
||||||
|
---
|
||||||
|
--- \*vim.iter()\* wraps its table or function argument into an \*Iter\* object with methods (such
|
||||||
|
--- as |Iter:filter()| and |Iter:map()|) that transform the underlying source data. These methods
|
||||||
|
--- can be chained together to create iterator "pipelines". Each pipeline stage receives as input
|
||||||
|
--- the output values from the prior stage. The values used in the first stage of the pipeline
|
||||||
|
--- depend on the type passed to this function:
|
||||||
|
---
|
||||||
|
--- - List tables pass only the value of each element
|
||||||
|
--- - Non-list tables pass both the key and value of each element
|
||||||
|
--- - Function iterators pass all of the values returned by their respective
|
||||||
|
--- function
|
||||||
|
---
|
||||||
|
--- Examples:
|
||||||
|
--- <pre>lua
|
||||||
|
--- local it = vim.iter({ 1, 2, 3, 4, 5 })
|
||||||
|
--- it:map(function(v)
|
||||||
|
--- return v * 3
|
||||||
|
--- end)
|
||||||
|
--- it:rev()
|
||||||
|
--- it:skip(2)
|
||||||
|
--- it:totable()
|
||||||
|
--- -- { 9, 6, 3 }
|
||||||
|
---
|
||||||
|
--- vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
|
||||||
|
--- if i > 2 then return v end
|
||||||
|
--- end):totable()
|
||||||
|
--- -- { 3, 4, 5 }
|
||||||
|
---
|
||||||
|
--- local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
|
||||||
|
--- it:map(function(s) return tonumber(s) end)
|
||||||
|
--- for i, d in it:enumerate() do
|
||||||
|
--- print(string.format("Column %d is %d", i, d))
|
||||||
|
--- end
|
||||||
|
--- -- Column 1 is 1
|
||||||
|
--- -- Column 2 is 2
|
||||||
|
--- -- Column 3 is 3
|
||||||
|
--- -- Column 4 is 4
|
||||||
|
--- -- Column 5 is 5
|
||||||
|
---
|
||||||
|
--- vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
|
||||||
|
--- return k == 'z'
|
||||||
|
--- end)
|
||||||
|
--- -- true
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
--- In addition to the |vim.iter()| function, the |vim.iter| module provides convenience functions
|
||||||
|
--- like |vim.iter.filter()| and |vim.iter.totable()|.
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
---@class Iter
|
---@class Iter
|
||||||
local Iter = {}
|
local Iter = {}
|
||||||
@ -733,7 +785,6 @@ end
|
|||||||
--- </pre>
|
--- </pre>
|
||||||
---
|
---
|
||||||
--- over
|
--- over
|
||||||
---
|
|
||||||
--- <pre>lua
|
--- <pre>lua
|
||||||
--- vim.iter(t):enumerate()
|
--- vim.iter(t):enumerate()
|
||||||
--- </pre>
|
--- </pre>
|
||||||
@ -776,6 +827,7 @@ end
|
|||||||
---
|
---
|
||||||
---@param src table|function Table or iterator to drain values from
|
---@param src table|function Table or iterator to drain values from
|
||||||
---@return Iter
|
---@return Iter
|
||||||
|
---@private
|
||||||
function Iter.new(src, ...)
|
function Iter.new(src, ...)
|
||||||
local it = {}
|
local it = {}
|
||||||
if type(src) == 'table' then
|
if type(src) == 'table' then
|
||||||
@ -807,6 +859,7 @@ function Iter.new(src, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@private
|
||||||
function it.next()
|
function it.next()
|
||||||
return fn(src(s, var))
|
return fn(src(s, var))
|
||||||
end
|
end
|
||||||
@ -832,4 +885,57 @@ function ListIter.new(t)
|
|||||||
return it
|
return it
|
||||||
end
|
end
|
||||||
|
|
||||||
return Iter
|
--- Collect an iterator into a table.
|
||||||
|
---
|
||||||
|
--- This is a convenience function that performs:
|
||||||
|
--- <pre>lua
|
||||||
|
--- vim.iter(f):totable()
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
---@param f function Iterator function
|
||||||
|
---@return table
|
||||||
|
function M.totable(f, ...)
|
||||||
|
return Iter.new(f, ...):totable()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Filter a table or iterator.
|
||||||
|
---
|
||||||
|
--- This is a convenience function that performs:
|
||||||
|
--- <pre>lua
|
||||||
|
--- vim.iter(src):filter(f):totable()
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
---@see |Iter:filter()|
|
||||||
|
---
|
||||||
|
---@param f function(...):bool Filter function. Accepts the current iterator or table values as
|
||||||
|
--- arguments and returns true if those values should be kept in the
|
||||||
|
--- final table
|
||||||
|
---@param src table|function Table or iterator function to filter
|
||||||
|
---@return table
|
||||||
|
function M.filter(f, src, ...)
|
||||||
|
return Iter.new(src, ...):filter(f):totable()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Map and filter a table or iterator.
|
||||||
|
---
|
||||||
|
--- This is a convenience function that performs:
|
||||||
|
--- <pre>lua
|
||||||
|
--- vim.iter(src):map(f):totable()
|
||||||
|
--- </pre>
|
||||||
|
---
|
||||||
|
---@see |Iter:map()|
|
||||||
|
---
|
||||||
|
---@param f function(...):?any Map function. Accepts the current iterator or table values as
|
||||||
|
--- arguments and returns one or more new values. Nil values are removed
|
||||||
|
--- from the final table.
|
||||||
|
---@param src table|function Table or iterator function to filter
|
||||||
|
---@return table
|
||||||
|
function M.map(f, src, ...)
|
||||||
|
return Iter.new(src, ...):map(f):totable()
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(M, {
|
||||||
|
__call = function(_, ...)
|
||||||
|
return Iter.new(...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
@ -881,109 +881,4 @@ function vim.defaulttable(create)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create an Iter |lua-iter| object from a table or iterator.
|
|
||||||
---
|
|
||||||
--- The input value can be a table or a function iterator (see |luaref-in|).
|
|
||||||
---
|
|
||||||
--- This function wraps the input value into an interface which allows chaining
|
|
||||||
--- multiple pipeline stages in an efficient manner. Each pipeline stage
|
|
||||||
--- receives as input the output values from the prior stage. The values used in
|
|
||||||
--- the first stage of the pipeline depend on the type passed to this function:
|
|
||||||
---
|
|
||||||
--- - List tables pass only the value of each element
|
|
||||||
--- - Non-list tables pass both the key and value of each element
|
|
||||||
--- - Function iterators pass all of the values returned by their respective
|
|
||||||
--- function
|
|
||||||
---
|
|
||||||
--- Examples:
|
|
||||||
--- <pre>lua
|
|
||||||
--- local it = vim.iter({ 1, 2, 3, 4, 5 })
|
|
||||||
--- it:map(function(v)
|
|
||||||
--- return v * 3
|
|
||||||
--- end)
|
|
||||||
--- it:rev()
|
|
||||||
--- it:skip(2)
|
|
||||||
--- it:totable()
|
|
||||||
--- -- { 9, 6, 3 }
|
|
||||||
---
|
|
||||||
--- vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
|
|
||||||
--- if i > 2 then return v end
|
|
||||||
--- end):totable()
|
|
||||||
--- -- { 3, 4, 5 }
|
|
||||||
---
|
|
||||||
--- local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
|
|
||||||
--- it:map(function(s) return tonumber(s) end)
|
|
||||||
--- for i, d in it:enumerate() do
|
|
||||||
--- print(string.format("Column %d is %d", i, d))
|
|
||||||
--- end
|
|
||||||
--- -- Column 1 is 1
|
|
||||||
--- -- Column 2 is 2
|
|
||||||
--- -- Column 3 is 3
|
|
||||||
--- -- Column 4 is 4
|
|
||||||
--- -- Column 5 is 5
|
|
||||||
---
|
|
||||||
--- vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
|
|
||||||
--- return k == 'z'
|
|
||||||
--- end)
|
|
||||||
--- -- true
|
|
||||||
--- </pre>
|
|
||||||
---
|
|
||||||
---@see |lua-iter|
|
|
||||||
---
|
|
||||||
---@param src table|function Table or iterator.
|
|
||||||
---@return Iter @|lua-iter|
|
|
||||||
function vim.iter(src, ...)
|
|
||||||
local Iter = require('vim.iter')
|
|
||||||
return Iter.new(src, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Collect an iterator into a table.
|
|
||||||
---
|
|
||||||
--- This is a convenience function that performs:
|
|
||||||
--- <pre>lua
|
|
||||||
--- vim.iter(f):totable()
|
|
||||||
--- </pre>
|
|
||||||
---
|
|
||||||
---@param f function Iterator function
|
|
||||||
---@return table
|
|
||||||
function vim.totable(f, ...)
|
|
||||||
return vim.iter(f, ...):totable()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Filter a table or iterator.
|
|
||||||
---
|
|
||||||
--- This is a convenience function that performs:
|
|
||||||
--- <pre>lua
|
|
||||||
--- vim.iter(src):filter(f):totable()
|
|
||||||
--- </pre>
|
|
||||||
---
|
|
||||||
---@see |Iter:filter()|
|
|
||||||
---
|
|
||||||
---@param f function(...):bool Filter function. Accepts the current iterator or table values as
|
|
||||||
--- arguments and returns true if those values should be kept in the
|
|
||||||
--- final table
|
|
||||||
---@param src table|function Table or iterator function to filter
|
|
||||||
---@return table
|
|
||||||
function vim.filter(f, src, ...)
|
|
||||||
return vim.iter(src, ...):filter(f):totable()
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Map and filter a table or iterator.
|
|
||||||
---
|
|
||||||
--- This is a convenience function that performs:
|
|
||||||
--- <pre>lua
|
|
||||||
--- vim.iter(src):map(f):totable()
|
|
||||||
--- </pre>
|
|
||||||
---
|
|
||||||
---@see |Iter:map()|
|
|
||||||
---
|
|
||||||
---@param f function(...):?any Map function. Accepts the current iterator or table values as
|
|
||||||
--- arguments and returns one or more new values. Nil values are removed
|
|
||||||
--- from the final table.
|
|
||||||
---@param src table|function Table or iterator function to filter
|
|
||||||
---@return table
|
|
||||||
function vim.map(f, src, ...)
|
|
||||||
return vim.iter(src, ...):map(f):totable()
|
|
||||||
end
|
|
||||||
|
|
||||||
return vim
|
return vim
|
||||||
|
@ -188,7 +188,7 @@ CONFIG = {
|
|||||||
f'*vim.{name}()*'
|
f'*vim.{name}()*'
|
||||||
if fstem.lower() == '_editor'
|
if fstem.lower() == '_editor'
|
||||||
else f'*{name}()*'
|
else f'*{name}()*'
|
||||||
if fstem in ('iter.lua')
|
if name[0].isupper()
|
||||||
else f'*{fstem}.{name}()*'),
|
else f'*{fstem}.{name}()*'),
|
||||||
'module_override': {
|
'module_override': {
|
||||||
# `shared` functions are exposed on the `vim` module.
|
# `shared` functions are exposed on the `vim` module.
|
||||||
@ -202,6 +202,7 @@ CONFIG = {
|
|||||||
'fs': 'vim.fs',
|
'fs': 'vim.fs',
|
||||||
'secure': 'vim.secure',
|
'secure': 'vim.secure',
|
||||||
'version': 'vim.version',
|
'version': 'vim.version',
|
||||||
|
'iter': 'vim.iter',
|
||||||
},
|
},
|
||||||
'append_only': [
|
'append_only': [
|
||||||
'shared.lua',
|
'shared.lua',
|
||||||
|
425
test/functional/lua/iter_spec.lua
Normal file
425
test/functional/lua/iter_spec.lua
Normal file
@ -0,0 +1,425 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local eq = helpers.eq
|
||||||
|
local matches = helpers.matches
|
||||||
|
local pcall_err = helpers.pcall_err
|
||||||
|
|
||||||
|
describe('vim.iter', function()
|
||||||
|
it('filter()', function()
|
||||||
|
local function odd(v)
|
||||||
|
return v % 2 ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local t = { 1, 2, 3, 4, 5 }
|
||||||
|
eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable())
|
||||||
|
eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable())
|
||||||
|
eq({}, vim.iter(t):filter(function(v) return v > 5 end):totable())
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(ipairs(t))
|
||||||
|
it:filter(function(i, v) return i > 1 and v < 5 end)
|
||||||
|
it:map(function(_, v) return v * 2 end)
|
||||||
|
eq({ 4, 6, 8 }, it:totable())
|
||||||
|
end
|
||||||
|
|
||||||
|
local it = vim.iter(string.gmatch('the quick brown fox', '%w+'))
|
||||||
|
eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('map()', function()
|
||||||
|
local t = { 1, 2, 3, 4, 5 }
|
||||||
|
eq(
|
||||||
|
{ 2, 4, 6, 8, 10 },
|
||||||
|
vim
|
||||||
|
.iter(t)
|
||||||
|
:map(function(v)
|
||||||
|
return 2 * v
|
||||||
|
end)
|
||||||
|
:totable()
|
||||||
|
)
|
||||||
|
|
||||||
|
local it = vim.gsplit(
|
||||||
|
[[
|
||||||
|
Line 1
|
||||||
|
Line 2
|
||||||
|
Line 3
|
||||||
|
Line 4
|
||||||
|
]],
|
||||||
|
'\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
eq(
|
||||||
|
{ 'Lion 2', 'Lion 4' },
|
||||||
|
vim
|
||||||
|
.iter(it)
|
||||||
|
:map(function(s)
|
||||||
|
local lnum = s:match('(%d+)')
|
||||||
|
if lnum and tonumber(lnum) % 2 == 0 then
|
||||||
|
return vim.trim(s:gsub('Line', 'Lion'))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
:totable()
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('for loops', function()
|
||||||
|
local t = {1, 2, 3, 4, 5}
|
||||||
|
local acc = 0
|
||||||
|
for v in vim.iter(t):map(function(v) return v * 3 end) do
|
||||||
|
acc = acc + v
|
||||||
|
end
|
||||||
|
eq(45, acc)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('totable()', function()
|
||||||
|
do
|
||||||
|
local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end)
|
||||||
|
eq({{1, 1}, {2, 4}, {3, 9}}, it:totable())
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber)
|
||||||
|
eq({1, 4, 17, 2, 9, 3}, it:totable())
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('next()', function()
|
||||||
|
local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end)
|
||||||
|
eq(2, it:next())
|
||||||
|
eq(4, it:next())
|
||||||
|
eq(6, it:next())
|
||||||
|
eq(nil, it:next())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('rev()', function()
|
||||||
|
eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable())
|
||||||
|
|
||||||
|
local it = vim.iter(string.gmatch("abc", "%w"))
|
||||||
|
matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('skip()', function()
|
||||||
|
do
|
||||||
|
local t = {4, 3, 2, 1}
|
||||||
|
eq(t, vim.iter(t):skip(0):totable())
|
||||||
|
eq({3, 2, 1}, vim.iter(t):skip(1):totable())
|
||||||
|
eq({2, 1}, vim.iter(t):skip(2):totable())
|
||||||
|
eq({1}, vim.iter(t):skip(#t - 1):totable())
|
||||||
|
eq({}, vim.iter(t):skip(#t):totable())
|
||||||
|
eq({}, vim.iter(t):skip(#t + 1):totable())
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local function skip(n)
|
||||||
|
return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable()
|
||||||
|
end
|
||||||
|
eq({'a', 'b', 'c', 'd'}, skip(0))
|
||||||
|
eq({'b', 'c', 'd'}, skip(1))
|
||||||
|
eq({'c', 'd'}, skip(2))
|
||||||
|
eq({'d'}, skip(3))
|
||||||
|
eq({}, skip(4))
|
||||||
|
eq({}, skip(5))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('skipback()', function()
|
||||||
|
do
|
||||||
|
local t = {4, 3, 2, 1}
|
||||||
|
eq(t, vim.iter(t):skipback(0):totable())
|
||||||
|
eq({4, 3, 2}, vim.iter(t):skipback(1):totable())
|
||||||
|
eq({4, 3}, vim.iter(t):skipback(2):totable())
|
||||||
|
eq({4}, vim.iter(t):skipback(#t - 1):totable())
|
||||||
|
eq({}, vim.iter(t):skipback(#t):totable())
|
||||||
|
eq({}, vim.iter(t):skipback(#t + 1):totable())
|
||||||
|
end
|
||||||
|
|
||||||
|
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
|
||||||
|
matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('slice()', function()
|
||||||
|
local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||||
|
eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable())
|
||||||
|
eq({}, vim.iter(t):slice(6, 5):totable())
|
||||||
|
eq({}, vim.iter(t):slice(0, 0):totable())
|
||||||
|
eq({1}, vim.iter(t):slice(1, 1):totable())
|
||||||
|
eq({1, 2}, vim.iter(t):slice(1, 2):totable())
|
||||||
|
eq({10}, vim.iter(t):slice(10, 10):totable())
|
||||||
|
eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('nth()', function()
|
||||||
|
do
|
||||||
|
local t = {4, 3, 2, 1}
|
||||||
|
eq(nil, vim.iter(t):nth(0))
|
||||||
|
eq(4, vim.iter(t):nth(1))
|
||||||
|
eq(3, vim.iter(t):nth(2))
|
||||||
|
eq(2, vim.iter(t):nth(3))
|
||||||
|
eq(1, vim.iter(t):nth(4))
|
||||||
|
eq(nil, vim.iter(t):nth(5))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local function nth(n)
|
||||||
|
return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n)
|
||||||
|
end
|
||||||
|
eq(nil, nth(0))
|
||||||
|
eq('a', nth(1))
|
||||||
|
eq('b', nth(2))
|
||||||
|
eq('c', nth(3))
|
||||||
|
eq('d', nth(4))
|
||||||
|
eq(nil, nth(5))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('nthback()', function()
|
||||||
|
do
|
||||||
|
local t = {4, 3, 2, 1}
|
||||||
|
eq(nil, vim.iter(t):nthback(0))
|
||||||
|
eq(1, vim.iter(t):nthback(1))
|
||||||
|
eq(2, vim.iter(t):nthback(2))
|
||||||
|
eq(3, vim.iter(t):nthback(3))
|
||||||
|
eq(4, vim.iter(t):nthback(4))
|
||||||
|
eq(nil, vim.iter(t):nthback(5))
|
||||||
|
end
|
||||||
|
|
||||||
|
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
|
||||||
|
matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('any()', function()
|
||||||
|
local function odd(v)
|
||||||
|
return v % 2 ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local t = { 4, 8, 9, 10 }
|
||||||
|
eq(true, vim.iter(t):any(odd))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local t = { 4, 8, 10 }
|
||||||
|
eq(false, vim.iter(t):any(odd))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end))
|
||||||
|
eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('all()', function()
|
||||||
|
local function odd(v)
|
||||||
|
return v % 2 ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local t = { 3, 5, 7, 9 }
|
||||||
|
eq(true, vim.iter(t):all(odd))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local t = { 3, 5, 7, 10 }
|
||||||
|
eq(false, vim.iter(t):all(odd))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end))
|
||||||
|
eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('last()', function()
|
||||||
|
local s = 'abcdefghijklmnopqrstuvwxyz'
|
||||||
|
eq('z', vim.iter(vim.split(s, '')):last())
|
||||||
|
eq('z', vim.iter(vim.gsplit(s, '')):last())
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('enumerate()', function()
|
||||||
|
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
|
||||||
|
eq({1, 'a'}, {it:next()})
|
||||||
|
eq({2, 'b'}, {it:next()})
|
||||||
|
eq({3, 'c'}, {it:next()})
|
||||||
|
eq({}, {it:next()})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('peek()', function()
|
||||||
|
do
|
||||||
|
local it = vim.iter({ 3, 6, 9, 12 })
|
||||||
|
eq(3, it:peek())
|
||||||
|
eq(3, it:peek())
|
||||||
|
eq(3, it:next())
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(vim.gsplit('hi', ''))
|
||||||
|
matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('find()', function()
|
||||||
|
local t = {3, 6, 9, 12}
|
||||||
|
eq(12, vim.iter(t):find(12))
|
||||||
|
eq(nil, vim.iter(t):find(15))
|
||||||
|
eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end))
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(t)
|
||||||
|
local pred = function(v) return v % 3 == 0 end
|
||||||
|
eq(3, it:find(pred))
|
||||||
|
eq(6, it:find(pred))
|
||||||
|
eq(9, it:find(pred))
|
||||||
|
eq(12, it:find(pred))
|
||||||
|
eq(nil, it:find(pred))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(vim.gsplit('AbCdE', ''))
|
||||||
|
local pred = function(s) return s:match('[A-Z]') end
|
||||||
|
eq('A', it:find(pred))
|
||||||
|
eq('C', it:find(pred))
|
||||||
|
eq('E', it:find(pred))
|
||||||
|
eq(nil, it:find(pred))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('rfind()', function()
|
||||||
|
local t = {1, 2, 3, 2, 1}
|
||||||
|
do
|
||||||
|
local it = vim.iter(t)
|
||||||
|
eq(1, it:rfind(1))
|
||||||
|
eq(1, it:rfind(1))
|
||||||
|
eq(nil, it:rfind(1))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(t):enumerate()
|
||||||
|
local pred = function(i) return i % 2 ~= 0 end
|
||||||
|
eq({5, 1}, {it:rfind(pred)})
|
||||||
|
eq({3, 3}, {it:rfind(pred)})
|
||||||
|
eq({1, 1}, {it:rfind(pred)})
|
||||||
|
eq(nil, it:rfind(pred))
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(vim.gsplit('AbCdE', ''))
|
||||||
|
matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E'))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('nextback()', function()
|
||||||
|
do
|
||||||
|
local it = vim.iter({ 1, 2, 3, 4 })
|
||||||
|
eq(4, it:nextback())
|
||||||
|
eq(3, it:nextback())
|
||||||
|
eq(2, it:nextback())
|
||||||
|
eq(1, it:nextback())
|
||||||
|
eq(nil, it:nextback())
|
||||||
|
eq(nil, it:nextback())
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(vim.gsplit('hi', ''))
|
||||||
|
matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('peekback()', function()
|
||||||
|
do
|
||||||
|
local it = vim.iter({ 1, 2, 3, 4 })
|
||||||
|
eq(4, it:peekback())
|
||||||
|
eq(4, it:peekback())
|
||||||
|
eq(4, it:nextback())
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(vim.gsplit('hi', ''))
|
||||||
|
matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('fold()', function()
|
||||||
|
local t = {1, 2, 3, 4, 5}
|
||||||
|
eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end))
|
||||||
|
eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v)
|
||||||
|
table.insert(acc, 1, v)
|
||||||
|
return acc
|
||||||
|
end))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('handles map-like tables', function()
|
||||||
|
local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
|
||||||
|
if v % 2 ~= 0 then
|
||||||
|
return k:upper(), v * 2
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local t = it:fold({}, function(t, k, v)
|
||||||
|
t[k] = v
|
||||||
|
return t
|
||||||
|
end)
|
||||||
|
eq({ A = 2, C = 6 }, t)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('handles table values mid-pipeline', function()
|
||||||
|
local map = {
|
||||||
|
item = {
|
||||||
|
file = 'test',
|
||||||
|
},
|
||||||
|
item_2 = {
|
||||||
|
file = 'test',
|
||||||
|
},
|
||||||
|
item_3 = {
|
||||||
|
file = 'test',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local output = vim.iter(map):map(function(key, value)
|
||||||
|
return { [key] = value.file }
|
||||||
|
end):totable()
|
||||||
|
|
||||||
|
table.sort(output, function(a, b)
|
||||||
|
return next(a) < next(b)
|
||||||
|
end)
|
||||||
|
|
||||||
|
eq({
|
||||||
|
{ item = 'test' },
|
||||||
|
{ item_2 = 'test' },
|
||||||
|
{ item_3 = 'test' },
|
||||||
|
}, output)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('handles nil values', function()
|
||||||
|
local t = {1, 2, 3, 4, 5}
|
||||||
|
do
|
||||||
|
local it = vim.iter(t):enumerate():map(function(i, v)
|
||||||
|
if i % 2 == 0 then
|
||||||
|
return nil, v*v
|
||||||
|
end
|
||||||
|
return v, nil
|
||||||
|
end)
|
||||||
|
eq({
|
||||||
|
{ [1] = 1 },
|
||||||
|
{ [2] = 4 },
|
||||||
|
{ [1] = 3 },
|
||||||
|
{ [2] = 16 },
|
||||||
|
{ [1] = 5 },
|
||||||
|
}, it:totable())
|
||||||
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
local it = vim.iter(ipairs(t)):map(function(i, v)
|
||||||
|
if i % 2 == 0 then
|
||||||
|
return nil, v*v
|
||||||
|
end
|
||||||
|
return v, nil
|
||||||
|
end)
|
||||||
|
eq({
|
||||||
|
{ [1] = 1 },
|
||||||
|
{ [2] = 4 },
|
||||||
|
{ [1] = 3 },
|
||||||
|
{ [2] = 16 },
|
||||||
|
{ [1] = 5 },
|
||||||
|
}, it:totable())
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
@ -3031,427 +3031,6 @@ describe('lua stdlib', function()
|
|||||||
eq(false, if_nil(d, c))
|
eq(false, if_nil(d, c))
|
||||||
eq(NIL, if_nil(a))
|
eq(NIL, if_nil(a))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('vim.iter', function()
|
|
||||||
it('filter()', function()
|
|
||||||
local function odd(v)
|
|
||||||
return v % 2 ~= 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local t = { 1, 2, 3, 4, 5 }
|
|
||||||
eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable())
|
|
||||||
eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable())
|
|
||||||
eq({}, vim.iter(t):filter(function(v) if v > 5 then return v end end):totable())
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(ipairs(t))
|
|
||||||
it:filter(function(i, v) return i > 1 and v < 5 end)
|
|
||||||
it:map(function(_, v) return v * 2 end)
|
|
||||||
eq({ 4, 6, 8 }, it:totable())
|
|
||||||
end
|
|
||||||
|
|
||||||
local it = vim.iter(string.gmatch('the quick brown fox', '%w+'))
|
|
||||||
eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable())
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('map()', function()
|
|
||||||
local t = { 1, 2, 3, 4, 5 }
|
|
||||||
eq(
|
|
||||||
{ 2, 4, 6, 8, 10 },
|
|
||||||
vim
|
|
||||||
.iter(t)
|
|
||||||
:map(function(v)
|
|
||||||
return 2 * v
|
|
||||||
end)
|
|
||||||
:totable()
|
|
||||||
)
|
|
||||||
|
|
||||||
local it = vim.gsplit(
|
|
||||||
[[
|
|
||||||
Line 1
|
|
||||||
Line 2
|
|
||||||
Line 3
|
|
||||||
Line 4
|
|
||||||
]],
|
|
||||||
'\n'
|
|
||||||
)
|
|
||||||
|
|
||||||
eq(
|
|
||||||
{ 'Lion 2', 'Lion 4' },
|
|
||||||
vim
|
|
||||||
.iter(it)
|
|
||||||
:map(function(s)
|
|
||||||
local lnum = s:match('(%d+)')
|
|
||||||
if lnum and tonumber(lnum) % 2 == 0 then
|
|
||||||
return vim.trim(s:gsub('Line', 'Lion'))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
:totable()
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('for loops', function()
|
|
||||||
local t = {1, 2, 3, 4, 5}
|
|
||||||
local acc = 0
|
|
||||||
for v in vim.iter(t):map(function(v) return v * 3 end) do
|
|
||||||
acc = acc + v
|
|
||||||
end
|
|
||||||
eq(45, acc)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('totable()', function()
|
|
||||||
do
|
|
||||||
local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end)
|
|
||||||
eq({{1, 1}, {2, 4}, {3, 9}}, it:totable())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber)
|
|
||||||
eq({1, 4, 17, 2, 9, 3}, it:totable())
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('next()', function()
|
|
||||||
local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end)
|
|
||||||
eq(2, it:next())
|
|
||||||
eq(4, it:next())
|
|
||||||
eq(6, it:next())
|
|
||||||
eq(nil, it:next())
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('rev()', function()
|
|
||||||
eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable())
|
|
||||||
|
|
||||||
local it = vim.iter(string.gmatch("abc", "%w"))
|
|
||||||
matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it))
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('skip()', function()
|
|
||||||
do
|
|
||||||
local t = {4, 3, 2, 1}
|
|
||||||
eq(t, vim.iter(t):skip(0):totable())
|
|
||||||
eq({3, 2, 1}, vim.iter(t):skip(1):totable())
|
|
||||||
eq({2, 1}, vim.iter(t):skip(2):totable())
|
|
||||||
eq({1}, vim.iter(t):skip(#t - 1):totable())
|
|
||||||
eq({}, vim.iter(t):skip(#t):totable())
|
|
||||||
eq({}, vim.iter(t):skip(#t + 1):totable())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local function skip(n)
|
|
||||||
return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable()
|
|
||||||
end
|
|
||||||
eq({'a', 'b', 'c', 'd'}, skip(0))
|
|
||||||
eq({'b', 'c', 'd'}, skip(1))
|
|
||||||
eq({'c', 'd'}, skip(2))
|
|
||||||
eq({'d'}, skip(3))
|
|
||||||
eq({}, skip(4))
|
|
||||||
eq({}, skip(5))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('skipback()', function()
|
|
||||||
do
|
|
||||||
local t = {4, 3, 2, 1}
|
|
||||||
eq(t, vim.iter(t):skipback(0):totable())
|
|
||||||
eq({4, 3, 2}, vim.iter(t):skipback(1):totable())
|
|
||||||
eq({4, 3}, vim.iter(t):skipback(2):totable())
|
|
||||||
eq({4}, vim.iter(t):skipback(#t - 1):totable())
|
|
||||||
eq({}, vim.iter(t):skipback(#t):totable())
|
|
||||||
eq({}, vim.iter(t):skipback(#t + 1):totable())
|
|
||||||
end
|
|
||||||
|
|
||||||
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
|
|
||||||
matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0))
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('slice()', function()
|
|
||||||
local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
|
||||||
eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable())
|
|
||||||
eq({}, vim.iter(t):slice(6, 5):totable())
|
|
||||||
eq({}, vim.iter(t):slice(0, 0):totable())
|
|
||||||
eq({1}, vim.iter(t):slice(1, 1):totable())
|
|
||||||
eq({1, 2}, vim.iter(t):slice(1, 2):totable())
|
|
||||||
eq({10}, vim.iter(t):slice(10, 10):totable())
|
|
||||||
eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable())
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('nth()', function()
|
|
||||||
do
|
|
||||||
local t = {4, 3, 2, 1}
|
|
||||||
eq(nil, vim.iter(t):nth(0))
|
|
||||||
eq(4, vim.iter(t):nth(1))
|
|
||||||
eq(3, vim.iter(t):nth(2))
|
|
||||||
eq(2, vim.iter(t):nth(3))
|
|
||||||
eq(1, vim.iter(t):nth(4))
|
|
||||||
eq(nil, vim.iter(t):nth(5))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local function nth(n)
|
|
||||||
return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n)
|
|
||||||
end
|
|
||||||
eq(nil, nth(0))
|
|
||||||
eq('a', nth(1))
|
|
||||||
eq('b', nth(2))
|
|
||||||
eq('c', nth(3))
|
|
||||||
eq('d', nth(4))
|
|
||||||
eq(nil, nth(5))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('nthback()', function()
|
|
||||||
do
|
|
||||||
local t = {4, 3, 2, 1}
|
|
||||||
eq(nil, vim.iter(t):nthback(0))
|
|
||||||
eq(1, vim.iter(t):nthback(1))
|
|
||||||
eq(2, vim.iter(t):nthback(2))
|
|
||||||
eq(3, vim.iter(t):nthback(3))
|
|
||||||
eq(4, vim.iter(t):nthback(4))
|
|
||||||
eq(nil, vim.iter(t):nthback(5))
|
|
||||||
end
|
|
||||||
|
|
||||||
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
|
|
||||||
matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1))
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('any()', function()
|
|
||||||
local function odd(v)
|
|
||||||
return v % 2 ~= 0
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local t = { 4, 8, 9, 10 }
|
|
||||||
eq(true, vim.iter(t):any(odd))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local t = { 4, 8, 10 }
|
|
||||||
eq(false, vim.iter(t):any(odd))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end))
|
|
||||||
eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('all()', function()
|
|
||||||
local function odd(v)
|
|
||||||
return v % 2 ~= 0
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local t = { 3, 5, 7, 9 }
|
|
||||||
eq(true, vim.iter(t):all(odd))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local t = { 3, 5, 7, 10 }
|
|
||||||
eq(false, vim.iter(t):all(odd))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end))
|
|
||||||
eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('last()', function()
|
|
||||||
local s = 'abcdefghijklmnopqrstuvwxyz'
|
|
||||||
eq('z', vim.iter(vim.split(s, '')):last())
|
|
||||||
eq('z', vim.iter(vim.gsplit(s, '')):last())
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('enumerate()', function()
|
|
||||||
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
|
|
||||||
eq({1, 'a'}, {it:next()})
|
|
||||||
eq({2, 'b'}, {it:next()})
|
|
||||||
eq({3, 'c'}, {it:next()})
|
|
||||||
eq({}, {it:next()})
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('peek()', function()
|
|
||||||
do
|
|
||||||
local it = vim.iter({ 3, 6, 9, 12 })
|
|
||||||
eq(3, it:peek())
|
|
||||||
eq(3, it:peek())
|
|
||||||
eq(3, it:next())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(vim.gsplit('hi', ''))
|
|
||||||
matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('find()', function()
|
|
||||||
local t = {3, 6, 9, 12}
|
|
||||||
eq(12, vim.iter(t):find(12))
|
|
||||||
eq(nil, vim.iter(t):find(15))
|
|
||||||
eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end))
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(t)
|
|
||||||
local pred = function(v) return v % 3 == 0 end
|
|
||||||
eq(3, it:find(pred))
|
|
||||||
eq(6, it:find(pred))
|
|
||||||
eq(9, it:find(pred))
|
|
||||||
eq(12, it:find(pred))
|
|
||||||
eq(nil, it:find(pred))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(vim.gsplit('AbCdE', ''))
|
|
||||||
local pred = function(s) return s:match('[A-Z]') end
|
|
||||||
eq('A', it:find(pred))
|
|
||||||
eq('C', it:find(pred))
|
|
||||||
eq('E', it:find(pred))
|
|
||||||
eq(nil, it:find(pred))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('rfind()', function()
|
|
||||||
local t = {1, 2, 3, 2, 1}
|
|
||||||
do
|
|
||||||
local it = vim.iter(t)
|
|
||||||
eq(1, it:rfind(1))
|
|
||||||
eq(1, it:rfind(1))
|
|
||||||
eq(nil, it:rfind(1))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(t):enumerate()
|
|
||||||
local pred = function(i) return i % 2 ~= 0 end
|
|
||||||
eq({5, 1}, {it:rfind(pred)})
|
|
||||||
eq({3, 3}, {it:rfind(pred)})
|
|
||||||
eq({1, 1}, {it:rfind(pred)})
|
|
||||||
eq(nil, it:rfind(pred))
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(vim.gsplit('AbCdE', ''))
|
|
||||||
matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E'))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('nextback()', function()
|
|
||||||
do
|
|
||||||
local it = vim.iter({ 1, 2, 3, 4 })
|
|
||||||
eq(4, it:nextback())
|
|
||||||
eq(3, it:nextback())
|
|
||||||
eq(2, it:nextback())
|
|
||||||
eq(1, it:nextback())
|
|
||||||
eq(nil, it:nextback())
|
|
||||||
eq(nil, it:nextback())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(vim.gsplit('hi', ''))
|
|
||||||
matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('peekback()', function()
|
|
||||||
do
|
|
||||||
local it = vim.iter({ 1, 2, 3, 4 })
|
|
||||||
eq(4, it:peekback())
|
|
||||||
eq(4, it:peekback())
|
|
||||||
eq(4, it:peekback())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(vim.gsplit('hi', ''))
|
|
||||||
matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('fold()', function()
|
|
||||||
local t = {1, 2, 3, 4, 5}
|
|
||||||
eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end))
|
|
||||||
eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v)
|
|
||||||
table.insert(acc, 1, v)
|
|
||||||
return acc
|
|
||||||
end))
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('handles map-like tables', function()
|
|
||||||
local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v)
|
|
||||||
if v % 2 ~= 0 then
|
|
||||||
return k:upper(), v * 2
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local t = it:fold({}, function(t, k, v)
|
|
||||||
t[k] = v
|
|
||||||
return t
|
|
||||||
end)
|
|
||||||
eq({ A = 2, C = 6 }, t)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('handles table values mid-pipeline', function()
|
|
||||||
local map = {
|
|
||||||
item = {
|
|
||||||
file = 'test',
|
|
||||||
},
|
|
||||||
item_2 = {
|
|
||||||
file = 'test',
|
|
||||||
},
|
|
||||||
item_3 = {
|
|
||||||
file = 'test',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
local output = vim.iter(map):map(function(key, value)
|
|
||||||
return { [key] = value.file }
|
|
||||||
end):totable()
|
|
||||||
|
|
||||||
table.sort(output, function(a, b)
|
|
||||||
return next(a) < next(b)
|
|
||||||
end)
|
|
||||||
|
|
||||||
eq({
|
|
||||||
{ item = 'test' },
|
|
||||||
{ item_2 = 'test' },
|
|
||||||
{ item_3 = 'test' },
|
|
||||||
}, output)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('handles nil values', function()
|
|
||||||
local t = {1, 2, 3, 4, 5}
|
|
||||||
do
|
|
||||||
local it = vim.iter(t):enumerate():map(function(i, v)
|
|
||||||
if i % 2 == 0 then
|
|
||||||
return nil, v*v
|
|
||||||
end
|
|
||||||
return v, nil
|
|
||||||
end)
|
|
||||||
eq({
|
|
||||||
{ [1] = 1 },
|
|
||||||
{ [2] = 4 },
|
|
||||||
{ [1] = 3 },
|
|
||||||
{ [2] = 16 },
|
|
||||||
{ [1] = 5 },
|
|
||||||
}, it:totable())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local it = vim.iter(ipairs(t)):map(function(i, v)
|
|
||||||
if i % 2 == 0 then
|
|
||||||
return nil, v*v
|
|
||||||
end
|
|
||||||
return v, nil
|
|
||||||
end)
|
|
||||||
eq({
|
|
||||||
{ [1] = 1 },
|
|
||||||
{ [2] = 4 },
|
|
||||||
{ [1] = 3 },
|
|
||||||
{ [2] = 16 },
|
|
||||||
{ [1] = 5 },
|
|
||||||
}, it:totable())
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('lua: builtin modules', function()
|
describe('lua: builtin modules', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user