From aa16590999a66798eca7d2ba09e971aacdeb54b4 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sat, 4 Mar 2023 22:07:39 +0900 Subject: docs(lua): number → integer (#22517) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- runtime/lua/vim/shared.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index cc48e3f193..1c8defc93a 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -418,8 +418,8 @@ end ---@generic T: table ---@param dst T List which will be modified and appended to ---@param src table List from which values will be inserted ----@param start (number|nil) Start index on src. Defaults to 1 ----@param finish (number|nil) Final index on src. Defaults to `#src` +---@param start (integer|nil) Start index on src. Defaults to 1 +---@param finish (integer|nil) Final index on src. Defaults to `#src` ---@return T dst function vim.list_extend(dst, src, start, finish) vim.validate({ @@ -529,7 +529,7 @@ end --- ---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua ---@param t table Table ----@return number Number of non-nil values in table +---@return integer Number of non-nil values in table function vim.tbl_count(t) vim.validate({ t = { t, 't' } }) @@ -544,8 +544,8 @@ end --- ---@generic T ---@param list T[] (list) Table ----@param start number|nil Start range of slice ----@param finish number|nil End range of slice +---@param start integer|nil Start range of slice +---@param finish integer|nil End range of slice ---@return T[] (list) Copy of table sliced from start to finish (inclusive) function vim.list_slice(list, start, finish) local new_list = {} -- cgit From 9c49c1047079427ff0a2356cb37302934845108e Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 20 Mar 2023 08:12:33 +0100 Subject: feat(vim.gsplit): gain features of vim.split Problem: - vim.split has more features than vim.gsplit. - Cannot inspect the "separator" segments of vim.split or vim.gsplit. Solution: - Move common implementation from vim.split into vim.gsplit. - TODO: deprecate vim.split in favor of vim.totable(vim.gsplit())? - Introduce `keepsep` parameter. Related: 84f66909e4008a57da947f1640bfc24da5e41a72 --- runtime/lua/vim/shared.lua | 122 ++++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 45 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 1c8defc93a..95ddb3c70d 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -59,6 +59,13 @@ end)() --- Splits a string at each instance of a separator. --- +--- Example: +---
lua
+---   for s in vim.gsplit(':aa::b:', ':', {plain=true}) do
+---     print(s)
+---   end
+---   
+--- ---@see |vim.split()| ---@see |luaref-patterns| ---@see https://www.lua.org/pil/20.2.html @@ -66,17 +73,40 @@ end)() --- ---@param s string String to split ---@param sep string Separator or pattern ----@param plain (boolean|nil) If `true` use `sep` literally (passed to string.find) ----@return fun():string (function) Iterator over the split components -function vim.gsplit(s, sep, plain) - vim.validate({ s = { s, 's' }, sep = { sep, 's' }, plain = { plain, 'b', true } }) +---@param opts (table|nil) Keyword arguments |kwargs|: +--- - keepsep: (boolean) Include segments matching `sep` instead of discarding them. +--- - plain: (boolean) Use `sep` literally (as in string.find). +--- - trimempty: (boolean) Discard empty segments at start and end of the sequence. +---@return fun():string|nil (function) Iterator over the split components +function vim.gsplit(s, sep, opts) + local plain + local trimempty = false + local keepsep = false + if type(opts) == 'boolean' then + plain = opts -- For backwards compatibility. + else + vim.validate({ s = { s, 's' }, sep = { sep, 's' }, opts = { opts, 't', true } }) + opts = opts or {} + plain, trimempty, keepsep = opts.plain, opts.trimempty, opts.keepsep + assert(not trimempty or not keepsep, 'keepsep+trimempty not supported') + end local start = 1 local done = false + local sepseg = nil -- Last matched `sep` segment. + local sepesc = plain and vim.pesc(sep) or sep + + -- For `trimempty`: + local empty_start = true -- Only empty segments seen so far. + local empty_segs = 0 -- Empty segments found between non-empty segments. + local nonemptyseg = nil local function _pass(i, j, ...) if i then assert(j + 1 > start, 'Infinite loop detected') + if keepsep then + sepseg = s:match(sepesc, start) + end local seg = s:sub(start, i - 1) start = j + 1 return seg, ... @@ -87,16 +117,48 @@ function vim.gsplit(s, sep, plain) end return function() - if done or (s == '' and sep == '') then - return - end - if sep == '' then + if trimempty and empty_segs > 0 then + -- trimempty: Pop the collected empty segments. + empty_segs = empty_segs - 1 + return '' + elseif trimempty and nonemptyseg then + local seg = nonemptyseg + nonemptyseg = nil + return seg + elseif keepsep and sepseg then + local seg = sepseg + sepseg = nil + return seg + elseif done or (s == '' and sep == '') then + return nil + elseif sep == '' then if start == #s then done = true end return _pass(start + 1, start) end - return _pass(s:find(sep, start, plain)) + + local seg = _pass(s:find(sep, start, plain)) + + -- Trim empty segments from start/end. + if trimempty and seg == '' then + while not done and seg == '' do + empty_segs = empty_segs + 1 + seg = _pass(s:find(sep, start, plain)) + end + if done and seg == '' then + return nil + elseif empty_start then + empty_start = false + empty_segs = 0 + return seg + end + nonemptyseg = seg ~= '' and seg or nil + seg = '' + empty_segs = empty_segs - 1 + end + + return seg end end @@ -108,51 +170,21 @@ end --- split("axaby", "ab?") --> {'','x','y'} --- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'} --- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'} +--- split("|x|y|z|", "|", {keepsep=true}) --> {'|', 'x', '|', 'y', '|', 'z', '|'} --- --- ---@see |vim.gsplit()| --- ---@param s string String to split ---@param sep string Separator or pattern ----@param kwargs (table|nil) Keyword arguments: ---- - plain: (boolean) If `true` use `sep` literally (passed to string.find) ---- - trimempty: (boolean) If `true` remove empty items from the front ---- and back of the list +---@param opts (table|nil) Keyword arguments |kwargs| accepted by |vim.gsplit()| ---@return string[] List of split components -function vim.split(s, sep, kwargs) - local plain - local trimempty = false - if type(kwargs) == 'boolean' then - -- Support old signature for backward compatibility - plain = kwargs - else - vim.validate({ kwargs = { kwargs, 't', true } }) - kwargs = kwargs or {} - plain = kwargs.plain - trimempty = kwargs.trimempty - end - +function vim.split(s, sep, opts) + -- TODO(justinmk): deprecate vim.split in favor of vim.totable(vim.gsplit()) local t = {} - local skip = trimempty - for c in vim.gsplit(s, sep, plain) do - if c ~= '' then - skip = false - end - - if not skip then - table.insert(t, c) - end + for c in vim.gsplit(s, sep, opts) do + table.insert(t, c) end - - if trimempty then - for i = #t, 1, -1 do - if t[i] ~= '' then - break - end - table.remove(t, i) - end - end - return t end -- cgit From 8a70adbde03ee9931dc4e1b6f31bd8635eb3633b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 20 Mar 2023 13:36:06 +0100 Subject: fix(vim.version): prerelease compare Problem: semver specifies that digit sequences in a prerelease string should be compared as numbers, not lexically: https://semver.org/#spec-item-11 > Precedence for two pre-release versions with the same major, minor, > and patch version MUST be determined by comparing each dot separated > identifier from left to right until a difference is found as follows: > 1. Identifiers consisting of only digits are compared numerically. > 2. Identifiers with letters or hyphens are compared lexically in ASCII sort order. > 3. Numeric identifiers always have lower precedence than non-numeric identifiers. > 4. A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal. Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0. Solution: cmp_prerel() treats all digit sequences in a prerelease string as numbers. This doesn't _exactly_ match the spec, which specifies that only dot-delimited digit sequences should be treated as numbers... --- runtime/lua/vim/shared.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 95ddb3c70d..9eb49cdfac 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -66,14 +66,15 @@ end)() --- end --- --- ----@see |vim.split()| ----@see |luaref-patterns| ----@see https://www.lua.org/pil/20.2.html ----@see http://lua-users.org/wiki/StringLibraryTutorial ---- ----@param s string String to split ----@param sep string Separator or pattern ----@param opts (table|nil) Keyword arguments |kwargs|: +--- @see |string.gmatch()| +--- @see |vim.split()| +--- @see |luaref-patterns| +--- @see https://www.lua.org/pil/20.2.html +--- @see http://lua-users.org/wiki/StringLibraryTutorial +--- +--- @param s string String to split +--- @param sep string Separator or pattern +--- @param opts (table|nil) Keyword arguments |kwargs|: --- - keepsep: (boolean) Include segments matching `sep` instead of discarding them. --- - plain: (boolean) Use `sep` literally (as in string.find). --- - trimempty: (boolean) Discard empty segments at start and end of the sequence. -- cgit From e51139f5c1d70bef1424f29e63eb527514e42865 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 22 Mar 2023 15:14:51 +0100 Subject: refactor(vim.gsplit): remove "keepsep" string.gmatch() is superior, use that instead. --- runtime/lua/vim/shared.lua | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 9eb49cdfac..884929e33a 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -66,6 +66,14 @@ end)() --- end --- --- +--- If you want to also inspect the separator itself (instead of discarding it), use +--- |string.gmatch()|. Example: +---
lua
+---   for word, num in ('foo111bar222'):gmatch('([^0-9]*)(%d*)') do
+---     print(('word: %s num: %s'):format(word, num))
+---   end
+---   
+--- --- @see |string.gmatch()| --- @see |vim.split()| --- @see |luaref-patterns| @@ -75,27 +83,22 @@ end)() --- @param s string String to split --- @param sep string Separator or pattern --- @param opts (table|nil) Keyword arguments |kwargs|: ---- - keepsep: (boolean) Include segments matching `sep` instead of discarding them. --- - plain: (boolean) Use `sep` literally (as in string.find). --- - trimempty: (boolean) Discard empty segments at start and end of the sequence. ---@return fun():string|nil (function) Iterator over the split components function vim.gsplit(s, sep, opts) local plain local trimempty = false - local keepsep = false if type(opts) == 'boolean' then plain = opts -- For backwards compatibility. else vim.validate({ s = { s, 's' }, sep = { sep, 's' }, opts = { opts, 't', true } }) opts = opts or {} - plain, trimempty, keepsep = opts.plain, opts.trimempty, opts.keepsep - assert(not trimempty or not keepsep, 'keepsep+trimempty not supported') + plain, trimempty = opts.plain, opts.trimempty end local start = 1 local done = false - local sepseg = nil -- Last matched `sep` segment. - local sepesc = plain and vim.pesc(sep) or sep -- For `trimempty`: local empty_start = true -- Only empty segments seen so far. @@ -105,9 +108,6 @@ function vim.gsplit(s, sep, opts) local function _pass(i, j, ...) if i then assert(j + 1 > start, 'Infinite loop detected') - if keepsep then - sepseg = s:match(sepesc, start) - end local seg = s:sub(start, i - 1) start = j + 1 return seg, ... @@ -126,10 +126,6 @@ function vim.gsplit(s, sep, opts) local seg = nonemptyseg nonemptyseg = nil return seg - elseif keepsep and sepseg then - local seg = sepseg - sepseg = nil - return seg elseif done or (s == '' and sep == '') then return nil elseif sep == '' then @@ -171,17 +167,16 @@ end --- split("axaby", "ab?") --> {'','x','y'} --- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'} --- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'} ---- split("|x|y|z|", "|", {keepsep=true}) --> {'|', 'x', '|', 'y', '|', 'z', '|'} --- --- ---@see |vim.gsplit()| +---@see |string.gmatch()| --- ---@param s string String to split ---@param sep string Separator or pattern ---@param opts (table|nil) Keyword arguments |kwargs| accepted by |vim.gsplit()| ---@return string[] List of split components function vim.split(s, sep, opts) - -- TODO(justinmk): deprecate vim.split in favor of vim.totable(vim.gsplit()) local t = {} for c in vim.gsplit(s, sep, opts) do table.insert(t, c) -- cgit From 643c0ed571f1ac6e83f73ab2593132901278b4da Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Sat, 1 Apr 2023 08:02:58 -0600 Subject: feat: allow function passed to defaulttable to take an argument (#22839) Pass the value of the key being accessed to the create function, to allow users to dynamically generate default values. --- runtime/lua/vim/shared.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 884929e33a..9e337e93e8 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -796,13 +796,15 @@ end --- a.b.c = 1 --- --- ----@param create function|nil The function called to create a missing value. +---@param create function?(key:any):any The function called to create a missing value. ---@return table Empty table with metamethod function vim.defaulttable(create) - create = create or vim.defaulttable + create = create or function(_) + return vim.defaulttable() + end return setmetatable({}, { __index = function(tbl, key) - rawset(tbl, key, create()) + rawset(tbl, key, create(key)) return rawget(tbl, key) end, }) -- cgit From a5c572bd446a89be2dccb2f7479ff1b017074640 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 4 Apr 2023 19:07:33 +0200 Subject: docs: fix typos Co-authored-by: Gregory Anders Co-authored-by: Raphael Co-authored-by: C.D. MacEachern Co-authored-by: himanoa --- runtime/lua/vim/shared.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 9e337e93e8..eb734fb512 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -655,7 +655,7 @@ end --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} --- --> NOP (success) --- ---- vim.validate{arg1={1, {'string', table'}}} +--- vim.validate{arg1={1, {'string', 'table'}}} --- --> error('arg1: expected string|table, got number') --- --- -- cgit From bfb28b62dab756ec76a73506c2070ddf491a0cdd Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:29:13 -0600 Subject: refactor: remove modelines from Lua files Now that we have builtin EditorConfig support and a formatting check in CI, these are not necessary. --- runtime/lua/vim/shared.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index eb734fb512..9245adae3a 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -811,4 +811,3 @@ function vim.defaulttable(create) end return vim --- vim:sw=2 ts=2 et -- cgit From 4d04feb6629cb049cb2a13ba35f0c8d3c6b67ff4 Mon Sep 17 00:00:00 2001 From: Christian Clason Date: Fri, 14 Apr 2023 10:39:57 +0200 Subject: feat(lua): vim.tbl_contains supports general tables and predicates (#23040) * feat(lua): vim.tbl_contains supports general tables and predicates Problem: `vim.tbl_contains` only works for list-like tables (integer keys without gaps) and primitive values (in particular, not for nested tables). Solution: Rename `vim.tbl_contains` to `vim.list_contains` and add new `vim.tbl_contains` that works for general tables and optionally allows `value` to be a predicate function that is checked for every key. --- runtime/lua/vim/shared.lua | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 9245adae3a..7ecb56eb92 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -252,12 +252,53 @@ function vim.tbl_filter(func, t) return rettab end ---- Checks if a list-like (vector) table contains `value`. +--- Checks if a table contains a given value, specified either directly or via +--- a predicate that is checked for each value. +--- +--- Example: +---
lua
+---  vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v)
+---    return vim.deep_equal(v, { 'b', 'c' })
+---  end, { predicate = true })
+---  -- true
+--- 
+--- +---@see |vim.list_contains()| for checking values in list-like tables --- ---@param t table Table to check +---@param value any Value to compare or predicate function reference +---@param opts (table|nil) Keyword arguments |kwargs|: +--- - predicate: (boolean) `value` is a function reference to be checked (default false) +---@return boolean `true` if `t` contains `value` +function vim.tbl_contains(t, value, opts) + vim.validate({ t = { t, 't' }, opts = { opts, 't', true } }) + + local pred + if opts and opts.predicate then + vim.validate({ value = { value, 'c' } }) + pred = value + else + pred = function(v) + return v == value + end + end + + for _, v in pairs(t) do + if pred(v) then + return true + end + end + return false +end + +--- Checks if a list-like table (integer keys without gaps) contains `value`. +--- +---@see |vim.tbl_contains()| for checking values in general tables +--- +---@param t table Table to check (must be list-like, not validated) ---@param value any Value to compare ---@return boolean `true` if `t` contains `value` -function vim.tbl_contains(t, value) +function vim.list_contains(t, value) vim.validate({ t = { t, 't' } }) for _, v in ipairs(t) do -- cgit From 7caf0eafd83b5a92f2ff219b3a64ffae4174b9af Mon Sep 17 00:00:00 2001 From: NAKAI Tsuyoshi <82267684+uga-rosa@users.noreply.github.com> Date: Fri, 14 Apr 2023 19:01:08 +0900 Subject: feat(lua)!: add stricter vim.tbl_islist() and rename old one to vim.tbl_isarray() (#16440) feat(lua)!: add stricter vim.tbl_islist(), rename vim.tbl_isarray() Problem: `vim.tbl_islist` allows gaps in tables with integer keys ("arrays"). Solution: Rename `vim.tbl_islist` to `vim.tbl_isarray`, add new `vim.tbl.islist` that checks for consecutive integer keys that start from 1. --- runtime/lua/vim/shared.lua | 47 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 7ecb56eb92..f700f4a6b3 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -320,10 +320,10 @@ function vim.tbl_isempty(t) return next(t) == nil end ---- We only merge empty tables or tables that are not a list +--- We only merge empty tables or tables that are not an array (indexed by integers) ---@private local function can_merge(v) - return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.tbl_islist(v)) + return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.tbl_isarray(v)) end local function tbl_extend(behavior, deep_extend, ...) @@ -554,15 +554,15 @@ function vim.spairs(t) end end ---- Tests if a Lua table can be treated as an array. +--- Tests if a Lua table can be treated as an array (a table indexed by integers). --- --- Empty table `{}` is assumed to be an array, unless it was created by --- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result, --- for example from |rpcrequest()| or |vim.fn|. --- ----@param t table Table ----@return boolean `true` if array-like table, else `false` -function vim.tbl_islist(t) +---@param t table +---@return boolean `true` if array-like table, else `false`. +function vim.tbl_isarray(t) if type(t) ~= 'table' then return false end @@ -570,7 +570,8 @@ function vim.tbl_islist(t) local count = 0 for k, _ in pairs(t) do - if type(k) == 'number' then + --- Check if the number k is an integer + if type(k) == 'number' and k == math.floor(k) then count = count + 1 else return false @@ -589,6 +590,38 @@ function vim.tbl_islist(t) end end +--- Tests if a Lua table can be treated as a list (a table indexed by consecutive integers starting from 1). +--- +--- Empty table `{}` is assumed to be an list, unless it was created by +--- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result, +--- for example from |rpcrequest()| or |vim.fn|. +--- +---@param t table +---@return boolean `true` if list-like table, else `false`. +function vim.tbl_islist(t) + if type(t) ~= 'table' then + return false + end + + local num_elem = vim.tbl_count(t) + + if num_elem == 0 then + -- TODO(bfredl): in the future, we will always be inside nvim + -- then this check can be deleted. + if vim._empty_dict_mt == nil then + return nil + end + return getmetatable(t) ~= vim._empty_dict_mt + else + for i = 1, num_elem do + if t[i] == nil then + return false + end + end + return true + end +end + --- Counts the number of non-nil values in table `t`. --- ---
lua
-- 
cgit 


From ab1edecfb7c73c82c2d5886cb8e270b44aca7d01 Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Mon, 17 Apr 2023 12:54:19 -0600
Subject: feat(lua): add vim.iter (#23029)

vim.iter wraps a table or iterator function into an `Iter` object with
methods such as `filter`, `map`, and `fold` which can be chained to
produce iterator pipelines that do not create new tables at each step.
---
 runtime/lua/vim/shared.lua | 105 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

(limited to 'runtime/lua/vim/shared.lua')

diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index f700f4a6b3..1a96ef9bc4 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -884,4 +884,109 @@ function vim.defaulttable(create)
   })
 end
 
+--- Create an Iter |lua-iter| object from a table or iterator.
+---
+--- The input value can be a table  or a function iterator (see |luaref-in|).
+---
+--- This function wraps the input value into an interface which allows chaining
+--- multiple pipeline stages in an efficient manner. Each pipeline stage
+--- receives as input the output values from the prior stage. The values used in
+--- the first stage of the pipeline depend on the type passed to this function:
+---
+--- - List tables pass only the value of each element
+--- - Non-list tables pass both the key and value of each element
+--- - Function iterators pass all of the values returned by their respective
+---   function
+---
+--- Examples:
+--- 
lua
+--- local it = vim.iter({ 1, 2, 3, 4, 5 })
+--- it:map(function(v)
+---   return v * 3
+--- end)
+--- it:rev()
+--- it:skip(2)
+--- it:totable()
+--- -- { 9, 6, 3 }
+---
+--- vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
+---   if i > 2 then return v end
+--- end):totable()
+--- -- { 3, 4, 5 }
+---
+--- local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
+--- it:map(function(s) return tonumber(s) end)
+--- for i, d in it:enumerate() do
+---   print(string.format("Column %d is %d", i, d))
+--- end
+--- -- Column 1 is 1
+--- -- Column 2 is 2
+--- -- Column 3 is 3
+--- -- Column 4 is 4
+--- -- Column 5 is 5
+---
+--- vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
+---   return k == 'z'
+--- end)
+--- -- true
+--- 
+--- +---@see |lua-iter| +--- +---@param src table|function Table or iterator. +---@return Iter @|lua-iter| +function vim.iter(src, ...) + local Iter = require('vim.iter') + return Iter.new(src, ...) +end + +--- Collect an iterator into a table. +--- +--- This is a convenience function that performs: +---
lua
+--- vim.iter(f):totable()
+--- 
+--- +---@param f function Iterator function +---@return table +function vim.totable(f, ...) + return vim.iter(f, ...):totable() +end + +--- Filter a table or iterator. +--- +--- This is a convenience function that performs: +---
lua
+--- vim.iter(src):filter(f):totable()
+--- 
+--- +---@see |Iter:filter()| +--- +---@param f function(...):bool Filter function. Accepts the current iterator or table values as +--- arguments and returns true if those values should be kept in the +--- final table +---@param src table|function Table or iterator function to filter +---@return table +function vim.filter(f, src, ...) + return vim.iter(src, ...):filter(f):totable() +end + +--- Map and filter a table or iterator. +--- +--- This is a convenience function that performs: +---
lua
+--- vim.iter(src):map(f):totable()
+--- 
+--- +---@see |Iter:map()| +--- +---@param f function(...):?any Map function. Accepts the current iterator or table values as +--- arguments and returns one or more new values. Nil values are removed +--- from the final table. +---@param src table|function Table or iterator function to filter +---@return table +function vim.map(f, src, ...) + return vim.iter(src, ...):map(f):totable() +end + return vim -- cgit From 622b1ae38a36c3d26fad19faa788d622f7835921 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 21 Apr 2023 06:46:18 +0200 Subject: fix(lua): vim.split may trim inner empty items Problem: `vim.split('a:::', ':', {trimempty=true})` trims inner empty items. Regression from 9c49c1047079427ff0a2356cb37302934845108e Solution: Set `empty_start=false` when first non-empty item is found. close #23212 --- runtime/lua/vim/shared.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 1a96ef9bc4..08f8afd087 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -138,7 +138,9 @@ function vim.gsplit(s, sep, opts) local seg = _pass(s:find(sep, start, plain)) -- Trim empty segments from start/end. - if trimempty and seg == '' then + if seg ~= '' then + empty_start = false + elseif trimempty then while not done and seg == '' do empty_segs = empty_segs + 1 seg = _pass(s:find(sep, start, plain)) -- cgit From 824766612d4e7d53b717bd1e2b0d1d895054accd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 21 Apr 2023 07:26:44 +0200 Subject: refactor(lua): simplify vim.gsplit impl --- runtime/lua/vim/shared.lua | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 08f8afd087..5f4ea8822b 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -100,10 +100,9 @@ function vim.gsplit(s, sep, opts) local start = 1 local done = false - -- For `trimempty`: + -- For `trimempty`: queue of collected segments, to be emitted at next pass. + local segs = {} local empty_start = true -- Only empty segments seen so far. - local empty_segs = 0 -- Empty segments found between non-empty segments. - local nonemptyseg = nil local function _pass(i, j, ...) if i then @@ -118,14 +117,9 @@ function vim.gsplit(s, sep, opts) end return function() - if trimempty and empty_segs > 0 then - -- trimempty: Pop the collected empty segments. - empty_segs = empty_segs - 1 - return '' - elseif trimempty and nonemptyseg then - local seg = nonemptyseg - nonemptyseg = nil - return seg + if trimempty and #segs > 0 then + -- trimempty: Pop the collected segments. + return table.remove(segs) elseif done or (s == '' and sep == '') then return nil elseif sep == '' then @@ -138,23 +132,24 @@ function vim.gsplit(s, sep, opts) local seg = _pass(s:find(sep, start, plain)) -- Trim empty segments from start/end. - if seg ~= '' then + if trimempty and seg ~= '' then empty_start = false - elseif trimempty then + elseif trimempty and seg == '' then while not done and seg == '' do - empty_segs = empty_segs + 1 + table.insert(segs, 1, '') seg = _pass(s:find(sep, start, plain)) end if done and seg == '' then return nil elseif empty_start then empty_start = false - empty_segs = 0 + segs = {} return seg end - nonemptyseg = seg ~= '' and seg or nil - seg = '' - empty_segs = empty_segs - 1 + if seg ~= '' then + table.insert(segs, 1, seg) + end + return table.remove(segs) end return seg -- cgit From 1e73891d696a00b046ab19d245001424b174c931 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Mon, 24 Apr 2023 19:57:40 -0600 Subject: refactor(iter): move helper functions under vim.iter vim.iter is now both a function and a module (similar to vim.version). --- runtime/lua/vim/shared.lua | 105 --------------------------------------------- 1 file changed, 105 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 5f4ea8822b..a55deb1415 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -881,109 +881,4 @@ function vim.defaulttable(create) }) end ---- Create an Iter |lua-iter| object from a table or iterator. ---- ---- The input value can be a table or a function iterator (see |luaref-in|). ---- ---- This function wraps the input value into an interface which allows chaining ---- multiple pipeline stages in an efficient manner. Each pipeline stage ---- receives as input the output values from the prior stage. The values used in ---- the first stage of the pipeline depend on the type passed to this function: ---- ---- - List tables pass only the value of each element ---- - Non-list tables pass both the key and value of each element ---- - Function iterators pass all of the values returned by their respective ---- function ---- ---- Examples: ----
lua
---- local it = vim.iter({ 1, 2, 3, 4, 5 })
---- it:map(function(v)
----   return v * 3
---- end)
---- it:rev()
---- it:skip(2)
---- it:totable()
---- -- { 9, 6, 3 }
----
---- vim.iter(ipairs({ 1, 2, 3, 4, 5 })):map(function(i, v)
----   if i > 2 then return v end
---- end):totable()
---- -- { 3, 4, 5 }
----
---- local it = vim.iter(vim.gsplit('1,2,3,4,5', ','))
---- it:map(function(s) return tonumber(s) end)
---- for i, d in it:enumerate() do
----   print(string.format("Column %d is %d", i, d))
---- end
---- -- Column 1 is 1
---- -- Column 2 is 2
---- -- Column 3 is 3
---- -- Column 4 is 4
---- -- Column 5 is 5
----
---- vim.iter({ a = 1, b = 2, c = 3, z = 26 }):any(function(k, v)
----   return k == 'z'
---- end)
---- -- true
---- 
---- ----@see |lua-iter| ---- ----@param src table|function Table or iterator. ----@return Iter @|lua-iter| -function vim.iter(src, ...) - local Iter = require('vim.iter') - return Iter.new(src, ...) -end - ---- Collect an iterator into a table. ---- ---- This is a convenience function that performs: ----
lua
---- vim.iter(f):totable()
---- 
---- ----@param f function Iterator function ----@return table -function vim.totable(f, ...) - return vim.iter(f, ...):totable() -end - ---- Filter a table or iterator. ---- ---- This is a convenience function that performs: ----
lua
---- vim.iter(src):filter(f):totable()
---- 
---- ----@see |Iter:filter()| ---- ----@param f function(...):bool Filter function. Accepts the current iterator or table values as ---- arguments and returns true if those values should be kept in the ---- final table ----@param src table|function Table or iterator function to filter ----@return table -function vim.filter(f, src, ...) - return vim.iter(src, ...):filter(f):totable() -end - ---- Map and filter a table or iterator. ---- ---- This is a convenience function that performs: ----
lua
---- vim.iter(src):map(f):totable()
---- 
---- ----@see |Iter:map()| ---- ----@param f function(...):?any Map function. Accepts the current iterator or table values as ---- arguments and returns one or more new values. Nil values are removed ---- from the final table. ----@param src table|function Table or iterator function to filter ----@return table -function vim.map(f, src, ...) - return vim.iter(src, ...):map(f):totable() -end - return vim -- cgit From 08991b078267e5de0a19a136d00d4f71ad651a32 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 13 May 2023 21:33:22 +0200 Subject: docs: small fixes Co-authored-by: Christian Clason Co-authored-by: Gregory Anders Co-authored-by: HiPhish Co-authored-by: Julio B Co-authored-by: T727 <74924917+T-727@users.noreply.github.com> Co-authored-by: camoz Co-authored-by: champignoom <66909116+champignoom@users.noreply.github.com> --- runtime/lua/vim/shared.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index a55deb1415..4f230c4412 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -361,7 +361,7 @@ local function tbl_extend(behavior, deep_extend, ...) return ret end ---- Merges two or more map-like tables. +--- Merges two or more tables. --- ---@see |extend()| --- @@ -369,13 +369,13 @@ end --- - "error": raise an error --- - "keep": use value from the leftmost map --- - "force": use value from the rightmost map ----@param ... table Two or more map-like tables +---@param ... table Two or more tables ---@return table Merged table function vim.tbl_extend(behavior, ...) return tbl_extend(behavior, false, ...) end ---- Merges recursively two or more map-like tables. +--- Merges recursively two or more tables. --- ---@see |vim.tbl_extend()| --- @@ -385,7 +385,7 @@ end --- - "error": raise an error --- - "keep": use value from the leftmost map --- - "force": use value from the rightmost map ----@param ... T2 Two or more map-like tables +---@param ... T2 Two or more tables ---@return T1|T2 (table) Merged table function vim.tbl_deep_extend(behavior, ...) return tbl_extend(behavior, true, ...) -- cgit From 7c661207cc4357553ed2b057b6c8f28400024361 Mon Sep 17 00:00:00 2001 From: Mathias Fußenegger Date: Thu, 8 Jun 2023 12:11:24 +0200 Subject: feat(lua): add ringbuffer (#22894) https://en.wikipedia.org/wiki/Circular_buffer --- runtime/lua/vim/shared.lua | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 4f230c4412..f899157ab7 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -881,4 +881,98 @@ function vim.defaulttable(create) }) end +do + ---@class vim.Ringbuf + ---@field private _items table[] + ---@field private _idx_read integer + ---@field private _idx_write integer + ---@field private _size integer + local Ringbuf = {} + + --- Clear all items + function Ringbuf.clear(self) + self._items = {} + self._idx_read = 0 + self._idx_write = 0 + end + + --- Adds an item, overriding the oldest item if the buffer is full. + ---@generic T + ---@param item T + function Ringbuf.push(self, item) + self._items[self._idx_write] = item + self._idx_write = (self._idx_write + 1) % self._size + if self._idx_write == self._idx_read then + self._idx_read = (self._idx_read + 1) % self._size + end + end + + --- Removes and returns the first unread item + ---@generic T + ---@return T? + function Ringbuf.pop(self) + local idx_read = self._idx_read + if idx_read == self._idx_write then + return nil + end + local item = self._items[idx_read] + self._items[idx_read] = nil + self._idx_read = (idx_read + 1) % self._size + return item + end + + --- Returns the first unread item without removing it + ---@generic T + ---@return T? + function Ringbuf.peek(self) + if self._idx_read == self._idx_write then + return nil + end + return self._items[self._idx_read] + end + + --- Create a ring buffer limited to a maximal number of items. + --- Once the buffer is full, adding a new entry overrides the oldest entry. + --- + ---
+  ---   local ringbuf = vim.ringbuf(4)
+  ---   ringbuf:push("a")
+  ---   ringbuf:push("b")
+  ---   ringbuf:push("c")
+  ---   ringbuf:push("d")
+  ---   ringbuf:push("e")    -- overrides "a"
+  ---   print(ringbuf:pop()) -- returns "b"
+  ---   print(ringbuf:pop()) -- returns "c"
+  ---
+  ---   -- Can be used as iterator. Pops remaining items:
+  ---   for val in ringbuf do
+  ---     print(val)
+  ---   end
+  --- 
+ --- + --- Returns a Ringbuf instance with the following methods: + --- + --- - |Ringbuf:push()| + --- - |Ringbuf:pop()| + --- - |Ringbuf:peek()| + --- - |Ringbuf:clear()| + --- + ---@param size integer + ---@return vim.Ringbuf ringbuf (table) + function vim.ringbuf(size) + local ringbuf = { + _items = {}, + _size = size + 1, + _idx_read = 0, + _idx_write = 0, + } + return setmetatable(ringbuf, { + __index = Ringbuf, + __call = function(self) + return self:pop() + end, + }) + end +end + return vim -- cgit From d3b9feccb39124cefbe4b0c492fb0bc3f777d0b4 Mon Sep 17 00:00:00 2001 From: Stanislav Asunkin <1353637+stasjok@users.noreply.github.com> Date: Mon, 12 Jun 2023 01:48:13 +0300 Subject: docs: fix vim.tbl_get type annotations #23992 --- runtime/lua/vim/shared.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index f899157ab7..dd05299295 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -456,7 +456,7 @@ end ---
--- ---@param o table Table to index ----@param ... string Optional strings (0 or more, variadic) via which to index the table +---@param ... any Optional keys (0 or more, variadic) via which to index the table --- ---@return any Nested value indexed by key (if it exists), else nil function vim.tbl_get(o, ...) -- cgit From be74807eef13ff8c90d55cf8b22b01d6d33b1641 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 18 Jul 2023 15:42:30 +0100 Subject: docs(lua): more improvements (#24387) * docs(lua): teach lua2dox how to table * docs(lua): teach gen_vimdoc.py about local functions No more need to mark local functions with @private * docs(lua): mention @nodoc and @meta in dev-lua-doc * fixup! Co-authored-by: Justin M. Keyes --------- Co-authored-by: Justin M. Keyes --- runtime/lua/vim/shared.lua | 83 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 41 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index dd05299295..291b003d87 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -8,6 +8,45 @@ vim = vim or {} +local function _id(v) + return v +end + +local deepcopy + +local deepcopy_funcs = { + table = function(orig, cache) + if cache[orig] then + return cache[orig] + end + local copy = {} + + cache[orig] = copy + local mt = getmetatable(orig) + for k, v in pairs(orig) do + copy[deepcopy(k, cache)] = deepcopy(v, cache) + end + return setmetatable(copy, mt) + end, + number = _id, + string = _id, + ['nil'] = _id, + boolean = _id, + ['function'] = _id, +} + +deepcopy = function(orig, _cache) + local f = deepcopy_funcs[type(orig)] + if f then + return f(orig, _cache or {}) + else + if type(orig) == 'userdata' and orig == vim.NIL then + return vim.NIL + end + error('Cannot deepcopy object of type ' .. type(orig)) + end +end + --- Returns a deep copy of the given object. Non-table objects are copied as --- in a typical Lua assignment, whereas table objects are copied recursively. --- Functions are naively copied, so functions in the copied table point to the @@ -17,45 +56,9 @@ vim = vim or {} ---@generic T: table ---@param orig T Table to copy ---@return T Table of copied keys and (nested) values. -function vim.deepcopy(orig) end -- luacheck: no unused -vim.deepcopy = (function() - local function _id(v) - return v - end - - local deepcopy_funcs = { - table = function(orig, cache) - if cache[orig] then - return cache[orig] - end - local copy = {} - - cache[orig] = copy - local mt = getmetatable(orig) - for k, v in pairs(orig) do - copy[vim.deepcopy(k, cache)] = vim.deepcopy(v, cache) - end - return setmetatable(copy, mt) - end, - number = _id, - string = _id, - ['nil'] = _id, - boolean = _id, - ['function'] = _id, - } - - return function(orig, cache) - local f = deepcopy_funcs[type(orig)] - if f then - return f(orig, cache or {}) - else - if type(orig) == 'userdata' and orig == vim.NIL then - return vim.NIL - end - error('Cannot deepcopy object of type ' .. type(orig)) - end - end -end)() +function vim.deepcopy(orig) + return deepcopy(orig) +end --- Splits a string at each instance of a separator. --- @@ -318,7 +321,6 @@ function vim.tbl_isempty(t) end --- We only merge empty tables or tables that are not an array (indexed by integers) ----@private local function can_merge(v) return type(v) == 'table' and (vim.tbl_isempty(v) or not vim.tbl_isarray(v)) end @@ -770,7 +772,6 @@ do return type(val) == t or (t == 'callable' and vim.is_callable(val)) end - ---@private local function is_valid(opt) if type(opt) ~= 'table' then return false, string.format('opt: expected table, got %s', type(opt)) -- cgit From d2f81330247ee060d557330b2716ccea8f789a50 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 12 Jul 2023 19:27:14 +0200 Subject: docs: misc Co-authored-by: Kevin Pham --- runtime/lua/vim/shared.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 291b003d87..5ce5b200d3 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -60,7 +60,8 @@ function vim.deepcopy(orig) return deepcopy(orig) end ---- Splits a string at each instance of a separator. +--- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion +--- (as opposed to |vim.split()| which is "eager"). --- --- Example: ---
lua
@@ -159,7 +160,8 @@ function vim.gsplit(s, sep, opts)
   end
 end
 
---- Splits a string at each instance of a separator.
+--- Splits a string at each instance of a separator and returns the result as a table (unlike
+--- |vim.gsplit()|).
 ---
 --- Examples:
 --- 
lua
@@ -530,8 +532,8 @@ end
 ---
 ---@see Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
 ---
----@param t table List-like table
----@return iterator over sorted keys and their values
+---@param t table Dict-like table
+---@return # iterator over sorted keys and their values
 function vim.spairs(t)
   assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
 
-- 
cgit 


From b034378cf58bea18ea1bdb4d63692a1336b5752b Mon Sep 17 00:00:00 2001
From: "Justin M. Keyes" 
Date: Thu, 3 Aug 2023 08:35:10 -0700
Subject: docs: luaref cleanup #24541
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- drop "luaref-" prefix in favor of "lua-" or nothing, where possible.
- remove redundant "luaref--lang…" and "luaref-api…" tags.
---
 runtime/lua/vim/shared.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'runtime/lua/vim/shared.lua')

diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 5ce5b200d3..32575a1cc9 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -80,7 +80,7 @@ end
 ---
 --- @see |string.gmatch()|
 --- @see |vim.split()|
---- @see |luaref-patterns|
+--- @see |lua-patterns|
 --- @see https://www.lua.org/pil/20.2.html
 --- @see http://lua-users.org/wiki/StringLibraryTutorial
 ---
@@ -660,7 +660,7 @@ end
 
 --- Trim whitespace (Lua pattern "%s") from both sides of a string.
 ---
----@see |luaref-patterns|
+---@see |lua-patterns|
 ---@see https://www.lua.org/pil/20.2.html
 ---@param s string String to trim
 ---@return string String with whitespace removed from its beginning and end
-- 
cgit 


From c43c745a14dced87a23227d7be4f1c33d4455193 Mon Sep 17 00:00:00 2001
From: Christian Clason 
Date: Wed, 9 Aug 2023 11:06:13 +0200
Subject: fix(lua): improve annotations for stricter luals diagnostics (#24609)

Problem: luals returns stricter diagnostics with bundled luarc.json
Solution: Improve some function and type annotations:

* use recognized uv.* types
* disable diagnostic for global `vim` in shared.lua
* docs: don't start comment lines with taglink (otherwise LuaLS will interpret it as a type)
* add type alias for lpeg pattern
* fix return annotation for `vim.secure.trust`
* rename local Range object in vim.version (shadows `Range` in vim.treesitter)
* fix some "missing fields" warnings
* add missing required fields for test functions in eval.lua
* rename lsp meta files for consistency
---
 runtime/lua/vim/shared.lua | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'runtime/lua/vim/shared.lua')

diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 32575a1cc9..422d49d746 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -6,6 +6,7 @@
 -- or the test suite. (Eventually the test suite will be run in a worker process,
 -- so this wouldn't be a separate case to consider)
 
+---@diagnostic disable-next-line: lowercase-global
 vim = vim or {}
 
 local function _id(v)
@@ -533,7 +534,7 @@ end
 ---@see Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
 ---
 ---@param t table Dict-like table
----@return # iterator over sorted keys and their values
+---@return function iterator over sorted keys and their values
 function vim.spairs(t)
   assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
 
-- 
cgit 


From 2e92065686f62851318150a315591c30b8306a4b Mon Sep 17 00:00:00 2001
From: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date: Thu, 14 Sep 2023 08:23:01 -0500
Subject: docs: replace 
 with ``` (#25136)

---
 runtime/lua/vim/shared.lua | 120 ++++++++++++++++++++++++---------------------
 1 file changed, 64 insertions(+), 56 deletions(-)

(limited to 'runtime/lua/vim/shared.lua')

diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 422d49d746..0c38fa955a 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -65,19 +65,21 @@ end
 --- (as opposed to |vim.split()| which is "eager").
 ---
 --- Example:
----   
lua
----   for s in vim.gsplit(':aa::b:', ':', {plain=true}) do
----     print(s)
----   end
----   
+--- +--- ```lua +--- for s in vim.gsplit(':aa::b:', ':', {plain=true}) do +--- print(s) +--- end +--- ``` --- --- If you want to also inspect the separator itself (instead of discarding it), use --- |string.gmatch()|. Example: ----
lua
----   for word, num in ('foo111bar222'):gmatch('([^0-9]*)(%d*)') do
----     print(('word: %s num: %s'):format(word, num))
----   end
----   
+--- +--- ```lua +--- for word, num in ('foo111bar222'):gmatch('([^0-9]*)(%d*)') do +--- print(('word: %s num: %s'):format(word, num)) +--- end +--- ``` --- --- @see |string.gmatch()| --- @see |vim.split()| @@ -165,12 +167,13 @@ end --- |vim.gsplit()|). --- --- Examples: ----
lua
----  split(":aa::b:", ":")                   --> {'','aa','','b',''}
----  split("axaby", "ab?")                   --> {'','x','y'}
----  split("x*yz*o", "*", {plain=true})      --> {'x','yz','o'}
----  split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'}
---- 
+--- +--- ```lua +--- split(":aa::b:", ":") --> {'','aa','','b',''} +--- split("axaby", "ab?") --> {'','x','y'} +--- split("x*yz*o", "*", {plain=true}) --> {'x','yz','o'} +--- split("|x|y|z|", "|", {trimempty=true}) --> {'x', 'y', 'z'} +--- ``` --- ---@see |vim.gsplit()| ---@see |string.gmatch()| @@ -259,12 +262,13 @@ end --- a predicate that is checked for each value. --- --- Example: ----
lua
----  vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v)
----    return vim.deep_equal(v, { 'b', 'c' })
----  end, { predicate = true })
----  -- true
---- 
+--- +--- ```lua +--- vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v) +--- return vim.deep_equal(v, { 'b', 'c' }) +--- end, { predicate = true }) +--- -- true +--- ``` --- ---@see |vim.list_contains()| for checking values in list-like tables --- @@ -455,10 +459,11 @@ end --- Return `nil` if the key does not exist. --- --- Examples: ----
lua
----  vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true
----  vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil
---- 
+--- +--- ```lua +--- vim.tbl_get({ key = { nested_key = true }}, 'key', 'nested_key') == true +--- vim.tbl_get({ key = {}}, 'key', 'nested_key') == nil +--- ``` --- ---@param o table Table to index ---@param ... any Optional keys (0 or more, variadic) via which to index the table @@ -626,10 +631,10 @@ end --- Counts the number of non-nil values in table `t`. --- ----
lua
+--- ```lua
 --- vim.tbl_count({ a=1, b=2 })  --> 2
 --- vim.tbl_count({ 1, 2 })      --> 2
---- 
+--- ``` --- ---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua ---@param t table Table @@ -703,38 +708,41 @@ end --- Validates a parameter specification (types and values). --- --- Usage example: ----
lua
----  function user.new(name, age, hobbies)
----    vim.validate{
----      name={name, 'string'},
----      age={age, 'number'},
----      hobbies={hobbies, 'table'},
----    }
----    ...
----  end
---- 
+--- +--- ```lua +--- function user.new(name, age, hobbies) +--- vim.validate{ +--- name={name, 'string'}, +--- age={age, 'number'}, +--- hobbies={hobbies, 'table'}, +--- } +--- ... +--- end +--- ``` --- --- Examples with explicit argument values (can be run directly): ----
lua
----  vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
----     --> NOP (success)
 ---
----  vim.validate{arg1={1, 'table'}}
----     --> error('arg1: expected table, got number')
+--- ```lua
+--- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
+---    --> NOP (success)
 ---
----  vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
----     --> error('arg1: expected even number, got 3')
---- 
+--- vim.validate{arg1={1, 'table'}} +--- --> error('arg1: expected table, got number') +--- +--- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} +--- --> error('arg1: expected even number, got 3') +--- ``` --- --- If multiple types are valid they can be given as a list. ----
lua
----  vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
----     --> NOP (success)
 ---
----  vim.validate{arg1={1, {'string', 'table'}}}
----     --> error('arg1: expected string|table, got number')
+--- ```lua
+--- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
+--- -- NOP (success)
+---
+--- vim.validate{arg1={1, {'string', 'table'}}}
+--- -- error('arg1: expected string|table, got number')
 ---
---- 
+--- ``` --- ---@param opt table Names of parameters to validate. Each key is a parameter --- name; each value is a tuple in one of these forms: @@ -866,10 +874,10 @@ end --- If {create} is `nil`, this will create a defaulttable whose constructor function is --- this function, effectively allowing to create nested tables on the fly: --- ----
lua
+--- ```lua
 --- local a = vim.defaulttable()
 --- a.b.c = 1
---- 
+--- ``` --- ---@param create function?(key:any):any The function called to create a missing value. ---@return table Empty table with metamethod @@ -938,7 +946,7 @@ do --- Create a ring buffer limited to a maximal number of items. --- Once the buffer is full, adding a new entry overrides the oldest entry. --- - ---
+  --- ```lua
   ---   local ringbuf = vim.ringbuf(4)
   ---   ringbuf:push("a")
   ---   ringbuf:push("b")
@@ -952,7 +960,7 @@ do
   ---   for val in ringbuf do
   ---     print(val)
   ---   end
-  --- 
+ --- ``` --- --- Returns a Ringbuf instance with the following methods: --- -- cgit From 1b55f51d0d8468ca357514a868ac8e188b0c8722 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 20 Sep 2023 04:15:23 -0700 Subject: docs: misc #24561 fix #24699 fix #25253 --- runtime/lua/vim/shared.lua | 153 ++++++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 77 deletions(-) (limited to 'runtime/lua/vim/shared.lua') diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 0c38fa955a..9542d93789 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -534,12 +534,12 @@ function vim.tbl_flatten(t) return result end ---- Enumerate a table sorted by its keys. +--- Enumerates key-value pairs of a table, ordered by key. --- ---@see Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua --- ---@param t table Dict-like table ----@return function iterator over sorted keys and their values +---@return function # |for-in| iterator over sorted keys and their values function vim.spairs(t) assert(type(t) == 'table', string.format('Expected table, got %s', type(t))) @@ -551,7 +551,6 @@ function vim.spairs(t) table.sort(keys) -- Return the iterator function. - -- TODO(justinmk): Return "iterator function, table {t}, and nil", like pairs()? local i = 0 return function() i = i + 1 @@ -561,11 +560,14 @@ function vim.spairs(t) end end ---- Tests if a Lua table can be treated as an array (a table indexed by integers). +--- Tests if `t` is an "array": a table indexed _only_ by integers (potentially non-contiguous). --- ---- Empty table `{}` is assumed to be an array, unless it was created by ---- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result, ---- for example from |rpcrequest()| or |vim.fn|. +--- If the indexes start from 1 and are contiguous then the array is also a list. |vim.tbl_islist()| +--- +--- Empty table `{}` is an array, unless it was created by |vim.empty_dict()| or returned as +--- a dict-like |API| or Vimscript result, for example from |rpcrequest()| or |vim.fn|. +--- +---@see https://github.com/openresty/luajit2#tableisarray --- ---@param t table ---@return boolean `true` if array-like table, else `false`. @@ -597,11 +599,13 @@ function vim.tbl_isarray(t) end end ---- Tests if a Lua table can be treated as a list (a table indexed by consecutive integers starting from 1). +--- Tests if `t` is a "list": a table indexed _only_ by contiguous integers starting from 1 (what +--- |lua-length| calls a "regular array"). +--- +--- Empty table `{}` is a list, unless it was created by |vim.empty_dict()| or returned as +--- a dict-like |API| or Vimscript result, for example from |rpcrequest()| or |vim.fn|. --- ---- Empty table `{}` is assumed to be an list, unless it was created by ---- |vim.empty_dict()| or returned as a dict-like |API| or Vimscript result, ---- for example from |rpcrequest()| or |vim.fn|. +---@see |vim.tbl_isarray()| --- ---@param t table ---@return boolean `true` if list-like table, else `false`. @@ -705,61 +709,6 @@ function vim.endswith(s, suffix) return #suffix == 0 or s:sub(-#suffix) == suffix end ---- Validates a parameter specification (types and values). ---- ---- Usage example: ---- ---- ```lua ---- function user.new(name, age, hobbies) ---- vim.validate{ ---- name={name, 'string'}, ---- age={age, 'number'}, ---- hobbies={hobbies, 'table'}, ---- } ---- ... ---- end ---- ``` ---- ---- Examples with explicit argument values (can be run directly): ---- ---- ```lua ---- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} ---- --> NOP (success) ---- ---- vim.validate{arg1={1, 'table'}} ---- --> error('arg1: expected table, got number') ---- ---- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} ---- --> error('arg1: expected even number, got 3') ---- ``` ---- ---- If multiple types are valid they can be given as a list. ---- ---- ```lua ---- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} ---- -- NOP (success) ---- ---- vim.validate{arg1={1, {'string', 'table'}}} ---- -- error('arg1: expected string|table, got number') ---- ---- ``` ---- ----@param opt table Names of parameters to validate. Each key is a parameter ---- name; each value is a tuple in one of these forms: ---- 1. (arg_value, type_name, optional) ---- - arg_value: argument value ---- - type_name: string|table type name, one of: ("table", "t", "string", ---- "s", "number", "n", "boolean", "b", "function", "f", "nil", ---- "thread", "userdata") or list of them. ---- - optional: (optional) boolean, if true, `nil` is valid ---- 2. (arg_value, fn, msg) ---- - arg_value: argument value ---- - fn: any function accepting one argument, returns true if and ---- only if the argument is valid. Can optionally return an additional ---- informative error message as the second returned value. ---- - msg: (optional) error string if validation fails -function vim.validate(opt) end -- luacheck: no unused - do local type_names = { ['table'] = 'table', @@ -844,6 +793,59 @@ do return true, nil end + --- Validates a parameter specification (types and values). + --- + --- Usage example: + --- + --- ```lua + --- function user.new(name, age, hobbies) + --- vim.validate{ + --- name={name, 'string'}, + --- age={age, 'number'}, + --- hobbies={hobbies, 'table'}, + --- } + --- ... + --- end + --- ``` + --- + --- Examples with explicit argument values (can be run directly): + --- + --- ```lua + --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}} + --- --> NOP (success) + --- + --- vim.validate{arg1={1, 'table'}} + --- --> error('arg1: expected table, got number') + --- + --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}} + --- --> error('arg1: expected even number, got 3') + --- ``` + --- + --- If multiple types are valid they can be given as a list. + --- + --- ```lua + --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}} + --- -- NOP (success) + --- + --- vim.validate{arg1={1, {'string', 'table'}}} + --- -- error('arg1: expected string|table, got number') + --- + --- ``` + --- + ---@param opt table Names of parameters to validate. Each key is a parameter + --- name; each value is a tuple in one of these forms: + --- 1. (arg_value, type_name, optional) + --- - arg_value: argument value + --- - type_name: string|table type name, one of: ("table", "t", "string", + --- "s", "number", "n", "boolean", "b", "function", "f", "nil", + --- "thread", "userdata") or list of them. + --- - optional: (optional) boolean, if true, `nil` is valid + --- 2. (arg_value, fn, msg) + --- - arg_value: argument value + --- - fn: any function accepting one argument, returns true if and + --- only if the argument is valid. Can optionally return an additional + --- informative error message as the second returned value. + --- - msg: (optional) error string if validation fails function vim.validate(opt) local ok, err_msg = is_valid(opt) if not ok then @@ -866,28 +868,25 @@ function vim.is_callable(f) return type(m.__call) == 'function' end ---- Creates a table whose members are automatically created when accessed, if they don't already ---- exist. ---- ---- They mimic defaultdict in python. +--- Creates a table whose missing keys are provided by {createfn} (like Python's "defaultdict"). --- ---- If {create} is `nil`, this will create a defaulttable whose constructor function is ---- this function, effectively allowing to create nested tables on the fly: +--- If {createfn} is `nil` it defaults to defaulttable() itself, so accessing nested keys creates +--- nested tables: --- --- ```lua --- local a = vim.defaulttable() --- a.b.c = 1 --- ``` --- ----@param create function?(key:any):any The function called to create a missing value. ----@return table Empty table with metamethod -function vim.defaulttable(create) - create = create or function(_) +---@param createfn function?(key:any):any Provides the value for a missing `key`. +---@return table # Empty table with `__index` metamethod. +function vim.defaulttable(createfn) + createfn = createfn or function(_) return vim.defaulttable() end return setmetatable({}, { __index = function(tbl, key) - rawset(tbl, key, create(key)) + rawset(tbl, key, createfn(key)) return rawget(tbl, key) end, }) -- cgit