aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2023-11-25 06:35:31 -0800
committerGitHub <noreply@github.com>2023-11-25 06:35:31 -0800
commitfc4385ad94c0a12d2ce8b6d275d8336a740b04fd (patch)
tree8f508fca389d7cf5d8ec6fe4c62940af5ecdeda9
parent0da62b579fbd3a21c7ab808f1bb10263d469a1e9 (diff)
downloadrneovim-fc4385ad94c0a12d2ce8b6d275d8336a740b04fd.tar.gz
rneovim-fc4385ad94c0a12d2ce8b6d275d8336a740b04fd.tar.bz2
rneovim-fc4385ad94c0a12d2ce8b6d275d8336a740b04fd.zip
docs: vim.iter #26169
closes #24141 closes #24746
-rw-r--r--runtime/doc/develop.txt8
-rw-r--r--runtime/doc/lua.txt145
-rw-r--r--runtime/doc/news.txt9
-rw-r--r--runtime/lua/vim/iter.lua117
4 files changed, 129 insertions, 150 deletions
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index 107915d017..f1d74326c7 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -288,7 +288,13 @@ Interface conventions ~
- When accepting a buffer id, etc., 0 means "current buffer", nil means "all
buffers". Likewise for window id, tabpage id, etc.
- Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()|
-
+- Any function signature that accepts a callback function should define the
+ callback as the LAST parameter, if possible. This improves readability of
+ calls by placing the less "noisy" arguments near the start. >
+ GOOD:
+ filter(table, opts, function() … end)
+ BAD:
+ filter(function() … end, table, opts)
API DESIGN GUIDELINES *dev-api*
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index b155e646ab..a79b26dfb0 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -70,17 +70,23 @@ https://www.lua.org/doc/cacm2018.pdf
- Stackful coroutines enable cooperative multithreading, generators, and
versatile control for both Lua and its host (Nvim).
- *iterator*
+ *iterator*
An iterator is just a function that can be called repeatedly to get the "next"
value of a collection (or any other |iterable|). This interface is expected by
|for-in| loops, produced by |pairs()|, supported by |vim.iter|, etc.
https://www.lua.org/pil/7.1.html
- *iterable*
+ *iterable*
An "iterable" is anything that |vim.iter()| can consume: tables, dicts, lists,
iterator functions, tables implementing the |__call()| metamethod, and
|vim.iter()| objects.
+ *list-iterator*
+Iterators on |lua-list| tables have a "middle" and "end", whereas iterators in
+general may be logically infinite. Therefore some |vim.iter| operations (e.g.
+|Iter:rev()|) make sense only on list-like tables (which are finite by
+definition).
+
*lua-function-call*
Lua functions can be called in multiple ways. Consider the function: >lua
local foo = function(a, b)
@@ -332,8 +338,8 @@ Additionally Lua does not have integer numbers. To distinguish between these
cases there is the following agreement:
*lua-list*
0. Empty table is empty list.
-1. Table with N incrementally growing integral numbers, starting from 1 and
- ending with N is considered to be a list.
+1. Table with N consecutive integer indices starting from 1 and ending with
+ N is considered a list. See also |list-iterator|.
*lua-dict*
2. Table with string keys, none of which contains NUL byte, is considered to
be a dictionary.
@@ -3205,22 +3211,27 @@ Lua module: vim.iter *vim.iter*
*vim.iter()* is an interface for |iterable|s: it wraps a 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 (arrays) pass only the value of each element
-• Non-list tables (dictionaries) pass both the key and value of each
- element
-• Function |iterator|s pass all of the values returned by their respective
- function
-• Tables with a metatable implementing |__call()| are treated as function
- iterators
-
-The iterator pipeline terminates when the original table or function
-iterator runs out of values (for function iterators, this means that the
-first value returned by the function is nil).
+be chained to create iterator "pipelines": the output of each pipeline
+stage is input to the next stage. The first stage depends on the type
+passed to `vim.iter()`:
+
+• List tables (arrays, |lua-list|) yield only the value of each element.
+ • Use |Iter:enumerate()| to also pass the index to the next stage.
+ • Or initialize with ipairs(): `vim.iter(ipairs(…))`.
+
+• Non-list tables (|lua-dict|) yield both the key and value of each
+ element.
+• Function |iterator|s yield all values returned by the underlying
+ function.
+• Tables with a |__call()| metamethod are treated as function iterators.
+
+The iterator pipeline terminates when the underlying |iterable| is
+exhausted (for function iterators this means it returned nil).
+
+Note: `vim.iter()` scans table input to decide if it is a list or a dict;
+to avoid this cost you can wrap the table with an iterator e.g.
+`vim.iter(ipairs({…}))`, but that precludes the use of |list-iterator|
+operations such as |Iter:rev()|).
Examples: >lua
local it = vim.iter({ 1, 2, 3, 4, 5 })
@@ -3266,9 +3277,8 @@ 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
+ Filters a table or other |iterable|. >lua
+ -- Equivalent to:
vim.iter(src):filter(f):totable()
<
@@ -3285,7 +3295,7 @@ filter({f}, {src}, {...}) *vim.iter.filter()*
• |Iter:filter()|
Iter:all({pred}) *Iter:all()*
- Return true if all of the items in the iterator match the given predicate.
+ Returns true if all items in the iterator match the given predicate.
Parameters: ~
• {pred} function(...):bool Predicate function. Takes all values
@@ -3293,7 +3303,8 @@ Iter:all({pred}) *Iter:all()*
and returns true if the predicate matches.
Iter:any({pred}) *Iter:any()*
- Return true if any of the items in the iterator match the given predicate.
+ Returns true if any of the items in the iterator match the given
+ predicate.
Parameters: ~
• {pred} function(...):bool Predicate function. Takes all values
@@ -3301,12 +3312,11 @@ Iter:any({pred}) *Iter:any()*
and returns true if the predicate matches.
Iter:each({f}) *Iter:each()*
- Call a function once for each item in the pipeline.
-
- This is used for functions which have side effects. To modify the values
- in the iterator, use |Iter:map()|.
+ Calls a function once for each item in the pipeline, draining the
+ iterator.
- This function drains the iterator.
+ For functions with side effects. To modify the values in the iterator, use
+ |Iter:map()|.
Parameters: ~
• {f} function(...) Function to execute for each item in the pipeline.
@@ -3314,19 +3324,17 @@ Iter:each({f}) *Iter:each()*
pipeline as arguments.
Iter:enumerate() *Iter:enumerate()*
- Add an iterator stage that returns the current iterator count as well as
- the iterator value.
+ Yields the item index (count) and value for each item of an iterator
+ pipeline.
- For list tables, prefer >lua
+ For list tables, this is more efficient: >lua
vim.iter(ipairs(t))
<
- over >lua
+ instead of: >lua
vim.iter(t):enumerate()
<
- as the former is faster.
-
Example: >lua
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
it:next()
@@ -3341,7 +3349,7 @@ Iter:enumerate() *Iter:enumerate()*
Iter
Iter:filter({f}) *Iter:filter()*
- Add a filter step to the iterator pipeline.
+ Filters an iterator pipeline.
Example: >lua
local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded)
@@ -3379,7 +3387,7 @@ Iter:find({f}) *Iter:find()*
any
Iter:fold({init}, {f}) *Iter:fold()*
- Fold ("reduce") an iterator or table into a single value.
+ Folds ("reduces") an iterator into a single value.
Examples: >lua
-- Create a new table with only even values
@@ -3401,9 +3409,7 @@ Iter:fold({init}, {f}) *Iter:fold()*
any
Iter:last() *Iter:last()*
- Return the last item in the iterator.
-
- Drains the iterator.
+ Drains the iterator and returns the last item.
Example: >lua
local it = vim.iter(vim.gsplit('abcdefg', ''))
@@ -3419,7 +3425,7 @@ Iter:last() *Iter:last()*
any
Iter:map({f}) *Iter:map()*
- Add a map step to the iterator pipeline.
+ Maps the items of an iterator pipeline to the values returned by `f`.
If the map function returns nil, the value is filtered from the iterator.
@@ -3443,7 +3449,7 @@ Iter:map({f}) *Iter:map()*
Iter
Iter:next() *Iter:next()*
- Return the next value from the iterator.
+ Gets the next value from the iterator.
Example: >lua
local it = vim.iter(string.gmatch('1 2 3', '%d+')):map(tonumber)
@@ -3459,9 +3465,8 @@ Iter:next() *Iter:next()*
any
Iter:nextback() *Iter:nextback()*
- Return the next value from the end of the iterator.
-
- Only supported for iterators on list-like tables.
+ "Pops" a value from a |list-iterator| (gets the last value and decrements
+ the tail).
Example: >lua
local it = vim.iter({1, 2, 3, 4})
@@ -3475,9 +3480,7 @@ Iter:nextback() *Iter:nextback()*
any
Iter:nth({n}) *Iter:nth()*
- Return the nth value in the iterator.
-
- This function advances the iterator.
+ Gets the nth value of an iterator (and advances to it).
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 })
@@ -3494,11 +3497,7 @@ Iter:nth({n}) *Iter:nth()*
any
Iter:nthback({n}) *Iter:nthback()*
- Return the nth value from the end of the iterator.
-
- This function advances the iterator.
-
- Only supported for iterators on list-like tables.
+ Gets the nth value from the end of a |list-iterator| (and advances to it).
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 })
@@ -3515,9 +3514,7 @@ Iter:nthback({n}) *Iter:nthback()*
any
Iter:peek() *Iter:peek()*
- Peek at the next value in the iterator without consuming it.
-
- Only supported for iterators on list-like tables.
+ Gets the next value in a |list-iterator| without consuming it.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 })
@@ -3533,9 +3530,9 @@ Iter:peek() *Iter:peek()*
any
Iter:peekback() *Iter:peekback()*
- Return the next value from the end of the iterator without consuming it.
+ Gets the last value of a |list-iterator| without consuming it.
- Only supported for iterators on list-like tables.
+ See also |Iter:last()|.
Example: >lua
local it = vim.iter({1, 2, 3, 4})
@@ -3551,9 +3548,7 @@ Iter:peekback() *Iter:peekback()*
any
Iter:rev() *Iter:rev()*
- Reverse an iterator.
-
- Only supported for iterators on list-like tables.
+ Reverses a |list-iterator| pipeline.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }):rev()
@@ -3565,14 +3560,12 @@ Iter:rev() *Iter:rev()*
Iter
Iter:rfind({f}) *Iter:rfind()*
- Find the first value in the iterator that satisfies the given predicate,
+ Gets the first value in a |list-iterator| that satisfies a predicate,
starting from the end.
Advances the iterator. Returns nil and drains the iterator if no value is
found.
- Only supported for iterators on list-like tables.
-
Examples: >lua
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
it:rfind(1)
@@ -3588,7 +3581,7 @@ Iter:rfind({f}) *Iter:rfind()*
• Iter.find
Iter:skip({n}) *Iter:skip()*
- Skip values in the iterator.
+ Skips `n` values of an iterator pipeline.
Example: >lua
local it = vim.iter({ 3, 6, 9, 12 }):skip(2)
@@ -3603,9 +3596,7 @@ Iter:skip({n}) *Iter:skip()*
Iter
Iter:skipback({n}) *Iter:skipback()*
- Skip values in the iterator starting from the end.
-
- Only supported for iterators on list-like tables.
+ Skips `n` values backwards from the end of a |list-iterator| pipeline.
Example: >lua
local it = vim.iter({ 1, 2, 3, 4, 5 }):skipback(2)
@@ -3622,11 +3613,9 @@ Iter:skipback({n}) *Iter:skipback()*
Iter
Iter:slice({first}, {last}) *Iter:slice()*
- Slice an iterator, changing its start and end positions.
-
- This is equivalent to :skip(first - 1):skipback(len - last + 1)
+ Sets the start and end of a |list-iterator| pipeline.
- Only supported for iterators on list-like tables.
+ Equivalent to `:skip(first - 1):skipback(len - last + 1)`.
Parameters: ~
• {first} (number)
@@ -3662,9 +3651,8 @@ Iter:totable() *Iter:totable()*
(table)
map({f}, {src}, {...}) *vim.iter.map()*
- Map and filter a table or iterator.
-
- This is a convenience function that performs: >lua
+ Maps a table or other |iterable|. >lua
+ -- Equivalent to:
vim.iter(src):map(f):totable()
<
@@ -3681,9 +3669,8 @@ map({f}, {src}, {...}) *vim.iter.map()*
• |Iter:map()|
totable({f}, {...}) *vim.iter.totable()*
- Collect an iterator into a table.
-
- This is a convenience function that performs: >lua
+ Collects an |iterable| into a table. >lua
+ -- Equivalent to:
vim.iter(f):totable()
<
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 8073a4f162..b5bef13325 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -96,6 +96,15 @@ The following changes may require adaptations in user config or plugins.
line number -> priority -> sign id -> recently placed
==============================================================================
+BREAKING CHANGES IN HEAD *news-breaking-dev*
+
+The following breaking changes were made during the development cycle to
+unreleased features on Nvim HEAD.
+
+• ...
+• ...
+
+==============================================================================
NEW FEATURES *news-features*
The following new APIs and features were added.
diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua
index 595baa7019..874bdfb437 100644
--- a/runtime/lua/vim/iter.lua
+++ b/runtime/lua/vim/iter.lua
@@ -2,17 +2,23 @@
---
--- \*vim.iter()\* is an interface for |iterable|s: it wraps a 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:
+--- underlying source data. These methods can be chained to create iterator "pipelines": the output
+--- of each pipeline stage is input to the next stage. The first stage depends on the type passed to
+--- `vim.iter()`:
---
---- - List tables (arrays) pass only the value of each element
---- - Non-list tables (dictionaries) pass both the key and value of each element
---- - Function |iterator|s pass all of the values returned by their respective function
---- - Tables with a metatable implementing |__call()| are treated as function iterators
+--- - List tables (arrays, |lua-list|) yield only the value of each element.
+--- - Use |Iter:enumerate()| to also pass the index to the next stage.
+--- - Or initialize with ipairs(): `vim.iter(ipairs(…))`.
+--- - Non-list tables (|lua-dict|) yield both the key and value of each element.
+--- - Function |iterator|s yield all values returned by the underlying function.
+--- - Tables with a |__call()| metamethod are treated as function iterators.
---
---- The iterator pipeline terminates when the original table or function iterator runs out of values
---- (for function iterators, this means that the first value returned by the function is nil).
+--- The iterator pipeline terminates when the underlying |iterable| is exhausted (for function
+--- iterators this means it returned nil).
+---
+--- Note: `vim.iter()` scans table input to decide if it is a list or a dict; to avoid this cost you
+--- can wrap the table with an iterator e.g. `vim.iter(ipairs({…}))`, but that precludes the use of
+--- |list-iterator| operations such as |Iter:rev()|).
---
--- Examples:
---
@@ -138,7 +144,7 @@ local function apply(f, ...)
return false
end
---- Add a filter step to the iterator pipeline.
+--- Filters an iterator pipeline.
---
--- Example:
---
@@ -173,7 +179,7 @@ function ListIter.filter(self, f)
return self
end
---- Add a map step to the iterator pipeline.
+--- Maps the items of an iterator pipeline to the values returned by `f`.
---
--- If the map function returns nil, the value is filtered from the iterator.
---
@@ -253,12 +259,9 @@ function ListIter.map(self, f)
return self
end
---- Call a function once for each item in the pipeline.
----
---- This is used for functions which have side effects. To modify the values in
---- the iterator, use |Iter:map()|.
+--- Calls a function once for each item in the pipeline, draining the iterator.
---
---- This function drains the iterator.
+--- For functions with side effects. To modify the values in the iterator, use |Iter:map()|.
---
---@param f function(...) Function to execute for each item in the pipeline.
--- Takes all of the values returned by the previous stage
@@ -353,7 +356,7 @@ function ListIter.totable(self)
return self._table
end
---- Fold ("reduce") an iterator or table into a single value.
+--- Folds ("reduces") an iterator into a single value.
---
--- Examples:
---
@@ -400,7 +403,7 @@ function ListIter.fold(self, init, f)
return acc
end
---- Return the next value from the iterator.
+--- Gets the next value from the iterator.
---
--- Example:
---
@@ -432,9 +435,7 @@ function ListIter.next(self)
end
end
---- Reverse an iterator.
----
---- Only supported for iterators on list-like tables.
+--- Reverses a |list-iterator| pipeline.
---
--- Example:
---
@@ -459,9 +460,7 @@ function ListIter.rev(self)
return self
end
---- Peek at the next value in the iterator without consuming it.
----
---- Only supported for iterators on list-like tables.
+--- Gets the next value in a |list-iterator| without consuming it.
---
--- Example:
---
@@ -538,12 +537,10 @@ function Iter.find(self, f)
return unpack(result)
end
---- Find the first value in the iterator that satisfies the given predicate, starting from the end.
+--- Gets the first value in a |list-iterator| that satisfies a predicate, starting from the end.
---
--- Advances the iterator. Returns nil and drains the iterator if no value is found.
---
---- Only supported for iterators on list-like tables.
----
--- Examples:
---
--- ```lua
@@ -583,9 +580,7 @@ function ListIter.rfind(self, f) -- luacheck: no unused args
self._head = self._tail
end
---- Return the next value from the end of the iterator.
----
---- Only supported for iterators on list-like tables.
+--- "Pops" a value from a |list-iterator| (gets the last value and decrements the tail).
---
--- Example:
---
@@ -610,9 +605,9 @@ function ListIter.nextback(self)
end
end
---- Return the next value from the end of the iterator without consuming it.
+--- Gets the last value of a |list-iterator| without consuming it.
---
---- Only supported for iterators on list-like tables.
+--- See also |Iter:last()|.
---
--- Example:
---
@@ -638,7 +633,7 @@ function ListIter.peekback(self)
end
end
---- Skip values in the iterator.
+--- Skips `n` values of an iterator pipeline.
---
--- Example:
---
@@ -669,9 +664,7 @@ function ListIter.skip(self, n)
return self
end
---- Skip values in the iterator starting from the end.
----
---- Only supported for iterators on list-like tables.
+--- Skips `n` values backwards from the end of a |list-iterator| pipeline.
---
--- Example:
---
@@ -700,9 +693,7 @@ function ListIter.skipback(self, n)
return self
end
---- Return the nth value in the iterator.
----
---- This function advances the iterator.
+--- Gets the nth value of an iterator (and advances to it).
---
--- Example:
---
@@ -724,11 +715,7 @@ function Iter.nth(self, n)
end
end
---- Return the nth value from the end of the iterator.
----
---- This function advances the iterator.
----
---- Only supported for iterators on list-like tables.
+--- Gets the nth value from the end of a |list-iterator| (and advances to it).
---
--- Example:
---
@@ -750,11 +737,9 @@ function Iter.nthback(self, n)
end
end
---- Slice an iterator, changing its start and end positions.
+--- Sets the start and end of a |list-iterator| pipeline.
---
---- This is equivalent to :skip(first - 1):skipback(len - last + 1)
----
---- Only supported for iterators on list-like tables.
+--- Equivalent to `:skip(first - 1):skipback(len - last + 1)`.
---
---@param first number
---@param last number
@@ -769,7 +754,7 @@ function ListIter.slice(self, first, last)
return self:skip(math.max(0, first - 1)):skipback(math.max(0, self._tail - last - 1))
end
---- Return true if any of the items in the iterator match the given predicate.
+--- Returns true if any of the items in the iterator match the given predicate.
---
---@param pred function(...):bool Predicate function. Takes all values returned from the previous
--- stage in the pipeline as arguments and returns true if the
@@ -793,7 +778,7 @@ function Iter.any(self, pred)
return any
end
---- Return true if all of the items in the iterator match the given predicate.
+--- Returns true if all items in the iterator match the given predicate.
---
---@param pred function(...):bool Predicate function. Takes all values returned from the previous
--- stage in the pipeline as arguments and returns true if the
@@ -816,9 +801,7 @@ function Iter.all(self, pred)
return all
end
---- Return the last item in the iterator.
----
---- Drains the iterator.
+--- Drains the iterator and returns the last item.
---
--- Example:
---
@@ -853,22 +836,20 @@ function ListIter.last(self)
return v
end
---- Add an iterator stage that returns the current iterator count as well as the iterator value.
+--- Yields the item index (count) and value for each item of an iterator pipeline.
---
---- For list tables, prefer
+--- For list tables, this is more efficient:
---
--- ```lua
--- vim.iter(ipairs(t))
--- ```
---
---- over
+--- instead of:
---
--- ```lua
--- vim.iter(t):enumerate()
--- ```
---
---- as the former is faster.
----
--- Example:
---
--- ```lua
@@ -902,7 +883,7 @@ function ListIter.enumerate(self)
return self
end
---- Create a new Iter object from a table or iterator.
+--- Creates a new Iter object from a table or other |iterable|.
---
---@param src table|function Table or iterator to drain values from
---@return Iter
@@ -923,8 +904,7 @@ function Iter.new(src, ...)
local t = {}
- -- Check if source table can be treated like a list (indices are consecutive integers
- -- starting from 1)
+ -- O(n): scan the source table to decide if it is a list (consecutive integer indices 1…n).
local count = 0
for _ in pairs(src) do
count = count + 1
@@ -976,11 +956,10 @@ function ListIter.new(t)
return it
end
---- Collect an iterator into a table.
----
---- This is a convenience function that performs:
+--- Collects an |iterable| into a table.
---
--- ```lua
+--- -- Equivalent to:
--- vim.iter(f):totable()
--- ```
---
@@ -990,11 +969,10 @@ function M.totable(f, ...)
return Iter.new(f, ...):totable()
end
---- Filter a table or iterator.
----
---- This is a convenience function that performs:
+--- Filters a table or other |iterable|.
---
--- ```lua
+--- -- Equivalent to:
--- vim.iter(src):filter(f):totable()
--- ```
---
@@ -1009,11 +987,10 @@ 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:
+--- Maps a table or other |iterable|.
---
--- ```lua
+--- -- Equivalent to:
--- vim.iter(src):map(f):totable()
--- ```
---