diff options
Diffstat (limited to 'test/functional/lua')
-rw-r--r-- | test/functional/lua/buffer_updates_spec.lua | 19 | ||||
-rw-r--r-- | test/functional/lua/diagnostic_spec.lua | 114 | ||||
-rw-r--r-- | test/functional/lua/glob_spec.lua | 13 | ||||
-rw-r--r-- | test/functional/lua/highlight_spec.lua | 30 | ||||
-rw-r--r-- | test/functional/lua/runtime_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 21 | ||||
-rw-r--r-- | test/functional/lua/with_spec.lua | 292 |
7 files changed, 471 insertions, 20 deletions
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index d4af7e4732..6b575ad0ef 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -379,6 +379,25 @@ describe('lua buffer event callbacks: on_lines', function() ]], }) end) + + it('line lengths are correct when pressing TAB with folding #29119', function() + api.nvim_buf_set_lines(0, 0, -1, true, { 'a', 'b' }) + + exec_lua([[ + _G.res = {} + vim.o.foldmethod = 'indent' + vim.o.softtabstop = -1 + vim.api.nvim_buf_attach(0, false, { + on_lines = function(_, bufnr, _, row, _, end_row) + local lines = vim.api.nvim_buf_get_lines(bufnr, row, end_row, true) + table.insert(_G.res, lines) + end + }) + ]]) + + feed('i<Tab>') + eq({ '\ta' }, exec_lua('return _G.res[#_G.res]')) + end) end) describe('lua: nvim_buf_attach on_bytes', function() diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index a4f882e363..decb58dc4d 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -2291,6 +2291,38 @@ describe('vim.diagnostic', function() return lines ]] ) + + -- End position is exclusive + eq( + vim.NIL, + exec_lua [[ + local diagnostics = { + make_error("Syntax error", 1, 1, 2, 0), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local _, winnr = vim.diagnostic.open_float(0, {header=false, pos={2,0}}) + return winnr + ]] + ) + + -- Works when width == 0 + eq( + { '1. Syntax error' }, + exec_lua [[ + local diagnostics = { + make_error("Syntax error", 2, 0, 2, 0), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, pos={2,1}}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]] + ) end) it('can show diagnostics from a specific position', function() @@ -2299,7 +2331,7 @@ describe('vim.diagnostic', function() { 'Syntax error' }, exec_lua [[ local diagnostics = { - make_error("Syntax error", 1, 1, 1, 2), + make_error("Syntax error", 1, 1, 1, 3), make_warning("Some warning", 1, 3, 1, 4), } vim.api.nvim_win_set_buf(0, diagnostic_bufnr) @@ -2317,7 +2349,7 @@ describe('vim.diagnostic', function() { 'Some warning' }, exec_lua [[ local diagnostics = { - make_error("Syntax error", 1, 1, 1, 2), + make_error("Syntax error", 1, 1, 1, 3), make_warning("Some warning", 1, 3, 1, 4), } vim.api.nvim_win_set_buf(0, diagnostic_bufnr) @@ -2347,6 +2379,38 @@ describe('vim.diagnostic', function() return lines ]] ) + + -- End position is exclusive + eq( + vim.NIL, + exec_lua [[ + local diagnostics = { + make_error("Syntax error", 1, 1, 1, 3), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local _, winnr = vim.diagnostic.open_float(0, {header=false, scope="cursor", pos={1,3}}) + return winnr + ]] + ) + + -- Works when width == 0 + eq( + { 'Syntax error' }, + exec_lua [[ + local diagnostics = { + make_error("Syntax error", 2, 0, 2, 0), + } + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + vim.api.nvim_win_set_cursor(0, {1, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float({header=false, scope="cursor", pos={2,1}}) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]] + ) end) it( @@ -2755,20 +2819,32 @@ describe('vim.diagnostic', function() end) it('works for multi-line diagnostics #21949', function() - -- open float failed non diagnostic lnum - eq( - vim.NIL, - exec_lua [[ + -- create diagnostic + exec_lua [[ local diagnostics = { make_error("Error in two lines lnum is 1 and end_lnum is 2", 1, 1, 2, 3), } - local winids = {} vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics) + ]] + + -- open float failed non diagnostic lnum + eq( + vim.NIL, + exec_lua [[ + vim.api.nvim_win_set_cursor(0, {1, 0}) local _, winnr = vim.diagnostic.open_float(0, { header = false }) return winnr ]] ) + eq( + vim.NIL, + exec_lua [[ + vim.api.nvim_win_set_cursor(0, {1, 0}) + local _, winnr = vim.diagnostic.open_float(0, { header = false, scope = "cursor" }) + return winnr + ]] + ) -- can open a float window on lnum 1 eq( @@ -2782,6 +2858,18 @@ describe('vim.diagnostic', function() ]] ) + -- can open a cursor-scoped float window on lnum 1 + eq( + { 'Error in two lines lnum is 1 and end_lnum is 2' }, + exec_lua [[ + vim.api.nvim_win_set_cursor(0, {2, 1}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false, scope = "cursor" }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]] + ) + -- can open a float window on end_lnum 2 eq( { '1. Error in two lines lnum is 1 and end_lnum is 2' }, @@ -2793,6 +2881,18 @@ describe('vim.diagnostic', function() return lines ]] ) + + -- can open a cursor-scoped float window on end_lnum 2 + eq( + { 'Error in two lines lnum is 1 and end_lnum is 2' }, + exec_lua [[ + vim.api.nvim_win_set_cursor(0, {3, 2}) + local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false, scope = "cursor" }) + local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false) + vim.api.nvim_win_close(winnr, true) + return lines + ]] + ) end) end) diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua index 56cd4c9bb5..b3e1b79ee7 100644 --- a/test/functional/lua/glob_spec.lua +++ b/test/functional/lua/glob_spec.lua @@ -161,7 +161,7 @@ describe('glob', function() eq(false, match('{ab,cd}', 'a')) eq(true, match('{ab,cd}', 'cd')) eq(true, match('{a,b,c}', 'c')) - eq(true, match('{a,{b,c}}', 'c')) + eq(false, match('{a,{b,c}}', 'c')) -- {} cannot nest end) it('should match [] groups', function() @@ -223,6 +223,17 @@ describe('glob', function() eq(true, match('{[0-9],[a-z]}', '0')) eq(true, match('{[0-9],[a-z]}', 'a')) eq(false, match('{[0-9],[a-z]}', 'A')) + + -- glob is from willRename filter in typescript-language-server + -- https://github.com/typescript-language-server/typescript-language-server/blob/b224b878652438bcdd639137a6b1d1a6630129e4/src/lsp-server.ts#L266 + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.js')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.ts')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.mts')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.mjs')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.cjs')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.cts')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.jsx')) + eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.tsx')) end) end) end) diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua index 8f099ac233..ad709a06f1 100644 --- a/test/functional/lua/highlight_spec.lua +++ b/test/functional/lua/highlight_spec.lua @@ -4,7 +4,6 @@ local Screen = require('test.functional.ui.screen') local exec_lua = n.exec_lua local eq = t.eq -local neq = t.neq local eval = n.eval local command = n.command local clear = n.clear @@ -90,6 +89,22 @@ describe('vim.highlight.range', function() | ]]) end) + + it('can use -1 or v:maxcol to indicate end of line', function() + exec_lua([[ + local ns = vim.api.nvim_create_namespace('') + vim.highlight.range(0, ns, 'Search', { 0, 4 }, { 1, -1 }, {}) + vim.highlight.range(0, ns, 'Search', { 2, 6 }, { 3, vim.v.maxcol }, {}) + ]]) + screen:expect([[ + ^asdf{10:ghjkl}{100:$} | + {10:«口=口»}{100:$} | + qwerty{10:uiop}{100:$} | + {10:口口=口口}{1:$} | + zxcvbnm{1:$} | + | + ]]) + end) end) describe('vim.highlight.on_yank', function() @@ -126,9 +141,11 @@ describe('vim.highlight.on_yank', function() vim.api.nvim_buf_set_mark(0,"]",1,1,{}) vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}}) ]]) - neq({}, api.nvim__win_get_ns(0)) + local ns = api.nvim_create_namespace('hlyank') + local win = api.nvim_get_current_win() + eq({ win }, api.nvim__ns_get(ns).wins) command('wincmd w') - eq({}, api.nvim__win_get_ns(0)) + eq({ win }, api.nvim__ns_get(ns).wins) end) it('removes old highlight if new one is created before old one times out', function() @@ -138,14 +155,17 @@ describe('vim.highlight.on_yank', function() vim.api.nvim_buf_set_mark(0,"]",1,1,{}) vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}}) ]]) - neq({}, api.nvim__win_get_ns(0)) + local ns = api.nvim_create_namespace('hlyank') + eq(api.nvim_get_current_win(), api.nvim__ns_get(ns).wins[1]) command('wincmd w') exec_lua([[ vim.api.nvim_buf_set_mark(0,"[",1,1,{}) vim.api.nvim_buf_set_mark(0,"]",1,1,{}) vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}}) ]]) + local win = api.nvim_get_current_win() + eq({ win }, api.nvim__ns_get(ns).wins) command('wincmd w') - eq({}, api.nvim__win_get_ns(0)) + eq({ win }, api.nvim__ns_get(ns).wins) end) end) diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua index c6b0577ebe..f63363d6d9 100644 --- a/test/functional/lua/runtime_spec.lua +++ b/test/functional/lua/runtime_spec.lua @@ -406,7 +406,7 @@ describe('runtime:', function() eq('', eval('&commentstring')) eq('', eval('&omnifunc')) exec('edit file.cpp') - eq('/*%s*/', eval('&commentstring')) + eq('// %s', eval('&commentstring')) eq('ccomplete#Complete', eval('&omnifunc')) end) end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index d50b646085..23bb9f0a2e 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -135,14 +135,15 @@ describe('lua stdlib', function() -- See MAINTAIN.md for the soft/hard deprecation policy describe(('vim.deprecate prerel=%s,'):format(prerel or 'nil'), function() - local curver = exec_lua('return vim.version()') --[[@as {major:number, minor:number}]] - -- "0.10" or "0.10-dev+xxx" - local curstr = ('%s.%s%s'):format(curver.major, curver.minor, prerel or '') - -- "0.10" or "0.11" - local nextver = ('%s.%s'):format(curver.major, curver.minor + (prerel and 0 or 1)) - local was_removed = prerel and 'was removed' or 'will be removed' + local curver --- @type {major:number, minor:number} + + before_each(function() + curver = exec_lua('return vim.version()') + end) it('plugin=nil, same message skipped', function() + -- "0.10" or "0.10-dev+xxx" + local curstr = ('%s.%s%s'):format(curver.major, curver.minor, prerel or '') eq( dedent( [[ @@ -162,6 +163,10 @@ describe('lua stdlib', function() end) it('plugin=nil, show error if hard-deprecated', function() + -- "0.10" or "0.11" + local nextver = ('%s.%s'):format(curver.major, curver.minor + (prerel and 0 or 1)) + + local was_removed = prerel and 'was removed' or 'will be removed' eq( dedent( [[ @@ -2023,6 +2028,10 @@ describe('lua stdlib', function() vim.cmd "enew" ]] eq(100, fn.luaeval 'vim.wo.scrolloff') + + matches('only bufnr=0 is supported', pcall_err(exec_lua, 'vim.wo[0][10].signcolumn = "no"')) + + matches('only bufnr=0 is supported', pcall_err(exec_lua, 'local a = vim.wo[0][10].signcolumn')) end) describe('vim.opt', function() diff --git a/test/functional/lua/with_spec.lua b/test/functional/lua/with_spec.lua new file mode 100644 index 0000000000..36dee9630a --- /dev/null +++ b/test/functional/lua/with_spec.lua @@ -0,0 +1,292 @@ +local t = require('test.testutil') +local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') + +local fn = n.fn +local api = n.api +local command = n.command +local eq = t.eq +local exec_lua = n.exec_lua +local matches = t.matches +local pcall_err = t.pcall_err + +before_each(function() + n.clear() +end) + +describe('vim._with {buf = }', function() + it('does not trigger autocmd', function() + exec_lua [[ + local new = vim.api.nvim_create_buf(false, true) + vim.api.nvim_create_autocmd( { 'BufEnter', 'BufLeave', 'BufWinEnter', 'BufWinLeave' }, { + callback = function() _G.n = (_G.n or 0) + 1 end + }) + vim._with({buf = new}, function() + end) + assert(_G.n == nil) + ]] + end) + + it('trigger autocmd if changed within context', function() + exec_lua [[ + local new = vim.api.nvim_create_buf(false, true) + vim.api.nvim_create_autocmd( { 'BufEnter', 'BufLeave', 'BufWinEnter', 'BufWinLeave' }, { + callback = function() _G.n = (_G.n or 0) + 1 end + }) + vim._with({}, function() + vim.api.nvim_set_current_buf(new) + assert(_G.n ~= nil) + end) + ]] + end) + + it('can access buf options', function() + local buf1 = api.nvim_get_current_buf() + local buf2 = exec_lua [[ + buf2 = vim.api.nvim_create_buf(false, true) + return buf2 + ]] + + eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 })) + eq(false, api.nvim_get_option_value('autoindent', { buf = buf2 })) + + local val = exec_lua [[ + return vim._with({buf = buf2}, function() + vim.cmd "set autoindent" + return vim.api.nvim_get_current_buf() + end) + ]] + + eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 })) + eq(true, api.nvim_get_option_value('autoindent', { buf = buf2 })) + eq(buf1, api.nvim_get_current_buf()) + eq(buf2, val) + end) + + it('does not cause ml_get errors with invalid visual selection', function() + exec_lua [[ + 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<C-V>", "txn", false) + vim._with({buf = api.nvim_create_buf(false, true)}, function() vim.cmd "redraw" end) + ]] + end) + + it('can be nested crazily with hidden buffers', function() + eq( + true, + exec_lua([[ + local function scratch_buf_call(fn) + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_option_value('cindent', true, {buf = buf}) + return vim._with({buf = buf}, function() + return vim.api.nvim_get_current_buf() == buf + and vim.api.nvim_get_option_value('cindent', {buf = buf}) + and fn() + end) and vim.api.nvim_buf_delete(buf, {}) == nil + end + + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return true + end) + end) + end) + end) + end) + end) + end) + end) + end) + end) + end) + end) + ]]) + ) + end) + + it('can return values by reference', function() + eq( + { 4, 7 }, + exec_lua [[ + local val = {4, 10} + local ref = vim._with({ buf = 0}, function() return val end) + ref[2] = 7 + return val + ]] + ) + end) +end) + +describe('vim._with {win = }', function() + it('does not trigger autocmd', function() + exec_lua [[ + local old = vim.api.nvim_get_current_win() + vim.cmd("new") + local new = vim.api.nvim_get_current_win() + vim.api.nvim_create_autocmd( { 'WinEnter', 'WinLeave' }, { + callback = function() _G.n = (_G.n or 0) + 1 end + }) + vim._with({win = old}, function() + end) + assert(_G.n == nil) + ]] + end) + + it('trigger autocmd if changed within context', function() + exec_lua [[ + local old = vim.api.nvim_get_current_win() + vim.cmd("new") + local new = vim.api.nvim_get_current_win() + vim.api.nvim_create_autocmd( { 'WinEnter', 'WinLeave' }, { + callback = function() _G.n = (_G.n or 0) + 1 end + }) + vim._with({}, function() + vim.api.nvim_set_current_win(old) + assert(_G.n ~= nil) + end) + ]] + end) + + it('can access window options', function() + command('vsplit') + local win1 = api.nvim_get_current_win() + command('wincmd w') + local win2 = exec_lua [[ + win2 = vim.api.nvim_get_current_win() + return win2 + ]] + command('wincmd p') + + eq('', api.nvim_get_option_value('winhighlight', { win = win1 })) + eq('', api.nvim_get_option_value('winhighlight', { win = win2 })) + + local val = exec_lua [[ + return vim._with({win = win2}, function() + vim.cmd "setlocal winhighlight=Normal:Normal" + return vim.api.nvim_get_current_win() + end) + ]] + + eq('', api.nvim_get_option_value('winhighlight', { win = win1 })) + eq('Normal:Normal', api.nvim_get_option_value('winhighlight', { win = win2 })) + eq(win1, api.nvim_get_current_win()) + eq(win2, val) + end) + + 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.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 = 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. + exec_lua [[ + api.nvim_feedkeys(t "G<C-V>", "txn", false) + vim._with({win = win_empty}, function() vim.cmd "redraw" end) + ]] + + -- Start Visual in current window, extend it in other window with more lines. + exec_lua [[ + api.nvim_feedkeys(t "<Esc>gg", "txn", false) + api.nvim_set_current_win(win_empty) + api.nvim_feedkeys(t "gg<C-V>", "txn", false) + vim._with({win = win_lines}, function() api.nvim_feedkeys(t "G<C-V>", "txn", false) end) + vim.cmd "redraw" + ]] + end) + + it('updates ruler if cursor moved', function() + local screen = Screen.new(30, 5) + screen:set_default_attr_ids { + [1] = { reverse = true }, + [2] = { bold = true, reverse = true }, + } + screen:attach() + exec_lua [[ + _G.api = vim.api + vim.opt.ruler = true + local lines = {} + for i = 0, 499 do lines[#lines + 1] = tostring(i) end + api.nvim_buf_set_lines(0, 0, -1, true, lines) + api.nvim_win_set_cursor(0, {20, 0}) + vim.cmd "split" + _G.win = api.nvim_get_current_win() + vim.cmd "wincmd w | redraw" + ]] + screen:expect [[ + 19 | + {1:[No Name] [+] 20,1 3%}| + ^19 | + {2:[No Name] [+] 20,1 3%}| + | + ]] + exec_lua [[ + vim._with({win = win}, function() api.nvim_win_set_cursor(0, {100, 0}) end) + vim.cmd "redraw" + ]] + screen:expect [[ + 99 | + {1:[No Name] [+] 100,1 19%}| + ^19 | + {2:[No Name] [+] 20,1 3%}| + | + ]] + end) + + it('can return values by reference', function() + eq( + { 7, 10 }, + exec_lua [[ + local val = {4, 10} + local ref = vim._with({win = 0}, function() return val end) + ref[1] = 7 + return val + ]] + ) + end) + + it('layout in current tabpage does not affect windows in others', function() + command('tab split') + local t2_move_win = api.nvim_get_current_win() + command('vsplit') + local t2_other_win = api.nvim_get_current_win() + command('tabprevious') + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + command('vsplit') + + exec_lua('vim._with({win = ...}, function() vim.cmd.wincmd "J" end)', t2_move_win) + eq({ 'col', { { 'leaf', t2_other_win }, { 'leaf', t2_move_win } } }, fn.winlayout(2)) + end) +end) + +describe('vim._with {lockmarks = true}', function() + it('is reset', function() + local mark = exec_lua [[ + vim.api.nvim_buf_set_lines(0, 0, 0, false, {"marky", "snarky", "malarkey"}) + vim.api.nvim_buf_set_mark(0,"m",1,0, {}) + vim._with({lockmarks = true}, function() + vim.api.nvim_buf_set_lines(0, 0, 2, false, {"mass", "mess", "moss"}) + end) + return vim.api.nvim_buf_get_mark(0,"m") + ]] + t.eq(mark, { 1, 0 }) + end) +end) |