iter.lua 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089
  1. --- @brief
  2. ---
  3. --- [vim.iter()]() is an interface for [iterable]s: it wraps a table or function argument into an
  4. --- [Iter]() object with methods (such as [Iter:filter()] and [Iter:map()]) that transform the
  5. --- underlying source data. These methods can be chained to create iterator "pipelines": the output
  6. --- of each pipeline stage is input to the next stage. The first stage depends on the type passed to
  7. --- `vim.iter()`:
  8. ---
  9. --- - Lists or arrays (|lua-list|) yield only the value of each element.
  10. --- - Holes (nil values) are allowed (but discarded).
  11. --- - Use pairs() to treat array/list tables as dicts (preserve holes and non-contiguous integer
  12. --- keys): `vim.iter(pairs(…))`.
  13. --- - Use |Iter:enumerate()| to also pass the index to the next stage.
  14. --- - Or initialize with ipairs(): `vim.iter(ipairs(…))`.
  15. --- - Non-list tables (|lua-dict|) yield both the key and value of each element.
  16. --- - Function |iterator|s yield all values returned by the underlying function.
  17. --- - Tables with a |__call()| metamethod are treated as function iterators.
  18. ---
  19. --- The iterator pipeline terminates when the underlying |iterable| is exhausted (for function
  20. --- iterators this means it returned nil).
  21. ---
  22. --- Note: `vim.iter()` scans table input to decide if it is a list or a dict; to avoid this cost you
  23. --- can wrap the table with an iterator e.g. `vim.iter(ipairs({…}))`, but that precludes the use of
  24. --- |list-iterator| operations such as |Iter:rev()|).
  25. ---
  26. --- Examples:
  27. ---
  28. --- ```lua
  29. --- local it = vim.iter({ 1, 2, 3, 4, 5 })
  30. --- it:map(function(v)
  31. --- return v * 3
  32. --- end)
  33. --- it:rev()
  34. --- it:skip(2)
  35. --- it:totable()
  36. --- -- { 9, 6, 3 }
  37. ---
  38. --- -- ipairs() is a function iterator which returns both the index (i) and the value (v)
  39. --- vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
  40. --- if i > 2 then return v end
  41. --- end):totable()
  42. --- -- { 3, 4, 5 }
  43. ---
  44. --- local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
  45. --- it:map(function(s) return tonumber(s) end)
  46. --- for i, d in it:enumerate() do
  47. --- print(string.format("Column %d is %d", i, d))
  48. --- end
  49. --- -- Column 1 is 1
  50. --- -- Column 2 is 2
  51. --- -- Column 3 is 3
  52. --- -- Column 4 is 4
  53. --- -- Column 5 is 5
  54. ---
  55. --- vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
  56. --- return k == 'z'
  57. --- end)
  58. --- -- true
  59. ---
  60. --- local rb = vim.ringbuf(3)
  61. --- rb:push("a")
  62. --- rb:push("b")
  63. --- vim.iter(rb):totable()
  64. --- -- { "a", "b" }
  65. --- ```
  66. --- LuaLS is bad at generics which this module mostly deals with
  67. --- @diagnostic disable:no-unknown
  68. ---@nodoc
  69. ---@class IterMod
  70. ---@operator call:Iter
  71. local M = {}
  72. ---@nodoc
  73. ---@class Iter
  74. local Iter = {}
  75. Iter.__index = Iter
  76. Iter.__call = function(self)
  77. return self:next()
  78. end
  79. --- Special case implementations for iterators on list tables.
  80. ---@nodoc
  81. ---@class ArrayIter : Iter
  82. ---@field _table table Underlying table data
  83. ---@field _head number Index to the front of a table iterator
  84. ---@field _tail number Index to the end of a table iterator (exclusive)
  85. local ArrayIter = {}
  86. ArrayIter.__index = setmetatable(ArrayIter, Iter)
  87. ArrayIter.__call = function(self)
  88. return self:next()
  89. end
  90. --- Packed tables use this as their metatable
  91. local packedmt = {}
  92. local function unpack(t)
  93. if type(t) == 'table' and getmetatable(t) == packedmt then
  94. return _G.unpack(t, 1, t.n)
  95. end
  96. return t
  97. end
  98. local function pack(...)
  99. local n = select('#', ...)
  100. if n > 1 then
  101. return setmetatable({ n = n, ... }, packedmt)
  102. end
  103. return ...
  104. end
  105. local function sanitize(t)
  106. if type(t) == 'table' and getmetatable(t) == packedmt then
  107. -- Remove length tag and metatable
  108. t.n = nil
  109. setmetatable(t, nil)
  110. end
  111. return t
  112. end
  113. --- Flattens a single array-like table. Errors if it attempts to flatten a
  114. --- dict-like table
  115. ---@param t table table which should be flattened
  116. ---@param max_depth number depth to which the table should be flattened
  117. ---@param depth number current iteration depth
  118. ---@param result table output table that contains flattened result
  119. ---@return table|nil flattened table if it can be flattened, otherwise nil
  120. local function flatten(t, max_depth, depth, result)
  121. if depth < max_depth and type(t) == 'table' then
  122. for k, v in pairs(t) do
  123. if type(k) ~= 'number' or k <= 0 or math.floor(k) ~= k then
  124. -- short-circuit: this is not a list like table
  125. return nil
  126. end
  127. if flatten(v, max_depth, depth + 1, result) == nil then
  128. return nil
  129. end
  130. end
  131. elseif t ~= nil then
  132. result[#result + 1] = t
  133. end
  134. return result
  135. end
  136. --- Determine if the current iterator stage should continue.
  137. ---
  138. --- If any arguments are passed to this function, then return those arguments
  139. --- and stop the current iterator stage. Otherwise, return true to signal that
  140. --- the current stage should continue.
  141. ---
  142. ---@param ... any Function arguments.
  143. ---@return boolean True if the iterator stage should continue, false otherwise
  144. ---@return any Function arguments.
  145. local function continue(...)
  146. if select(1, ...) ~= nil then
  147. return false, ...
  148. end
  149. return true
  150. end
  151. --- If no input arguments are given return false, indicating the current
  152. --- iterator stage should stop. Otherwise, apply the arguments to the function
  153. --- f. If that function returns no values, the current iterator stage continues.
  154. --- Otherwise, those values are returned.
  155. ---
  156. ---@param f function Function to call with the given arguments
  157. ---@param ... any Arguments to apply to f
  158. ---@return boolean True if the iterator pipeline should continue, false otherwise
  159. ---@return any Return values of f
  160. local function apply(f, ...)
  161. if select(1, ...) ~= nil then
  162. return continue(f(...))
  163. end
  164. return false
  165. end
  166. --- Filters an iterator pipeline.
  167. ---
  168. --- Example:
  169. ---
  170. --- ```lua
  171. --- local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded)
  172. --- ```
  173. ---
  174. ---@param f fun(...):boolean Takes all values returned from the previous stage
  175. --- in the pipeline and returns false or nil if the
  176. --- current iterator element should be removed.
  177. ---@return Iter
  178. function Iter:filter(f)
  179. return self:map(function(...)
  180. if f(...) then
  181. return ...
  182. end
  183. end)
  184. end
  185. ---@private
  186. function ArrayIter:filter(f)
  187. local inc = self._head < self._tail and 1 or -1
  188. local n = self._head
  189. for i = self._head, self._tail - inc, inc do
  190. local v = self._table[i]
  191. if f(unpack(v)) then
  192. self._table[n] = v
  193. n = n + inc
  194. end
  195. end
  196. self._tail = n
  197. return self
  198. end
  199. --- Flattens a |list-iterator|, un-nesting nested values up to the given {depth}.
  200. --- Errors if it attempts to flatten a dict-like value.
  201. ---
  202. --- Examples:
  203. ---
  204. --- ```lua
  205. --- vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable()
  206. --- -- { 1, 2, { 3 } }
  207. ---
  208. --- vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable()
  209. --- -- { 1, { a = 2 }, 3 }
  210. ---
  211. --- vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable()
  212. --- -- error: attempt to flatten a dict-like table
  213. --- ```
  214. ---
  215. ---@param depth? number Depth to which |list-iterator| should be flattened
  216. --- (defaults to 1)
  217. ---@return Iter
  218. ---@diagnostic disable-next-line:unused-local
  219. function Iter:flatten(depth) -- luacheck: no unused args
  220. error('flatten() requires an array-like table')
  221. end
  222. ---@private
  223. function ArrayIter:flatten(depth)
  224. depth = depth or 1
  225. local inc = self._head < self._tail and 1 or -1
  226. local target = {}
  227. for i = self._head, self._tail - inc, inc do
  228. local flattened = flatten(self._table[i], depth, 0, {})
  229. -- exit early if we try to flatten a dict-like table
  230. if flattened == nil then
  231. error('flatten() requires an array-like table')
  232. end
  233. for _, v in pairs(flattened) do
  234. target[#target + 1] = v
  235. end
  236. end
  237. self._head = 1
  238. self._tail = #target + 1
  239. self._table = target
  240. return self
  241. end
  242. --- Maps the items of an iterator pipeline to the values returned by `f`.
  243. ---
  244. --- If the map function returns nil, the value is filtered from the iterator.
  245. ---
  246. --- Example:
  247. ---
  248. --- ```lua
  249. --- local it = vim.iter({ 1, 2, 3, 4 }):map(function(v)
  250. --- if v % 2 == 0 then
  251. --- return v * 3
  252. --- end
  253. --- end)
  254. --- it:totable()
  255. --- -- { 6, 12 }
  256. --- ```
  257. ---
  258. ---@param f fun(...):...:any Mapping function. Takes all values returned from
  259. --- the previous stage in the pipeline as arguments
  260. --- and returns one or more new values, which are used
  261. --- in the next pipeline stage. Nil return values
  262. --- are filtered from the output.
  263. ---@return Iter
  264. function Iter:map(f)
  265. -- Implementation note: the reader may be forgiven for observing that this
  266. -- function appears excessively convoluted. The problem to solve is that each
  267. -- stage of the iterator pipeline can return any number of values, and the
  268. -- number of values could even change per iteration. And the return values
  269. -- must be checked to determine if the pipeline has ended, so we cannot
  270. -- naively forward them along to the next stage.
  271. --
  272. -- A simple approach is to pack all of the return values into a table, check
  273. -- for nil, then unpack the table for the next stage. However, packing and
  274. -- unpacking tables is quite slow. There is no other way in Lua to handle an
  275. -- unknown number of function return values than to simply forward those
  276. -- values along to another function. Hence the intricate function passing you
  277. -- see here.
  278. local next = self.next
  279. --- Drain values from the upstream iterator source until a value can be
  280. --- returned.
  281. ---
  282. --- This is a recursive function. The base case is when the first argument is
  283. --- false, which indicates that the rest of the arguments should be returned
  284. --- as the values for the current iteration stage.
  285. ---
  286. ---@param cont boolean If true, the current iterator stage should continue to
  287. --- pull values from its upstream pipeline stage.
  288. --- Otherwise, this stage is complete and returns the
  289. --- values passed.
  290. ---@param ... any Values to return if cont is false.
  291. ---@return any
  292. local function fn(cont, ...)
  293. if cont then
  294. return fn(apply(f, next(self)))
  295. end
  296. return ...
  297. end
  298. self.next = function()
  299. return fn(apply(f, next(self)))
  300. end
  301. return self
  302. end
  303. ---@private
  304. function ArrayIter:map(f)
  305. local inc = self._head < self._tail and 1 or -1
  306. local n = self._head
  307. for i = self._head, self._tail - inc, inc do
  308. local v = pack(f(unpack(self._table[i])))
  309. if v ~= nil then
  310. self._table[n] = v
  311. n = n + inc
  312. end
  313. end
  314. self._tail = n
  315. return self
  316. end
  317. --- Calls a function once for each item in the pipeline, draining the iterator.
  318. ---
  319. --- For functions with side effects. To modify the values in the iterator, use |Iter:map()|.
  320. ---
  321. ---@param f fun(...) Function to execute for each item in the pipeline.
  322. --- Takes all of the values returned by the previous stage
  323. --- in the pipeline as arguments.
  324. function Iter:each(f)
  325. local function fn(...)
  326. if select(1, ...) ~= nil then
  327. f(...)
  328. return true
  329. end
  330. end
  331. while fn(self:next()) do
  332. end
  333. end
  334. ---@private
  335. function ArrayIter:each(f)
  336. local inc = self._head < self._tail and 1 or -1
  337. for i = self._head, self._tail - inc, inc do
  338. f(unpack(self._table[i]))
  339. end
  340. self._head = self._tail
  341. end
  342. --- Collect the iterator into a table.
  343. ---
  344. --- The resulting table depends on the initial source in the iterator pipeline.
  345. --- Array-like tables and function iterators will be collected into an array-like
  346. --- table. If multiple values are returned from the final stage in the iterator
  347. --- pipeline, each value will be included in a table.
  348. ---
  349. --- Examples:
  350. ---
  351. --- ```lua
  352. --- vim.iter(string.gmatch('100 20 50', '%d+')):map(tonumber):totable()
  353. --- -- { 100, 20, 50 }
  354. ---
  355. --- vim.iter({ 1, 2, 3 }):map(function(v) return v, 2 * v end):totable()
  356. --- -- { { 1, 2 }, { 2, 4 }, { 3, 6 } }
  357. ---
  358. --- vim.iter({ a = 1, b = 2, c = 3 }):filter(function(k, v) return v % 2 ~= 0 end):totable()
  359. --- -- { { 'a', 1 }, { 'c', 3 } }
  360. --- ```
  361. ---
  362. --- The generated table is an array-like table with consecutive, numeric indices.
  363. --- To create a map-like table with arbitrary keys, use |Iter:fold()|.
  364. ---
  365. ---
  366. ---@return table
  367. function Iter:totable()
  368. local t = {}
  369. while true do
  370. local args = pack(self:next())
  371. if args == nil then
  372. break
  373. end
  374. t[#t + 1] = sanitize(args)
  375. end
  376. return t
  377. end
  378. ---@private
  379. function ArrayIter:totable()
  380. if self.next ~= ArrayIter.next or self._head >= self._tail then
  381. return Iter.totable(self)
  382. end
  383. local needs_sanitize = getmetatable(self._table[self._head]) == packedmt
  384. -- Reindex and sanitize.
  385. local len = self._tail - self._head
  386. if needs_sanitize then
  387. for i = 1, len do
  388. self._table[i] = sanitize(self._table[self._head - 1 + i])
  389. end
  390. else
  391. for i = 1, len do
  392. self._table[i] = self._table[self._head - 1 + i]
  393. end
  394. end
  395. for i = len + 1, table.maxn(self._table) do
  396. self._table[i] = nil
  397. end
  398. self._head = 1
  399. self._tail = len + 1
  400. return self._table
  401. end
  402. --- Collect the iterator into a delimited string.
  403. ---
  404. --- Each element in the iterator is joined into a string separated by {delim}.
  405. ---
  406. --- Consumes the iterator.
  407. ---
  408. --- @param delim string Delimiter
  409. --- @return string
  410. function Iter:join(delim)
  411. return table.concat(self:totable(), delim)
  412. end
  413. --- Folds ("reduces") an iterator into a single value. [Iter:reduce()]()
  414. ---
  415. --- Examples:
  416. ---
  417. --- ```lua
  418. --- -- Create a new table with only even values
  419. --- vim.iter({ a = 1, b = 2, c = 3, d = 4 })
  420. --- :filter(function(k, v) return v % 2 == 0 end)
  421. --- :fold({}, function(acc, k, v)
  422. --- acc[k] = v
  423. --- return acc
  424. --- end) --> { b = 2, d = 4 }
  425. ---
  426. --- -- Get the "maximum" item of an iterable.
  427. --- vim.iter({ -99, -4, 3, 42, 0, 0, 7 })
  428. --- :fold({}, function(acc, v)
  429. --- acc.max = math.max(v, acc.max or v)
  430. --- return acc
  431. --- end) --> { max = 42 }
  432. --- ```
  433. ---
  434. ---@generic A
  435. ---
  436. ---@param init A Initial value of the accumulator.
  437. ---@param f fun(acc:A, ...):A Accumulation function.
  438. ---@return A
  439. function Iter:fold(init, f)
  440. local acc = init
  441. --- Use a closure to handle var args returned from iterator
  442. local function fn(...)
  443. if select(1, ...) ~= nil then
  444. acc = f(acc, ...)
  445. return true
  446. end
  447. end
  448. while fn(self:next()) do
  449. end
  450. return acc
  451. end
  452. ---@private
  453. function ArrayIter:fold(init, f)
  454. local acc = init
  455. local inc = self._head < self._tail and 1 or -1
  456. for i = self._head, self._tail - inc, inc do
  457. acc = f(acc, unpack(self._table[i]))
  458. end
  459. return acc
  460. end
  461. --- Gets the next value from the iterator.
  462. ---
  463. --- Example:
  464. ---
  465. --- ```lua
  466. ---
  467. --- local it = vim.iter(string.gmatch('1 2 3', '%d+')):map(tonumber)
  468. --- it:next()
  469. --- -- 1
  470. --- it:next()
  471. --- -- 2
  472. --- it:next()
  473. --- -- 3
  474. ---
  475. --- ```
  476. ---
  477. ---@return any
  478. function Iter:next()
  479. -- This function is provided by the source iterator in Iter.new. This definition exists only for
  480. -- the docstring
  481. end
  482. ---@private
  483. function ArrayIter:next()
  484. if self._head ~= self._tail then
  485. local v = self._table[self._head]
  486. local inc = self._head < self._tail and 1 or -1
  487. self._head = self._head + inc
  488. return unpack(v)
  489. end
  490. end
  491. --- Reverses a |list-iterator| pipeline.
  492. ---
  493. --- Example:
  494. ---
  495. --- ```lua
  496. ---
  497. --- local it = vim.iter({ 3, 6, 9, 12 }):rev()
  498. --- it:totable()
  499. --- -- { 12, 9, 6, 3 }
  500. ---
  501. --- ```
  502. ---
  503. ---@return Iter
  504. function Iter:rev()
  505. error('rev() requires an array-like table')
  506. end
  507. ---@private
  508. function ArrayIter:rev()
  509. local inc = self._head < self._tail and 1 or -1
  510. self._head, self._tail = self._tail - inc, self._head - inc
  511. return self
  512. end
  513. --- Gets the next value in a |list-iterator| without consuming it.
  514. ---
  515. --- Example:
  516. ---
  517. --- ```lua
  518. ---
  519. --- local it = vim.iter({ 3, 6, 9, 12 })
  520. --- it:peek()
  521. --- -- 3
  522. --- it:peek()
  523. --- -- 3
  524. --- it:next()
  525. --- -- 3
  526. ---
  527. --- ```
  528. ---
  529. ---@return any
  530. function Iter:peek()
  531. error('peek() requires an array-like table')
  532. end
  533. ---@private
  534. function ArrayIter:peek()
  535. if self._head ~= self._tail then
  536. return self._table[self._head]
  537. end
  538. end
  539. --- Find the first value in the iterator that satisfies the given predicate.
  540. ---
  541. --- Advances the iterator. Returns nil and drains the iterator if no value is found.
  542. ---
  543. --- Examples:
  544. ---
  545. --- ```lua
  546. ---
  547. --- local it = vim.iter({ 3, 6, 9, 12 })
  548. --- it:find(12)
  549. --- -- 12
  550. ---
  551. --- local it = vim.iter({ 3, 6, 9, 12 })
  552. --- it:find(20)
  553. --- -- nil
  554. ---
  555. --- local it = vim.iter({ 3, 6, 9, 12 })
  556. --- it:find(function(v) return v % 4 == 0 end)
  557. --- -- 12
  558. ---
  559. --- ```
  560. ---@param f any
  561. ---@return any
  562. function Iter:find(f)
  563. if type(f) ~= 'function' then
  564. local val = f
  565. f = function(v)
  566. return v == val
  567. end
  568. end
  569. local result = nil
  570. --- Use a closure to handle var args returned from iterator
  571. local function fn(...)
  572. if select(1, ...) ~= nil then
  573. if f(...) then
  574. result = pack(...)
  575. else
  576. return true
  577. end
  578. end
  579. end
  580. while fn(self:next()) do
  581. end
  582. return unpack(result)
  583. end
  584. --- Gets the first value satisfying a predicate, from the end of a |list-iterator|.
  585. ---
  586. --- Advances the iterator. Returns nil and drains the iterator if no value is found.
  587. ---
  588. --- Examples:
  589. ---
  590. --- ```lua
  591. ---
  592. --- local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
  593. --- it:rfind(1)
  594. --- -- 5 1
  595. --- it:rfind(1)
  596. --- -- 1 1
  597. ---
  598. --- ```
  599. ---
  600. ---@see Iter.find
  601. ---
  602. ---@param f any
  603. ---@return any
  604. ---@diagnostic disable-next-line: unused-local
  605. function Iter:rfind(f) -- luacheck: no unused args
  606. error('rfind() requires an array-like table')
  607. end
  608. ---@private
  609. function ArrayIter:rfind(f)
  610. if type(f) ~= 'function' then
  611. local val = f
  612. f = function(v)
  613. return v == val
  614. end
  615. end
  616. local inc = self._head < self._tail and 1 or -1
  617. for i = self._tail - inc, self._head, -inc do
  618. local v = self._table[i]
  619. if f(unpack(v)) then
  620. self._tail = i
  621. return unpack(v)
  622. end
  623. end
  624. self._head = self._tail
  625. end
  626. --- Transforms an iterator to yield only the first n values.
  627. ---
  628. --- Example:
  629. ---
  630. --- ```lua
  631. --- local it = vim.iter({ 1, 2, 3, 4 }):take(2)
  632. --- it:next()
  633. --- -- 1
  634. --- it:next()
  635. --- -- 2
  636. --- it:next()
  637. --- -- nil
  638. --- ```
  639. ---
  640. ---@param n integer
  641. ---@return Iter
  642. function Iter:take(n)
  643. local next = self.next
  644. local i = 0
  645. self.next = function()
  646. if i < n then
  647. i = i + 1
  648. return next(self)
  649. end
  650. end
  651. return self
  652. end
  653. ---@private
  654. function ArrayIter:take(n)
  655. local inc = self._head < self._tail and n or -n
  656. local cmp = self._head < self._tail and math.min or math.max
  657. self._tail = cmp(self._tail, self._head + inc)
  658. return self
  659. end
  660. --- "Pops" a value from a |list-iterator| (gets the last value and decrements the tail).
  661. ---
  662. --- Example:
  663. ---
  664. --- ```lua
  665. --- local it = vim.iter({1, 2, 3, 4})
  666. --- it:pop()
  667. --- -- 4
  668. --- it:pop()
  669. --- -- 3
  670. --- ```
  671. ---
  672. ---@return any
  673. function Iter:pop()
  674. error('pop() requires an array-like table')
  675. end
  676. --- @nodoc
  677. function ArrayIter:pop()
  678. if self._head ~= self._tail then
  679. local inc = self._head < self._tail and 1 or -1
  680. self._tail = self._tail - inc
  681. return self._table[self._tail]
  682. end
  683. end
  684. --- Gets the last value of a |list-iterator| without consuming it.
  685. ---
  686. --- Example:
  687. ---
  688. --- ```lua
  689. --- local it = vim.iter({1, 2, 3, 4})
  690. --- it:rpeek()
  691. --- -- 4
  692. --- it:rpeek()
  693. --- -- 4
  694. --- it:pop()
  695. --- -- 4
  696. --- ```
  697. ---
  698. ---@see Iter.last
  699. ---
  700. ---@return any
  701. function Iter:rpeek()
  702. error('rpeek() requires an array-like table')
  703. end
  704. ---@nodoc
  705. function ArrayIter:rpeek()
  706. if self._head ~= self._tail then
  707. local inc = self._head < self._tail and 1 or -1
  708. return self._table[self._tail - inc]
  709. end
  710. end
  711. --- Skips `n` values of an iterator pipeline.
  712. ---
  713. --- Example:
  714. ---
  715. --- ```lua
  716. ---
  717. --- local it = vim.iter({ 3, 6, 9, 12 }):skip(2)
  718. --- it:next()
  719. --- -- 9
  720. ---
  721. --- ```
  722. ---
  723. ---@param n number Number of values to skip.
  724. ---@return Iter
  725. function Iter:skip(n)
  726. for _ = 1, n do
  727. local _ = self:next()
  728. end
  729. return self
  730. end
  731. ---@private
  732. function ArrayIter:skip(n)
  733. local inc = self._head < self._tail and n or -n
  734. self._head = self._head + inc
  735. if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then
  736. self._head = self._tail
  737. end
  738. return self
  739. end
  740. --- Discards `n` values from the end of a |list-iterator| pipeline.
  741. ---
  742. --- Example:
  743. ---
  744. --- ```lua
  745. --- local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2)
  746. --- it:next()
  747. --- -- 1
  748. --- it:pop()
  749. --- -- 3
  750. --- ```
  751. ---
  752. ---@param n number Number of values to skip.
  753. ---@return Iter
  754. ---@diagnostic disable-next-line: unused-local
  755. function Iter:rskip(n) -- luacheck: no unused args
  756. error('rskip() requires an array-like table')
  757. end
  758. ---@private
  759. function ArrayIter:rskip(n)
  760. local inc = self._head < self._tail and n or -n
  761. self._tail = self._tail - inc
  762. if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then
  763. self._head = self._tail
  764. end
  765. return self
  766. end
  767. --- Gets the nth value of an iterator (and advances to it).
  768. ---
  769. --- If `n` is negative, offsets from the end of a |list-iterator|.
  770. ---
  771. --- Example:
  772. ---
  773. --- ```lua
  774. --- local it = vim.iter({ 3, 6, 9, 12 })
  775. --- it:nth(2)
  776. --- -- 6
  777. --- it:nth(2)
  778. --- -- 12
  779. ---
  780. --- local it2 = vim.iter({ 3, 6, 9, 12 })
  781. --- it2:nth(-2)
  782. --- -- 9
  783. --- it2:nth(-2)
  784. --- -- 3
  785. --- ```
  786. ---
  787. ---@param n number Index of the value to return. May be negative if the source is a |list-iterator|.
  788. ---@return any
  789. function Iter:nth(n)
  790. if n > 0 then
  791. return self:skip(n - 1):next()
  792. elseif n < 0 then
  793. return self:rskip(math.abs(n) - 1):pop()
  794. end
  795. end
  796. --- Sets the start and end of a |list-iterator| pipeline.
  797. ---
  798. --- Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
  799. ---
  800. ---@param first number
  801. ---@param last number
  802. ---@return Iter
  803. ---@diagnostic disable-next-line: unused-local
  804. function Iter:slice(first, last) -- luacheck: no unused args
  805. error('slice() requires an array-like table')
  806. end
  807. ---@private
  808. function ArrayIter:slice(first, last)
  809. return self:skip(math.max(0, first - 1)):rskip(math.max(0, self._tail - last - 1))
  810. end
  811. --- Returns true if any of the items in the iterator match the given predicate.
  812. ---
  813. ---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous
  814. --- stage in the pipeline as arguments and returns true if the
  815. --- predicate matches.
  816. function Iter:any(pred)
  817. local any = false
  818. --- Use a closure to handle var args returned from iterator
  819. local function fn(...)
  820. if select(1, ...) ~= nil then
  821. if pred(...) then
  822. any = true
  823. else
  824. return true
  825. end
  826. end
  827. end
  828. while fn(self:next()) do
  829. end
  830. return any
  831. end
  832. --- Returns true if all items in the iterator match the given predicate.
  833. ---
  834. ---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous
  835. --- stage in the pipeline as arguments and returns true if the
  836. --- predicate matches.
  837. function Iter:all(pred)
  838. local all = true
  839. local function fn(...)
  840. if select(1, ...) ~= nil then
  841. if not pred(...) then
  842. all = false
  843. else
  844. return true
  845. end
  846. end
  847. end
  848. while fn(self:next()) do
  849. end
  850. return all
  851. end
  852. --- Drains the iterator and returns the last item.
  853. ---
  854. --- Example:
  855. ---
  856. --- ```lua
  857. ---
  858. --- local it = vim.iter(vim.gsplit('abcdefg', ''))
  859. --- it:last()
  860. --- -- 'g'
  861. ---
  862. --- local it = vim.iter({ 3, 6, 9, 12, 15 })
  863. --- it:last()
  864. --- -- 15
  865. ---
  866. --- ```
  867. ---
  868. ---@see Iter.rpeek
  869. ---
  870. ---@return any
  871. function Iter:last()
  872. local last = self:next()
  873. local cur = self:next()
  874. while cur do
  875. last = cur
  876. cur = self:next()
  877. end
  878. return last
  879. end
  880. ---@private
  881. function ArrayIter:last()
  882. local inc = self._head < self._tail and 1 or -1
  883. local v = self._table[self._tail - inc]
  884. self._head = self._tail
  885. return v
  886. end
  887. --- Yields the item index (count) and value for each item of an iterator pipeline.
  888. ---
  889. --- For list tables, this is more efficient:
  890. ---
  891. --- ```lua
  892. --- vim.iter(ipairs(t))
  893. --- ```
  894. ---
  895. --- instead of:
  896. ---
  897. --- ```lua
  898. --- vim.iter(t):enumerate()
  899. --- ```
  900. ---
  901. --- Example:
  902. ---
  903. --- ```lua
  904. ---
  905. --- local it = vim.iter(vim.gsplit('abc', '')):enumerate()
  906. --- it:next()
  907. --- -- 1 'a'
  908. --- it:next()
  909. --- -- 2 'b'
  910. --- it:next()
  911. --- -- 3 'c'
  912. ---
  913. --- ```
  914. ---
  915. ---@return Iter
  916. function Iter:enumerate()
  917. local i = 0
  918. return self:map(function(...)
  919. i = i + 1
  920. return i, ...
  921. end)
  922. end
  923. ---@private
  924. function ArrayIter:enumerate()
  925. local inc = self._head < self._tail and 1 or -1
  926. for i = self._head, self._tail - inc, inc do
  927. local v = self._table[i]
  928. self._table[i] = pack(i, v)
  929. end
  930. return self
  931. end
  932. --- Creates a new Iter object from a table or other |iterable|.
  933. ---
  934. ---@param src table|function Table or iterator to drain values from
  935. ---@return Iter
  936. ---@private
  937. function Iter.new(src, ...)
  938. local it = {}
  939. if type(src) == 'table' then
  940. local mt = getmetatable(src)
  941. if mt and type(mt.__call) == 'function' then
  942. ---@private
  943. function it.next()
  944. return src()
  945. end
  946. setmetatable(it, Iter)
  947. return it
  948. end
  949. local t = {}
  950. -- O(n): scan the source table to decide if it is an array (only positive integer indices).
  951. for k, v in pairs(src) do
  952. if type(k) ~= 'number' or k <= 0 or math.floor(k) ~= k then
  953. return Iter.new(pairs(src))
  954. end
  955. t[#t + 1] = v -- Coerce to list-like table.
  956. end
  957. return ArrayIter.new(t)
  958. end
  959. if type(src) == 'function' then
  960. local s, var = ...
  961. --- Use a closure to handle var args returned from iterator
  962. local function fn(...)
  963. -- Per the Lua 5.1 reference manual, an iterator is complete when the first returned value is
  964. -- nil (even if there are other, non-nil return values). See |for-in|.
  965. if select(1, ...) ~= nil then
  966. var = select(1, ...)
  967. return ...
  968. end
  969. end
  970. ---@private
  971. function it.next()
  972. return fn(src(s, var))
  973. end
  974. setmetatable(it, Iter)
  975. else
  976. error('src must be a table or function')
  977. end
  978. return it
  979. end
  980. --- Create a new ArrayIter
  981. ---
  982. ---@param t table Array-like table. Caller guarantees that this table is a valid array. Can have
  983. --- holes (nil values).
  984. ---@return Iter
  985. ---@private
  986. function ArrayIter.new(t)
  987. local it = {}
  988. it._table = t
  989. it._head = 1
  990. it._tail = #t + 1
  991. setmetatable(it, ArrayIter)
  992. return it
  993. end
  994. return setmetatable(M, {
  995. __call = function(_, ...)
  996. return Iter.new(...)
  997. end,
  998. }) --[[@as IterMod]]