mirror of
https://github.com/neovim/neovim.git
synced 2026-05-23 21:30:11 +00:00
fix(vim.iter): add richer generic annotations
Improve the vim.iter annotations with richer generics that track element and tuple types through iterator pipelines, including multi-value stages and list-specific methods. Extend the LuaCATS parser and vimdoc generator so those richer generic classes and overloads round-trip into the generated help. These annotations are only supported by EmmyLua, so LuaLS still uses a broader fallback in _meta.lua. AI-assisted: Codex
This commit is contained in:
committed by
Lewis Russell
parent
2b7a00746d
commit
d7ef55e881
@@ -180,7 +180,7 @@ LSP
|
||||
LUA
|
||||
• *vim.loop* Use |vim.uv| instead.
|
||||
• *vim.tbl_add_reverse_lookup()*
|
||||
• *vim.tbl_flatten()* Use |Iter:flatten()| instead.
|
||||
• *vim.tbl_flatten()* Use |IterArray:flatten()| instead.
|
||||
• *vim.tbl_islist()* Use |vim.islist()| instead.
|
||||
|
||||
OPTIONS
|
||||
|
||||
@@ -128,7 +128,7 @@ iterator functions, tables implementing the |__call()| metamethod, and
|
||||
*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
|
||||
|IterArray:rev()|) make sense only on list-like tables (which are finite by
|
||||
definition).
|
||||
|
||||
*lua-function-call*
|
||||
@@ -3028,7 +3028,7 @@ The iterator pipeline terminates when the underlying |iterable| is exhausted
|
||||
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()|).
|
||||
operations such as |IterArray:rev()|).
|
||||
|
||||
Examples: >lua
|
||||
local it = vim.iter({ 1, 2, 3, 4, 5 })
|
||||
@@ -3077,9 +3077,9 @@ Iter:all({pred}) *Iter:all()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {pred} (`fun(...):boolean`) Predicate function. Takes all values
|
||||
returned from the previous stage in the pipeline as arguments
|
||||
and returns true if the predicate matches.
|
||||
• {pred} (`fun(v: V1, ...: V...): boolean`) Predicate function. Takes
|
||||
all values returned from the previous stage in the pipeline as
|
||||
arguments and returns true if the predicate matches.
|
||||
|
||||
Iter:any({pred}) *Iter:any()*
|
||||
Returns true if any of the items in the iterator match the given
|
||||
@@ -3089,9 +3089,9 @@ Iter:any({pred}) *Iter:any()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {pred} (`fun(...):boolean`) Predicate function. Takes all values
|
||||
returned from the previous stage in the pipeline as arguments
|
||||
and returns true if the predicate matches.
|
||||
• {pred} (`fun(v: V1, ...: V...): boolean`) Predicate function. Takes
|
||||
all values returned from the previous stage in the pipeline as
|
||||
arguments and returns true if the predicate matches.
|
||||
|
||||
Iter:each({f}) *Iter:each()*
|
||||
Calls a function once for each item in the pipeline, draining the
|
||||
@@ -3104,9 +3104,9 @@ Iter:each({f}) *Iter:each()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {f} (`fun(...)`) Function to execute for each item in the pipeline.
|
||||
Takes all of the values returned by the previous stage in the
|
||||
pipeline as arguments.
|
||||
• {f} (`fun(v: V1, ...: V...)`) Function to execute for each item in
|
||||
the pipeline. Takes all of the values returned by the previous
|
||||
stage in the pipeline as arguments.
|
||||
|
||||
Iter:enumerate() *Iter:enumerate()*
|
||||
Yields the item index (count) and value for each item of an iterator
|
||||
@@ -3134,8 +3134,11 @@ Iter:enumerate() *Iter:enumerate()*
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Overloads: ~
|
||||
• `fun<V1, V...>(self: vim.IterArray<V1, V...>): vim.IterArray<integer, V1, V...>`
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
(`vim.Iter<integer, V1, V...>`)
|
||||
|
||||
Iter:filter({f}) *Iter:filter()*
|
||||
Filters an iterator pipeline.
|
||||
@@ -3145,12 +3148,15 @@ Iter:filter({f}) *Iter:filter()*
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {f} (`fun(...):boolean`) Takes all values returned from the previous
|
||||
stage in the pipeline and returns false or nil if the current
|
||||
iterator element should be removed.
|
||||
• {f} (`fun(v: V1, ...: V...): boolean`) Takes all values returned from
|
||||
the previous stage in the pipeline and returns false or nil if
|
||||
the current iterator element should be removed.
|
||||
|
||||
Overloads: ~
|
||||
• `fun<V1, V...>(self: vim.IterArray<V1, V...>, f: fun(v: V1, ...: V...): boolean): vim.IterArray<V1, V...>`
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
(`vim.Iter<V1, V...>`)
|
||||
|
||||
Iter:find({f}) *Iter:find()*
|
||||
Find the first value in the iterator that satisfies the given predicate.
|
||||
@@ -3177,35 +3183,14 @@ Iter:find({f}) *Iter:find()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {f} (`any`)
|
||||
• {f} (`(fun(v: V1, ...: V...): boolean)|any`)
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
Overloads: ~
|
||||
• `fun<V1, V...>(self: vim.IterArray<V1, V...>, f: V1|fun(v: V1, ...: V...): boolean): V1?, V...`
|
||||
|
||||
Iter:flatten({depth}) *Iter:flatten()*
|
||||
Flattens a |list-iterator|, un-nesting nested values up to the given
|
||||
{depth}. Errors if it attempts to flatten a dict-like value.
|
||||
|
||||
Examples: >lua
|
||||
vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable()
|
||||
-- { 1, 2, { 3 } }
|
||||
|
||||
vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable()
|
||||
-- { 1, { a = 2 }, 3 }
|
||||
|
||||
vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable()
|
||||
-- error: attempt to flatten a dict-like table
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {depth} (`number?`) Depth to which |list-iterator| should be
|
||||
flattened (defaults to 1)
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
Iter:fold({init}, {f}) *Iter:fold()*
|
||||
Folds ("reduces") an iterator into a single value. *Iter:reduce()*
|
||||
@@ -3232,7 +3217,7 @@ Iter:fold({init}, {f}) *Iter:fold()*
|
||||
|
||||
Parameters: ~
|
||||
• {init} (`any`) Initial value of the accumulator.
|
||||
• {f} (`fun(acc:A, ...):A`) Accumulation function.
|
||||
• {f} (`fun(acc: A, v: V1, ...: V...): A`) Accumulation function.
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
@@ -3270,11 +3255,12 @@ Iter:last() *Iter:last()*
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
See also: ~
|
||||
• |Iter:rpeek()|
|
||||
• |IterArray:rpeek()|
|
||||
|
||||
Iter:map({f}) *Iter:map()*
|
||||
Maps the items of an iterator pipeline to the values returned by `f`.
|
||||
@@ -3295,13 +3281,17 @@ Iter:map({f}) *Iter:map()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {f} (`fun(...):...:any`) Mapping function. Takes all values returned
|
||||
from the previous stage in the pipeline as arguments and returns
|
||||
one or more new values, which are used in the next pipeline
|
||||
stage. Nil return values are filtered from the output.
|
||||
• {f} (`fun(v: V1, ...: V...): K2, V2...`) Mapping function. Takes all
|
||||
values returned from the previous stage in the pipeline as
|
||||
arguments and returns one or more new values, which are used in
|
||||
the next pipeline stage. Nil return values are filtered from the
|
||||
output.
|
||||
|
||||
Overloads: ~
|
||||
• `fun<V1, V..., K1, K...>(self: vim.IterArray<V1, V...>, f: fun(v: V1, ...: V...): K1, K...): vim.IterArray<K1, K...>`
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
(`vim.Iter<K2, V2...>`)
|
||||
|
||||
Iter:next() *Iter:next()*
|
||||
Gets the next value from the iterator.
|
||||
@@ -3320,8 +3310,9 @@ Iter:next() *Iter:next()*
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
Iter:nth({n}) *Iter:nth()*
|
||||
Gets the nth value of an iterator (and advances to it).
|
||||
@@ -3346,11 +3337,12 @@ Iter:nth({n}) *Iter:nth()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`number`) Index of the value to return. May be negative if the
|
||||
• {n} (`integer`) Index of the value to return. May be negative if the
|
||||
source is a |list-iterator|.
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
Iter:peek() *Iter:peek()*
|
||||
Gets the next value from the iterator without consuming it.
|
||||
@@ -3372,112 +3364,9 @@ Iter:peek() *Iter:peek()*
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
Iter:pop() *Iter:pop()*
|
||||
"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})
|
||||
it:pop()
|
||||
-- 4
|
||||
it:pop()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
Iter:rev() *Iter:rev()*
|
||||
Reverses a |list-iterator| pipeline.
|
||||
|
||||
Example: >lua
|
||||
|
||||
local it = vim.iter({ 3, 6, 9, 12 }):rev()
|
||||
it:totable()
|
||||
-- { 12, 9, 6, 3 }
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
|
||||
Iter:rfind({f}) *Iter:rfind()*
|
||||
Gets the first value satisfying a predicate, from the end of a
|
||||
|list-iterator|.
|
||||
|
||||
Advances the iterator. Returns nil and drains the iterator if no value is
|
||||
found.
|
||||
|
||||
Examples: >lua
|
||||
|
||||
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
|
||||
it:rfind(1)
|
||||
-- 5 1
|
||||
it:rfind(1)
|
||||
-- 1 1
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {f} (`any`)
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
See also: ~
|
||||
• |Iter:find()|
|
||||
|
||||
Iter:rpeek() *Iter:rpeek()*
|
||||
Gets the last value of a |list-iterator| without consuming it.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({1, 2, 3, 4})
|
||||
it:rpeek()
|
||||
-- 4
|
||||
it:rpeek()
|
||||
-- 4
|
||||
it:pop()
|
||||
-- 4
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
See also: ~
|
||||
• |Iter:last()|
|
||||
|
||||
Iter:rskip({n}) *Iter:rskip()*
|
||||
Discards `n` values from the end of a |list-iterator| pipeline.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2)
|
||||
it:next()
|
||||
-- 1
|
||||
it:pop()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`number`) Number of values to skip.
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
Iter:skip({n}) *Iter:skip()*
|
||||
Skips `n` values of an iterator pipeline, or skips values while a
|
||||
@@ -3503,26 +3392,14 @@ Iter:skip({n}) *Iter:skip()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`integer|fun(...):boolean`) Number of values to skip or a
|
||||
predicate.
|
||||
• {n} (`integer|fun(v: V1, ...: V...): boolean`) Number of values to
|
||||
skip or a predicate.
|
||||
|
||||
Overloads: ~
|
||||
• `fun<V1, V...>(self: vim.IterArray<V1, V...>, n: integer|fun(v: V1, ...: V...): boolean): vim.IterArray<V1, V...>`
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
|
||||
Iter:slice({first}, {last}) *Iter:slice()*
|
||||
Sets the start and end of a |list-iterator| pipeline.
|
||||
|
||||
Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {first} (`number`)
|
||||
• {last} (`number`)
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
(`vim.Iter<V1, V...>`)
|
||||
|
||||
Iter:take({n}) *Iter:take()*
|
||||
Transforms an iterator to yield only the first n values, or all values
|
||||
@@ -3549,11 +3426,14 @@ Iter:take({n}) *Iter:take()*
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`integer|fun(...):boolean`) Number of values to take or a
|
||||
predicate.
|
||||
• {n} (`integer|fun(v: V1, ...: V...): boolean`) Number of values to
|
||||
take or a predicate.
|
||||
|
||||
Overloads: ~
|
||||
• `fun<V1, V...>(self: vim.IterArray<V1, V...>, n: integer|fun(v: V1, ...: V...): boolean): vim.IterArray<V1, V...>`
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
(`vim.Iter<V1, V...>`)
|
||||
|
||||
Iter:totable() *Iter:totable()*
|
||||
Collect the iterator into a table.
|
||||
@@ -3581,8 +3461,12 @@ Iter:totable() *Iter:totable()*
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Overloads: ~
|
||||
• `fun<T>(self: vim.Iter<T>): T[]`
|
||||
• `fun<V1, V2, V...>(self: vim.Iter<V1, V2, V...>): [V1, V2, V...][]`
|
||||
|
||||
Return: ~
|
||||
(`table`)
|
||||
(`any[]`)
|
||||
|
||||
Iter:unique({key}) *Iter:unique()*
|
||||
Removes duplicate values from an iterator pipeline.
|
||||
@@ -3615,15 +3499,165 @@ Iter:unique({key}) *Iter:unique()*
|
||||
Since: 0.12.0
|
||||
|
||||
Parameters: ~
|
||||
• {key} (`fun(...):any?`) Optional hash function to determine
|
||||
uniqueness of values.
|
||||
• {key} (`fun(v: V1, ...: V...): any?`) Optional hash function to
|
||||
determine uniqueness of values.
|
||||
|
||||
Overloads: ~
|
||||
• `fun<V1, V...>(self: vim.IterArray<V1, V...>, key: fun(v: V1, ...: V...): any?): vim.IterArray<V1, V...>`
|
||||
|
||||
Return: ~
|
||||
(`Iter`)
|
||||
(`vim.Iter<V1, V...>`)
|
||||
|
||||
See also: ~
|
||||
• |vim.list.unique()|
|
||||
|
||||
IterArray:flatten({depth}) *IterArray:flatten()*
|
||||
Flattens a |list-iterator|, un-nesting nested values up to the given
|
||||
{depth}. Errors if it attempts to flatten a dict-like value.
|
||||
|
||||
Examples: >lua
|
||||
vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable()
|
||||
-- { 1, 2, { 3 } }
|
||||
|
||||
vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable()
|
||||
-- { 1, { a = 2 }, 3 }
|
||||
|
||||
vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable()
|
||||
-- error: attempt to flatten a dict-like table
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {depth} (`integer?`) Depth to which |list-iterator| should be
|
||||
flattened (defaults to 1)
|
||||
|
||||
Return: ~
|
||||
(`vim.IterArray<V1, V...>`)
|
||||
|
||||
IterArray:pop() *IterArray:pop()*
|
||||
"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})
|
||||
it:pop()
|
||||
-- 4
|
||||
it:pop()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
IterArray:rev() *IterArray:rev()*
|
||||
Reverses a |list-iterator| pipeline.
|
||||
|
||||
Example: >lua
|
||||
|
||||
local it = vim.iter({ 3, 6, 9, 12 }):rev()
|
||||
it:totable()
|
||||
-- { 12, 9, 6, 3 }
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return: ~
|
||||
(`vim.IterArray<V1, V...>`)
|
||||
|
||||
IterArray:rfind({f}) *IterArray:rfind()*
|
||||
Gets the first value satisfying a predicate, from the end of a
|
||||
|list-iterator|.
|
||||
|
||||
Advances the iterator. Returns nil and drains the iterator if no value is
|
||||
found.
|
||||
|
||||
Examples: >lua
|
||||
|
||||
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
|
||||
it:rfind(1)
|
||||
-- 5 1
|
||||
it:rfind(1)
|
||||
-- 1 1
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {f} (`V1|fun(v: V1, ...: V...): boolean`)
|
||||
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
See also: ~
|
||||
• |Iter:find()|
|
||||
|
||||
IterArray:rpeek() *IterArray:rpeek()*
|
||||
Gets the last value of a |list-iterator| without consuming it.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({1, 2, 3, 4})
|
||||
it:rpeek()
|
||||
-- 4
|
||||
it:rpeek()
|
||||
-- 4
|
||||
it:pop()
|
||||
-- 4
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Return (multiple): ~
|
||||
(`V1?`)
|
||||
(`V...`)
|
||||
|
||||
See also: ~
|
||||
• |Iter:last()|
|
||||
|
||||
IterArray:rskip({n}) *IterArray:rskip()*
|
||||
Discards `n` values from the end of a |list-iterator| pipeline.
|
||||
|
||||
Example: >lua
|
||||
local it = vim.iter({ 1, 2, 3, 4, 5 }):rskip(2)
|
||||
it:next()
|
||||
-- 1
|
||||
it:pop()
|
||||
-- 3
|
||||
<
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {n} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`vim.IterArray<V1, V...>`)
|
||||
|
||||
IterArray:slice({first}, {last}) *IterArray:slice()*
|
||||
Sets the start and end of a |list-iterator| pipeline.
|
||||
|
||||
Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
|
||||
|
||||
Attributes: ~
|
||||
Since: 0.10.0
|
||||
|
||||
Parameters: ~
|
||||
• {first} (`integer`)
|
||||
• {last} (`integer`)
|
||||
|
||||
Return: ~
|
||||
(`vim.IterArray<V1, V...>`)
|
||||
|
||||
|
||||
==============================================================================
|
||||
Lua module: vim.json *vim.json*
|
||||
|
||||
@@ -7,6 +7,59 @@ error('Cannot require a meta file')
|
||||
---@type uv
|
||||
vim.uv = ...
|
||||
|
||||
--- LuaLS fallback surface for the richer iterator annotations in `vim.iter`.
|
||||
--- EmmyLua reads the precise generics from `runtime/lua/vim/iter.lua`; LuaLS uses
|
||||
--- these broader shapes for downstream type-checking.
|
||||
--- @class vim.Iter
|
||||
--- @field filter fun(self: vim.Iter, f: fun(...): boolean): vim.Iter
|
||||
--- @field unique fun(self: vim.Iter, key?: fun(...): any): vim.Iter
|
||||
--- @field flatten fun(self: vim.Iter, depth?: integer): vim.IterArray
|
||||
--- @field map fun(self: vim.Iter, f: fun(...): ...): vim.Iter
|
||||
--- @field each fun(self: vim.Iter, f: fun(...)): nil
|
||||
--- @field totable fun(self: vim.Iter): table
|
||||
--- @field join fun(self: vim.Iter, delim: string): string
|
||||
--- @field fold fun(self: vim.Iter, init: any, f: fun(acc: any, ...): any): any
|
||||
--- @field next fun(self: vim.Iter): any
|
||||
--- @field rev fun(self: vim.Iter): vim.IterArray
|
||||
--- @field peek fun(self: vim.Iter): any
|
||||
--- @field find fun(self: vim.Iter, f: any): any
|
||||
--- @field rfind fun(self: vim.Iter, f: any): any
|
||||
--- @field take fun(self: vim.Iter, n: integer|fun(...): boolean): vim.Iter
|
||||
--- @field pop fun(self: vim.Iter): any
|
||||
--- @field rpeek fun(self: vim.Iter): any
|
||||
--- @field skip fun(self: vim.Iter, n: integer|fun(...): boolean): vim.Iter
|
||||
--- @field rskip fun(self: vim.Iter, n: integer): vim.IterArray
|
||||
--- @field nth fun(self: vim.Iter, n: integer): any
|
||||
--- @field slice fun(self: vim.Iter, first: integer, last: integer): vim.IterArray
|
||||
--- @field any fun(self: vim.Iter, pred: fun(...): boolean): boolean
|
||||
--- @field all fun(self: vim.Iter, pred: fun(...): boolean): boolean
|
||||
--- @field last fun(self: vim.Iter): any
|
||||
--- @field enumerate fun(self: vim.Iter): vim.Iter
|
||||
|
||||
--- @class vim.IterArray : vim.Iter
|
||||
--- @field filter fun(self: vim.IterArray, f: fun(...): boolean): vim.IterArray
|
||||
--- @field unique fun(self: vim.IterArray, key?: fun(...): any): vim.IterArray
|
||||
--- @field flatten fun(self: vim.IterArray, depth?: integer): vim.IterArray
|
||||
--- @field map fun(self: vim.IterArray, f: fun(...): ...): vim.IterArray
|
||||
--- @field totable fun(self: vim.IterArray): table
|
||||
--- @field fold fun(self: vim.IterArray, init: any, f: fun(acc: any, ...): any): any
|
||||
--- @field next fun(self: vim.IterArray): any
|
||||
--- @field rev fun(self: vim.IterArray): vim.IterArray
|
||||
--- @field peek fun(self: vim.IterArray): any
|
||||
--- @field find fun(self: vim.IterArray, f: any): any
|
||||
--- @field rfind fun(self: vim.IterArray, f: any): any
|
||||
--- @field take fun(self: vim.IterArray, n: integer|fun(...): boolean): vim.IterArray
|
||||
--- @field pop fun(self: vim.IterArray): any
|
||||
--- @field rpeek fun(self: vim.IterArray): any
|
||||
--- @field skip fun(self: vim.IterArray, n: integer|fun(...): boolean): vim.IterArray
|
||||
--- @field rskip fun(self: vim.IterArray, n: integer): vim.IterArray
|
||||
--- @field slice fun(self: vim.IterArray, first: integer, last: integer): vim.IterArray
|
||||
--- @field last fun(self: vim.IterArray): any
|
||||
--- @field enumerate fun(self: vim.IterArray): vim.IterArray
|
||||
|
||||
--- @class vim.IterModule
|
||||
--- @operator call: fun(src: any, ...): vim.Iter
|
||||
|
||||
--- The following modules are loaded specially in _init_packages.lua
|
||||
|
||||
vim.F = require('vim.F')
|
||||
@@ -18,7 +71,11 @@ vim.func = require('vim.func')
|
||||
vim.glob = require('vim.glob')
|
||||
vim.health = require('vim.health')
|
||||
vim.hl = require('vim.hl')
|
||||
vim.iter = require('vim.iter')
|
||||
local iter = require('vim.iter')
|
||||
-- `require('vim.iter')` carries the richer EmmyLua generic surface. Force
|
||||
-- LuaLS onto the fallback module shape above so `make luals` stays clean.
|
||||
---@cast iter vim.IterModule
|
||||
vim.iter = iter
|
||||
vim.keymap = require('vim.keymap')
|
||||
vim.loader = require('vim.loader')
|
||||
vim.lsp = require('vim.lsp')
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
---
|
||||
--- 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()|).
|
||||
--- |list-iterator| operations such as |IterArray:rev()|).
|
||||
---
|
||||
--- Examples:
|
||||
---
|
||||
@@ -64,36 +64,38 @@
|
||||
--- -- { "a", "b" }
|
||||
--- ```
|
||||
|
||||
--- LuaLS is bad at generics which this module mostly deals with
|
||||
--- @diagnostic disable:no-unknown
|
||||
|
||||
---@nodoc
|
||||
---@class IterMod
|
||||
---@operator call:Iter
|
||||
-- LuaLS cannot model the variadic EmmyLua generics used by this module.
|
||||
---@diagnostic disable: no-unknown, undefined-doc-name, luadoc-miss-symbol, missing-return, missing-return-value, param-type-mismatch, return-type-mismatch, redundant-return-value, undefined-field
|
||||
|
||||
--- @nodoc
|
||||
--- @class vim.IterModule
|
||||
--- @operator call: vim.Iter<any, any...>
|
||||
--- @overload fun<T>(src: T[]): vim.IterArray<T>
|
||||
--- @overload fun<K, V>(src: table<K, V>): vim.Iter<K, V>
|
||||
--- @overload fun(src: table, ...): vim.Iter<any, any...>
|
||||
--- @overload fun(src: function, ...): vim.Iter<any, any...>
|
||||
local M = {}
|
||||
|
||||
---@nodoc
|
||||
---@class Iter
|
||||
---@field _peeked any
|
||||
---@field _next fun():... The underlying function that returns the next value(s) from the source.
|
||||
--- @nodoc
|
||||
--- @class vim.Iter<V1, V...>
|
||||
--- @field private _peeked V1|[V1, V...]? Cached peek value, if any. Nil if no value is peeked.
|
||||
--- @field private _next fun(): V1, V... The underlying function that returns the next packed value from the source.
|
||||
--- @overload fun(self: vim.Iter<V1, V...>): V1?, V...
|
||||
local Iter = {}
|
||||
Iter.__index = Iter
|
||||
Iter.__call = function(self)
|
||||
return self:next()
|
||||
end
|
||||
|
||||
--- Special case implementations for iterators on list tables.
|
||||
---@nodoc
|
||||
---@class ArrayIter : Iter
|
||||
---@field _table table Underlying table data
|
||||
---@field _head number Index to the front of a table iterator
|
||||
---@field _tail number Index to the end of a table iterator (exclusive)
|
||||
local ArrayIter = {}
|
||||
ArrayIter.__index = setmetatable(ArrayIter, Iter)
|
||||
ArrayIter.__call = function(self)
|
||||
return self:next()
|
||||
end
|
||||
-- Special case implementations for iterators on list tables.
|
||||
--- @nodoc
|
||||
--- @class vim.IterArray<V1, V...> : vim.Iter<V1, V...>
|
||||
--- @field private _table (V1|[V1, V...])[] Underlying table data. Items may be packed tuples after transforms.
|
||||
--- @field private _head integer Index to the front of a table iterator
|
||||
--- @field private _tail integer Index to the end of a table iterator (exclusive)
|
||||
local IterArray = setmetatable({}, Iter)
|
||||
IterArray.__index = IterArray
|
||||
IterArray.__call = Iter.__call
|
||||
|
||||
--- Packed tables use this as their metatable
|
||||
local packedmt = {}
|
||||
@@ -105,6 +107,9 @@ local function unpack(t)
|
||||
return t
|
||||
end
|
||||
|
||||
--- @generic T...
|
||||
--- @param ... T... Values to pack
|
||||
--- @return T|[T...]
|
||||
local function pack(...)
|
||||
local n = select('#', ...)
|
||||
if n > 1 then
|
||||
@@ -124,11 +129,11 @@ end
|
||||
|
||||
--- Flattens a single array-like table. Errors if it attempts to flatten a
|
||||
--- dict-like table
|
||||
---@param t table table which should be flattened
|
||||
---@param max_depth number depth to which the table should be flattened
|
||||
---@param depth number current iteration depth
|
||||
---@param result table output table that contains flattened result
|
||||
---@return table|nil flattened table if it can be flattened, otherwise nil
|
||||
--- @param t table table which should be flattened
|
||||
--- @param max_depth integer depth to which the table should be flattened
|
||||
--- @param depth integer current iteration depth
|
||||
--- @param result table output table that contains flattened result
|
||||
--- @return table? flattened table if it can be flattened, otherwise nil
|
||||
local function flatten(t, max_depth, depth, result)
|
||||
if depth < max_depth and type(t) == 'table' then
|
||||
for k, v in pairs(t) do
|
||||
@@ -154,9 +159,9 @@ end
|
||||
--- and stop the current iterator stage. Otherwise, return true to signal that
|
||||
--- the current stage should continue.
|
||||
---
|
||||
---@param ... any Function arguments.
|
||||
---@return boolean True if the iterator stage should continue, false otherwise
|
||||
---@return any Function arguments.
|
||||
--- @param ... any Function arguments.
|
||||
--- @return boolean True if the iterator stage should continue, false otherwise
|
||||
--- @return any Function arguments.
|
||||
local function continue(...)
|
||||
if select(1, ...) ~= nil then
|
||||
return false, ...
|
||||
@@ -169,10 +174,11 @@ end
|
||||
--- f. If that function returns no values, the current iterator stage continues.
|
||||
--- Otherwise, those values are returned.
|
||||
---
|
||||
---@param f function Function to call with the given arguments
|
||||
---@param ... any Arguments to apply to f
|
||||
---@return boolean True if the iterator pipeline should continue, false otherwise
|
||||
---@return any Return values of f
|
||||
--- @generic T, R
|
||||
--- @param f fun(...:T...): R... Function to call with the given arguments
|
||||
--- @param ... T... Arguments to apply to f
|
||||
--- @return boolean : True if the iterator pipeline should continue, false otherwise
|
||||
--- @return R... : Return values of f
|
||||
local function apply(f, ...)
|
||||
if select(1, ...) ~= nil then
|
||||
return continue(f(...))
|
||||
@@ -188,10 +194,11 @@ end
|
||||
--- local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded)
|
||||
--- ```
|
||||
---
|
||||
---@param f fun(...):boolean Takes all values returned from the previous stage
|
||||
--- @param f fun(v: V1, ...: V...): boolean Takes all values returned from the previous stage
|
||||
--- in the pipeline and returns false or nil if the
|
||||
--- current iterator element should be removed.
|
||||
---@return Iter
|
||||
--- @return vim.Iter<V1, V...>
|
||||
--- @overload fun<V1, V...>(self: vim.IterArray<V1, V...>, f: fun(v: V1, ...: V...): boolean): vim.IterArray<V1, V...>
|
||||
function Iter:filter(f)
|
||||
return self:map(function(...)
|
||||
if f(...) then
|
||||
@@ -200,8 +207,10 @@ function Iter:filter(f)
|
||||
end)
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:filter(f)
|
||||
--- @nodoc
|
||||
--- @param f fun(v: V1, ...: V...): boolean
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:filter(f)
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
local n = self._head
|
||||
for i = self._head, self._tail - inc, inc do
|
||||
@@ -243,10 +252,11 @@ end
|
||||
--- -- { {id=1}, {id=2} }
|
||||
--- ```
|
||||
---
|
||||
---@since 14
|
||||
---@param key? fun(...):any Optional hash function to determine uniqueness of values.
|
||||
---@return Iter
|
||||
---@see |vim.list.unique()|
|
||||
--- @since 14
|
||||
--- @param key? fun(v: V1, ...: V...): any Optional hash function to determine uniqueness of values.
|
||||
--- @return vim.Iter<V1, V...>
|
||||
--- @overload fun<V1, V...>(self: vim.IterArray<V1, V...>, key: fun(v: V1, ...: V...): any?): vim.IterArray<V1, V...>
|
||||
--- @see |vim.list.unique()|
|
||||
function Iter:unique(key)
|
||||
local seen = {} --- @type table<any,boolean>
|
||||
|
||||
@@ -267,6 +277,12 @@ function Iter:unique(key)
|
||||
end)
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line:unused-local
|
||||
function Iter:flatten(depth)
|
||||
error('flatten() requires an array-like table')
|
||||
end
|
||||
|
||||
--- Flattens a |list-iterator|, un-nesting nested values up to the given {depth}.
|
||||
--- Errors if it attempts to flatten a dict-like value.
|
||||
---
|
||||
@@ -283,17 +299,11 @@ end
|
||||
--- -- error: attempt to flatten a dict-like table
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@param depth? number Depth to which |list-iterator| should be flattened
|
||||
--- @since 12
|
||||
--- @param depth? integer Depth to which |list-iterator| should be flattened
|
||||
--- (defaults to 1)
|
||||
---@return Iter
|
||||
---@diagnostic disable-next-line:unused-local
|
||||
function Iter:flatten(depth) -- luacheck: no unused args
|
||||
error('flatten() requires an array-like table')
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:flatten(depth)
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:flatten(depth)
|
||||
depth = depth or 1
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
local target = {}
|
||||
@@ -333,13 +343,15 @@ end
|
||||
--- -- { 6, 12 }
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@param f fun(...):...:any Mapping function. Takes all values returned from
|
||||
--- @since 12
|
||||
--- @generic K2, V2...
|
||||
--- @param f fun(v: V1, ...: V...): K2, V2... Mapping function. Takes all values returned from
|
||||
--- the previous stage in the pipeline as arguments
|
||||
--- and returns one or more new values, which are used
|
||||
--- in the next pipeline stage. Nil return values
|
||||
--- are filtered from the output.
|
||||
---@return Iter
|
||||
--- @return vim.Iter<K2, V2...>
|
||||
--- @overload fun<V1, V..., K1, K...>(self: vim.IterArray<V1, V...>, f: fun(v: V1, ...: V...): K1, K...): vim.IterArray<K1, K...>
|
||||
function Iter:map(f)
|
||||
-- Implementation note: the reader may be forgiven for observing that this
|
||||
-- function appears excessively convoluted. The problem to solve is that each
|
||||
@@ -364,12 +376,12 @@ function Iter:map(f)
|
||||
--- false, which indicates that the rest of the arguments should be returned
|
||||
--- as the values for the current iteration stage.
|
||||
---
|
||||
---@param cont boolean If true, the current iterator stage should continue to
|
||||
--- @param cont boolean If true, the current iterator stage should continue to
|
||||
--- pull values from its upstream pipeline stage.
|
||||
--- Otherwise, this stage is complete and returns the
|
||||
--- values passed.
|
||||
---@param ... any Values to return if cont is false.
|
||||
---@return any
|
||||
--- @param ... any Values to return if cont is false.
|
||||
--- @return any
|
||||
local function fn(cont, ...)
|
||||
if cont then
|
||||
return fn(apply(f, next(self)))
|
||||
@@ -377,14 +389,18 @@ function Iter:map(f)
|
||||
return ...
|
||||
end
|
||||
|
||||
--- @diagnostic disable-next-line: duplicate-set-field
|
||||
self.next = function()
|
||||
return fn(apply(f, next(self)))
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:map(f)
|
||||
--- @nodoc
|
||||
--- @generic K1, K...
|
||||
--- @param f fun(v: V1, ...: V...): K1, K...
|
||||
--- @return vim.IterArray<K1, K...>
|
||||
function IterArray:map(f)
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
local n = self._head
|
||||
for i = self._head, self._tail - inc, inc do
|
||||
@@ -402,8 +418,8 @@ end
|
||||
---
|
||||
--- For functions with side effects. To modify the values in the iterator, use |Iter:map()|.
|
||||
---
|
||||
---@since 12
|
||||
---@param f fun(...) Function to execute for each item in the pipeline.
|
||||
--- @since 12
|
||||
--- @param f fun(v: V1, ...: V...) Function to execute for each item in the pipeline.
|
||||
--- Takes all of the values returned by the previous stage
|
||||
--- in the pipeline as arguments.
|
||||
function Iter:each(f)
|
||||
@@ -417,8 +433,9 @@ function Iter:each(f)
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:each(f)
|
||||
--- @private
|
||||
--- @param f fun(v: V1, ...: V...)
|
||||
function IterArray:each(f)
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
for i = self._head, self._tail - inc, inc do
|
||||
f(unpack(self._table[i]))
|
||||
@@ -450,8 +467,10 @@ end
|
||||
--- To create a map-like table with arbitrary keys, use |Iter:fold()|.
|
||||
---
|
||||
---
|
||||
---@since 12
|
||||
---@return table
|
||||
--- @since 12
|
||||
--- @overload fun<T>(self: vim.Iter<T>): T[]
|
||||
--- @overload fun<V1, V2, V...>(self: vim.Iter<V1, V2, V...>): [V1, V2, V...][]
|
||||
--- @return any[]
|
||||
function Iter:totable()
|
||||
local t = {}
|
||||
|
||||
@@ -466,9 +485,12 @@ function Iter:totable()
|
||||
return t
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:totable()
|
||||
if self.next ~= ArrayIter.next or self._head >= self._tail then
|
||||
--- @nodoc
|
||||
--- @overload fun<T>(self: vim.IterArray<T>): T[]
|
||||
--- @overload fun<V1, V2, V...>(self: vim.IterArray<V1, V2, V...>): [V1, V2, V...][]
|
||||
--- @return any[]
|
||||
function IterArray:totable()
|
||||
if self.next ~= IterArray.next or self._head >= self._tail then
|
||||
return Iter.totable(self)
|
||||
end
|
||||
|
||||
@@ -531,12 +553,12 @@ end
|
||||
--- end) --> { max = 42 }
|
||||
--- ```
|
||||
---
|
||||
---@generic A
|
||||
---
|
||||
---@since 12
|
||||
---@param init A Initial value of the accumulator.
|
||||
---@param f fun(acc:A, ...):A Accumulation function.
|
||||
---@return A
|
||||
--- @since 12
|
||||
--- @generic A
|
||||
--- @param init A Initial value of the accumulator.
|
||||
--- @param f fun(acc: A, v: V1, ...: V...): A Accumulation function.
|
||||
--- @return A
|
||||
function Iter:fold(init, f)
|
||||
local acc = init
|
||||
|
||||
@@ -553,8 +575,12 @@ function Iter:fold(init, f)
|
||||
return acc
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:fold(init, f)
|
||||
--- @nodoc
|
||||
--- @generic A
|
||||
--- @param init A
|
||||
--- @param f fun(acc: A, v: V1, ...: V...): A
|
||||
--- @return A
|
||||
function IterArray:fold(init, f)
|
||||
local acc = init
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
for i = self._head, self._tail - inc, inc do
|
||||
@@ -563,6 +589,7 @@ function ArrayIter:fold(init, f)
|
||||
return acc
|
||||
end
|
||||
|
||||
--- @diagnostic disable-next-line: duplicate-set-field
|
||||
--- Gets the next value from the iterator.
|
||||
---
|
||||
--- Example:
|
||||
@@ -579,8 +606,8 @@ end
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@return any
|
||||
--- @since 12
|
||||
--- @return V1?, V...
|
||||
function Iter:next()
|
||||
if self._peeked then
|
||||
local v = self._peeked
|
||||
@@ -592,8 +619,9 @@ function Iter:next()
|
||||
return self._next()
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:next()
|
||||
--- @package
|
||||
--- @return V1?, V...
|
||||
function IterArray:next()
|
||||
if self._head ~= self._tail then
|
||||
local v = self._table[self._head]
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
@@ -602,6 +630,12 @@ function ArrayIter:next()
|
||||
end
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line: unused-local
|
||||
function Iter:rev()
|
||||
error('rev() requires an array-like table')
|
||||
end
|
||||
|
||||
--- Reverses a |list-iterator| pipeline.
|
||||
---
|
||||
--- Example:
|
||||
@@ -614,14 +648,9 @@ end
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@return Iter
|
||||
function Iter:rev()
|
||||
error('rev() requires an array-like table')
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:rev()
|
||||
--- @since 12
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:rev()
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
self._head, self._tail = self._tail - inc, self._head - inc
|
||||
return self
|
||||
@@ -646,8 +675,8 @@ end
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@return any
|
||||
--- @since 12
|
||||
--- @return V1?, V...
|
||||
function Iter:peek()
|
||||
if not self._peeked then
|
||||
self._peeked = pack(self:next())
|
||||
@@ -656,10 +685,11 @@ function Iter:peek()
|
||||
return unpack(self._peeked)
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:peek()
|
||||
--- @private
|
||||
--- @return V1?, V...
|
||||
function IterArray:peek()
|
||||
if self._head ~= self._tail then
|
||||
return self._table[self._head]
|
||||
return unpack(self._table[self._head])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -684,9 +714,10 @@ end
|
||||
--- -- 12
|
||||
---
|
||||
--- ```
|
||||
---@since 12
|
||||
---@param f any
|
||||
---@return any
|
||||
--- @since 12
|
||||
--- @param f (fun(v: V1, ...: V...): boolean)|any
|
||||
--- @overload fun<V1, V...>(self: vim.IterArray<V1, V...>, f: V1|fun(v: V1, ...: V...): boolean): V1?, V...
|
||||
--- @return V1?, V...
|
||||
function Iter:find(f)
|
||||
if type(f) ~= 'function' then
|
||||
local val = f
|
||||
@@ -713,6 +744,12 @@ function Iter:find(f)
|
||||
return unpack(result)
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line:unused-local
|
||||
function Iter:rfind(f)
|
||||
error('rfind() requires an array-like table')
|
||||
end
|
||||
|
||||
--- Gets the first value satisfying a predicate, from the end of a |list-iterator|.
|
||||
---
|
||||
--- Advances the iterator. Returns nil and drains the iterator if no value is found.
|
||||
@@ -729,18 +766,12 @@ end
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@see |Iter:find()|
|
||||
--- @see |Iter:find()|
|
||||
---
|
||||
---@since 12
|
||||
---@param f any
|
||||
---@return any
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function Iter:rfind(f) -- luacheck: no unused args
|
||||
error('rfind() requires an array-like table')
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:rfind(f)
|
||||
--- @since 12
|
||||
--- @param f V1|fun(v: V1, ...: V...): boolean
|
||||
--- @return V1?, V...
|
||||
function IterArray:rfind(f)
|
||||
if type(f) ~= 'function' then
|
||||
local val = f
|
||||
f = function(v)
|
||||
@@ -781,21 +812,25 @@ end
|
||||
--- -- nil
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@param n integer|fun(...):boolean Number of values to take or a predicate.
|
||||
---@return Iter
|
||||
--- @since 12
|
||||
--- @param n integer|fun(v: V1, ...: V...): boolean Number of values to take or a predicate.
|
||||
--- @return vim.Iter<V1, V...>
|
||||
--- @overload fun<V1, V...>(self: vim.IterArray<V1, V...>, n: integer|fun(v: V1, ...: V...): boolean): vim.IterArray<V1, V...>
|
||||
function Iter:take(n)
|
||||
local i = 0
|
||||
local f = n
|
||||
if type(n) ~= 'function' then
|
||||
f = function()
|
||||
return i < n
|
||||
local pred --- @type fun(...): boolean
|
||||
if type(n) == 'function' then
|
||||
pred = n
|
||||
else
|
||||
local limit = n
|
||||
pred = function()
|
||||
return i < limit
|
||||
end
|
||||
end
|
||||
|
||||
local stop = false
|
||||
local function fn(...)
|
||||
if not stop and select(1, ...) ~= nil and f(...) then
|
||||
if not stop and select(1, ...) ~= nil and pred(...) then
|
||||
i = i + 1
|
||||
return ...
|
||||
else
|
||||
@@ -804,14 +839,17 @@ function Iter:take(n)
|
||||
end
|
||||
|
||||
local next = self.next
|
||||
--- @diagnostic disable-next-line:duplicate-set-field
|
||||
self.next = function()
|
||||
return fn(next(self))
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:take(n)
|
||||
--- @private
|
||||
--- @param n integer|fun(v: V1, ...: V...): boolean
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:take(n)
|
||||
if type(n) == 'function' then
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
for i = self._head, self._tail, inc do
|
||||
@@ -829,6 +867,12 @@ function ArrayIter:take(n)
|
||||
return self
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line: unused-local
|
||||
function Iter:pop()
|
||||
error('pop() requires an array-like table')
|
||||
end
|
||||
|
||||
--- "Pops" a value from a |list-iterator| (gets the last value and decrements the tail).
|
||||
---
|
||||
--- Example:
|
||||
@@ -841,21 +885,22 @@ end
|
||||
--- -- 3
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@return any
|
||||
function Iter:pop()
|
||||
error('pop() requires an array-like table')
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
function ArrayIter:pop()
|
||||
--- @since 12
|
||||
--- @return V1?, V...
|
||||
function IterArray:pop()
|
||||
if self._head ~= self._tail then
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
self._tail = self._tail - inc
|
||||
return self._table[self._tail]
|
||||
return unpack(self._table[self._tail])
|
||||
end
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line: unused-local
|
||||
function Iter:rpeek()
|
||||
error('rpeek() requires an array-like table')
|
||||
end
|
||||
|
||||
--- Gets the last value of a |list-iterator| without consuming it.
|
||||
---
|
||||
--- Example:
|
||||
@@ -870,19 +915,14 @@ end
|
||||
--- -- 4
|
||||
--- ```
|
||||
---
|
||||
---@see |Iter:last()|
|
||||
--- @see |Iter:last()|
|
||||
---
|
||||
---@since 12
|
||||
---@return any
|
||||
function Iter:rpeek()
|
||||
error('rpeek() requires an array-like table')
|
||||
end
|
||||
|
||||
---@nodoc
|
||||
function ArrayIter:rpeek()
|
||||
--- @since 12
|
||||
--- @return V1?, V...
|
||||
function IterArray:rpeek()
|
||||
if self._head ~= self._tail then
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
return self._table[self._tail - inc]
|
||||
return unpack(self._table[self._tail - inc])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -906,9 +946,10 @@ end
|
||||
--- -- 12
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@param n integer|fun(...):boolean Number of values to skip or a predicate.
|
||||
---@return Iter
|
||||
--- @since 12
|
||||
--- @param n integer|fun(v: V1, ...: V...): boolean Number of values to skip or a predicate.
|
||||
--- @return vim.Iter<V1, V...>
|
||||
--- @overload fun<V1, V...>(self: vim.IterArray<V1, V...>, n: integer|fun(v: V1, ...: V...): boolean): vim.IterArray<V1, V...>
|
||||
function Iter:skip(n)
|
||||
if type(n) == 'number' then
|
||||
for _ = 1, n do
|
||||
@@ -918,6 +959,7 @@ function Iter:skip(n)
|
||||
elseif type(n) == 'function' then
|
||||
local next = self.next
|
||||
|
||||
--- @diagnostic disable-next-line:duplicate-set-field
|
||||
self.next = function()
|
||||
while true do
|
||||
local peeked = self._peeked or pack(next(self))
|
||||
@@ -938,8 +980,10 @@ function Iter:skip(n)
|
||||
return self
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:skip(n)
|
||||
--- @private
|
||||
--- @param n integer|fun(v: V1, ...: V...): boolean
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:skip(n)
|
||||
if type(n) == 'function' then
|
||||
while self._head ~= self._tail do
|
||||
local v = self._table[self._head]
|
||||
@@ -960,6 +1004,12 @@ function ArrayIter:skip(n)
|
||||
return self
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line:unused-local
|
||||
function Iter:rskip(n)
|
||||
error('rskip() requires an array-like table')
|
||||
end
|
||||
|
||||
--- Discards `n` values from the end of a |list-iterator| pipeline.
|
||||
---
|
||||
--- Example:
|
||||
@@ -972,18 +1022,12 @@ end
|
||||
--- -- 3
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@param n number Number of values to skip.
|
||||
---@return Iter
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function Iter:rskip(n) -- luacheck: no unused args
|
||||
error('rskip() requires an array-like table')
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:rskip(n)
|
||||
local inc = self._head < self._tail and n or -n
|
||||
self._tail = self._tail - inc
|
||||
--- @since 12
|
||||
--- @param n integer
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:rskip(n)
|
||||
local inc = self._head < self._tail and n or vim._assert_integer(-n)
|
||||
self._tail = vim._assert_integer(self._tail - inc)
|
||||
if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then
|
||||
self._head = self._tail
|
||||
end
|
||||
@@ -1010,9 +1054,9 @@ end
|
||||
--- -- 3
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@param n number Index of the value to return. May be negative if the source is a |list-iterator|.
|
||||
---@return any
|
||||
--- @since 12
|
||||
--- @param n integer Index of the value to return. May be negative if the source is a |list-iterator|.
|
||||
--- @return V1?, V...
|
||||
function Iter:nth(n)
|
||||
if n > 0 then
|
||||
return self:skip(n - 1):next()
|
||||
@@ -1021,28 +1065,30 @@ function Iter:nth(n)
|
||||
end
|
||||
end
|
||||
|
||||
--- @nodoc
|
||||
--- @diagnostic disable-next-line:unused-local
|
||||
function Iter:slice(first, last)
|
||||
error('slice() requires an array-like table')
|
||||
end
|
||||
|
||||
--- Sets the start and end of a |list-iterator| pipeline.
|
||||
---
|
||||
--- Equivalent to `:skip(first - 1):rskip(len - last + 1)`.
|
||||
---
|
||||
---@since 12
|
||||
---@param first number
|
||||
---@param last number
|
||||
---@return Iter
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function Iter:slice(first, last) -- luacheck: no unused args
|
||||
error('slice() requires an array-like table')
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:slice(first, last)
|
||||
return self:skip(math.max(0, first - 1)):rskip(math.max(0, self._tail - last - 1))
|
||||
--- @since 12
|
||||
--- @param first integer
|
||||
--- @param last integer
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
function IterArray:slice(first, last)
|
||||
local left = vim._assert_integer(math.max(0, first - 1))
|
||||
local right = vim._assert_integer(math.max(0, self._tail - last - 1))
|
||||
return self:skip(left):rskip(right)
|
||||
end
|
||||
|
||||
--- Returns true if any of the items in the iterator match the given predicate.
|
||||
---
|
||||
---@since 12
|
||||
---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous
|
||||
--- @since 12
|
||||
--- @param pred fun(v: V1, ...: V...): boolean Predicate function. Takes all values returned from the previous
|
||||
--- stage in the pipeline as arguments and returns true if the
|
||||
--- predicate matches.
|
||||
function Iter:any(pred)
|
||||
@@ -1066,8 +1112,8 @@ end
|
||||
|
||||
--- Returns true if all items in the iterator match the given predicate.
|
||||
---
|
||||
---@since 12
|
||||
---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous
|
||||
--- @since 12
|
||||
--- @param pred fun(v: V1, ...: V...): boolean Predicate function. Takes all values returned from the previous
|
||||
--- stage in the pipeline as arguments and returns true if the
|
||||
--- predicate matches.
|
||||
function Iter:all(pred)
|
||||
@@ -1104,10 +1150,9 @@ end
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@see |Iter:rpeek()|
|
||||
---
|
||||
---@return any
|
||||
--- @since 12
|
||||
--- @see |IterArray:rpeek()|
|
||||
--- @return V1?, V...
|
||||
function Iter:last()
|
||||
local last = self:next()
|
||||
local cur = self:next()
|
||||
@@ -1118,15 +1163,16 @@ function Iter:last()
|
||||
return last
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:last()
|
||||
if self._head >= self._tail then
|
||||
--- @private
|
||||
--- @return V1?, V...
|
||||
function IterArray:last()
|
||||
if self._head == self._tail then
|
||||
return nil
|
||||
end
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
local v = self._table[self._tail - inc]
|
||||
self._head = self._tail
|
||||
return v
|
||||
return unpack(v)
|
||||
end
|
||||
|
||||
--- Yields the item index (count) and value for each item of an iterator pipeline.
|
||||
@@ -1157,8 +1203,9 @@ end
|
||||
---
|
||||
--- ```
|
||||
---
|
||||
---@since 12
|
||||
---@return Iter
|
||||
--- @since 12
|
||||
--- @overload fun<V1, V...>(self: vim.IterArray<V1, V...>): vim.IterArray<integer, V1, V...>
|
||||
--- @return vim.Iter<integer, V1, V...>
|
||||
function Iter:enumerate()
|
||||
local i = 0
|
||||
return self:map(function(...)
|
||||
@@ -1167,33 +1214,38 @@ function Iter:enumerate()
|
||||
end)
|
||||
end
|
||||
|
||||
---@private
|
||||
function ArrayIter:enumerate()
|
||||
--- @private
|
||||
--- @return vim.IterArray<integer, V1, V...>
|
||||
function IterArray:enumerate()
|
||||
local inc = self._head < self._tail and 1 or -1
|
||||
local n = 0
|
||||
for i = self._head, self._tail - inc, inc do
|
||||
n = n + 1
|
||||
local v = self._table[i]
|
||||
self._table[i] = pack(i, v)
|
||||
self._table[i] = pack(n, unpack(v))
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a new Iter object from a table or other |iterable|.
|
||||
---
|
||||
---@param src table|function Table or iterator to drain values from
|
||||
---@return Iter
|
||||
---@private
|
||||
--- @generic R1, R...
|
||||
--- @param src table<R1, R>|fun(s: table, v: any): R1, R... Table or iterator to drain values from
|
||||
--- @return vim.Iter<R1, R...>
|
||||
--- @overload fun<T>(src: T[]): vim.IterArray<T>
|
||||
--- @overload fun<K, V>(src: table<K, V>): vim.Iter<K, V>
|
||||
--- @private
|
||||
function Iter.new(src, ...)
|
||||
local it = {}
|
||||
if type(src) == 'table' then
|
||||
local mt = getmetatable(src)
|
||||
if mt and type(mt.__call) == 'function' then
|
||||
---@private
|
||||
--- @private
|
||||
it._next = function()
|
||||
return src()
|
||||
return mt.__call(src)
|
||||
end
|
||||
|
||||
setmetatable(it, Iter)
|
||||
return it
|
||||
return setmetatable(it, Iter)
|
||||
end
|
||||
|
||||
local t = {}
|
||||
@@ -1205,51 +1257,48 @@ function Iter.new(src, ...)
|
||||
end
|
||||
t[#t + 1] = v -- Coerce to list-like table.
|
||||
end
|
||||
return ArrayIter.new(t)
|
||||
end
|
||||
|
||||
if type(src) == 'function' then
|
||||
local s, var = ...
|
||||
|
||||
--- Use a closure to handle var args returned from iterator
|
||||
local function fn(...)
|
||||
-- Per the Lua 5.1 reference manual, an iterator is complete when the first returned value is
|
||||
-- nil (even if there are other, non-nil return values). See |for-in|.
|
||||
if select(1, ...) ~= nil then
|
||||
var = select(1, ...)
|
||||
return ...
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
it._next = function()
|
||||
return fn(src(s, var))
|
||||
end
|
||||
|
||||
setmetatable(it, Iter)
|
||||
else
|
||||
return IterArray.new(t)
|
||||
elseif type(src) ~= 'function' then
|
||||
error('src must be a table or function')
|
||||
end
|
||||
return it
|
||||
|
||||
local s, var = ...
|
||||
|
||||
--- Use a closure to handle var args returned from iterator
|
||||
local function fn(...)
|
||||
-- Per the Lua 5.1 reference manual, an iterator is complete when the first returned value is
|
||||
-- nil (even if there are other, non-nil return values). See |for-in|.
|
||||
if select(1, ...) ~= nil then
|
||||
var = select(1, ...)
|
||||
return ...
|
||||
end
|
||||
end
|
||||
|
||||
--- @private
|
||||
it._next = function()
|
||||
return fn(src(s, var))
|
||||
end
|
||||
|
||||
return setmetatable(it, Iter)
|
||||
end
|
||||
|
||||
--- Create a new ArrayIter
|
||||
--- Create a new IterArray
|
||||
---
|
||||
---@param t table Array-like table. Caller guarantees that this table is a valid array. Can have
|
||||
--- holes (nil values).
|
||||
---@return Iter
|
||||
---@private
|
||||
function ArrayIter.new(t)
|
||||
local it = {}
|
||||
it._table = t
|
||||
it._head = 1
|
||||
it._tail = #t + 1
|
||||
setmetatable(it, ArrayIter)
|
||||
return it
|
||||
--- @generic V1, V...
|
||||
--- @param t (V1|[V1, V...])[] List-like table. Caller guarantees that this table is a valid
|
||||
--- internal list buffer.
|
||||
--- @return vim.IterArray<V1, V...>
|
||||
--- @private
|
||||
function IterArray.new(t)
|
||||
return setmetatable({
|
||||
_table = t,
|
||||
_head = 1,
|
||||
_tail = #t + 1,
|
||||
}, IterArray)
|
||||
end
|
||||
|
||||
return setmetatable(M, {
|
||||
__call = function(_, ...)
|
||||
return Iter.new(...)
|
||||
end,
|
||||
}) --[[@as IterMod]]
|
||||
})
|
||||
|
||||
@@ -88,7 +88,9 @@ local v = setmetatable({}, {
|
||||
--- @class nvim.luacats.Class
|
||||
--- @field kind 'class'
|
||||
--- @field name string
|
||||
--- @field generics? string[]
|
||||
--- @field parent? string
|
||||
--- @field parent_generics? string[]
|
||||
--- @field access? 'private'|'protected'|'package'
|
||||
|
||||
--- @class nvim.luacats.Field
|
||||
@@ -149,7 +151,7 @@ local typedef = P({
|
||||
+ (v.types * opt_postfix)
|
||||
+ (P(ty_ident) * P('...')) -- Generic vararg
|
||||
+ v.types,
|
||||
types = v.generics + v.kv_table + v.tuple + v.dict + v.table_literal + v.fun + ty_prims,
|
||||
types = v.fun + v.generics + v.kv_table + v.tuple + v.dict + v.table_literal + ty_prims,
|
||||
|
||||
tuple = Pf('[') * comma1(v.type) * Plf(']'),
|
||||
dict = Pf('{') * comma1(Pf('[') * v.type * Pf(']') * colon * v.type) * Plf('}'),
|
||||
@@ -157,10 +159,18 @@ local typedef = P({
|
||||
table_literal = Pf('{') * comma1(opt_ident * Pf(':') * v.type) * Plf('}'),
|
||||
fun_param = (opt_ident + ellipsis) * opt(colon * v.type),
|
||||
fun_ret = v.type + (ellipsis * opt(colon * v.type)),
|
||||
fun = opt(Pf('async')) * Pf('fun') * paren(comma(v.fun_param)) * opt(Pf(':') * comma1(v.fun_ret)),
|
||||
generic_decl_list = Pf('<') * comma1(ty_ident * opt(ellipsis) * opt(colon * v.type)) * Plf('>'),
|
||||
fun = opt(Pf('async') + Pf('sync')) * Pf('fun') * opt(v.generic_decl_list) * paren(
|
||||
comma(v.fun_param)
|
||||
) * opt(Pf(':') * comma1(v.fun_ret)),
|
||||
generics = P(ty_ident) * Pf('<') * comma1(v.type) * Plf('>'),
|
||||
}) / function(match)
|
||||
return vim.trim(match):gsub('^%((.*)%)$', '%1'):gsub('%?+', '?')
|
||||
return (vim.trim(match):gsub('^%((.*)%)$', '%1'):gsub('%?+', '?'))
|
||||
end
|
||||
|
||||
--- @param name string
|
||||
local function generic_opt(name)
|
||||
return (Pf('<') * Cg(Ct(comma1(typedef)), name) * Plf('>')) + -Plf('<')
|
||||
end
|
||||
|
||||
local access = P('private') + P('protected') + P('package')
|
||||
@@ -170,7 +180,7 @@ local desc_delim = Sf '#:' + ws
|
||||
local desc = Cg(rep(any), 'desc')
|
||||
local opt_desc = opt(desc_delim * desc)
|
||||
local ty_name = Cg(ty_ident, 'name')
|
||||
local opt_parent = opt(colon * Cg(ty_ident, 'parent'))
|
||||
local opt_parent = opt(colon * Cg(ty_ident, 'parent') * generic_opt('parent_generics'))
|
||||
local lname = (ident + ellipsis) * opt(P('?'))
|
||||
|
||||
-- stylua: ignore
|
||||
@@ -182,7 +192,7 @@ local grammar = P {
|
||||
+ annot('type', comma1(Ct(v.ctype)) * opt_desc)
|
||||
+ annot('cast', ty_name * ws * opt(Sf('+-')) * v.ctype)
|
||||
+ annot('generic', ty_name * opt(colon * v.ctype))
|
||||
+ annot('class', opt(paren(cattr)) * fill * ty_name * opt_parent)
|
||||
+ annot('class', opt(paren(cattr)) * fill * ty_name * generic_opt('generics') * opt_parent)
|
||||
+ annot('field', opt(caccess * ws) * v.field_name * ws * v.ctype * opt_desc)
|
||||
+ annot('operator', ty_name * opt(paren(Cg(v.ctype, 'argtype'))) * colon * v.ctype)
|
||||
+ annot(access)
|
||||
|
||||
@@ -143,7 +143,9 @@ local function process_doc_line(line, state)
|
||||
--- @cast parsed nvim.luacats.Class
|
||||
cur_obj.kind = 'class'
|
||||
cur_obj.name = parsed.name
|
||||
cur_obj.generics = parsed.generics
|
||||
cur_obj.parent = parsed.parent
|
||||
cur_obj.parent_generics = parsed.parent_generics
|
||||
cur_obj.access = parsed.access
|
||||
cur_obj.desc = state.doc_lines and table.concat(state.doc_lines, '\n') or nil
|
||||
state.doc_lines = nil
|
||||
|
||||
@@ -178,6 +178,32 @@ describe('luacats grammar', function()
|
||||
parent = 'vim.diagnostic.GetOpts',
|
||||
})
|
||||
|
||||
test('@class vim.Iter<V1, V...>', {
|
||||
kind = 'class',
|
||||
name = 'vim.Iter',
|
||||
generics = { 'V1', 'V...' },
|
||||
})
|
||||
|
||||
test('@class vim.IterArray<T> : vim.Iter<T, never>', {
|
||||
kind = 'class',
|
||||
name = 'vim.IterArray',
|
||||
generics = { 'T' },
|
||||
parent = 'vim.Iter',
|
||||
parent_generics = { 'T', 'never' },
|
||||
})
|
||||
|
||||
test('@class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}>', {
|
||||
kind = 'class',
|
||||
name = 'vim.lsp.Client.Progress',
|
||||
parent = 'vim.Ringbuf',
|
||||
parent_generics = { '{token: integer|string, value: any}' },
|
||||
})
|
||||
|
||||
test('@overload fun<V1, V2, V...>(self: vim.Iter<V1, V2, V...>): [V1, V2, V...][]', {
|
||||
kind = 'overload',
|
||||
type = 'fun<V1, V2, V...>(self: vim.Iter<V1, V2, V...>): [V1, V2, V...][]',
|
||||
})
|
||||
|
||||
test('@param opt? { cmd?: string[] } Options', {
|
||||
kind = 'param',
|
||||
name = 'opt?',
|
||||
|
||||
Reference in New Issue
Block a user