From 46a87a5d2bac598fed0870f0d3c926087f95d30f Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 14 Feb 2023 05:19:04 -0500 Subject: refactor(api): VALIDATE macros #22187 Problem: - API validation involves too much boilerplate. - API validation errors are not consistently worded. Solution: Introduce some macros. Currently these are clumsy, but they at least help with consistency and avoid some nesting. --- test/functional/lua/vim_spec.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 867f366d06..b43e5b28db 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -1458,7 +1458,7 @@ describe('lua stdlib', function() ]] eq('', funcs.luaeval "vim.bo.filetype") eq(true, funcs.luaeval "vim.bo[BUF].modifiable") - matches("no such option: 'nosuchopt'$", + matches("Invalid option %(not found%): 'nosuchopt'$", pcall_err(exec_lua, 'return vim.bo.nosuchopt')) matches("Expected lua string$", pcall_err(exec_lua, 'return vim.bo[0][0].autoread')) @@ -1479,7 +1479,7 @@ describe('lua stdlib', function() eq(0, funcs.luaeval "vim.wo.cole") eq(0, funcs.luaeval "vim.wo[0].cole") eq(0, funcs.luaeval "vim.wo[1001].cole") - matches("no such option: 'notanopt'$", + matches("Invalid option %(not found%): 'notanopt'$", pcall_err(exec_lua, 'return vim.wo.notanopt')) matches("Expected lua string$", pcall_err(exec_lua, 'return vim.wo[0][0].list')) -- cgit From 79571b92ced968ad27bee2a7515a4a04e84dbad2 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Wed, 27 Jan 2021 09:00:28 +0100 Subject: feat(lua): omnifunc for builting lua interpreter also make implicit submodules "uri" and "_inspector" work with completion this is needed for `:lua=vim.uri_` wildmenu completion to work even before uri or _inspector functions are used. --- test/functional/lua/vim_spec.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index b43e5b28db..77628487ca 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2900,6 +2900,29 @@ describe('lua stdlib', function() end) end) + it('vim.lua_omnifunc', function() + local screen = Screen.new(60,5) + screen:set_default_attr_ids { + [1] = {foreground = Screen.colors.Blue1, bold = true}; + [2] = {background = Screen.colors.WebGray}; + [3] = {background = Screen.colors.LightMagenta}; + [4] = {bold = true}; + [5] = {foreground = Screen.colors.SeaGreen, bold = true}; + } + screen:attach() + command [[ set omnifunc=v:lua.vim.lua_omnifunc ]] + + -- Note: the implementation is shared with lua command line completion. + -- More tests for completion in lua/command_line_completion_spec.lua + feed [[ivim.insp]] + screen:expect{grid=[[ + vim.inspect^ | + {1:~ }{2: inspect }{1: }| + {1:~ }{3: inspect_pos }{1: }| + {1:~ }| + {4:-- Omni completion (^O^N^P) }{5:match 1 of 2} | + ]]} + end) end) describe('lua: builtin modules', function() -- cgit From 673d2b52fa4335aa083c52e6686f0728e25b8ebd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Tue, 7 Mar 2023 16:04:57 +0100 Subject: refactor!: rename vim.pretty_print => vim.print Problem: The function name `vim.pretty_print`: 1. is verbose, which partially defeats its purpose as sugar 2. does not draw from existing precedent or any sort of convention (except external projects like penlight or python?), which reduces discoverability, and degrades signaling about best practices. Solution: - Rename to `vim.print`. - Change the behavior so that 1. strings are printed without quotes 2. each arg is printed on its own line 3. tables are indented with 2 instead of 4 spaces - Example: :lua ='a', 'b', 42, {a=3} a b 42 { a = 3 } Comparison of alternatives: - `vim.print`: - pro: consistent with Lua's `print()` - pro: aligns with potential `nvim_print` API function which will replace nvim_echo, nvim_notify, etc. - con: behaves differently than Lua's `print()`, slightly misleading? - `vim.echo`: - pro: `:echo` has similar "pretty print" behavior. - con: inconsistent with Lua idioms. - `vim.p`: - pro: very short, fits with `vim.o`, etc. - con: not as discoverable as "echo" - con: less opportunity for `local p = vim.p` because of potential shadowing. --- test/functional/lua/vim_spec.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 77628487ca..470102df5e 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -6,6 +6,7 @@ local nvim_prog = helpers.nvim_prog local funcs = helpers.funcs local meths = helpers.meths local command = helpers.command +local dedent = helpers.dedent local insert = helpers.insert local clear = helpers.clear local eq = helpers.eq @@ -2269,7 +2270,7 @@ describe('lua stdlib', function() describe('vim.region', function() it('charwise', function() - insert(helpers.dedent( [[ + insert(dedent( [[ text tααt tααt text text tαxt txtα tex text tαxt tαxt @@ -2923,6 +2924,24 @@ describe('lua stdlib', function() {4:-- Omni completion (^O^N^P) }{5:match 1 of 2} | ]]} end) + + it('vim.print', function() + -- vim.print() returns its args. + eq({42, 'abc', { a = { b = 77 }}}, + exec_lua[[return {vim.print(42, 'abc', { a = { b = 77 }})}]]) + + -- vim.print() pretty-prints the args. + eq(dedent[[ + + 42 + abc + { + a = { + b = 77 + } + }]], + eval[[execute('lua vim.print(42, "abc", { a = { b = 77 }})')]]) + end) end) describe('lua: builtin modules', function() -- cgit From 210120dde81ec289ae01e1d247df08f0b147c08a Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 15 Mar 2023 08:56:13 -0400 Subject: fix(lua): vim.deprecate() shows ":help deprecated" #22677 Problem: vim.deprecate() shows ":help deprecated" for third-party plugins. ":help deprecated" only describes deprecations in Nvim, and is unrelated to any 3rd party deprecations. Solution: If `plugin` is specified, don't show ":help deprecated". fix #22235 --- test/functional/lua/vim_spec.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 470102df5e..0483ec46f0 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -127,6 +127,22 @@ describe('lua stdlib', function() eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")')) end) + it('vim.deprecate', function() + -- vim.deprecate(name, alternative, version, plugin, backtrace) + eq(dedent[[ + foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated + This feature will be removed in Nvim version 2.17]], + exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '2.17')) + -- Same message, skipped. + eq(vim.NIL, + exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '2.17')) + -- When `plugin` is specified, don't show ":help deprecated". #22235 + eq(dedent[[ + foo.bar() is deprecated, use zub.wooo{ok=yay} instead. + This feature will be removed in my-plugin.nvim version 0.3.0]], + exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.3.0', 'my-plugin.nvim', false)) + end) + it('vim.startswith', function() eq(true, funcs.luaeval('vim.startswith("123", "1")')) eq(true, funcs.luaeval('vim.startswith("123", "")')) -- 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 --- test/functional/lua/vim_spec.lua | 65 +++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 27 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 0483ec46f0..4cf38a1567 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -292,51 +292,62 @@ describe('lua stdlib', function() ]]} end) - it("vim.split", function() - local split = function(str, sep, kwargs) - return exec_lua('return vim.split(...)', str, sep, kwargs) - end - + it('vim.gsplit, vim.split', function() local tests = { - { "a,b", ",", false, false, { 'a', 'b' } }, - { ":aa::bb:", ":", false, false, { '', 'aa', '', 'bb', '' } }, - { ":aa::bb:", ":", false, true, { 'aa', '', 'bb' } }, - { "::ee::ff:", ":", false, false, { '', '', 'ee', '', 'ff', '' } }, - { "::ee::ff:", ":", false, true, { 'ee', '', 'ff' } }, - { "ab", ".", false, false, { '', '', '' } }, - { "a1b2c", "[0-9]", false, false, { 'a', 'b', 'c' } }, - { "xy", "", false, false, { 'x', 'y' } }, - { "here be dragons", " ", false, false, { "here", "be", "dragons"} }, - { "axaby", "ab?", false, false, { '', 'x', 'y' } }, - { "f v2v v3v w2w ", "([vw])2%1", false, false, { 'f ', ' v3v ', ' ' } }, - { "", "", false, false, {} }, - { "", "a", false, false, { '' } }, - { "x*yz*oo*l", "*", true, false, { 'x', 'yz', 'oo', 'l' } }, + { 'a,b', ',', false, false, { 'a', 'b' } }, + { ':aa::::bb:', ':', false, false, { '', 'aa', '', '', '', 'bb', '' } }, + { ':aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } }, + { ':aa::bb:', ':', false, true, { 'aa', '', 'bb' } }, + { '/a/b:/b/\n', '[:\n]', false, true, { '/a/b', '/b/' } }, + { '::ee::ff:', ':', false, false, { '', '', 'ee', '', 'ff', '' } }, + { '::ee::ff::', ':', false, true, { 'ee', '', 'ff' } }, + { 'ab', '.', false, false, { '', '', '' } }, + { 'a1b2c', '[0-9]', false, false, { 'a', 'b', 'c' } }, + { 'xy', '', false, false, { 'x', 'y' } }, + { 'here be dragons', ' ', false, false, { 'here', 'be', 'dragons'} }, + { 'axaby', 'ab?', false, false, { '', 'x', 'y' } }, + { 'f v2v v3v w2w ', '([vw])2%1', false, false, { 'f ', ' v3v ', ' ' } }, + { '', '', false, false, {} }, + { '', '', false, true, {} }, + { '\n', '[:\n]', false, true, {} }, + { '', 'a', false, false, { '' } }, + { 'x*yz*oo*l', '*', true, false, { 'x', 'yz', 'oo', 'l' } }, } for _, t in ipairs(tests) do - eq(t[5], split(t[1], t[2], {plain=t[3], trimempty=t[4]})) + eq(t[5], vim.split(t[1], t[2], {plain=t[3], trimempty=t[4]})) end -- Test old signature - eq({'x', 'yz', 'oo', 'l'}, split("x*yz*oo*l", "*", true)) + eq({'x', 'yz', 'oo', 'l'}, vim.split("x*yz*oo*l", "*", true)) local loops = { { "abc", ".-" }, } for _, t in ipairs(loops) do - matches("Infinite loop detected", pcall_err(split, t[1], t[2])) + matches("Infinite loop detected", pcall_err(vim.split, t[1], t[2])) end + -- `keepsep` + eq({ '', '.', '', '.', 'aa', '.', 'bb', '.', 'cc', '.', 'dd', '.', 'ee', '.', '', }, + vim.split('..aa.bb.cc.dd.ee.', '%.', {keepsep=true})) + eq({ '..aa', '1', '.bb', '2', '', '2', '.cc.', '9', '', }, + vim.split('..aa1.bb22.cc.9', '%d', {keepsep=true})) + eq({ '..aa', '1', '.bb', '22', '.cc.', '9', '', }, + vim.split('..aa1.bb22.cc.9', '%d+', {keepsep=true})) + -- Validates args. - eq(true, pcall(split, 'string', 'string')) + eq(true, pcall(vim.split, 'string', 'string')) matches('s: expected string, got number', - pcall_err(split, 1, 'string')) + pcall_err(vim.split, 1, 'string')) matches('sep: expected string, got number', - pcall_err(split, 'string', 1)) - matches('kwargs: expected table, got number', - pcall_err(split, 'string', 'string', 1)) + pcall_err(vim.split, 'string', 1)) + matches('opts: expected table, got number', + pcall_err(vim.split, 'string', 'string', 1)) + -- Not supported (yet). + matches('keepsep%+trimempty not supported', + pcall_err(vim.split, 'foo bar', ' ', {keepsep=true, trimempty=true})) end) it('vim.trim', function() -- 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. --- test/functional/lua/vim_spec.lua | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 4cf38a1567..a0428ed933 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -329,14 +329,6 @@ describe('lua stdlib', function() matches("Infinite loop detected", pcall_err(vim.split, t[1], t[2])) end - -- `keepsep` - eq({ '', '.', '', '.', 'aa', '.', 'bb', '.', 'cc', '.', 'dd', '.', 'ee', '.', '', }, - vim.split('..aa.bb.cc.dd.ee.', '%.', {keepsep=true})) - eq({ '..aa', '1', '.bb', '2', '', '2', '.cc.', '9', '', }, - vim.split('..aa1.bb22.cc.9', '%d', {keepsep=true})) - eq({ '..aa', '1', '.bb', '22', '.cc.', '9', '', }, - vim.split('..aa1.bb22.cc.9', '%d+', {keepsep=true})) - -- Validates args. eq(true, pcall(vim.split, 'string', 'string')) matches('s: expected string, got number', @@ -345,9 +337,6 @@ describe('lua stdlib', function() pcall_err(vim.split, 'string', 1)) matches('opts: expected table, got number', pcall_err(vim.split, 'string', 'string', 1)) - -- Not supported (yet). - matches('keepsep%+trimempty not supported', - pcall_err(vim.split, 'foo bar', ' ', {keepsep=true, trimempty=true})) end) it('vim.trim', function() -- 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. --- test/functional/lua/vim_spec.lua | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index a0428ed933..4f401eed8f 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2915,6 +2915,15 @@ describe('lua stdlib', function() return a ]]) end) + + it('accepts the key name', function() + eq({ b = 'b', c = 'c' }, exec_lua [[ + local a = vim.defaulttable(function(k) return k end) + local _ = a.b + local _ = a.c + return a + ]]) + end) end) it('vim.lua_omnifunc', function() -- cgit From 34ac75b32927328a0c691c5bda987c0fdb5ce9eb Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 5 Apr 2023 17:19:53 +0100 Subject: refactor: rename local API alias from a to api Problem: Codebase inconsistently binds vim.api onto a or api. Solution: Use api everywhere. a as an identifier is too short to have at the module level. --- test/functional/lua/vim_spec.lua | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 4f401eed8f..9508469a61 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2721,11 +2721,11 @@ describe('lua stdlib', function() it('does not cause ml_get errors with invalid visual selection', function() -- Should be fixed by vim-patch:8.2.4028. exec_lua [[ - local a = vim.api - local t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end - a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"}) - a.nvim_feedkeys(t "G", "txn", false) - a.nvim_buf_call(a.nvim_create_buf(false, true), function() vim.cmd "redraw" end) + local api = vim.api + local t = function(s) return api.nvim_replace_termcodes(s, true, true, true) end + api.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"}) + api.nvim_feedkeys(t "G", "txn", false) + api.nvim_buf_call(api.nvim_create_buf(false, true), function() vim.cmd "redraw" end) ]] end) @@ -2800,29 +2800,29 @@ describe('lua stdlib', function() it('does not cause ml_get errors with invalid visual selection', function() -- Add lines to the current buffer and make another window looking into an empty buffer. exec_lua [[ - _G.a = vim.api - _G.t = function(s) return a.nvim_replace_termcodes(s, true, true, true) end - _G.win_lines = a.nvim_get_current_win() + _G.api = vim.api + _G.t = function(s) return api.nvim_replace_termcodes(s, true, true, true) end + _G.win_lines = api.nvim_get_current_win() vim.cmd "new" - _G.win_empty = a.nvim_get_current_win() - a.nvim_set_current_win(win_lines) - a.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"}) + _G.win_empty = api.nvim_get_current_win() + api.nvim_set_current_win(win_lines) + api.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"}) ]] -- Start Visual in current window, redraw in other window with fewer lines. -- Should be fixed by vim-patch:8.2.4018. exec_lua [[ - a.nvim_feedkeys(t "G", "txn", false) - a.nvim_win_call(win_empty, function() vim.cmd "redraw" end) + api.nvim_feedkeys(t "G", "txn", false) + api.nvim_win_call(win_empty, function() vim.cmd "redraw" end) ]] -- Start Visual in current window, extend it in other window with more lines. -- Fixed for win_execute by vim-patch:8.2.4026, but nvim_win_call should also not be affected. exec_lua [[ - a.nvim_feedkeys(t "gg", "txn", false) - a.nvim_set_current_win(win_empty) - a.nvim_feedkeys(t "gg", "txn", false) - a.nvim_win_call(win_lines, function() a.nvim_feedkeys(t "G", "txn", false) end) + api.nvim_feedkeys(t "gg", "txn", false) + api.nvim_set_current_win(win_empty) + api.nvim_feedkeys(t "gg", "txn", false) + api.nvim_win_call(win_lines, function() api.nvim_feedkeys(t "G", "txn", false) end) vim.cmd "redraw" ]] end) @@ -2836,14 +2836,14 @@ describe('lua stdlib', function() } screen:attach() exec_lua [[ - _G.a = vim.api + _G.api = vim.api vim.opt.ruler = true local lines = {} for i = 0, 499 do lines[#lines + 1] = tostring(i) end - a.nvim_buf_set_lines(0, 0, -1, true, lines) - a.nvim_win_set_cursor(0, {20, 0}) + api.nvim_buf_set_lines(0, 0, -1, true, lines) + api.nvim_win_set_cursor(0, {20, 0}) vim.cmd "split" - _G.win = a.nvim_get_current_win() + _G.win = api.nvim_get_current_win() vim.cmd "wincmd w | redraw" ]] screen:expect [[ @@ -2854,7 +2854,7 @@ describe('lua stdlib', function() | ]] exec_lua [[ - a.nvim_win_call(win, function() a.nvim_win_set_cursor(0, {100, 0}) end) + api.nvim_win_call(win, function() api.nvim_win_set_cursor(0, {100, 0}) end) vim.cmd "redraw" ]] screen:expect [[ -- cgit From d675bd01b1e78b93e559320b262bdae40b3b54b2 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Fri, 7 Apr 2023 08:22:47 -0600 Subject: feat(lua): allow vim.F.if_nil to take multiple arguments (#22903) The first argument which is non-nil is returned. This is useful when using nested default values (e.g. in the EditorConfig plugin). Before: local enable = vim.F.if_nil(vim.b.editorconfig, vim.F.if_nil(vim.g.editorconfig, true)) After: local enable = vim.F.if_nil(vim.b.editorconfig, vim.g.editorconfig, true) --- test/functional/lua/vim_spec.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 9508469a61..45d9263c0c 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2967,6 +2967,32 @@ describe('lua stdlib', function() }]], eval[[execute('lua vim.print(42, "abc", { a = { b = 77 }})')]]) end) + + it('vim.F.if_nil', function() + local function if_nil(...) + return exec_lua([[ + local args = {...} + local nargs = select('#', ...) + for i = 1, nargs do + if args[i] == vim.NIL then + args[i] = nil + end + end + return vim.F.if_nil(unpack(args, 1, nargs)) + ]], ...) + end + + local a = NIL + local b = NIL + local c = 42 + local d = false + eq(42, if_nil(a, c)) + eq(false, if_nil(d, b)) + eq(42, if_nil(a, b, c, d)) + eq(false, if_nil(d)) + eq(false, if_nil(d, c)) + eq(NIL, if_nil(a)) + end) end) describe('lua: builtin modules', function() -- cgit From 9e86f473e0f4e21c5f40bf990c53194d593a0f9f Mon Sep 17 00:00:00 2001 From: NAKAI Tsuyoshi <82267684+uga-rosa@users.noreply.github.com> Date: Tue, 11 Apr 2023 23:28:46 +0900 Subject: feat(lua): vim.region accepts getpos() arg (#22635) --- test/functional/lua/vim_spec.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 45d9263c0c..85e45788e8 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2297,6 +2297,10 @@ describe('lua stdlib', function() insert([[αα]]) eq({0,5}, exec_lua[[ return vim.region(0,{0,0},{0,4},'3',true)[0] ]]) end) + it('getpos() input', function() + insert('getpos') + eq({0,6}, exec_lua[[ return vim.region(0,{0,0},'.','v',true)[0] ]]) + end) end) describe('vim.on_key', function() -- 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. --- test/functional/lua/vim_spec.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 85e45788e8..6b69018bc0 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -461,6 +461,22 @@ describe('lua stdlib', function() pcall_err(exec_lua, [[return vim.pesc(2)]])) end) + it('vim.list_contains', function() + eq(true, exec_lua("return vim.list_contains({'a','b','c'}, 'c')")) + eq(false, exec_lua("return vim.list_contains({'a','b','c'}, 'd')")) + end) + + it('vim.tbl_contains', function() + eq(true, exec_lua("return vim.tbl_contains({'a','b','c'}, 'c')")) + eq(false, exec_lua("return vim.tbl_contains({'a','b','c'}, 'd')")) + eq(true, exec_lua("return vim.tbl_contains({[2]='a',foo='b',[5] = 'c'}, 'c')")) + eq(true, exec_lua([[ + return vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v) + return vim.deep_equal(v, { 'b', 'c' }) + end, { predicate = true }) + ]])) + end) + it('vim.tbl_keys', function() eq({}, exec_lua("return vim.tbl_keys({})")) for _, v in pairs(exec_lua("return vim.tbl_keys({'a', 'b', 'c'})")) 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. --- test/functional/lua/vim_spec.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 6b69018bc0..1ee1a13fd5 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -521,6 +521,19 @@ describe('lua stdlib', function() ]])) end) + it('vim.tbl_isarray', function() + eq(true, exec_lua("return vim.tbl_isarray({})")) + eq(false, exec_lua("return vim.tbl_isarray(vim.empty_dict())")) + eq(true, exec_lua("return vim.tbl_isarray({'a', 'b', 'c'})")) + eq(false, exec_lua("return vim.tbl_isarray({'a', '32', a='hello', b='baz'})")) + eq(false, exec_lua("return vim.tbl_isarray({1, a='hello', b='baz'})")) + eq(false, exec_lua("return vim.tbl_isarray({a='hello', b='baz', 1})")) + eq(false, exec_lua("return vim.tbl_isarray({1, 2, nil, a='hello'})")) + eq(true, exec_lua("return vim.tbl_isarray({1, 2, nil, 4})")) + eq(true, exec_lua("return vim.tbl_isarray({nil, 2, 3, 4})")) + eq(false, exec_lua("return vim.tbl_isarray({1, [1.5]=2, [3]=3})")) + end) + it('vim.tbl_islist', function() eq(true, exec_lua("return vim.tbl_islist({})")) eq(false, exec_lua("return vim.tbl_islist(vim.empty_dict())")) @@ -529,6 +542,9 @@ describe('lua stdlib', function() eq(false, exec_lua("return vim.tbl_islist({1, a='hello', b='baz'})")) eq(false, exec_lua("return vim.tbl_islist({a='hello', b='baz', 1})")) eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, a='hello'})")) + eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, 4})")) + eq(false, exec_lua("return vim.tbl_islist({nil, 2, 3, 4})")) + eq(false, exec_lua("return vim.tbl_islist({1, [1.5]=2, [3]=3})")) end) it('vim.tbl_isempty', function() -- 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. --- test/functional/lua/vim_spec.lua | 354 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 354 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 1ee1a13fd5..e5caf6f6f7 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3029,6 +3029,360 @@ describe('lua stdlib', function() eq(false, if_nil(d, c)) eq(NIL, if_nil(a)) end) + + describe('vim.iter', function() + it('filter()', function() + local function odd(v) + return v % 2 ~= 0 + end + + local t = { 1, 2, 3, 4, 5 } + eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable()) + eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable()) + eq({}, vim.iter(t):filter(function(v) if v > 5 then return v end end):totable()) + + do + local it = vim.iter(ipairs(t)) + it:filter(function(i, v) return i > 1 and v < 5 end) + it:map(function(_, v) return v * 2 end) + eq({ 4, 6, 8 }, it:totable()) + end + + local it = vim.iter(string.gmatch('the quick brown fox', '%w+')) + eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable()) + end) + + it('map()', function() + local t = { 1, 2, 3, 4, 5 } + eq( + { 2, 4, 6, 8, 10 }, + vim + .iter(t) + :map(function(v) + return 2 * v + end) + :totable() + ) + + local it = vim.gsplit( + [[ + Line 1 + Line 2 + Line 3 + Line 4 + ]], + '\n' + ) + + eq( + { 'Lion 2', 'Lion 4' }, + vim + .iter(it) + :map(function(s) + local lnum = s:match('(%d+)') + if lnum and tonumber(lnum) % 2 == 0 then + return vim.trim(s:gsub('Line', 'Lion')) + end + end) + :totable() + ) + end) + + it('for loops', function() + local t = {1, 2, 3, 4, 5} + local acc = 0 + for v in vim.iter(t):map(function(v) return v * 3 end) do + acc = acc + v + end + eq(45, acc) + end) + + it('totable()', function() + do + local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end) + eq({{1, 1}, {2, 4}, {3, 9}}, it:totable()) + end + + do + local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber) + eq({1, 4, 17, 2, 9, 3}, it:totable()) + end + end) + + it('next()', function() + local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end) + eq(2, it:next()) + eq(4, it:next()) + eq(6, it:next()) + eq(nil, it:next()) + end) + + it('rev()', function() + eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable()) + + local it = vim.iter(string.gmatch("abc", "%w")) + matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it)) + end) + + it('skip()', function() + do + local t = {4, 3, 2, 1} + eq(t, vim.iter(t):skip(0):totable()) + eq({3, 2, 1}, vim.iter(t):skip(1):totable()) + eq({2, 1}, vim.iter(t):skip(2):totable()) + eq({1}, vim.iter(t):skip(#t - 1):totable()) + eq({}, vim.iter(t):skip(#t):totable()) + eq({}, vim.iter(t):skip(#t + 1):totable()) + end + + do + local function skip(n) + return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable() + end + eq({'a', 'b', 'c', 'd'}, skip(0)) + eq({'b', 'c', 'd'}, skip(1)) + eq({'c', 'd'}, skip(2)) + eq({'d'}, skip(3)) + eq({}, skip(4)) + eq({}, skip(5)) + end + end) + + it('skipback()', function() + do + local t = {4, 3, 2, 1} + eq(t, vim.iter(t):skipback(0):totable()) + eq({4, 3, 2}, vim.iter(t):skipback(1):totable()) + eq({4, 3}, vim.iter(t):skipback(2):totable()) + eq({4}, vim.iter(t):skipback(#t - 1):totable()) + eq({}, vim.iter(t):skipback(#t):totable()) + eq({}, vim.iter(t):skipback(#t + 1):totable()) + end + + local it = vim.iter(vim.gsplit('a|b|c|d', '|')) + matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0)) + end) + + it('slice()', function() + local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} + eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable()) + eq({}, vim.iter(t):slice(6, 5):totable()) + eq({}, vim.iter(t):slice(0, 0):totable()) + eq({1}, vim.iter(t):slice(1, 1):totable()) + eq({1, 2}, vim.iter(t):slice(1, 2):totable()) + eq({10}, vim.iter(t):slice(10, 10):totable()) + eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable()) + end) + + it('nth()', function() + do + local t = {4, 3, 2, 1} + eq(nil, vim.iter(t):nth(0)) + eq(4, vim.iter(t):nth(1)) + eq(3, vim.iter(t):nth(2)) + eq(2, vim.iter(t):nth(3)) + eq(1, vim.iter(t):nth(4)) + eq(nil, vim.iter(t):nth(5)) + end + + do + local function nth(n) + return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n) + end + eq(nil, nth(0)) + eq('a', nth(1)) + eq('b', nth(2)) + eq('c', nth(3)) + eq('d', nth(4)) + eq(nil, nth(5)) + end + end) + + it('nthback()', function() + do + local t = {4, 3, 2, 1} + eq(nil, vim.iter(t):nthback(0)) + eq(1, vim.iter(t):nthback(1)) + eq(2, vim.iter(t):nthback(2)) + eq(3, vim.iter(t):nthback(3)) + eq(4, vim.iter(t):nthback(4)) + eq(nil, vim.iter(t):nthback(5)) + end + + local it = vim.iter(vim.gsplit('a|b|c|d', '|')) + matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1)) + end) + + it('any()', function() + local function odd(v) + return v % 2 ~= 0 + end + + do + local t = { 4, 8, 9, 10 } + eq(true, vim.iter(t):any(odd)) + end + + do + local t = { 4, 8, 10 } + eq(false, vim.iter(t):any(odd)) + end + + do + eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end)) + eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end)) + end + end) + + it('all()', function() + local function odd(v) + return v % 2 ~= 0 + end + + do + local t = { 3, 5, 7, 9 } + eq(true, vim.iter(t):all(odd)) + end + + do + local t = { 3, 5, 7, 10 } + eq(false, vim.iter(t):all(odd)) + end + + do + eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end)) + eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end)) + end + end) + + it('last()', function() + local s = 'abcdefghijklmnopqrstuvwxyz' + eq('z', vim.iter(vim.split(s, '')):last()) + eq('z', vim.iter(vim.gsplit(s, '')):last()) + end) + + it('enumerate()', function() + local it = vim.iter(vim.gsplit('abc', '')):enumerate() + eq({1, 'a'}, {it:next()}) + eq({2, 'b'}, {it:next()}) + eq({3, 'c'}, {it:next()}) + eq({}, {it:next()}) + end) + + it('peek()', function() + do + local it = vim.iter({ 3, 6, 9, 12 }) + eq(3, it:peek()) + eq(3, it:peek()) + eq(3, it:next()) + end + + do + local it = vim.iter(vim.gsplit('hi', '')) + matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it)) + end + end) + + it('find()', function() + local t = {3, 6, 9, 12} + eq(12, vim.iter(t):find(12)) + eq(nil, vim.iter(t):find(15)) + eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end)) + + do + local it = vim.iter(t) + local pred = function(v) return v % 3 == 0 end + eq(3, it:find(pred)) + eq(6, it:find(pred)) + eq(9, it:find(pred)) + eq(12, it:find(pred)) + eq(nil, it:find(pred)) + end + + do + local it = vim.iter(vim.gsplit('AbCdE', '')) + local pred = function(s) return s:match('[A-Z]') end + eq('A', it:find(pred)) + eq('C', it:find(pred)) + eq('E', it:find(pred)) + eq(nil, it:find(pred)) + end + end) + + it('rfind()', function() + local t = {1, 2, 3, 2, 1} + do + local it = vim.iter(t) + eq(1, it:rfind(1)) + eq(1, it:rfind(1)) + eq(nil, it:rfind(1)) + end + + do + local it = vim.iter(t):enumerate() + local pred = function(i) return i % 2 ~= 0 end + eq({5, 1}, {it:rfind(pred)}) + eq({3, 3}, {it:rfind(pred)}) + eq({1, 1}, {it:rfind(pred)}) + eq(nil, it:rfind(pred)) + end + + do + local it = vim.iter(vim.gsplit('AbCdE', '')) + matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E')) + end + end) + + it('nextback()', function() + do + local it = vim.iter({ 1, 2, 3, 4 }) + eq(4, it:nextback()) + eq(3, it:nextback()) + eq(2, it:nextback()) + eq(1, it:nextback()) + eq(nil, it:nextback()) + eq(nil, it:nextback()) + end + + do + local it = vim.iter(vim.gsplit('hi', '')) + matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it)) + end + end) + + it('peekback()', function() + do + local it = vim.iter({ 1, 2, 3, 4 }) + eq(4, it:peekback()) + eq(4, it:peekback()) + eq(4, it:peekback()) + end + + do + local it = vim.iter(vim.gsplit('hi', '')) + matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it)) + end + end) + + it('fold()', function() + local t = {1, 2, 3, 4, 5} + eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end)) + eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v) + table.insert(acc, 1, v) + return acc + end)) + end) + + it('handles map-like tables', function() + local t = { a = 1, b = 2, c = 3 } + local it = vim.iter(t):map(function(k, v) + if v % 2 ~= 0 then + return k:upper(), v * 2 + end + end) + eq({ A = 2, C = 6 }, it:totable()) + end) + end) end) describe('lua: builtin modules', function() -- cgit From 6b96122453fda22dc44a581af1d536988c1adf41 Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Wed, 19 Apr 2023 06:45:56 -0600 Subject: fix(iter): add tag to packed table If pack() is called with a single value, it does not create a table; it simply returns the value it is passed. When unpack is called with a table argument, it interprets that table as a list of values that were packed together into a table. This causes a problem when the single value being packed is _itself_ a table. pack() will not place it into another table, but unpack() sees the table argument and tries to unpack it. To fix this, we add a simple "tag" to packed table values so that unpack() only attempts to unpack tables that have this tag. Other tables are left alone. The tag is simply the length of the table. --- test/functional/lua/vim_spec.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index e5caf6f6f7..07b0f0340a 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3381,6 +3381,33 @@ describe('lua stdlib', function() end end) eq({ A = 2, C = 6 }, it:totable()) + + it('handles table values mid-pipeline', function() + local map = { + item = { + file = 'test', + }, + item_2 = { + file = 'test', + }, + item_3 = { + file = 'test', + }, + } + + local output = vim.iter(map):map(function(key, value) + return { [key] = value.file } + end):totable() + + table.sort(output, function(a, b) + return next(a) < next(b) + end) + + eq({ + { item = 'test' }, + { item_2 = 'test' }, + { item_3 = 'test' }, + }, output) end) end) end) -- cgit From 94894068794dbb99804cda689b6c37e70376c8ca Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Wed, 19 Apr 2023 07:05:04 -0600 Subject: fix(iter): remove special case totable for map-like tables This was originally meant as a convenience but prevents possible functionality. For example: -- Get the keys of the table with even values local t = { a = 1, b = 2, c = 3, d = 4 } vim.iter(t):map(function(k, v) if v % 2 == 0 then return k end end):totable() The example above would not work, because the map() function returns only a single value, and cannot be converted back into a table (there are many such examples like this). Instead, to convert an iterator into a map-like table, users can use fold(): vim.iter(t):fold({}, function(t, k, v) t[k] = v return t end) --- test/functional/lua/vim_spec.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 07b0f0340a..e37d477376 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3374,13 +3374,18 @@ describe('lua stdlib', function() end) it('handles map-like tables', function() - local t = { a = 1, b = 2, c = 3 } - local it = vim.iter(t):map(function(k, v) + local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v) if v % 2 ~= 0 then return k:upper(), v * 2 end end) - eq({ A = 2, C = 6 }, it:totable()) + + local t = it:fold({}, function(t, k, v) + t[k] = v + return t + end) + eq({ A = 2, C = 6 }, t) + end) it('handles table values mid-pipeline', function() local map = { -- 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 --- test/functional/lua/vim_spec.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index e37d477376..b8cc15b2ca 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -294,9 +294,11 @@ describe('lua stdlib', function() it('vim.gsplit, vim.split', function() local tests = { + -- plain trimempty { 'a,b', ',', false, false, { 'a', 'b' } }, { ':aa::::bb:', ':', false, false, { '', 'aa', '', '', '', 'bb', '' } }, { ':aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } }, + { 'aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } }, { ':aa::bb:', ':', false, true, { 'aa', '', 'bb' } }, { '/a/b:/b/\n', '[:\n]', false, true, { '/a/b', '/b/' } }, { '::ee::ff:', ':', false, false, { '', '', 'ee', '', 'ff', '' } }, @@ -315,7 +317,7 @@ describe('lua stdlib', function() } for _, t in ipairs(tests) do - eq(t[5], vim.split(t[1], t[2], {plain=t[3], trimempty=t[4]})) + eq(t[5], vim.split(t[1], t[2], {plain=t[3], trimempty=t[4]}), t[1]) end -- Test old signature -- cgit From f68af3c3bc92c12f7dbbd32f44df8ab57a58ac98 Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Fri, 21 Apr 2023 16:13:39 -0600 Subject: refactor(iter): use metatable as packed table tag (#23254) This is a more robust method for tagging a packed table as it completely eliminates the possibility of mistaking an actual table key as the packed table tag. --- test/functional/lua/vim_spec.lua | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index b8cc15b2ca..42927f7e1b 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3416,6 +3416,41 @@ describe('lua stdlib', function() { item_3 = 'test' }, }, output) end) + + it('handles nil values', function() + local t = {1, 2, 3, 4, 5} + do + local it = vim.iter(t):enumerate():map(function(i, v) + if i % 2 == 0 then + return nil, v*v + end + return v, nil + end) + eq({ + { [1] = 1 }, + { [2] = 4 }, + { [1] = 3 }, + { [2] = 16 }, + { [1] = 5 }, + }, it:totable()) + end + + do + local it = vim.iter(ipairs(t)):map(function(i, v) + if i % 2 == 0 then + return nil, v*v + end + return v, nil + end) + eq({ + { [1] = 1 }, + { [2] = 4 }, + { [1] = 3 }, + { [2] = 16 }, + { [1] = 5 }, + }, it:totable()) + end + end) end) end) -- cgit From 147bb87245cdb348e67c659415d0661d48aa5f1e Mon Sep 17 00:00:00 2001 From: Gregory Anders Date: Fri, 21 Apr 2023 07:04:35 -0600 Subject: test: move vim.iter tests to separate file --- test/functional/lua/vim_spec.lua | 421 --------------------------------------- 1 file changed, 421 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 42927f7e1b..53c21fd668 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3031,427 +3031,6 @@ describe('lua stdlib', function() eq(false, if_nil(d, c)) eq(NIL, if_nil(a)) end) - - describe('vim.iter', function() - it('filter()', function() - local function odd(v) - return v % 2 ~= 0 - end - - local t = { 1, 2, 3, 4, 5 } - eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable()) - eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable()) - eq({}, vim.iter(t):filter(function(v) if v > 5 then return v end end):totable()) - - do - local it = vim.iter(ipairs(t)) - it:filter(function(i, v) return i > 1 and v < 5 end) - it:map(function(_, v) return v * 2 end) - eq({ 4, 6, 8 }, it:totable()) - end - - local it = vim.iter(string.gmatch('the quick brown fox', '%w+')) - eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable()) - end) - - it('map()', function() - local t = { 1, 2, 3, 4, 5 } - eq( - { 2, 4, 6, 8, 10 }, - vim - .iter(t) - :map(function(v) - return 2 * v - end) - :totable() - ) - - local it = vim.gsplit( - [[ - Line 1 - Line 2 - Line 3 - Line 4 - ]], - '\n' - ) - - eq( - { 'Lion 2', 'Lion 4' }, - vim - .iter(it) - :map(function(s) - local lnum = s:match('(%d+)') - if lnum and tonumber(lnum) % 2 == 0 then - return vim.trim(s:gsub('Line', 'Lion')) - end - end) - :totable() - ) - end) - - it('for loops', function() - local t = {1, 2, 3, 4, 5} - local acc = 0 - for v in vim.iter(t):map(function(v) return v * 3 end) do - acc = acc + v - end - eq(45, acc) - end) - - it('totable()', function() - do - local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end) - eq({{1, 1}, {2, 4}, {3, 9}}, it:totable()) - end - - do - local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber) - eq({1, 4, 17, 2, 9, 3}, it:totable()) - end - end) - - it('next()', function() - local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end) - eq(2, it:next()) - eq(4, it:next()) - eq(6, it:next()) - eq(nil, it:next()) - end) - - it('rev()', function() - eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable()) - - local it = vim.iter(string.gmatch("abc", "%w")) - matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it)) - end) - - it('skip()', function() - do - local t = {4, 3, 2, 1} - eq(t, vim.iter(t):skip(0):totable()) - eq({3, 2, 1}, vim.iter(t):skip(1):totable()) - eq({2, 1}, vim.iter(t):skip(2):totable()) - eq({1}, vim.iter(t):skip(#t - 1):totable()) - eq({}, vim.iter(t):skip(#t):totable()) - eq({}, vim.iter(t):skip(#t + 1):totable()) - end - - do - local function skip(n) - return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable() - end - eq({'a', 'b', 'c', 'd'}, skip(0)) - eq({'b', 'c', 'd'}, skip(1)) - eq({'c', 'd'}, skip(2)) - eq({'d'}, skip(3)) - eq({}, skip(4)) - eq({}, skip(5)) - end - end) - - it('skipback()', function() - do - local t = {4, 3, 2, 1} - eq(t, vim.iter(t):skipback(0):totable()) - eq({4, 3, 2}, vim.iter(t):skipback(1):totable()) - eq({4, 3}, vim.iter(t):skipback(2):totable()) - eq({4}, vim.iter(t):skipback(#t - 1):totable()) - eq({}, vim.iter(t):skipback(#t):totable()) - eq({}, vim.iter(t):skipback(#t + 1):totable()) - end - - local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('skipback%(%) requires a list%-like table', pcall_err(it.skipback, it, 0)) - end) - - it('slice()', function() - local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable()) - eq({}, vim.iter(t):slice(6, 5):totable()) - eq({}, vim.iter(t):slice(0, 0):totable()) - eq({1}, vim.iter(t):slice(1, 1):totable()) - eq({1, 2}, vim.iter(t):slice(1, 2):totable()) - eq({10}, vim.iter(t):slice(10, 10):totable()) - eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable()) - end) - - it('nth()', function() - do - local t = {4, 3, 2, 1} - eq(nil, vim.iter(t):nth(0)) - eq(4, vim.iter(t):nth(1)) - eq(3, vim.iter(t):nth(2)) - eq(2, vim.iter(t):nth(3)) - eq(1, vim.iter(t):nth(4)) - eq(nil, vim.iter(t):nth(5)) - end - - do - local function nth(n) - return vim.iter(vim.gsplit('a|b|c|d', '|')):nth(n) - end - eq(nil, nth(0)) - eq('a', nth(1)) - eq('b', nth(2)) - eq('c', nth(3)) - eq('d', nth(4)) - eq(nil, nth(5)) - end - end) - - it('nthback()', function() - do - local t = {4, 3, 2, 1} - eq(nil, vim.iter(t):nthback(0)) - eq(1, vim.iter(t):nthback(1)) - eq(2, vim.iter(t):nthback(2)) - eq(3, vim.iter(t):nthback(3)) - eq(4, vim.iter(t):nthback(4)) - eq(nil, vim.iter(t):nthback(5)) - end - - local it = vim.iter(vim.gsplit('a|b|c|d', '|')) - matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1)) - end) - - it('any()', function() - local function odd(v) - return v % 2 ~= 0 - end - - do - local t = { 4, 8, 9, 10 } - eq(true, vim.iter(t):any(odd)) - end - - do - local t = { 4, 8, 10 } - eq(false, vim.iter(t):any(odd)) - end - - do - eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end)) - eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end)) - end - end) - - it('all()', function() - local function odd(v) - return v % 2 ~= 0 - end - - do - local t = { 3, 5, 7, 9 } - eq(true, vim.iter(t):all(odd)) - end - - do - local t = { 3, 5, 7, 10 } - eq(false, vim.iter(t):all(odd)) - end - - do - eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end)) - eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end)) - end - end) - - it('last()', function() - local s = 'abcdefghijklmnopqrstuvwxyz' - eq('z', vim.iter(vim.split(s, '')):last()) - eq('z', vim.iter(vim.gsplit(s, '')):last()) - end) - - it('enumerate()', function() - local it = vim.iter(vim.gsplit('abc', '')):enumerate() - eq({1, 'a'}, {it:next()}) - eq({2, 'b'}, {it:next()}) - eq({3, 'c'}, {it:next()}) - eq({}, {it:next()}) - end) - - it('peek()', function() - do - local it = vim.iter({ 3, 6, 9, 12 }) - eq(3, it:peek()) - eq(3, it:peek()) - eq(3, it:next()) - end - - do - local it = vim.iter(vim.gsplit('hi', '')) - matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it)) - end - end) - - it('find()', function() - local t = {3, 6, 9, 12} - eq(12, vim.iter(t):find(12)) - eq(nil, vim.iter(t):find(15)) - eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end)) - - do - local it = vim.iter(t) - local pred = function(v) return v % 3 == 0 end - eq(3, it:find(pred)) - eq(6, it:find(pred)) - eq(9, it:find(pred)) - eq(12, it:find(pred)) - eq(nil, it:find(pred)) - end - - do - local it = vim.iter(vim.gsplit('AbCdE', '')) - local pred = function(s) return s:match('[A-Z]') end - eq('A', it:find(pred)) - eq('C', it:find(pred)) - eq('E', it:find(pred)) - eq(nil, it:find(pred)) - end - end) - - it('rfind()', function() - local t = {1, 2, 3, 2, 1} - do - local it = vim.iter(t) - eq(1, it:rfind(1)) - eq(1, it:rfind(1)) - eq(nil, it:rfind(1)) - end - - do - local it = vim.iter(t):enumerate() - local pred = function(i) return i % 2 ~= 0 end - eq({5, 1}, {it:rfind(pred)}) - eq({3, 3}, {it:rfind(pred)}) - eq({1, 1}, {it:rfind(pred)}) - eq(nil, it:rfind(pred)) - end - - do - local it = vim.iter(vim.gsplit('AbCdE', '')) - matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E')) - end - end) - - it('nextback()', function() - do - local it = vim.iter({ 1, 2, 3, 4 }) - eq(4, it:nextback()) - eq(3, it:nextback()) - eq(2, it:nextback()) - eq(1, it:nextback()) - eq(nil, it:nextback()) - eq(nil, it:nextback()) - end - - do - local it = vim.iter(vim.gsplit('hi', '')) - matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it)) - end - end) - - it('peekback()', function() - do - local it = vim.iter({ 1, 2, 3, 4 }) - eq(4, it:peekback()) - eq(4, it:peekback()) - eq(4, it:peekback()) - end - - do - local it = vim.iter(vim.gsplit('hi', '')) - matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it)) - end - end) - - it('fold()', function() - local t = {1, 2, 3, 4, 5} - eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end)) - eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v) - table.insert(acc, 1, v) - return acc - end)) - end) - - it('handles map-like tables', function() - local it = vim.iter({ a = 1, b = 2, c = 3 }):map(function(k, v) - if v % 2 ~= 0 then - return k:upper(), v * 2 - end - end) - - local t = it:fold({}, function(t, k, v) - t[k] = v - return t - end) - eq({ A = 2, C = 6 }, t) - end) - - it('handles table values mid-pipeline', function() - local map = { - item = { - file = 'test', - }, - item_2 = { - file = 'test', - }, - item_3 = { - file = 'test', - }, - } - - local output = vim.iter(map):map(function(key, value) - return { [key] = value.file } - end):totable() - - table.sort(output, function(a, b) - return next(a) < next(b) - end) - - eq({ - { item = 'test' }, - { item_2 = 'test' }, - { item_3 = 'test' }, - }, output) - end) - - it('handles nil values', function() - local t = {1, 2, 3, 4, 5} - do - local it = vim.iter(t):enumerate():map(function(i, v) - if i % 2 == 0 then - return nil, v*v - end - return v, nil - end) - eq({ - { [1] = 1 }, - { [2] = 4 }, - { [1] = 3 }, - { [2] = 16 }, - { [1] = 5 }, - }, it:totable()) - end - - do - local it = vim.iter(ipairs(t)):map(function(i, v) - if i % 2 == 0 then - return nil, v*v - end - return v, nil - end) - eq({ - { [1] = 1 }, - { [2] = 4 }, - { [1] = 3 }, - { [2] = 16 }, - { [1] = 5 }, - }, it:totable()) - end - end) - end) end) describe('lua: builtin modules', function() -- cgit From 45bcf8386918bbb475fbe20c48b508aa89ed0624 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 20 Apr 2023 13:19:38 +0200 Subject: refactor(build): include lpeg as a library --- test/functional/lua/vim_spec.lua | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 53c21fd668..86eb600bd9 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -3031,6 +3031,15 @@ describe('lua stdlib', function() eq(false, if_nil(d, c)) eq(NIL, if_nil(a)) end) + + it('lpeg', function() + eq(5, exec_lua [[ + local m = vim.lpeg + return m.match(m.R'09'^1, '4504ab') + ]]) + + eq(4, exec_lua [[ return vim.re.match("abcde", '[a-c]+') ]]) + end) end) describe('lua: builtin modules', function() -- cgit From 1fe1bb084d0099fc4f9bfdc11189485d0f74b75a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 19 Dec 2022 16:37:45 +0000 Subject: refactor(options): deprecate nvim[_buf|_win]_[gs]et_option Co-authored-by: zeertzjq Co-authored-by: famiu --- test/functional/lua/vim_spec.lua | 60 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'test/functional/lua/vim_spec.lua') diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 86eb600bd9..9a7654d610 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -1496,9 +1496,9 @@ describe('lua stdlib', function() it('vim.bo', function() eq('', funcs.luaeval "vim.bo.filetype") exec_lua [[ - vim.api.nvim_buf_set_option(0, "filetype", "markdown") + vim.api.nvim_set_option_value("filetype", "markdown", {buf = 0}) BUF = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_option(BUF, "modifiable", false) + vim.api.nvim_set_option_value("modifiable", false, {buf = BUF}) ]] eq(false, funcs.luaeval "vim.bo.modified") eq('markdown', funcs.luaeval "vim.bo.filetype") @@ -1519,9 +1519,9 @@ describe('lua stdlib', function() it('vim.wo', function() exec_lua [[ - vim.api.nvim_win_set_option(0, "cole", 2) + vim.api.nvim_set_option_value("cole", 2, {win=0}) vim.cmd "split" - vim.api.nvim_win_set_option(0, "cole", 2) + vim.api.nvim_set_option_value("cole", 2, {win=0}) ]] eq(2, funcs.luaeval "vim.wo.cole") exec_lua [[ @@ -1566,8 +1566,8 @@ describe('lua stdlib', function() local result = exec_lua [[ local result = {} - table.insert(result, vim.api.nvim_get_option('scrolloff')) - table.insert(result, vim.api.nvim_win_get_option(0, 'scrolloff')) + table.insert(result, vim.api.nvim_get_option_value('scrolloff', {scope='global'})) + table.insert(result, vim.api.nvim_get_option_value('scrolloff', {win=0})) return result ]] @@ -1631,20 +1631,20 @@ describe('lua stdlib', function() local result = {} vim.opt.makeprg = "global-local" - table.insert(result, vim.api.nvim_get_option('makeprg')) - table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + table.insert(result, vim.go.makeprg) + table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0})) vim.opt_local.mp = "only-local" - table.insert(result, vim.api.nvim_get_option('makeprg')) - table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + table.insert(result, vim.go.makeprg) + table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0})) vim.opt_global.makeprg = "only-global" - table.insert(result, vim.api.nvim_get_option('makeprg')) - table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + table.insert(result, vim.go.makeprg) + table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0})) vim.opt.makeprg = "global-local" - table.insert(result, vim.api.nvim_get_option('makeprg')) - table.insert(result, vim.api.nvim_buf_get_option(0, 'makeprg')) + table.insert(result, vim.go.makeprg) + table.insert(result, vim.api.nvim_get_option_value('makeprg', {buf=0})) return result ]] @@ -2173,7 +2173,7 @@ describe('lua stdlib', function() it('can handle isfname ,,,', function() local result = exec_lua [[ vim.opt.isfname = "a,b,,,c" - return { vim.opt.isfname:get(), vim.api.nvim_get_option('isfname') } + return { vim.opt.isfname:get(), vim.go.isfname } ]] eq({{",", "a", "b", "c"}, "a,b,,,c"}, result) @@ -2183,7 +2183,7 @@ describe('lua stdlib', function() it('can handle isfname ,^,,', function() local result = exec_lua [[ vim.opt.isfname = "a,b,^,,c" - return { vim.opt.isfname:get(), vim.api.nvim_get_option('isfname') } + return { vim.opt.isfname:get(), vim.go.isfname } ]] eq({{"^,", "a", "b", "c"}, "a,b,^,,c"}, result) @@ -2734,14 +2734,14 @@ describe('lua stdlib', function() describe('vim.api.nvim_buf_call', function() it('can access buf options', function() - local buf1 = meths.get_current_buf() + local buf1 = meths.get_current_buf().id local buf2 = exec_lua [[ buf2 = vim.api.nvim_create_buf(false, true) return buf2 ]] - eq(false, meths.buf_get_option(buf1, 'autoindent')) - eq(false, meths.buf_get_option(buf2, 'autoindent')) + eq(false, meths.get_option_value('autoindent', {buf=buf1})) + eq(false, meths.get_option_value('autoindent', {buf=buf2})) local val = exec_lua [[ return vim.api.nvim_buf_call(buf2, function() @@ -2750,9 +2750,9 @@ describe('lua stdlib', function() end) ]] - eq(false, meths.buf_get_option(buf1, 'autoindent')) - eq(true, meths.buf_get_option(buf2, 'autoindent')) - eq(buf1, meths.get_current_buf()) + eq(false, meths.get_option_value('autoindent', {buf=buf1})) + eq(true, meths.get_option_value('autoindent', {buf=buf2})) + eq(buf1, meths.get_current_buf().id) eq(buf2, val) end) @@ -2771,10 +2771,10 @@ describe('lua stdlib', function() eq(true, exec_lua([[ local function scratch_buf_call(fn) local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_option(buf, 'cindent', true) + vim.api.nvim_set_option_value('cindent', true, {buf = buf}) return vim.api.nvim_buf_call(buf, function() return vim.api.nvim_get_current_buf() == buf - and vim.api.nvim_buf_get_option(buf, 'cindent') + and vim.api.nvim_get_option_value('cindent', {buf = buf}) and fn() end) and vim.a