diff options
author | Gregory Anders <greg@gpanders.com> | 2023-04-24 19:57:40 -0600 |
---|---|---|
committer | Gregory Anders <greg@gpanders.com> | 2023-04-25 08:23:16 -0600 |
commit | 1e73891d696a00b046ab19d245001424b174c931 (patch) | |
tree | 70f5e63c1764d04749be3a13822b57e9b6c6caac | |
parent | 147bb87245cdb348e67c659415d0661d48aa5f1e (diff) | |
download | rneovim-1e73891d696a00b046ab19d245001424b174c931.tar.gz rneovim-1e73891d696a00b046ab19d245001424b174c931.tar.bz2 rneovim-1e73891d696a00b046ab19d245001424b174c931.zip |
refactor(iter): move helper functions under vim.iter
vim.iter is now both a function and a module (similar to vim.version).
-rw-r--r-- | runtime/doc/lua.txt | 223 | ||||
-rw-r--r-- | runtime/lua/vim/_init_packages.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/iter.lua | 112 | ||||
-rw-r--r-- | runtime/lua/vim/shared.lua | 105 | ||||
-rwxr-xr-x | scripts/gen_vimdoc.py | 3 |
5 files changed, 214 insertions, 230 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 8e68e9a792..2d3ea75588 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1653,26 +1653,6 @@ endswith({s}, {suffix}) *vim.endswith()* Return: ~ (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()* Splits a string at each instance of a separator. @@ -1718,64 +1698,6 @@ is_callable({f}) *vim.is_callable()* Return: ~ (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()* Checks if a list-like table (integer keys without gaps) contains `value`. @@ -1818,26 +1740,6 @@ list_slice({list}, {start}, {finish}) *vim.list_slice()* Return: ~ (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()* Escapes magic chars in |lua-patterns|. @@ -2099,20 +2001,6 @@ tbl_values({t}) *vim.tbl_values()* Return: ~ (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 whitespace (Lua pattern "%s") from both sides of a string. @@ -2933,6 +2821,79 @@ range({spec}) *vim.version.range()* ============================================================================== 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()* Return true if all of the items in the iterator match the given predicate. @@ -2971,9 +2932,7 @@ Iter:enumerate({self}) *Iter:enumerate()* vim.iter(ipairs(t)) < - over - - >lua + over >lua vim.iter(t):enumerate() < @@ -3331,16 +3290,38 @@ Iter:totable({self}) *Iter:totable()* Return: ~ (table) -new({src}, {...}) *new()* - Create a new Iter object from a table or iterator. +map({f}, {src}, {...}) *vim.iter.map()* + Map and filter a table or iterator. + + This is a convenience function that performs: >lua + + vim.iter(src):map(f):totable() +< 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: ~ - Iter + (table) -next() *next()* - TODO: Documentation + See also: ~ + • |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: diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua index 2cf2e91a8c..5db258c011 100644 --- a/runtime/lua/vim/_init_packages.lua +++ b/runtime/lua/vim/_init_packages.lua @@ -55,6 +55,7 @@ vim._submodules = { inspect = true, version = true, fs = true, + iter = true, } -- These are for loading runtime modules in the vim namespace lazily. diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 2545853b41..c2e2c5bd9f 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -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 local Iter = {} @@ -733,7 +785,6 @@ end --- </pre> --- --- over ---- --- <pre>lua --- vim.iter(t):enumerate() --- </pre> @@ -776,6 +827,7 @@ end --- ---@param src table|function Table or iterator to drain values from ---@return Iter +---@private function Iter.new(src, ...) local it = {} if type(src) == 'table' then @@ -807,6 +859,7 @@ function Iter.new(src, ...) end end + ---@private function it.next() return fn(src(s, var)) end @@ -832,4 +885,57 @@ function ListIter.new(t) return it 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, +}) diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 5f4ea8822b..a55deb1415 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -881,109 +881,4 @@ function vim.defaulttable(create) }) 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 diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 52d03d9746..d0686e92bc 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -188,7 +188,7 @@ CONFIG = { f'*vim.{name}()*' if fstem.lower() == '_editor' else f'*{name}()*' - if fstem in ('iter.lua') + if name[0].isupper() else f'*{fstem}.{name}()*'), 'module_override': { # `shared` functions are exposed on the `vim` module. @@ -202,6 +202,7 @@ CONFIG = { 'fs': 'vim.fs', 'secure': 'vim.secure', 'version': 'vim.version', + 'iter': 'vim.iter', }, 'append_only': [ 'shared.lua', |