diff options
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r-- | runtime/lua/vim/iter.lua | 92 |
1 files changed, 43 insertions, 49 deletions
diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index b73c03ba9a..c5d5ef835b 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -18,26 +18,19 @@ ListIter.__call = function(self) return self:next() end ---- Special case implementations for iterators on non-list tables. ----@class TableIter : Iter -local TableIter = {} -TableIter.__index = setmetatable(TableIter, Iter) -TableIter.__call = function(self) - return self:next() -end - ---@private local function unpack(t) - if type(t) == 'table' then - return _G.unpack(t) + if type(t) == 'table' and t.__n ~= nil then + return _G.unpack(t, 1, t.__n) end return t end ---@private local function pack(...) - if select('#', ...) > 1 then - return { ... } + local n = select('#', ...) + if n > 1 then + return { __n = n, ... } end return ... end @@ -184,10 +177,10 @@ end --- Collect the iterator into a table. --- ---- The resulting table depends on the initial source in the iterator pipeline. List-like tables ---- and function iterators will be collected into a list-like table. If multiple values are returned ---- from the final stage in the iterator pipeline, each value will be included in a table. If a ---- map-like table was used as the initial source, then a map-like table is returned. +--- The resulting table depends on the initial source in the iterator pipeline. +--- List-like tables and function iterators will be collected into a list-like +--- table. If multiple values are returned from the final stage in the iterator +--- pipeline, each value will be included in a table. --- --- Examples: --- <pre>lua @@ -198,9 +191,13 @@ end --- -- { { 1, 2 }, { 2, 4 }, { 3, 6 } } --- --- vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable() ---- -- { a = 1, c = 3 } +--- -- { { 'a', 1 }, { 'c', 3 } } --- </pre> --- +--- The generated table is a list-like table with consecutive, numeric indices. +--- To create a map-like table with arbitrary keys, use |Iter:fold()|. +--- +--- ---@return table function Iter.totable(self) local t = {} @@ -210,6 +207,12 @@ function Iter.totable(self) if args == nil then break end + + if type(args) == 'table' then + -- Removed packed table tag if it exists + args.__n = nil + end + t[#t + 1] = args end return t @@ -218,23 +221,35 @@ end ---@private function ListIter.totable(self) if self._head == 1 and self._tail == #self._table + 1 and self.next == ListIter.next then + -- Remove any packed table tags + for i = 1, #self._table do + local v = self._table[i] + if type(v) == 'table' then + v.__n = nil + self._table[i] = v + end + end return self._table end return Iter.totable(self) end ----@private -function TableIter.totable(self) - local t = {} - for k, v in self do - t[k] = v - end - return t -end - --- Fold an iterator or table into a single value. --- +--- Examples: +--- <pre> +--- -- Create a new table with only even values +--- local t = { a = 1, b = 2, c = 3, d = 4 } +--- local it = vim.iter(t) +--- it:filter(function(k, v) return v % 2 == 0 end) +--- it:fold({}, function(t, k, v) +--- t[k] = v +--- return t +--- end) +--- -- { b = 2, d = 4 } +--- </pre> +--- ---@generic A --- ---@param init A Initial value of the accumulator. @@ -747,7 +762,7 @@ function ListIter.enumerate(self) local inc = self._head < self._tail and 1 or -1 for i = self._head, self._tail - inc, inc do local v = self._table[i] - self._table[i] = { i, v } + self._table[i] = pack(i, v) end return self end @@ -768,7 +783,7 @@ function Iter.new(src, ...) count = count + 1 local v = src[count] if v == nil then - return TableIter.new(src) + return Iter.new(pairs(src)) end t[count] = v end @@ -812,25 +827,4 @@ function ListIter.new(t) return it end ---- Create a new TableIter ---- ----@param t table Table to iterate over. For list-like tables, use ListIter.new instead. ----@return Iter ----@private -function TableIter.new(t) - local it = {} - - local index = nil - function it.next() - local k, v = next(t, index) - if k ~= nil then - index = k - return k, v - end - end - - setmetatable(it, TableIter) - return it -end - return Iter |