aboutsummaryrefslogtreecommitdiff
path: root/test/functional/lua
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/lua')
-rw-r--r--test/functional/lua/api_spec.lua21
-rw-r--r--test/functional/lua/base64_spec.lua15
-rw-r--r--test/functional/lua/buffer_updates_spec.lua127
-rw-r--r--test/functional/lua/command_line_completion_spec.lua9
-rw-r--r--test/functional/lua/commands_spec.lua35
-rw-r--r--test/functional/lua/comment_spec.lua651
-rw-r--r--test/functional/lua/diagnostic_spec.lua406
-rw-r--r--test/functional/lua/ffi_spec.lua23
-rw-r--r--test/functional/lua/filetype_spec.lua40
-rw-r--r--test/functional/lua/fs_spec.lua253
-rw-r--r--test/functional/lua/glob_spec.lua12
-rw-r--r--test/functional/lua/highlight_spec.lua28
-rw-r--r--test/functional/lua/inspector_spec.lua12
-rw-r--r--test/functional/lua/iter_spec.lua240
-rw-r--r--test/functional/lua/json_spec.lua24
-rw-r--r--test/functional/lua/loader_spec.lua29
-rw-r--r--test/functional/lua/loop_spec.lua36
-rw-r--r--test/functional/lua/luaeval_spec.lua29
-rw-r--r--test/functional/lua/mpack_spec.lua11
-rw-r--r--test/functional/lua/overrides_spec.lua27
-rw-r--r--test/functional/lua/runtime_spec.lua23
-rw-r--r--test/functional/lua/secure_spec.lua87
-rw-r--r--test/functional/lua/snippet_spec.lua78
-rw-r--r--test/functional/lua/spell_spec.lua12
-rw-r--r--test/functional/lua/system_spec.lua10
-rw-r--r--test/functional/lua/text_spec.lua8
-rw-r--r--test/functional/lua/thread_spec.lua22
-rw-r--r--test/functional/lua/ui_event_spec.lua74
-rw-r--r--test/functional/lua/ui_spec.lua33
-rw-r--r--test/functional/lua/uri_spec.lua18
-rw-r--r--test/functional/lua/version_spec.lua19
-rw-r--r--test/functional/lua/vim_spec.lua306
-rw-r--r--test/functional/lua/watch_spec.lua28
-rw-r--r--test/functional/lua/xdiff_spec.lua12
34 files changed, 2077 insertions, 681 deletions
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua
index acd56a0ddb..56969150bd 100644
--- a/test/functional/lua/api_spec.lua
+++ b/test/functional/lua/api_spec.lua
@@ -1,15 +1,16 @@
-- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
-
-local exc_exec = helpers.exc_exec
-local remove_trace = helpers.remove_trace
-local fn = helpers.fn
-local clear = helpers.clear
-local eval = helpers.eval
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local exc_exec = n.exc_exec
+local remove_trace = t.remove_trace
+local fn = n.fn
+local clear = n.clear
+local eval = n.eval
local NIL = vim.NIL
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local pcall_err = helpers.pcall_err
+local eq = t.eq
+local exec_lua = n.exec_lua
+local pcall_err = t.pcall_err
before_each(clear)
diff --git a/test/functional/lua/base64_spec.lua b/test/functional/lua/base64_spec.lua
index 21fd536a98..529f5f56e8 100644
--- a/test/functional/lua/base64_spec.lua
+++ b/test/functional/lua/base64_spec.lua
@@ -1,9 +1,11 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local pcall_err = helpers.pcall_err
-local matches = helpers.matches
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local pcall_err = t.pcall_err
+local matches = t.matches
describe('vim.base64', function()
before_each(clear)
@@ -42,6 +44,7 @@ describe('vim.base64', function()
̦H̬̤̗̤͝e͜ ̜̥̝̻͍̟́w̕h̖̯͓o̝͙̖͎̱̮ ҉̺̙̞̟͈W̷̼̭a̺̪͍į͈͕̭͙̯̜t̶̼̮s̘͙͖̕ ̠̫̠B̻͍͙͉̳ͅe̵h̵̬͇̫͙i̹͓̳̳̮͎̫̕n͟d̴̪̜̖ ̰͉̩͇͙̲͞ͅT͖̼͓̪͢h͏͓̮̻e̬̝̟ͅ ̤̹̝W͙̞̝͔͇͝ͅa͏͓͔̹̼̣l̴͔̰̤̟͔ḽ̫.͕
Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮
]],
+ 'Hello\0world',
}
for _, v in ipairs(values) do
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 714e1b951f..d4af7e4732 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -1,17 +1,19 @@
-- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
-
-local command = helpers.command
-local api = helpers.api
-local fn = helpers.fn
-local clear = helpers.clear
-local eq = helpers.eq
-local fail = helpers.fail
-local exec_lua = helpers.exec_lua
-local feed = helpers.feed
-local expect_events = helpers.expect_events
-local write_file = helpers.write_file
-local dedent = helpers.dedent
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+local Screen = require('test.functional.ui.screen')
+
+local command = n.command
+local api = n.api
+local fn = n.fn
+local clear = n.clear
+local eq = t.eq
+local fail = t.fail
+local exec_lua = n.exec_lua
+local feed = n.feed
+local expect_events = t.expect_events
+local write_file = t.write_file
+local dedent = t.dedent
local origlines = {
'original line 1',
@@ -291,11 +293,11 @@ describe('lua buffer event callbacks: on_lines', function()
exec_lua(code)
command('q!')
- helpers.assert_alive()
+ n.assert_alive()
exec_lua(code)
command('bd!')
- helpers.assert_alive()
+ n.assert_alive()
end)
it('#12718 lnume', function()
@@ -312,31 +314,71 @@ describe('lua buffer event callbacks: on_lines', function()
feed('G0')
feed('p')
-- Is the last arg old_byte_size correct? Doesn't matter for this PR
- eq(api.nvim_get_var('linesev'), { 'lines', 1, 4, 2, 3, 5, 4 })
+ eq({ 'lines', 1, 4, 2, 3, 5, 4 }, api.nvim_get_var('linesev'))
feed('2G0')
feed('p')
- eq(api.nvim_get_var('linesev'), { 'lines', 1, 5, 1, 4, 4, 8 })
+ eq({ 'lines', 1, 5, 1, 4, 4, 8 }, api.nvim_get_var('linesev'))
feed('1G0')
feed('P')
- eq(api.nvim_get_var('linesev'), { 'lines', 1, 6, 0, 3, 3, 9 })
+ eq({ 'lines', 1, 6, 0, 3, 3, 9 }, api.nvim_get_var('linesev'))
end)
- it(
- 'calling nvim_buf_call() from callback does not cause Normal mode CTRL-A to misbehave #16729',
- function()
- exec_lua([[
+ it('nvim_buf_call() from callback does not cause wrong Normal mode CTRL-A #16729', function()
+ exec_lua([[
vim.api.nvim_buf_attach(0, false, {
on_lines = function(...)
vim.api.nvim_buf_call(0, function() end)
end,
})
]])
- feed('itest123<Esc><C-A>')
- eq('test124', api.nvim_get_current_line())
- end
- )
+ feed('itest123<Esc><C-A>')
+ eq('test124', api.nvim_get_current_line())
+ end)
+
+ it('setting extmark in on_lines callback works', function()
+ local screen = Screen.new(40, 6)
+ screen:attach()
+
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'aaa', 'bbb', 'ccc' })
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace('')
+ vim.api.nvim_buf_attach(0, false, {
+ on_lines = function(_, _, _, row, _, end_row)
+ vim.api.nvim_buf_clear_namespace(0, ns, row, end_row)
+ for i = row, end_row - 1 do
+ local id = vim.api.nvim_buf_set_extmark(0, ns, i, 0, {
+ virt_text = {{ 'NEW' .. tostring(i), 'WarningMsg' }},
+ })
+ end
+ end,
+ })
+ ]])
+
+ feed('o')
+ screen:expect({
+ grid = [[
+ aaa |
+ ^ {19:NEW1} |
+ bbb |
+ ccc |
+ {1:~ }|
+ {5:-- INSERT --} |
+ ]],
+ })
+ feed('<CR>')
+ screen:expect({
+ grid = [[
+ aaa |
+ {19:NEW1} |
+ ^ {19:NEW2} |
+ bbb |
+ ccc |
+ {5:-- INSERT --} |
+ ]],
+ })
+ end)
end)
describe('lua: nvim_buf_attach on_bytes', function()
@@ -426,14 +468,14 @@ describe('lua: nvim_buf_attach on_bytes', function()
it('opening lines', function()
local check_events = setup_eventcheck(verify, origlines)
- -- api.nvim_set_option_value('autoindent', true, {})
+ api.nvim_set_option_value('autoindent', false, {})
feed 'Go'
check_events {
{ 'test1', 'bytes', 1, 3, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
}
feed '<cr>'
check_events {
- { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
+ { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
}
end)
@@ -447,7 +489,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed '<cr>'
check_events {
{ 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 4, 4, 0, 0, 0 },
- { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 4, 5 },
+ { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 0, 0, 1, 4, 5 },
}
end)
@@ -477,7 +519,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
api.nvim_set_option_value('filetype', 'c', {})
feed 'A<CR>'
check_events {
- { 'test1', 'bytes', 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 },
+ { 'test1', 'bytes', 1, 3, 0, 10, 10, 0, 0, 0, 1, 3, 4 },
}
feed '<ESC>'
@@ -493,7 +535,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed '<CR>'
check_events {
{ 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 1, 1, 0, 0, 0 },
- { 'test1', 'bytes', 1, 7, 1, 2, 13, 0, 0, 0, 1, 3, 4 },
+ { 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 0, 0, 1, 3, 4 },
}
end)
@@ -541,7 +583,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed 'cc'
check_events {
- { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 15, 15, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 15, 15, 0, 0, 0 },
}
feed '<ESC>'
@@ -924,7 +966,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
command('e! Xtest-undofile')
command('set undodir=. | set undofile')
- local ns = helpers.request('nvim_create_namespace', 'ns1')
+ local ns = n.request('nvim_create_namespace', 'ns1')
api.nvim_buf_set_extmark(0, ns, 0, 0, {})
eq({ '12345', 'hello world' }, api.nvim_buf_get_lines(0, 0, -1, true))
@@ -1225,6 +1267,25 @@ describe('lua: nvim_buf_attach on_bytes', function()
}
end)
+ it('prompt buffer', function()
+ local check_events = setup_eventcheck(verify, {})
+ api.nvim_set_option_value('buftype', 'prompt', {})
+ feed('i')
+ check_events {
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
+ }
+ feed('<CR>')
+ check_events {
+ { 'test1', 'bytes', 1, 4, 1, 0, 3, 0, 0, 0, 1, 0, 1 },
+ { 'test1', 'bytes', 1, 5, 1, 0, 3, 0, 0, 0, 0, 2, 2 },
+ }
+ feed('<CR>')
+ check_events {
+ { 'test1', 'bytes', 1, 6, 2, 0, 6, 0, 0, 0, 1, 0, 1 },
+ { 'test1', 'bytes', 1, 7, 2, 0, 6, 0, 0, 0, 0, 2, 2 },
+ }
+ end)
+
local function test_lockmarks(mode)
local description = (mode ~= '') and mode or '(baseline)'
it('test_lockmarks ' .. description .. ' %delete _', function()
diff --git a/test/functional/lua/command_line_completion_spec.lua b/test/functional/lua/command_line_completion_spec.lua
index b88a38082f..2ba432133b 100644
--- a/test/functional/lua/command_line_completion_spec.lua
+++ b/test/functional/lua/command_line_completion_spec.lua
@@ -1,8 +1,9 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local clear = helpers.clear
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
+local clear = n.clear
+local eq = t.eq
+local exec_lua = n.exec_lua
local get_completions = function(input, env)
return exec_lua('return {vim._expand_pat(...)}', input, env)
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index b8d0638ce5..57b084d3d6 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -1,24 +1,25 @@
-- Test suite for checking :lua* commands
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local eq = helpers.eq
+local eq = t.eq
local NIL = vim.NIL
-local eval = helpers.eval
-local feed = helpers.feed
-local clear = helpers.clear
-local matches = helpers.matches
-local api = helpers.api
-local exec_lua = helpers.exec_lua
-local exec_capture = helpers.exec_capture
-local fn = helpers.fn
-local source = helpers.source
-local dedent = helpers.dedent
-local command = helpers.command
-local exc_exec = helpers.exc_exec
-local pcall_err = helpers.pcall_err
-local write_file = helpers.write_file
-local remove_trace = helpers.remove_trace
+local eval = n.eval
+local feed = n.feed
+local clear = n.clear
+local matches = t.matches
+local api = n.api
+local exec_lua = n.exec_lua
+local exec_capture = n.exec_capture
+local fn = n.fn
+local source = n.source
+local dedent = t.dedent
+local command = n.command
+local exc_exec = n.exc_exec
+local pcall_err = t.pcall_err
+local write_file = t.write_file
+local remove_trace = t.remove_trace
before_each(clear)
diff --git a/test/functional/lua/comment_spec.lua b/test/functional/lua/comment_spec.lua
new file mode 100644
index 0000000000..bbf061a2ab
--- /dev/null
+++ b/test/functional/lua/comment_spec.lua
@@ -0,0 +1,651 @@
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local api = n.api
+local clear = n.clear
+local eq = t.eq
+local exec_capture = n.exec_capture
+local exec_lua = n.exec_lua
+local feed = n.feed
+
+-- Reference text
+-- aa
+-- aa
+-- aa
+--
+-- aa
+-- aa
+-- aa
+local example_lines = { 'aa', ' aa', ' aa', '', ' aa', ' aa', 'aa' }
+
+local set_commentstring = function(commentstring)
+ api.nvim_set_option_value('commentstring', commentstring, { buf = 0 })
+end
+
+local get_lines = function(from, to)
+ from, to = from or 0, to or -1
+ return api.nvim_buf_get_lines(0, from, to, false)
+end
+
+local set_lines = function(lines, from, to)
+ from, to = from or 0, to or -1
+ api.nvim_buf_set_lines(0, from, to, false, lines)
+end
+
+local set_cursor = function(row, col)
+ api.nvim_win_set_cursor(0, { row, col })
+end
+
+local get_cursor = function()
+ return api.nvim_win_get_cursor(0)
+end
+
+local setup_treesitter = function()
+ -- NOTE: This leverages bundled Vimscript and Lua tree-sitter parsers
+ api.nvim_set_option_value('filetype', 'vim', { buf = 0 })
+ exec_lua('vim.treesitter.start()')
+end
+
+before_each(function()
+ clear({ args_rm = { '--cmd' }, args = { '--clean' } })
+end)
+
+describe('commenting', function()
+ before_each(function()
+ set_lines(example_lines)
+ set_commentstring('# %s')
+ end)
+
+ describe('toggle_lines()', function()
+ local toggle_lines = function(...)
+ exec_lua('require("vim._comment").toggle_lines(...)', ...)
+ end
+
+ it('works', function()
+ toggle_lines(3, 5)
+ eq(get_lines(2, 5), { ' # aa', ' #', ' # aa' })
+
+ toggle_lines(3, 5)
+ eq(get_lines(2, 5), { ' aa', '', ' aa' })
+ end)
+
+ it("works with different 'commentstring' options", function()
+ local validate = function(lines_before, lines_after, lines_again)
+ set_lines(lines_before)
+ toggle_lines(1, #lines_before)
+ eq(get_lines(), lines_after)
+ toggle_lines(1, #lines_before)
+ eq(get_lines(), lines_again or lines_before)
+ end
+
+ -- Single whitespace inside comment parts (main case)
+ set_commentstring('# %s #')
+ -- - General case
+ validate(
+ { 'aa', ' aa', 'aa ', ' aa ' },
+ { '# aa #', '# aa #', '# aa #', '# aa #' }
+ )
+ -- - Tabs
+ validate(
+ { 'aa', '\taa', 'aa\t', '\taa\t' },
+ { '# aa #', '# \taa #', '# aa\t #', '# \taa\t #' }
+ )
+ -- - With indent
+ validate({ ' aa', ' aa' }, { ' # aa #', ' # aa #' })
+ -- - With blank/empty lines
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' # aa #', ' ##', ' ##', ' ##' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring('# %s')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '# aa', '# aa', '# aa ', '# aa ' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '# aa', '# \taa', '# aa\t', '# \taa\t' })
+ validate({ ' aa', ' aa' }, { ' # aa', ' # aa' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' # aa', ' #', ' #', ' #' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring('%s #')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { 'aa #', ' aa #', 'aa #', ' aa #' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { 'aa #', '\taa #', 'aa\t #', '\taa\t #' })
+ validate({ ' aa', ' aa' }, { ' aa #', ' aa #' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' aa #', ' #', ' #', ' #' },
+ { ' aa', '', '', '' }
+ )
+
+ -- No whitespace in parts
+ set_commentstring('#%s#')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '#aa#', '# aa#', '#aa #', '# aa #' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '#aa#', '#\taa#', '#aa\t#', '#\taa\t#' })
+ validate({ ' aa', ' aa' }, { ' #aa#', ' # aa#' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' #aa#', ' ##', ' ##', ' ##' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring('#%s')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '#aa', '# aa', '#aa ', '# aa ' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '#aa', '#\taa', '#aa\t', '#\taa\t' })
+ validate({ ' aa', ' aa' }, { ' #aa', ' # aa' })
+ validate({ ' aa', '', ' ', '\t' }, { ' #aa', ' #', ' #', ' #' }, { ' aa', '', '', '' })
+
+ set_commentstring('%s#')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { 'aa#', ' aa#', 'aa #', ' aa #' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { 'aa#', '\taa#', 'aa\t#', '\taa\t#' })
+ validate({ ' aa', ' aa' }, { ' aa#', ' aa#' })
+ validate({ ' aa', '', ' ', '\t' }, { ' aa#', ' #', ' #', ' #' }, { ' aa', '', '', '' })
+
+ -- Extra whitespace inside comment parts
+ set_commentstring('# %s #')
+ validate(
+ { 'aa', ' aa', 'aa ', ' aa ' },
+ { '# aa #', '# aa #', '# aa #', '# aa #' }
+ )
+ validate(
+ { 'aa', '\taa', 'aa\t', '\taa\t' },
+ { '# aa #', '# \taa #', '# aa\t #', '# \taa\t #' }
+ )
+ validate({ ' aa', ' aa' }, { ' # aa #', ' # aa #' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' # aa #', ' ##', ' ##', ' ##' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring('# %s')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '# aa', '# aa', '# aa ', '# aa ' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '# aa', '# \taa', '# aa\t', '# \taa\t' })
+ validate({ ' aa', ' aa' }, { ' # aa', ' # aa' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' # aa', ' #', ' #', ' #' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring('%s #')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { 'aa #', ' aa #', 'aa #', ' aa #' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { 'aa #', '\taa #', 'aa\t #', '\taa\t #' })
+ validate({ ' aa', ' aa' }, { ' aa #', ' aa #' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' aa #', ' #', ' #', ' #' },
+ { ' aa', '', '', '' }
+ )
+
+ -- Whitespace outside of comment parts
+ set_commentstring(' # %s # ')
+ validate(
+ { 'aa', ' aa', 'aa ', ' aa ' },
+ { ' # aa # ', ' # aa # ', ' # aa # ', ' # aa # ' }
+ )
+ validate(
+ { 'aa', '\taa', 'aa\t', '\taa\t' },
+ { ' # aa # ', ' # \taa # ', ' # aa\t # ', ' # \taa\t # ' }
+ )
+ validate({ ' aa', ' aa' }, { ' # aa # ', ' # aa # ' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' # aa # ', ' ##', ' ##', ' ##' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring(' # %s ')
+ validate(
+ { 'aa', ' aa', 'aa ', ' aa ' },
+ { ' # aa ', ' # aa ', ' # aa ', ' # aa ' }
+ )
+ validate(
+ { 'aa', '\taa', 'aa\t', '\taa\t' },
+ { ' # aa ', ' # \taa ', ' # aa\t ', ' # \taa\t ' }
+ )
+ validate({ ' aa', ' aa' }, { ' # aa ', ' # aa ' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' # aa ', ' #', ' #', ' #' },
+ { ' aa', '', '', '' }
+ )
+
+ set_commentstring(' %s # ')
+ validate(
+ { 'aa', ' aa', 'aa ', ' aa ' },
+ { ' aa # ', ' aa # ', ' aa # ', ' aa # ' }
+ )
+ validate(
+ { 'aa', '\taa', 'aa\t', '\taa\t' },
+ { ' aa # ', ' \taa # ', ' aa\t # ', ' \taa\t # ' }
+ )
+ validate({ ' aa', ' aa' }, { ' aa # ', ' aa # ' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' aa # ', ' #', ' #', ' #' },
+ { ' aa', '', '', '' }
+ )
+
+ -- LaTeX
+ set_commentstring('% %s')
+ validate({ 'aa', ' aa', 'aa ', ' aa ' }, { '% aa', '% aa', '% aa ', '% aa ' })
+ validate({ 'aa', '\taa', 'aa\t', '\taa\t' }, { '% aa', '% \taa', '% aa\t', '% \taa\t' })
+ validate({ ' aa', ' aa' }, { ' % aa', ' % aa' })
+ validate(
+ { ' aa', '', ' ', '\t' },
+ { ' % aa', ' %', ' %', ' %' },
+ { ' aa', '', '', '' }
+ )
+ end)
+
+ it('respects tree-sitter injections', function()
+ setup_treesitter()
+
+ local lines = {
+ 'set background=dark',
+ 'lua << EOF',
+ 'print(1)',
+ 'vim.api.nvim_exec2([[',
+ ' set background=light',
+ ']])',
+ 'EOF',
+ }
+
+ -- Single line comments
+ local validate = function(line, ref_output)
+ set_lines(lines)
+ toggle_lines(line, line)
+ eq(get_lines(line - 1, line)[1], ref_output)
+ end
+
+ validate(1, '"set background=dark')
+ validate(2, '"lua << EOF')
+ validate(3, '-- print(1)')
+ validate(4, '-- vim.api.nvim_exec2([[')
+ validate(5, ' "set background=light')
+ validate(6, '-- ]])')
+ validate(7, '"EOF')
+
+ -- Multiline comments should be computed based on first line 'commentstring'
+ set_lines(lines)
+ toggle_lines(1, 3)
+ local out_lines = get_lines()
+ eq(out_lines[1], '"set background=dark')
+ eq(out_lines[2], '"lua << EOF')
+ eq(out_lines[3], '"print(1)')
+ end)
+
+ it('correctly computes indent', function()
+ toggle_lines(2, 4)
+ eq(get_lines(1, 4), { ' # aa', ' # aa', ' #' })
+ end)
+
+ it('correctly detects comment/uncomment', function()
+ local validate = function(from, to, ref_lines)
+ set_lines({ '', 'aa', '# aa', '# aa', 'aa', '' })
+ toggle_lines(from, to)
+ eq(get_lines(), ref_lines)
+ end
+
+ -- It should uncomment only if all non-blank lines are comments
+ validate(3, 4, { '', 'aa', 'aa', 'aa', 'aa', '' })
+ validate(2, 4, { '', '# aa', '# # aa', '# # aa', 'aa', '' })
+ validate(3, 5, { '', 'aa', '# # aa', '# # aa', '# aa', '' })
+ validate(1, 6, { '#', '# aa', '# # aa', '# # aa', '# aa', '#' })
+
+ -- Blank lines should be ignored when making a decision
+ set_lines({ '# aa', '', ' ', '\t', '# aa' })
+ toggle_lines(1, 5)
+ eq(get_lines(), { 'aa', '', ' ', '\t', 'aa' })
+ end)
+
+ it('correctly matches comment parts during checking and uncommenting', function()
+ local validate = function(from, to, ref_lines)
+ set_lines({ '/*aa*/', '/* aa */', '/* aa */' })
+ toggle_lines(from, to)
+ eq(get_lines(), ref_lines)
+ end
+
+ -- Should first try to match 'commentstring' parts exactly with their
+ -- whitespace, with fallback on trimmed parts
+ set_commentstring('/*%s*/')
+ validate(1, 3, { 'aa', ' aa ', ' aa ' })
+ validate(2, 3, { '/*aa*/', ' aa ', ' aa ' })
+ validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' })
+
+ set_commentstring('/* %s */')
+ validate(1, 3, { 'aa', 'aa', ' aa ' })
+ validate(2, 3, { '/*aa*/', 'aa', ' aa ' })
+ validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' })
+
+ set_commentstring('/* %s */')
+ validate(1, 3, { 'aa', ' aa ', 'aa' })
+ validate(2, 3, { '/*aa*/', ' aa ', 'aa' })
+ validate(3, 3, { '/*aa*/', '/* aa */', 'aa' })
+
+ set_commentstring(' /*%s*/ ')
+ validate(1, 3, { 'aa', ' aa ', ' aa ' })
+ validate(2, 3, { '/*aa*/', ' aa ', ' aa ' })
+ validate(3, 3, { '/*aa*/', '/* aa */', ' aa ' })
+ end)
+
+ it('uncomments on inconsistent indent levels', function()
+ set_lines({ '# aa', ' # aa', ' # aa' })
+ toggle_lines(1, 3)
+ eq(get_lines(), { 'aa', ' aa', ' aa' })
+ end)
+
+ it('respects tabs', function()
+ api.nvim_set_option_value('expandtab', false, { buf = 0 })
+ set_lines({ '\t\taa', '\t\taa' })
+
+ toggle_lines(1, 2)
+ eq(get_lines(), { '\t\t# aa', '\t\t# aa' })
+
+ toggle_lines(1, 2)
+ eq(get_lines(), { '\t\taa', '\t\taa' })
+ end)
+
+ it('works with trailing whitespace', function()
+ -- Without right-hand side
+ set_commentstring('# %s')
+ set_lines({ ' aa', ' aa ', ' ' })
+ toggle_lines(1, 3)
+ eq(get_lines(), { ' # aa', ' # aa ', ' #' })
+ toggle_lines(1, 3)
+ eq(get_lines(), { ' aa', ' aa ', '' })
+
+ -- With right-hand side
+ set_commentstring('%s #')
+ set_lines({ ' aa', ' aa ', ' ' })
+ toggle_lines(1, 3)
+ eq(get_lines(), { ' aa #', ' aa #', ' #' })
+ toggle_lines(1, 3)
+ eq(get_lines(), { ' aa', ' aa ', '' })
+
+ -- Trailing whitespace after right side should be preserved for non-blanks
+ set_commentstring('%s #')
+ set_lines({ ' aa # ', ' aa #\t', ' # ', ' #\t' })
+ toggle_lines(1, 4)
+ eq(get_lines(), { ' aa ', ' aa\t', '', '' })
+ end)
+ end)
+
+ describe('Operator', function()
+ it('works in Normal mode', function()
+ set_cursor(2, 2)
+ feed('gc', 'ap')
+ eq(get_lines(), { '# aa', '# aa', '# aa', '#', ' aa', ' aa', 'aa' })
+ -- Cursor moves to start line
+ eq(get_cursor(), { 1, 0 })
+
+ -- Supports `v:count`
+ set_lines(example_lines)
+ set_cursor(2, 0)
+ feed('2gc', 'ap')
+ eq(get_lines(), { '# aa', '# aa', '# aa', '#', '# aa', '# aa', '# aa' })
+ end)
+
+ it('allows dot-repeat in Normal mode', function()
+ local doubly_commented = { '# # aa', '# # aa', '# # aa', '# #', '# aa', '# aa', '# aa' }
+
+ set_lines(example_lines)
+ set_cursor(2, 2)
+ feed('gc', 'ap')
+ feed('.')
+ eq(get_lines(), doubly_commented)
+
+ -- Not immediate dot-repeat
+ set_lines(example_lines)
+ set_cursor(2, 2)
+ feed('gc', 'ap')
+ set_cursor(7, 0)
+ feed('.')
+ eq(get_lines(), doubly_commented)
+ end)
+
+ it('works in Visual mode', function()
+ set_cursor(2, 2)
+ feed('v', 'ap', 'gc')
+ eq(get_lines(), { '# aa', '# aa', '# aa', '#', ' aa', ' aa', 'aa' })
+
+ -- Cursor moves to start line
+ eq(get_cursor(), { 1, 0 })
+ end)
+
+ it('allows dot-repeat after initial Visual mode', function()
+ -- local example_lines = { 'aa', ' aa', ' aa', '', ' aa', ' aa', 'aa' }
+
+ set_lines(example_lines)
+ set_cursor(2, 2)
+ feed('vip', 'gc')
+ eq(get_lines(), { '# aa', '# aa', '# aa', '', ' aa', ' aa', 'aa' })
+ eq(get_cursor(), { 1, 0 })
+
+ -- Dot-repeat after first application in Visual mode should apply to the same
+ -- relative region
+ feed('.')
+ eq(get_lines(), example_lines)
+
+ set_cursor(3, 0)
+ feed('.')
+ eq(get_lines(), { 'aa', ' aa', ' # aa', ' #', ' # aa', ' aa', 'aa' })
+ end)
+
+ it("respects 'commentstring'", function()
+ set_commentstring('/*%s*/')
+ set_cursor(2, 2)
+ feed('gc', 'ap')
+ eq(get_lines(), { '/*aa*/', '/* aa*/', '/* aa*/', '/**/', ' aa', ' aa', 'aa' })
+ end)
+
+ it("works with empty 'commentstring'", function()
+ set_commentstring('')
+ set_cursor(2, 2)
+ feed('gc', 'ap')
+ eq(get_lines(), example_lines)
+ eq(exec_capture('1messages'), [[Option 'commentstring' is empty.]])
+ end)
+
+ it('respects tree-sitter injections', function()
+ setup_treesitter()
+
+ local lines = {
+ 'set background=dark',
+ 'lua << EOF',
+ 'print(1)',
+ 'vim.api.nvim_exec2([[',
+ ' set background=light',
+ ']])',
+ 'EOF',
+ }
+
+ -- Single line comments
+ local validate = function(line, ref_output)
+ set_lines(lines)
+ set_cursor(line, 0)
+ feed('gc_')
+ eq(get_lines(line - 1, line)[1], ref_output)
+ end
+
+ validate(1, '"set background=dark')
+ validate(2, '"lua << EOF')
+ validate(3, '-- print(1)')
+ validate(4, '-- vim.api.nvim_exec2([[')
+ validate(5, ' "set background=light')
+ validate(6, '-- ]])')
+ validate(7, '"EOF')
+
+ -- Has proper dot-repeat which recomputes 'commentstring'
+ set_lines(lines)
+
+ set_cursor(1, 0)
+ feed('gc_')
+ eq(get_lines()[1], '"set background=dark')
+
+ set_cursor(3, 0)
+ feed('.')
+ eq(get_lines()[3], '-- print(1)')
+
+ -- Multiline comments should be computed based on cursor position
+ -- which in case of Visual selection means its left part
+ set_lines(lines)
+ set_cursor(1, 0)
+ feed('v2j', 'gc')
+ local out_lines = get_lines()
+ eq(out_lines[1], '"set background=dark')
+ eq(out_lines[2], '"lua << EOF')
+ eq(out_lines[3], '"print(1)')
+ end)
+
+ it("recomputes local 'commentstring' based on cursor position", function()
+ setup_treesitter()
+ local lines = {
+ ' print(1)',
+ 'lua << EOF',
+ ' print(1)',
+ 'EOF',
+ }
+ set_lines(lines)
+
+ set_cursor(1, 1)
+ feed('gc_')
+ eq(get_lines()[1], ' "print(1)')
+
+ set_lines(lines)
+ set_cursor(3, 2)
+ feed('.')
+ eq(get_lines()[3], ' -- print(1)')
+ end)
+
+ it('preserves marks', function()
+ set_cursor(2, 0)
+ -- Set '`<' and '`>' marks
+ feed('VV')
+ feed('gc', 'ip')
+ eq(api.nvim_buf_get_mark(0, '<'), { 2, 0 })
+ eq(api.nvim_buf_get_mark(0, '>'), { 2, 2147483647 })
+ end)
+ end)
+
+ describe('Current line', function()
+ it('works', function()
+ set_lines(example_lines)
+ set_cursor(1, 1)
+ feed('gcc')
+ eq(get_lines(0, 2), { '# aa', ' aa' })
+
+ -- Does not comment empty line
+ set_lines(example_lines)
+ set_cursor(4, 0)
+ feed('gcc')
+ eq(get_lines(2, 5), { ' aa', '', ' aa' })
+
+ -- Supports `v:count`
+ set_lines(example_lines)
+ set_cursor(2, 0)
+ feed('2gcc')
+ eq(get_lines(0, 3), { 'aa', ' # aa', ' # aa' })
+ end)
+
+ it('allows dot-repeat', function()
+ set_lines(example_lines)
+ set_cursor(1, 1)
+ feed('gcc')
+ feed('.')
+ eq(get_lines(), example_lines)
+
+ -- Not immediate dot-repeat
+ set_lines(example_lines)
+ set_cursor(1, 1)
+ feed('gcc')
+ set_cursor(7, 0)
+ feed('.')
+ eq(get_lines(6, 7), { '# aa' })
+ end)
+
+ it('respects tree-sitter injections', function()
+ setup_treesitter()
+
+ local lines = {
+ 'set background=dark',
+ 'lua << EOF',
+ 'print(1)',
+ 'EOF',
+ }
+ set_lines(lines)
+
+ set_cursor(1, 0)
+ feed('gcc')
+ eq(get_lines(), { '"set background=dark', 'lua << EOF', 'print(1)', 'EOF' })
+
+ -- Should work with dot-repeat
+ set_cursor(3, 0)
+ feed('.')
+ eq(get_lines(), { '"set background=dark', 'lua << EOF', '-- print(1)', 'EOF' })
+ end)
+ end)
+
+ describe('Textobject', function()
+ it('works', function()
+ set_lines({ 'aa', '# aa', '# aa', 'aa' })
+ set_cursor(2, 0)
+ feed('d', 'gc')
+ eq(get_lines(), { 'aa', 'aa' })
+ end)
+
+ it('allows dot-repeat', function()
+ set_lines({ 'aa', '# aa', '# aa', 'aa', '# aa' })
+ set_cursor(2, 0)
+ feed('d', 'gc')
+ set_cursor(3, 0)
+ feed('.')
+ eq(get_lines(), { 'aa', 'aa' })
+ end)
+
+ it('does nothing when not inside textobject', function()
+ -- Builtin operators
+ feed('d', 'gc')
+ eq(get_lines(), example_lines)
+
+ -- Comment operator
+ local validate_no_action = function(line, col)
+ set_lines(example_lines)
+ set_cursor(line, col)
+ feed('gc', 'gc')
+ eq(get_lines(), example_lines)
+ end
+
+ validate_no_action(1, 1)
+ validate_no_action(2, 2)
+
+ -- Doesn't work (but should) because both `[` and `]` are set to (1, 0)
+ -- (instead of more reasonable (1, -1) or (0, 2147483647)).
+ -- validate_no_action(1, 0)
+ end)
+
+ it('respects tree-sitter injections', function()
+ setup_treesitter()
+ local lines = {
+ '"set background=dark',
+ '"set termguicolors',
+ 'lua << EOF',
+ '-- print(1)',
+ '-- print(2)',
+ 'EOF',
+ }
+ set_lines(lines)
+
+ set_cursor(1, 0)
+ feed('dgc')
+ eq(get_lines(), { 'lua << EOF', '-- print(1)', '-- print(2)', 'EOF' })
+
+ -- Should work with dot-repeat
+ set_cursor(2, 0)
+ feed('.')
+ eq(get_lines(), { 'lua << EOF', 'EOF' })
+ end)
+ end)
+end)
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index 5802925339..05082bc132 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -1,13 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local NIL = vim.NIL
-local command = helpers.command
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local matches = helpers.matches
-local api = helpers.api
-local pcall_err = helpers.pcall_err
+local command = n.command
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local matches = t.matches
+local api = n.api
+local pcall_err = t.pcall_err
+local fn = n.fn
describe('vim.diagnostic', function()
before_each(function()
@@ -16,12 +18,12 @@ describe('vim.diagnostic', function()
exec_lua [[
require('vim.diagnostic')
- function make_diagnostic(msg, x1, y1, x2, y2, severity, source, code)
+ function make_diagnostic(msg, lnum, col, end_lnum, end_col, severity, source, code)
return {
- lnum = x1,
- col = y1,
- end_lnum = x2,
- end_col = y2,
+ lnum = lnum,
+ col = col,
+ end_lnum = end_lnum,
+ end_col = end_col,
message = msg,
severity = severity,
source = source,
@@ -29,20 +31,20 @@ describe('vim.diagnostic', function()
}
end
- function make_error(msg, x1, y1, x2, y2, source, code)
- return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.ERROR, source, code)
+ function make_error(msg, lnum, col, end_lnum, end_col, source, code)
+ return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.ERROR, source, code)
end
- function make_warning(msg, x1, y1, x2, y2, source, code)
- return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.WARN, source, code)
+ function make_warning(msg, lnum, col, end_lnum, end_col, source, code)
+ return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.WARN, source, code)
end
- function make_info(msg, x1, y1, x2, y2, source, code)
- return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.INFO, source, code)
+ function make_info(msg, lnum, col, end_lnum, end_col, source, code)
+ return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.INFO, source, code)
end
- function make_hint(msg, x1, y1, x2, y2, source, code)
- return make_diagnostic(msg, x1, y1, x2, y2, vim.diagnostic.severity.HINT, source, code)
+ function make_hint(msg, lnum, col, end_lnum, end_col, source, code)
+ return make_diagnostic(msg, lnum, col, end_lnum, end_col, vim.diagnostic.severity.HINT, source, code)
end
function count_diagnostics(bufnr, severity, namespace)
@@ -109,7 +111,7 @@ describe('vim.diagnostic', function()
'DiagnosticVirtualTextOk',
'DiagnosticVirtualTextWarn',
'DiagnosticWarn',
- }, exec_lua([[return vim.fn.getcompletion('Diagnostic', 'highlight')]]))
+ }, fn.getcompletion('Diagnostic', 'highlight'))
end)
it('retrieves diagnostics from all buffers and namespaces', function()
@@ -205,7 +207,7 @@ describe('vim.diagnostic', function()
diag[1].col = 10000
return vim.diagnostic.get()[1].col == 10000
]]
- eq(result, false)
+ eq(false, result)
end)
it('resolves buffer number 0 to the current buffer', function()
@@ -328,7 +330,7 @@ describe('vim.diagnostic', function()
eq(
{ 1, 1, 2, 0, 2 },
exec_lua [[
- vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
return {
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
@@ -343,7 +345,7 @@ describe('vim.diagnostic', function()
eq(
all_highlights,
exec_lua([[
- vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
return {
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.WARN, other_ns),
@@ -370,7 +372,7 @@ describe('vim.diagnostic', function()
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, ns_1_diags)
vim.diagnostic.set(other_ns, diagnostic_bufnr, ns_2_diags)
- vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
return {
count_extmarks(diagnostic_bufnr, diagnostic_ns),
@@ -382,8 +384,8 @@ describe('vim.diagnostic', function()
eq(
{ 4, 0 },
exec_lua [[
- vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
- vim.diagnostic.disable(diagnostic_bufnr, other_ns)
+ vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = other_ns })
return {
count_extmarks(diagnostic_bufnr, diagnostic_ns),
@@ -477,7 +479,32 @@ describe('vim.diagnostic', function()
end)
describe('enable() and disable()', function()
- it('works without arguments', function()
+ it('validation', function()
+ matches('expected boolean, got table', pcall_err(exec_lua, [[vim.diagnostic.enable({})]]))
+ matches(
+ 'filter: expected table, got string',
+ pcall_err(exec_lua, [[vim.diagnostic.enable(false, '')]])
+ )
+ matches(
+ 'Invalid buffer id: 42',
+ pcall_err(exec_lua, [[vim.diagnostic.enable(true, { bufnr = 42 })]])
+ )
+ matches(
+ 'expected boolean, got number',
+ pcall_err(exec_lua, [[vim.diagnostic.enable(42, {})]])
+ )
+ matches('expected boolean, got table', pcall_err(exec_lua, [[vim.diagnostic.enable({}, 42)]]))
+
+ -- Deprecated signature.
+ matches('Invalid buffer id: 42', pcall_err(exec_lua, [[vim.diagnostic.enable(42)]]))
+ -- Deprecated signature.
+ matches(
+ 'namespace does not exist or is anonymous',
+ pcall_err(exec_lua, [[vim.diagnostic.enable(nil, 42)]])
+ )
+ end)
+
+ it('without arguments', function()
local result = exec_lua [[
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
@@ -499,7 +526,7 @@ describe('vim.diagnostic', function()
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns))
- vim.diagnostic.disable()
+ vim.diagnostic.enable(false)
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns))
@@ -531,7 +558,7 @@ describe('vim.diagnostic', function()
eq(4, result[4])
end)
- it('works with only a buffer argument', function()
+ it('with buffer argument', function()
local result = exec_lua [[
local other_bufnr = vim.api.nvim_create_buf(true, false)
@@ -560,19 +587,19 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- vim.diagnostic.disable(diagnostic_bufnr)
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr })
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- vim.diagnostic.enable(diagnostic_bufnr)
+ vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr })
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- vim.diagnostic.disable(other_bufnr)
+ vim.diagnostic.enable(false, { bufnr = other_bufnr })
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
@@ -587,7 +614,7 @@ describe('vim.diagnostic', function()
eq(3, result[4])
end)
- it('works with only a namespace argument', function()
+ it('with a namespace argument', function()
local result = exec_lua [[
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
@@ -609,17 +636,17 @@ describe('vim.diagnostic', function()
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns))
- vim.diagnostic.disable(nil, diagnostic_ns)
+ vim.diagnostic.enable(false, { ns_id = diagnostic_ns })
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns))
- vim.diagnostic.enable(nil, diagnostic_ns)
+ vim.diagnostic.enable(true, { ns_id = diagnostic_ns })
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns))
- vim.diagnostic.disable(nil, other_ns)
+ vim.diagnostic.enable(false, { ns_id = other_ns })
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns))
@@ -633,8 +660,11 @@ describe('vim.diagnostic', function()
eq(2, result[4])
end)
- it('works with both a buffer and a namespace argument', function()
- local result = exec_lua [[
+ --- @return table
+ local function test_enable(legacy)
+ local result = exec_lua(
+ [[
+ local legacy = ...
local other_bufnr = vim.api.nvim_create_buf(true, false)
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
@@ -662,34 +692,68 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ if legacy then
+ vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ else
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
+ end
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- vim.diagnostic.disable(diagnostic_bufnr, other_ns)
+ if legacy then
+ vim.diagnostic.disable(diagnostic_bufnr, other_ns)
+ else
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = other_ns })
+ end
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ if legacy then
+ vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ else
+ vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
+ end
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
- -- Should have no effect
- vim.diagnostic.disable(other_bufnr, other_ns)
+ if legacy then
+ -- Should have no effect
+ vim.diagnostic.disable(other_bufnr, other_ns)
+ else
+ -- Should have no effect
+ vim.diagnostic.enable(false, { bufnr = other_bufnr, ns_id = other_ns })
+ end
table.insert(result, count_extmarks(diagnostic_bufnr, diagnostic_ns) +
count_extmarks(diagnostic_bufnr, other_ns) +
count_extmarks(other_bufnr, diagnostic_ns))
return result
- ]]
+ ]],
+ legacy
+ )
+
+ return result
+ end
+ it('with both buffer and namespace arguments', function()
+ local result = test_enable(false)
+ eq(4, result[1])
+ eq(2, result[2])
+ eq(1, result[3])
+ eq(3, result[4])
+ eq(3, result[5])
+ end)
+
+ it('with both buffer and namespace arguments (deprecated signature)', function()
+ -- Exercise the legacy/deprecated signature.
+ local result = test_enable(true)
eq(4, result[1])
eq(2, result[2])
eq(1, result[3])
@@ -870,15 +934,112 @@ describe('vim.diagnostic', function()
eq(
{ 4, 0 },
exec_lua [[
- vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
- make_error('Diagnostic #1', 3, 9001, 3, 9001),
- make_error('Diagnostic #2', 4, -1, 4, -1),
- })
- vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
- vim.api.nvim_win_set_cursor(0, {1, 1})
- vim.diagnostic.goto_next { float = false }
- return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]]
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 3, 9001, 3, 9001),
+ make_error('Diagnostic #2', 4, -1, 4, -1),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {1, 1})
+ vim.diagnostic.goto_next { float = false }
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ ]]
+ )
+ end)
+
+ it('jumps to diagnostic with highest severity', function()
+ exec_lua([[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_info('Info', 1, 0, 1, 1),
+ make_error('Error', 2, 0, 2, 1),
+ make_warning('Warning', 3, 0, 3, 1),
+ make_error('Error', 4, 0, 4, 1),
+ })
+
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {1, 0})
+ ]])
+
+ eq(
+ { 3, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next({_highest = true})
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 5, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next({_highest = true})
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ exec_lua([[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_info('Info', 1, 0, 1, 1),
+ make_hint('Hint', 2, 0, 2, 1),
+ make_warning('Warning', 3, 0, 3, 1),
+ make_hint('Hint', 4, 0, 4, 1),
+ make_warning('Warning', 5, 0, 5, 1),
+ })
+
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {1, 0})
+ ]])
+
+ eq(
+ { 4, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next({_highest = true})
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 6, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next({_highest = true})
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+ end)
+
+ it('jumps to next diagnostic if severity is non-nil', function()
+ exec_lua([[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_info('Info', 1, 0, 1, 1),
+ make_error('Error', 2, 0, 2, 1),
+ make_warning('Warning', 3, 0, 3, 1),
+ make_error('Error', 4, 0, 4, 1),
+ })
+
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {1, 0})
+ ]])
+
+ eq(
+ { 2, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next()
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 3, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next()
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
+ )
+
+ eq(
+ { 4, 0 },
+ exec_lua([[
+ vim.diagnostic.goto_next()
+ return vim.api.nvim_win_get_cursor(0)
+ ]])
)
end)
end)
@@ -940,6 +1101,29 @@ describe('vim.diagnostic', function()
]]
)
end)
+
+ it('works on blank line #28397', function()
+ eq(
+ { 0, 2 },
+ exec_lua [[
+ local test_bufnr = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_buf_set_lines(test_bufnr, 0, -1, false, {
+ 'first line',
+ '',
+ '',
+ 'end line',
+ })
+ vim.diagnostic.set(diagnostic_ns, test_bufnr, {
+ make_info('Diagnostic #1', 0, 2, 0, 2),
+ make_info('Diagnostic #2', 2, 0, 2, 0),
+ make_info('Diagnostic #3', 2, 0, 2, 0),
+ })
+ vim.api.nvim_win_set_buf(0, test_bufnr)
+ vim.api.nvim_win_set_cursor(0, {3, 0})
+ return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns}
+ ]]
+ )
+ end)
end)
describe('get()', function()
@@ -1013,13 +1197,13 @@ describe('vim.diagnostic', function()
it('allows filtering by line', function()
eq(
- 1,
+ 2,
exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 3),
make_info("Ignored information", 1, 1, 2, 3),
- make_error("Error On Other Line", 2, 1, 1, 5),
+ make_error("Error On Other Line", 3, 1, 3, 5),
})
return #vim.diagnostic.get(diagnostic_bufnr, {lnum = 2})
@@ -1129,13 +1313,16 @@ describe('vim.diagnostic', function()
it('allows filtering by line', function()
eq(
- exec_lua [[return { [vim.diagnostic.severity.ERROR] = 1 }]],
+ exec_lua [[return {
+ [vim.diagnostic.severity.WARN] = 1,
+ [vim.diagnostic.severity.INFO] = 1,
+ }]],
exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 3),
make_info("Ignored information", 1, 1, 2, 3),
- make_error("Error On Other Line", 2, 1, 1, 5),
+ make_error("Error On Other Line", 3, 1, 3, 5),
})
return vim.diagnostic.count(diagnostic_bufnr, {lnum = 2})
@@ -1554,7 +1741,7 @@ describe('vim.diagnostic', function()
end)
describe('set()', function()
- it('validates its arguments', function()
+ it('validation', function()
matches(
'expected a list of diagnostics',
pcall_err(exec_lua, [[vim.diagnostic.set(1, 0, {lnum = 1, col = 2})]])
@@ -1741,7 +1928,7 @@ describe('vim.diagnostic', function()
eq(
0,
exec_lua [[
- vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.enable(false, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
})
@@ -1752,7 +1939,7 @@ describe('vim.diagnostic', function()
eq(
2,
exec_lua [[
- vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
+ vim.diagnostic.enable(true, { bufnr = diagnostic_bufnr, ns_id = diagnostic_ns })
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
]]
)
@@ -1825,20 +2012,12 @@ describe('vim.diagnostic', function()
it('respects legacy signs placed with :sign define or sign_define #26618', function()
-- Legacy signs for diagnostics were deprecated in 0.10 and will be removed in 0.12
- eq(0, helpers.fn.has('nvim-0.12'))
+ eq(0, n.fn.has('nvim-0.12'))
- helpers.command(
- 'sign define DiagnosticSignError text= texthl= linehl=ErrorMsg numhl=ErrorMsg'
- )
- helpers.command(
- 'sign define DiagnosticSignWarn text= texthl= linehl=WarningMsg numhl=WarningMsg'
- )
- helpers.command(
- 'sign define DiagnosticSignInfo text= texthl= linehl=Underlined numhl=Underlined'
- )
- helpers.command(
- 'sign define DiagnosticSignHint text= texthl= linehl=Underlined numhl=Underlined'
- )
+ n.command('sign define DiagnosticSignError text= texthl= linehl=ErrorMsg numhl=ErrorMsg')
+ n.command('sign define DiagnosticSignWarn text= texthl= linehl=WarningMsg numhl=WarningMsg')
+ n.command('sign define DiagnosticSignInfo text= texthl= linehl=Underlined numhl=Underlined')
+ n.command('sign define DiagnosticSignHint text= texthl= linehl=Underlined numhl=Underlined')
local result = exec_lua [[
vim.diagnostic.config({
@@ -2451,6 +2630,47 @@ describe('vim.diagnostic', function()
]]
)
end)
+
+ it('works for multi-line diagnostics #21949', function()
+ -- open float failed non diagnostic lnum
+ eq(
+ vim.NIL,
+ 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)
+ local _, winnr = vim.diagnostic.open_float(0, { header = false })
+ return winnr
+ ]]
+ )
+
+ -- can open a float window on lnum 1
+ eq(
+ { '1. Error in two lines lnum is 1 and end_lnum is 2' },
+ exec_lua [[
+ vim.api.nvim_win_set_cursor(0, {2, 0})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
+ 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' },
+ exec_lua [[
+ vim.api.nvim_win_set_cursor(0, {3, 0})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
+ local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
+ vim.api.nvim_win_close(winnr, true)
+ return lines
+ ]]
+ )
+ end)
end)
describe('setloclist()', function()
@@ -2718,7 +2938,41 @@ describe('vim.diagnostic', function()
)
end)
- it('checks if diagnostics are disabled in a buffer', function()
+ it('is_enabled', function()
+ eq(
+ { false, false, false, false, false },
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ })
+ vim.api.nvim_set_current_buf(diagnostic_bufnr)
+ vim.diagnostic.enable(false)
+ return {
+ vim.diagnostic.is_enabled(),
+ vim.diagnostic.is_enabled{ bufnr = 0 },
+ vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr },
+ vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr, ns_id = diagnostic_ns },
+ vim.diagnostic.is_enabled{ bufnr = 0, ns_id = diagnostic_ns },
+ }
+ ]]
+ )
+
+ eq(
+ { true, true, true, true, true },
+ exec_lua [[
+ vim.diagnostic.enable()
+ return {
+ vim.diagnostic.is_enabled(),
+ vim.diagnostic.is_enabled{ bufnr = 0 },
+ vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr },
+ vim.diagnostic.is_enabled{ bufnr = diagnostic_bufnr, ns_id = diagnostic_ns },
+ vim.diagnostic.is_enabled{ bufnr = 0, ns_id = diagnostic_ns },
+ }
+ ]]
+ )
+ end)
+
+ it('is_disabled (deprecated)', function()
eq(
{ true, true, true, true },
exec_lua [[
diff --git a/test/functional/lua/ffi_spec.lua b/test/functional/lua/ffi_spec.lua
index c9e8e9d4ca..85ca264107 100644
--- a/test/functional/lua/ffi_spec.lua
+++ b/test/functional/lua/ffi_spec.lua
@@ -1,7 +1,9 @@
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local clear = helpers.clear
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local eq = t.eq
+local exec_lua = n.exec_lua
+local clear = n.clear
before_each(clear)
@@ -13,15 +15,19 @@ describe('ffi.cdef', function()
eq(
12,
- exec_lua [[
+ exec_lua [=[
local ffi = require('ffi')
- ffi.cdef('int curwin_col_off(void);')
+ ffi.cdef [[
+ typedef struct window_S win_T;
+ int win_col_off(win_T *wp);
+ extern win_T *curwin;
+ ]]
vim.cmd('set number numberwidth=4 signcolumn=yes:4')
- return ffi.C.curwin_col_off()
- ]]
+ return ffi.C.win_col_off(ffi.C.curwin)
+ ]=]
)
eq(
@@ -30,7 +36,6 @@ describe('ffi.cdef', function()
local ffi = require('ffi')
ffi.cdef[[
- typedef struct window_S win_T;
typedef struct {} stl_hlrec_t;
typedef struct {} StlClickRecord;
typedef struct {} statuscol_T;
diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua
index 8b0e0a8beb..7db04e6f6b 100644
--- a/test/functional/lua/filetype_spec.lua
+++ b/test/functional/lua/filetype_spec.lua
@@ -1,10 +1,16 @@
-local helpers = require('test.functional.helpers')(after_each)
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local api = helpers.api
-local clear = helpers.clear
-local pathroot = helpers.pathroot
-local command = helpers.command
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local exec_lua = n.exec_lua
+local eq = t.eq
+local api = n.api
+local clear = n.clear
+local pathroot = n.pathroot
+local command = n.command
+local mkdir = t.mkdir
+local rmdir = n.rmdir
+local write_file = t.write_file
+local uv = vim.uv
local root = pathroot()
@@ -161,10 +167,30 @@ describe('vim.filetype', function()
end)
describe('filetype.lua', function()
+ before_each(function()
+ mkdir('Xfiletype')
+ end)
+
+ after_each(function()
+ rmdir('Xfiletype')
+ end)
+
it('does not override user autocommands that set filetype #20333', function()
clear({
args = { '--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md' },
})
eq('notmarkdown', api.nvim_get_option_value('filetype', {}))
end)
+
+ it('uses unexpanded path for matching when editing a symlink #27914', function()
+ mkdir('Xfiletype/.config')
+ mkdir('Xfiletype/actual')
+ write_file('Xfiletype/actual/config', '')
+ uv.fs_symlink(assert(uv.fs_realpath('Xfiletype/actual')), 'Xfiletype/.config/git')
+ finally(function()
+ uv.fs_unlink('Xfiletype/.config/git')
+ end)
+ clear({ args = { '--clean', 'Xfiletype/.config/git/config' } })
+ eq('gitconfig', api.nvim_get_option_value('filetype', {}))
+ end)
end)
diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua
index 6821fe3c5e..aba02ab01b 100644
--- a/test/functional/lua/fs_spec.lua
+++ b/test/functional/lua/fs_spec.lua
@@ -1,16 +1,19 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local mkdir_p = helpers.mkdir_p
-local rmdir = helpers.rmdir
-local nvim_dir = helpers.nvim_dir
-local test_build_dir = helpers.paths.test_build_dir
-local test_source_path = helpers.paths.test_source_path
-local nvim_prog = helpers.nvim_prog
-local is_os = helpers.is_os
-local mkdir = helpers.mkdir
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local mkdir_p = n.mkdir_p
+local rmdir = n.rmdir
+local nvim_dir = n.nvim_dir
+local command = n.command
+local api = n.api
+local test_build_dir = t.paths.test_build_dir
+local test_source_path = t.paths.test_source_path
+local nvim_prog = n.nvim_prog
+local is_os = t.is_os
+local mkdir = t.mkdir
local nvim_prog_basename = is_os('win') and 'nvim.exe' or 'nvim'
@@ -36,6 +39,7 @@ local test_basename_dirname_eq = {
'c:/users/foo',
'c:/users/foo/bar.lua',
'c:/users/foo/bar/../',
+ '~/foo/bar\\baz',
}
local tests_windows_paths = {
@@ -54,7 +58,7 @@ describe('vim.fs', function()
it('works', function()
local test_dir = nvim_dir .. '/test'
mkdir_p(test_dir)
- local dirs = {}
+ local dirs = {} --- @type string[]
for dir in vim.fs.parents(test_dir .. '/foo.txt') do
dirs[#dirs + 1] = dir
if dir == test_build_dir then
@@ -70,25 +74,26 @@ describe('vim.fs', function()
it('works', function()
eq(test_build_dir, vim.fs.dirname(nvim_dir))
- local function test_paths(paths)
+ ---@param paths string[]
+ ---@param is_win? boolean
+ local function test_paths(paths, is_win)
+ local gsub = is_win and [[:gsub('\\', '/')]] or ''
+ local code = string.format(
+ [[
+ local path = ...
+ return vim.fn.fnamemodify(path,':h')%s
+ ]],
+ gsub
+ )
+
for _, path in ipairs(paths) do
- eq(
- exec_lua(
- [[
- local path = ...
- return vim.fn.fnamemodify(path,':h'):gsub('\\', '/')
- ]],
- path
- ),
- vim.fs.dirname(path),
- path
- )
+ eq(exec_lua(code, path), vim.fs.dirname(path), path)
end
end
test_paths(test_basename_dirname_eq)
if is_os('win') then
- test_paths(tests_windows_paths)
+ test_paths(tests_windows_paths, true)
end
end)
end)
@@ -97,25 +102,26 @@ describe('vim.fs', function()
it('works', function()
eq(nvim_prog_basename, vim.fs.basename(nvim_prog))
- local function test_paths(paths)
+ ---@param paths string[]
+ ---@param is_win? boolean
+ local function test_paths(paths, is_win)
+ local gsub = is_win and [[:gsub('\\', '/')]] or ''
+ local code = string.format(
+ [[
+ local path = ...
+ return vim.fn.fnamemodify(path,':t')%s
+ ]],
+ gsub
+ )
+
for _, path in ipairs(paths) do
- eq(
- exec_lua(
- [[
- local path = ...
- return vim.fn.fnamemodify(path,':t'):gsub('\\', '/')
- ]],
- path
- ),
- vim.fs.basename(path),
- path
- )
+ eq(exec_lua(code, path), vim.fs.basename(path), path)
end
end
test_paths(test_basename_dirname_eq)
if is_os('win') then
- test_paths(tests_windows_paths)
+ test_paths(tests_windows_paths, true)
end
end)
end)
@@ -274,6 +280,57 @@ describe('vim.fs', function()
end)
end)
+ describe('root()', function()
+ before_each(function()
+ command('edit test/functional/fixtures/tty-test.c')
+ end)
+
+ it('works with a single marker', function()
+ eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]]))
+ end)
+
+ it('works with multiple markers', function()
+ local bufnr = api.nvim_get_current_buf()
+ eq(
+ vim.fs.joinpath(test_source_path, 'test/functional/fixtures'),
+ exec_lua([[return vim.fs.root(..., {'CMakeLists.txt', '.git'})]], bufnr)
+ )
+ end)
+
+ it('works with a function', function()
+ ---@type string
+ local result = exec_lua([[
+ return vim.fs.root(0, function(name, path)
+ return name:match('%.txt$')
+ end)
+ ]])
+ eq(vim.fs.joinpath(test_source_path, 'test/functional/fixtures'), result)
+ end)
+
+ it('works with a filename argument', function()
+ eq(test_source_path, exec_lua([[return vim.fs.root(..., '.git')]], nvim_prog))
+ end)
+
+ it('works with a relative path', function()
+ eq(
+ test_source_path,
+ exec_lua([[return vim.fs.root(..., '.git')]], vim.fs.basename(nvim_prog))
+ )
+ end)
+
+ it('uses cwd for unnamed buffers', function()
+ command('new')
+ eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]]))
+ end)
+
+ it("uses cwd for buffers with non-empty 'buftype'", function()
+ command('new')
+ command('set buftype=nofile')
+ command('file lua://')
+ eq(test_source_path, exec_lua([[return vim.fs.root(0, '.git')]]))
+ end)
+ end)
+
describe('joinpath()', function()
it('works', function()
eq('foo/bar/baz', vim.fs.joinpath('foo', 'bar', 'baz'))
@@ -282,9 +339,6 @@ describe('vim.fs', function()
end)
describe('normalize()', function()
- it('works with backward slashes', function()
- eq('C:/Users/jdoe', vim.fs.normalize('C:\\Users\\jdoe'))
- end)
it('removes trailing /', function()
eq('/home/user', vim.fs.normalize('/home/user/'))
end)
@@ -292,7 +346,7 @@ describe('vim.fs', function()
eq('/', vim.fs.normalize('/'))
end)
it('works with ~', function()
- eq(vim.fs.normalize(vim.uv.os_homedir()) .. '/src/foo', vim.fs.normalize('~/src/foo'))
+ eq(vim.fs.normalize(assert(vim.uv.os_homedir())) .. '/src/foo', vim.fs.normalize('~/src/foo'))
end)
it('works with environment variables', function()
local xdg_config_home = test_build_dir .. '/.config'
@@ -307,10 +361,113 @@ describe('vim.fs', function()
)
)
end)
- if is_os('win') then
- it('Last slash is not truncated from root drive', function()
- eq('C:/', vim.fs.normalize('C:/'))
+
+ -- Opts required for testing posix paths and win paths
+ local posix_opts = is_os('win') and { win = false } or {}
+ local win_opts = is_os('win') and {} or { win = true }
+
+ it('preserves leading double slashes in POSIX paths', function()
+ eq('//foo', vim.fs.normalize('//foo', posix_opts))
+ eq('//foo/bar', vim.fs.normalize('//foo//bar////', posix_opts))
+ eq('/foo', vim.fs.normalize('///foo', posix_opts))
+ eq('//', vim.fs.normalize('//', posix_opts))
+ eq('/', vim.fs.normalize('///', posix_opts))
+ eq('/foo/bar', vim.fs.normalize('/foo//bar////', posix_opts))
+ end)
+
+ it('allows backslashes on unix-based os', function()
+ eq('/home/user/hello\\world', vim.fs.normalize('/home/user/hello\\world', posix_opts))
+ end)
+
+ it('preserves / after drive letters', function()
+ eq('C:/', vim.fs.normalize([[C:\]], win_opts))
+ end)
+
+ it('works with UNC and DOS device paths', function()
+ eq('//server/share/foo/bar', vim.fs.normalize([[\\server\\share\\\foo\bar\\\]], win_opts))
+ eq('//system07/C$/', vim.fs.normalize([[\\system07\C$\\\\]], win_opts))
+ eq('//./C:/foo/bar', vim.fs.normalize([[\\.\\C:\foo\\\\bar]], win_opts))
+ eq('//?/C:/foo/bar', vim.fs.normalize([[\\?\C:\\\foo\bar\\\\]], win_opts))
+ eq(
+ '//?/UNC/server/share/foo/bar',
+ vim.fs.normalize([[\\?\UNC\server\\\share\\\\foo\\\bar]], win_opts)
+ )
+ eq('//./BootPartition/foo/bar', vim.fs.normalize([[\\.\BootPartition\\foo\bar]], win_opts))
+ eq(
+ '//./Volume{12345678-1234-1234-1234-1234567890AB}/foo/bar',
+ vim.fs.normalize([[\\.\Volume{12345678-1234-1234-1234-1234567890AB}\\\foo\bar\\]], win_opts)
+ )
+ end)
+
+ it('handles invalid UNC and DOS device paths', function()
+ eq('//server/share', vim.fs.normalize([[\\server\share]], win_opts))
+ eq('//server/', vim.fs.normalize([[\\server\]], win_opts))
+ eq('//./UNC/server/share', vim.fs.normalize([[\\.\UNC\server\share]], win_opts))
+ eq('//?/UNC/server/', vim.fs.normalize([[\\?\UNC\server\]], win_opts))
+ eq('//?/UNC/server/..', vim.fs.normalize([[\\?\UNC\server\..]], win_opts))
+ eq('//./', vim.fs.normalize([[\\.\]], win_opts))
+ eq('//./foo', vim.fs.normalize([[\\.\foo]], win_opts))
+ eq('//./BootPartition', vim.fs.normalize([[\\.\BootPartition]], win_opts))
+ end)
+
+ it('converts backward slashes', function()
+ eq('C:/Users/jdoe', vim.fs.normalize([[C:\Users\jdoe]], win_opts))
+ end)
+
+ describe('. and .. component resolving', function()
+ it('works', function()
+ -- Windows paths
+ eq('C:/Users', vim.fs.normalize([[C:\Users\jdoe\Downloads\.\..\..\]], win_opts))
+ eq('C:/Users/jdoe', vim.fs.normalize([[C:\Users\jdoe\Downloads\.\..\.\.\]], win_opts))
+ eq('C:/', vim.fs.normalize('C:/Users/jdoe/Downloads/./../../../', win_opts))
+ eq('C:foo', vim.fs.normalize([[C:foo\bar\.\..\.]], win_opts))
+ -- POSIX paths
+ eq('/home', vim.fs.normalize('/home/jdoe/Downloads/./../..', posix_opts))
+ eq('/home/jdoe', vim.fs.normalize('/home/jdoe/Downloads/./../././', posix_opts))
+ eq('/', vim.fs.normalize('/home/jdoe/Downloads/./../../../', posix_opts))
+ -- OS-agnostic relative paths
+ eq('foo/bar/baz', vim.fs.normalize('foo/bar/foobar/../baz/./'))
+ eq('foo/bar', vim.fs.normalize('foo/bar/foobar/../baz/./../../bar/./.'))
end)
- end
+
+ it('works when relative path reaches current directory', function()
+ eq('C:', vim.fs.normalize('C:foo/bar/../../.', win_opts))
+
+ eq('.', vim.fs.normalize('.'))
+ eq('.', vim.fs.normalize('././././'))
+ eq('.', vim.fs.normalize('foo/bar/../../.'))
+ end)
+
+ it('works when relative path goes outside current directory', function()
+ eq('../../foo/bar', vim.fs.normalize('../../foo/bar'))
+ eq('../foo', vim.fs.normalize('foo/bar/../../../foo'))
+
+ eq('C:../foo', vim.fs.normalize('C:../foo', win_opts))
+ eq('C:../../foo/bar', vim.fs.normalize('C:foo/../../../foo/bar', win_opts))
+ end)
+
+ it('.. in root directory resolves to itself', function()
+ eq('C:/', vim.fs.normalize('C:/../../', win_opts))
+ eq('C:/foo', vim.fs.normalize('C:/foo/../../foo', win_opts))
+
+ eq('//server/share/', vim.fs.normalize([[\\server\share\..\..]], win_opts))
+ eq('//server/share/foo', vim.fs.normalize([[\\server\\share\foo\..\..\foo]], win_opts))
+
+ eq('//./C:/', vim.fs.normalize([[\\.\C:\..\..]], win_opts))
+ eq('//?/C:/foo', vim.fs.normalize([[\\?\C:\..\..\foo]], win_opts))
+
+ eq('//./UNC/server/share/', vim.fs.normalize([[\\.\UNC\\server\share\..\..\]], win_opts))
+ eq(
+ '//?/UNC/server/share/foo',
+ vim.fs.normalize([[\\?\UNC\server\\share\..\..\foo]], win_opts)
+ )
+
+ eq('//?/BootPartition/', vim.fs.normalize([[\\?\BootPartition\..\..]], win_opts))
+ eq('//./BootPartition/foo', vim.fs.normalize([[\\.\BootPartition\..\..\foo]], win_opts))
+
+ eq('/', vim.fs.normalize('/../../', posix_opts))
+ eq('/foo', vim.fs.normalize('/foo/../../foo', posix_opts))
+ end)
+ end)
end)
end)
diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua
index 1eac037575..56cd4c9bb5 100644
--- a/test/functional/lua/glob_spec.lua
+++ b/test/functional/lua/glob_spec.lua
@@ -1,10 +1,12 @@
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local eq = t.eq
+local exec_lua = n.exec_lua
describe('glob', function()
- before_each(helpers.clear)
- after_each(helpers.clear)
+ before_each(n.clear)
+ after_each(n.clear)
local match = function(...)
return exec_lua(
diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua
index 197f3139f3..c9f2d0a47f 100644
--- a/test/functional/lua/highlight_spec.lua
+++ b/test/functional/lua/highlight_spec.lua
@@ -1,11 +1,13 @@
-local helpers = require('test.functional.helpers')(after_each)
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local neq = helpers.neq
-local eval = helpers.eval
-local command = helpers.command
-local clear = helpers.clear
-local api = helpers.api
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+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
+local api = n.api
describe('vim.highlight.on_yank', function()
before_each(function()
@@ -19,7 +21,7 @@ describe('vim.highlight.on_yank', function()
vim.cmd('bwipeout!')
]])
vim.uv.sleep(10)
- helpers.feed('<cr>') -- avoid hang if error message exists
+ n.feed('<cr>') -- avoid hang if error message exists
eq('', eval('v:errmsg'))
end)
@@ -41,9 +43,9 @@ 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))
+ neq({}, api.nvim__win_get_ns(0))
command('wincmd w')
- eq({}, api.nvim_win_get_ns(0))
+ eq({}, api.nvim__win_get_ns(0))
end)
it('removes old highlight if new one is created before old one times out', function()
@@ -53,7 +55,7 @@ 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))
+ neq({}, api.nvim__win_get_ns(0))
command('wincmd w')
exec_lua([[
vim.api.nvim_buf_set_mark(0,"[",1,1,{})
@@ -61,6 +63,6 @@ describe('vim.highlight.on_yank', function()
vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
]])
command('wincmd w')
- eq({}, api.nvim_win_get_ns(0))
+ eq({}, api.nvim__win_get_ns(0))
end)
end)
diff --git a/test/functional/lua/inspector_spec.lua b/test/functional/lua/inspector_spec.lua
index ad8b5a45a8..8fadba6ee8 100644
--- a/test/functional/lua/inspector_spec.lua
+++ b/test/functional/lua/inspector_spec.lua
@@ -1,8 +1,10 @@
-local helpers = require('test.functional.helpers')(after_each)
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local eval = helpers.eval
-local clear = helpers.clear
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local exec_lua = n.exec_lua
+local eq = t.eq
+local eval = n.eval
+local clear = n.clear
describe('vim.inspect_pos', function()
before_each(function()
diff --git a/test/functional/lua/iter_spec.lua b/test/functional/lua/iter_spec.lua
index 8d6cf1264b..79e92e6a7d 100644
--- a/test/functional/lua/iter_spec.lua
+++ b/test/functional/lua/iter_spec.lua
@@ -1,7 +1,8 @@
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local matches = helpers.matches
-local pcall_err = helpers.pcall_err
+local t = require('test.testutil')
+
+local eq = t.eq
+local matches = t.matches
+local pcall_err = t.pcall_err
describe('vim.iter', function()
it('new() on iterable class instance', function()
@@ -18,12 +19,12 @@ describe('vim.iter', function()
return v % 2 ~= 0
end
- local t = { 1, 2, 3, 4, 5 }
- eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable())
+ local q = { 1, 2, 3, 4, 5 }
+ eq({ 1, 3, 5 }, vim.iter(q):filter(odd):totable())
eq(
{ 2, 4 },
vim
- .iter(t)
+ .iter(q)
:filter(function(v)
return not odd(v)
end)
@@ -32,7 +33,7 @@ describe('vim.iter', function()
eq(
{},
vim
- .iter(t)
+ .iter(q)
:filter(function(v)
return v > 5
end)
@@ -40,7 +41,7 @@ describe('vim.iter', function()
)
do
- local it = vim.iter(ipairs(t))
+ local it = vim.iter(ipairs(q))
it:filter(function(i, v)
return i > 1 and v < 5
end)
@@ -60,11 +61,11 @@ describe('vim.iter', function()
end)
it('map()', function()
- local t = { 1, 2, 3, 4, 5 }
+ local q = { 1, 2, 3, 4, 5 }
eq(
{ 2, 4, 6, 8, 10 },
vim
- .iter(t)
+ .iter(q)
:map(function(v)
return 2 * v
end)
@@ -96,10 +97,10 @@ describe('vim.iter', function()
end)
it('for loops', function()
- local t = { 1, 2, 3, 4, 5 }
+ local q = { 1, 2, 3, 4, 5 }
local acc = 0
for v in
- vim.iter(t):map(function(v)
+ vim.iter(q):map(function(v)
return v * 3
end)
do
@@ -116,6 +117,9 @@ describe('vim.iter', function()
eq({ { 1, 1 }, { 2, 4 }, { 3, 9 } }, it:totable())
end
+ -- Holes in array-like tables are removed
+ eq({ 1, 2, 3 }, vim.iter({ 1, nil, 2, nil, 3 }):totable())
+
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())
@@ -141,18 +145,18 @@ describe('vim.iter', 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))
+ matches('rev%(%) requires an array%-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())
+ local q = { 4, 3, 2, 1 }
+ eq(q, vim.iter(q):skip(0):totable())
+ eq({ 3, 2, 1 }, vim.iter(q):skip(1):totable())
+ eq({ 2, 1 }, vim.iter(q):skip(2):totable())
+ eq({ 1 }, vim.iter(q):skip(#q - 1):totable())
+ eq({}, vim.iter(q):skip(#q):totable())
+ eq({}, vim.iter(q):skip(#q + 1):totable())
end
do
@@ -168,44 +172,44 @@ describe('vim.iter', function()
end
end)
- it('skipback()', function()
+ it('rskip()', 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())
+ local q = { 4, 3, 2, 1 }
+ eq(q, vim.iter(q):rskip(0):totable())
+ eq({ 4, 3, 2 }, vim.iter(q):rskip(1):totable())
+ eq({ 4, 3 }, vim.iter(q):rskip(2):totable())
+ eq({ 4 }, vim.iter(q):rskip(#q - 1):totable())
+ eq({}, vim.iter(q):rskip(#q):totable())
+ eq({}, vim.iter(q):rskip(#q + 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))
+ matches('rskip%(%) requires an array%-like table', pcall_err(it.rskip, 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())
+ local q = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
+ eq({ 3, 4, 5, 6, 7 }, vim.iter(q):slice(3, 7):totable())
+ eq({}, vim.iter(q):slice(6, 5):totable())
+ eq({}, vim.iter(q):slice(0, 0):totable())
+ eq({ 1 }, vim.iter(q):slice(1, 1):totable())
+ eq({ 1, 2 }, vim.iter(q):slice(1, 2):totable())
+ eq({ 10 }, vim.iter(q):slice(10, 10):totable())
+ eq({ 8, 9, 10 }, vim.iter(q):slice(8, 11):totable())
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
- matches('slice%(%) requires a list%-like table', pcall_err(it.slice, it, 1, 3))
+ matches('slice%(%) requires an array%-like table', pcall_err(it.slice, it, 1, 3))
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))
+ local q = { 4, 3, 2, 1 }
+ eq(nil, vim.iter(q):nth(0))
+ eq(4, vim.iter(q):nth(1))
+ eq(3, vim.iter(q):nth(2))
+ eq(2, vim.iter(q):nth(3))
+ eq(1, vim.iter(q):nth(4))
+ eq(nil, vim.iter(q):nth(5))
end
do
@@ -221,35 +225,41 @@ describe('vim.iter', function()
end
end)
- it('nthback()', function()
+ it('nth(-x) advances in reverse order starting from end', 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))
+ local q = { 4, 3, 2, 1 }
+ eq(nil, vim.iter(q):nth(0))
+ eq(1, vim.iter(q):nth(-1))
+ eq(2, vim.iter(q):nth(-2))
+ eq(3, vim.iter(q):nth(-3))
+ eq(4, vim.iter(q):nth(-4))
+ eq(nil, vim.iter(q):nth(-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))
+ matches('rskip%(%) requires an array%-like table', pcall_err(it.nth, it, -1))
end)
it('take()', function()
do
- local t = { 4, 3, 2, 1 }
- eq({}, vim.iter(t):take(0):totable())
- eq({ 4 }, vim.iter(t):take(1):totable())
- eq({ 4, 3 }, vim.iter(t):take(2):totable())
- eq({ 4, 3, 2 }, vim.iter(t):take(3):totable())
- eq({ 4, 3, 2, 1 }, vim.iter(t):take(4):totable())
- eq({ 4, 3, 2, 1 }, vim.iter(t):take(5):totable())
+ local q = { 4, 3, 2, 1 }
+ eq({}, vim.iter(q):take(0):totable())
+ eq({ 4 }, vim.iter(q):take(1):totable())
+ eq({ 4, 3 }, vim.iter(q):take(2):totable())
+ eq({ 4, 3, 2 }, vim.iter(q):take(3):totable())
+ eq({ 4, 3, 2, 1 }, vim.iter(q):take(4):totable())
+ eq({ 4, 3, 2, 1 }, vim.iter(q):take(5):totable())
+ end
+
+ do
+ local q = { 4, 3, 2, 1 }
+ eq({ 1, 2, 3 }, vim.iter(q):rev():take(3):totable())
+ eq({ 2, 3, 4 }, vim.iter(q):take(3):rev():totable())
end
do
- local t = { 4, 3, 2, 1 }
- local it = vim.iter(t)
+ local q = { 4, 3, 2, 1 }
+ local it = vim.iter(q)
eq({ 4, 3 }, it:take(2):totable())
-- tail is already set from the previous take()
eq({ 4, 3 }, it:take(3):totable())
@@ -269,13 +279,13 @@ describe('vim.iter', function()
end
do
- local t = { 4, 8, 9, 10 }
- eq(true, vim.iter(t):any(odd))
+ local q = { 4, 8, 9, 10 }
+ eq(true, vim.iter(q):any(odd))
end
do
- local t = { 4, 8, 10 }
- eq(false, vim.iter(t):any(odd))
+ local q = { 4, 8, 10 }
+ eq(false, vim.iter(q):any(odd))
end
do
@@ -300,13 +310,13 @@ describe('vim.iter', function()
end
do
- local t = { 3, 5, 7, 9 }
- eq(true, vim.iter(t):all(odd))
+ local q = { 3, 5, 7, 9 }
+ eq(true, vim.iter(q):all(odd))
end
do
- local t = { 3, 5, 7, 10 }
- eq(false, vim.iter(t):all(odd))
+ local q = { 3, 5, 7, 10 }
+ eq(false, vim.iter(q):all(odd))
end
do
@@ -349,23 +359,23 @@ describe('vim.iter', function()
do
local it = vim.iter(vim.gsplit('hi', ''))
- matches('peek%(%) requires a list%-like table', pcall_err(it.peek, it))
+ matches('peek%(%) requires an array%-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))
+ local q = { 3, 6, 9, 12 }
+ eq(12, vim.iter(q):find(12))
+ eq(nil, vim.iter(q):find(15))
eq(
12,
- vim.iter(t):find(function(v)
+ vim.iter(q):find(function(v)
return v % 4 == 0
end)
)
do
- local it = vim.iter(t)
+ local it = vim.iter(q)
local pred = function(v)
return v % 3 == 0
end
@@ -389,16 +399,16 @@ describe('vim.iter', function()
end)
it('rfind()', function()
- local t = { 1, 2, 3, 2, 1 }
+ local q = { 1, 2, 3, 2, 1 }
do
- local it = vim.iter(t)
+ local it = vim.iter(q)
eq(1, it:rfind(1))
eq(1, it:rfind(1))
eq(nil, it:rfind(1))
end
do
- local it = vim.iter(t):enumerate()
+ local it = vim.iter(q):enumerate()
local pred = function(i)
return i % 2 ~= 0
end
@@ -410,52 +420,52 @@ describe('vim.iter', function()
do
local it = vim.iter(vim.gsplit('AbCdE', ''))
- matches('rfind%(%) requires a list%-like table', pcall_err(it.rfind, it, 'E'))
+ matches('rfind%(%) requires an array%-like table', pcall_err(it.rfind, it, 'E'))
end
end)
- it('nextback()', function()
+ it('pop()', 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())
+ eq(4, it:pop())
+ eq(3, it:pop())
+ eq(2, it:pop())
+ eq(1, it:pop())
+ eq(nil, it:pop())
+ eq(nil, it:pop())
end
do
local it = vim.iter(vim.gsplit('hi', ''))
- matches('nextback%(%) requires a list%-like table', pcall_err(it.nextback, it))
+ matches('pop%(%) requires an array%-like table', pcall_err(it.pop, it))
end
end)
- it('peekback()', function()
+ it('rpeek()', function()
do
local it = vim.iter({ 1, 2, 3, 4 })
- eq(4, it:peekback())
- eq(4, it:peekback())
- eq(4, it:nextback())
+ eq(4, it:rpeek())
+ eq(4, it:rpeek())
+ eq(4, it:pop())
end
do
local it = vim.iter(vim.gsplit('hi', ''))
- matches('peekback%(%) requires a list%-like table', pcall_err(it.peekback, it))
+ matches('rpeek%(%) requires an array%-like table', pcall_err(it.rpeek, it))
end
end)
it('fold()', function()
- local t = { 1, 2, 3, 4, 5 }
+ local q = { 1, 2, 3, 4, 5 }
eq(
115,
- vim.iter(t):fold(100, function(acc, v)
+ vim.iter(q):fold(100, function(acc, v)
return acc + v
end)
)
eq(
{ 5, 4, 3, 2, 1 },
- vim.iter(t):fold({}, function(acc, v)
+ vim.iter(q):fold({}, function(acc, v)
table.insert(acc, 1, v)
return acc
end)
@@ -463,30 +473,32 @@ describe('vim.iter', function()
end)
it('flatten()', function()
- local t = { { 1, { 2 } }, { { { { 3 } } }, { 4 } }, { 5 } }
+ local q = { { 1, { 2 } }, { { { { 3 } } }, { 4 } }, { 5 } }
- eq(t, vim.iter(t):flatten(-1):totable())
- eq(t, vim.iter(t):flatten(0):totable())
- eq({ 1, { 2 }, { { { 3 } } }, { 4 }, 5 }, vim.iter(t):flatten():totable())
- eq({ 1, 2, { { 3 } }, 4, 5 }, vim.iter(t):flatten(2):totable())
- eq({ 1, 2, { 3 }, 4, 5 }, vim.iter(t):flatten(3):totable())
- eq({ 1, 2, 3, 4, 5 }, vim.iter(t):flatten(4):totable())
+ eq(q, vim.iter(q):flatten(-1):totable())
+ eq(q, vim.iter(q):flatten(0):totable())
+ eq({ 1, { 2 }, { { { 3 } } }, { 4 }, 5 }, vim.iter(q):flatten():totable())
+ eq({ 1, 2, { { 3 } }, 4, 5 }, vim.iter(q):flatten(2):totable())
+ eq({ 1, 2, { 3 }, 4, 5 }, vim.iter(q):flatten(3):totable())
+ eq({ 1, 2, 3, 4, 5 }, vim.iter(q):flatten(4):totable())
local m = { a = 1, b = { 2, 3 }, d = { 4 } }
local it = vim.iter(m)
- local flat_err = 'flatten%(%) requires a list%-like table'
+ local flat_err = 'flatten%(%) requires an array%-like table'
matches(flat_err, pcall_err(it.flatten, it))
-- cases from the documentation
local simple_example = { 1, { 2 }, { { 3 } } }
eq({ 1, 2, { 3 } }, vim.iter(simple_example):flatten():totable())
- local not_list_like = vim.iter({ [2] = 2 })
- matches(flat_err, pcall_err(not_list_like.flatten, not_list_like))
+ local not_list_like = { [2] = 2 }
+ eq({ 2 }, vim.iter(not_list_like):flatten():totable())
+
+ local also_not_list_like = { nil, 2 }
+ eq({ 2 }, vim.iter(also_not_list_like):flatten():totable())
- local also_not_list_like = vim.iter({ nil, 2 })
- matches(flat_err, pcall_err(not_list_like.flatten, also_not_list_like))
+ eq({ 1, 2, 3 }, vim.iter({ nil, { 1, nil, 2 }, 3 }):flatten():totable())
local nested_non_lists = vim.iter({ 1, { { a = 2 } }, { { nil } }, { 3 } })
eq({ 1, { a = 2 }, { nil }, 3 }, nested_non_lists:flatten():totable())
@@ -501,11 +513,11 @@ describe('vim.iter', function()
end
end)
- local t = it:fold({}, function(t, k, v)
- t[k] = v
- return t
+ local q = it:fold({}, function(q, k, v)
+ q[k] = v
+ return q
end)
- eq({ A = 2, C = 6 }, t)
+ eq({ A = 2, C = 6 }, q)
end)
it('handles table values mid-pipeline', function()
diff --git a/test/functional/lua/json_spec.lua b/test/functional/lua/json_spec.lua
index d348e2de3c..a6e814d739 100644
--- a/test/functional/lua/json_spec.lua
+++ b/test/functional/lua/json_spec.lua
@@ -1,8 +1,10 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local pcall_err = helpers.pcall_err
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local pcall_err = t.pcall_err
describe('vim.json.decode()', function()
before_each(function()
@@ -30,6 +32,18 @@ describe('vim.json.decode()', function()
baz = vim.NIL,
foo = { a = 'b' },
}, exec_lua([[return vim.json.decode(..., {})]], jsonstr))
+ eq(
+ {
+ arr = { 1, 2, vim.NIL },
+ bar = { 3, 7 },
+ baz = vim.NIL,
+ foo = { a = 'b' },
+ },
+ exec_lua(
+ [[return vim.json.decode(..., { luanil = { array = false, object = false } })]],
+ jsonstr
+ )
+ )
eq({
arr = { 1, 2, vim.NIL },
bar = { 3, 7 },
diff --git a/test/functional/lua/loader_spec.lua b/test/functional/lua/loader_spec.lua
index 4e42a18405..f13e6664c5 100644
--- a/test/functional/lua/loader_spec.lua
+++ b/test/functional/lua/loader_spec.lua
@@ -1,10 +1,11 @@
-- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local exec_lua = helpers.exec_lua
-local command = helpers.command
-local clear = helpers.clear
-local eq = helpers.eq
+local exec_lua = n.exec_lua
+local command = n.command
+local clear = n.clear
+local eq = t.eq
describe('vim.loader', function()
before_each(clear)
@@ -35,7 +36,7 @@ describe('vim.loader', function()
vim.loader.enable()
]]
- local tmp = helpers.tmpname()
+ local tmp = t.tmpname()
command('edit ' .. tmp)
eq(
@@ -73,15 +74,15 @@ describe('vim.loader', function()
vim.loader.enable()
]]
- local tmp1, tmp2 = (function(t)
- assert(os.remove(t))
- assert(helpers.mkdir(t))
- assert(helpers.mkdir(t .. '/%'))
- return t .. '/%/x', t .. '/%%x'
- end)(helpers.tmpname())
+ local tmp = t.tmpname()
+ assert(os.remove(tmp))
+ assert(t.mkdir(tmp))
+ assert(t.mkdir(tmp .. '/%'))
+ local tmp1 = tmp .. '/%/x'
+ local tmp2 = tmp .. '/%%x'
- helpers.write_file(tmp1, 'return 1', true)
- helpers.write_file(tmp2, 'return 2', true)
+ t.write_file(tmp1, 'return 1', true)
+ t.write_file(tmp2, 'return 2', true)
vim.uv.fs_utime(tmp1, 0, 0)
vim.uv.fs_utime(tmp2, 0, 0)
eq(1, exec_lua('return loadfile(...)()', tmp1))
diff --git a/test/functional/lua/loop_spec.lua b/test/functional/lua/loop_spec.lua
index 71eaf29009..566a171a84 100644
--- a/test/functional/lua/loop_spec.lua
+++ b/test/functional/lua/loop_spec.lua
@@ -1,16 +1,18 @@
-- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local fn = helpers.fn
-local api = helpers.api
-local clear = helpers.clear
+
+local fn = n.fn
+local api = n.api
+local clear = n.clear
local sleep = vim.uv.sleep
-local feed = helpers.feed
-local eq = helpers.eq
-local eval = helpers.eval
-local matches = helpers.matches
-local exec_lua = helpers.exec_lua
-local retry = helpers.retry
+local feed = n.feed
+local eq = t.eq
+local eval = n.eval
+local matches = t.matches
+local exec_lua = n.exec_lua
+local retry = t.retry
before_each(clear)
@@ -131,6 +133,20 @@ describe('vim.uv', function()
{5:-- INSERT --} |
]])
eq({ blocking = false, mode = 'n' }, exec_lua('return _G.mode'))
+
+ exec_lua([[
+ local timer = vim.uv.new_timer()
+ timer:start(20, 0, function ()
+ _G.is_fast = vim.in_fast_event()
+ timer:close()
+ _G.value = vim.fn.has("nvim-0.5")
+ _G.unvalue = vim.fn.has("python3")
+ end)
+ ]])
+
+ screen:expect({ any = [[{3:Vim:E5560: Vimscript function must not be called i}]] })
+ feed('<cr>')
+ eq({ 1, nil }, exec_lua('return {_G.value, _G.unvalue}'))
end)
it("is equal to require('luv')", function()
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index b28cfa4dd2..3f62cd8325 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -1,19 +1,20 @@
-- Test suite for testing luaeval() function
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local pcall_err = helpers.pcall_err
-local exc_exec = helpers.exc_exec
-local remove_trace = helpers.remove_trace
-local exec_lua = helpers.exec_lua
-local command = helpers.command
-local api = helpers.api
-local fn = helpers.fn
-local clear = helpers.clear
-local eval = helpers.eval
-local feed = helpers.feed
+local pcall_err = t.pcall_err
+local exc_exec = n.exc_exec
+local remove_trace = t.remove_trace
+local exec_lua = n.exec_lua
+local command = n.command
+local api = n.api
+local fn = n.fn
+local clear = n.clear
+local eval = n.eval
+local feed = n.feed
local NIL = vim.NIL
-local eq = helpers.eq
+local eq = t.eq
before_each(clear)
@@ -38,8 +39,8 @@ describe('luaeval()', function()
describe('second argument', function()
it('is successfully received', function()
- local t = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}}
- eq(t, fn.luaeval("_A", t))
+ local q = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}}
+ eq(q, fn.luaeval("_A", q))
-- Not tested: nil, funcrefs, returned object identity: behaviour will
-- most likely change.
end)
diff --git a/test/functional/lua/mpack_spec.lua b/test/functional/lua/mpack_spec.lua
index 0b6a6d60bd..efd69d4607 100644
--- a/test/functional/lua/mpack_spec.lua
+++ b/test/functional/lua/mpack_spec.lua
@@ -1,9 +1,10 @@
-- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
-local clear = helpers.clear
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
+local clear = n.clear
+local eq = t.eq
+local exec_lua = n.exec_lua
describe('lua vim.mpack', function()
before_each(clear)
@@ -22,7 +23,7 @@ describe('lua vim.mpack', function()
{ { {}, 'foo', {} }, true, false },
exec_lua [[
local var = vim.mpack.decode(vim.mpack.encode({{}, "foo", vim.empty_dict()}))
- return {var, vim.tbl_islist(var[1]), vim.tbl_islist(var[3])}
+ return {var, vim.islist(var[1]), vim.islist(var[3])}
]]
)
end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index ecbdde3bfd..849978f080 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -1,19 +1,20 @@
-- Test for Vim overrides of lua built-ins
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local eq = helpers.eq
+local eq = t.eq
local NIL = vim.NIL
-local feed = helpers.feed
-local clear = helpers.clear
-local fn = helpers.fn
-local api = helpers.api
-local command = helpers.command
-local write_file = helpers.write_file
-local exec_capture = helpers.exec_capture
-local exec_lua = helpers.exec_lua
-local pcall_err = helpers.pcall_err
-local is_os = helpers.is_os
+local feed = n.feed
+local clear = n.clear
+local fn = n.fn
+local api = n.api
+local command = n.command
+local write_file = t.write_file
+local exec_capture = n.exec_capture
+local exec_lua = n.exec_lua
+local pcall_err = t.pcall_err
+local is_os = t.is_os
local fname = 'Xtest-functional-lua-overrides-luafile'
@@ -195,7 +196,7 @@ describe('print', function()
end)
describe('debug.debug', function()
- local screen
+ local screen --- @type test.functional.ui.screen
before_each(function()
screen = Screen.new()
diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua
index 6f36ccfb9e..4adce42c3e 100644
--- a/test/functional/lua/runtime_spec.lua
+++ b/test/functional/lua/runtime_spec.lua
@@ -1,17 +1,18 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local clear = helpers.clear
-local eq = helpers.eq
-local eval = helpers.eval
-local exec = helpers.exec
-local fn = helpers.fn
-local mkdir_p = helpers.mkdir_p
-local rmdir = helpers.rmdir
-local write_file = helpers.write_file
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local eq = t.eq
+local eval = n.eval
+local exec = n.exec
+local fn = n.fn
+local mkdir_p = n.mkdir_p
+local rmdir = n.rmdir
+local write_file = t.write_file
describe('runtime:', function()
local plug_dir = 'Test_Plugin'
- local sep = helpers.get_pathsep()
+ local sep = n.get_pathsep()
local init = 'dummy_init.lua'
setup(function()
diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua
index 7aed711b23..c58fd689b7 100644
--- a/test/functional/lua/secure_spec.lua
+++ b/test/functional/lua/secure_spec.lua
@@ -1,18 +1,21 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local eq = helpers.eq
-local clear = helpers.clear
-local command = helpers.command
-local pathsep = helpers.get_pathsep()
-local is_os = helpers.is_os
-local api = helpers.api
-local exec_lua = helpers.exec_lua
-local feed_command = helpers.feed_command
-local feed = helpers.feed
-local fn = helpers.fn
-local pcall_err = helpers.pcall_err
-local matches = helpers.matches
+local eq = t.eq
+local clear = n.clear
+local command = n.command
+local pathsep = n.get_pathsep()
+local is_os = t.is_os
+local api = n.api
+local exec_lua = n.exec_lua
+local feed_command = n.feed_command
+local feed = n.feed
+local fn = n.fn
+local stdpath = fn.stdpath
+local pcall_err = t.pcall_err
+local matches = t.matches
+local read_file = t.read_file
describe('vim.secure', function()
describe('read()', function()
@@ -20,8 +23,8 @@ describe('vim.secure', function()
setup(function()
clear { env = { XDG_STATE_HOME = xstate } }
- helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
- helpers.write_file(
+ n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
+ t.write_file(
'Xfile',
[[
let g:foobar = 42
@@ -31,7 +34,7 @@ describe('vim.secure', function()
teardown(function()
os.remove('Xfile')
- helpers.rmdir(xstate)
+ n.rmdir(xstate)
end)
it('works', function()
@@ -71,11 +74,11 @@ describe('vim.secure', function()
]],
}
- local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ local trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust))
eq(vim.NIL, exec_lua([[return vim.secure.read('Xfile')]]))
- os.remove(fn.stdpath('state') .. pathsep .. 'trust')
+ os.remove(stdpath('state') .. pathsep .. 'trust')
feed_command([[lua vim.secure.read('Xfile')]])
screen:expect {
@@ -100,12 +103,12 @@ describe('vim.secure', function()
]],
}
- local hash = fn.sha256(helpers.read_file('Xfile'))
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ local hash = fn.sha256(read_file('Xfile'))
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust))
eq(vim.NIL, exec_lua([[vim.secure.read('Xfile')]]))
- os.remove(fn.stdpath('state') .. pathsep .. 'trust')
+ os.remove(stdpath('state') .. pathsep .. 'trust')
feed_command([[lua vim.secure.read('Xfile')]])
screen:expect {
@@ -131,7 +134,7 @@ describe('vim.secure', function()
}
-- Trust database is not updated
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(nil, trust)
feed_command([[lua vim.secure.read('Xfile')]])
@@ -165,7 +168,7 @@ describe('vim.secure', function()
}
-- Trust database is not updated
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(nil, trust)
-- Cannot write file
@@ -179,15 +182,15 @@ describe('vim.secure', function()
setup(function()
clear { env = { XDG_STATE_HOME = xstate } }
- helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
+ n.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
end)
teardown(function()
- helpers.rmdir(xstate)
+ n.rmdir(xstate)
end)
before_each(function()
- helpers.write_file('test_file', 'test')
+ t.write_file('test_file', 'test')
end)
after_each(function()
@@ -210,70 +213,70 @@ describe('vim.secure', function()
it('trust then deny then remove a file using bufnr', function()
local cwd = fn.getcwd()
- local hash = fn.sha256(helpers.read_file('test_file'))
+ local hash = fn.sha256(read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ local trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('deny then trust then remove a file using bufnr', function()
local cwd = fn.getcwd()
- local hash = fn.sha256(helpers.read_file('test_file'))
+ local hash = fn.sha256(read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
- local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ local trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('trust using bufnr then deny then remove a file using path', function()
local cwd = fn.getcwd()
- local hash = fn.sha256(helpers.read_file('test_file'))
+ local hash = fn.sha256(read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ local trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
eq(
{ true, full_path },
exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]])
)
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
eq(
{ true, full_path },
exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]])
)
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('deny then trust then remove a file using bufnr', function()
local cwd = fn.getcwd()
- local hash = fn.sha256(helpers.read_file('test_file'))
+ local hash = fn.sha256(read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
@@ -281,18 +284,18 @@ describe('vim.secure', function()
{ true, full_path },
exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]])
)
- local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ local trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
eq(
{ true, full_path },
exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]])
)
- trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
+ trust = read_file(stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
diff --git a/test/functional/lua/snippet_spec.lua b/test/functional/lua/snippet_spec.lua
index e981bc6261..413aa93994 100644
--- a/test/functional/lua/snippet_spec.lua
+++ b/test/functional/lua/snippet_spec.lua
@@ -1,15 +1,17 @@
-local helpers = require('test.functional.helpers')(after_each)
-
-local buf_lines = helpers.buf_lines
-local clear = helpers.clear
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local feed = helpers.feed
-local fn = helpers.fn
-local matches = helpers.matches
-local pcall_err = helpers.pcall_err
-local poke_eventloop = helpers.poke_eventloop
-local retry = helpers.retry
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local buf_lines = n.buf_lines
+local clear = n.clear
+local eq = t.eq
+local exec_lua = n.exec_lua
+local feed = n.feed
+local api = n.api
+local fn = n.fn
+local matches = t.matches
+local pcall_err = t.pcall_err
+local poke_eventloop = n.poke_eventloop
+local retry = t.retry
describe('vim.snippet', function()
before_each(function()
@@ -95,9 +97,9 @@ describe('vim.snippet', function()
it('does not jump outside snippet range', function()
test_expand_success({ 'function $1($2)', ' $0', 'end' }, { 'function ()', ' ', 'end' })
- eq(false, exec_lua('return vim.snippet.jumpable(-1)'))
+ eq(false, exec_lua('return vim.snippet.active({ direction = -1 })'))
feed('<Tab><Tab>i')
- eq(false, exec_lua('return vim.snippet.jumpable(1)'))
+ eq(false, exec_lua('return vim.snippet.active( { direction = 1 })'))
end)
it('navigates backwards', function()
@@ -230,7 +232,7 @@ describe('vim.snippet', function()
end)
it('updates snippet state when built-in completion menu is visible', function()
- test_expand_success({ '$1 = function($2)\n$3\nend' }, { ' = function()', '', 'end' })
+ test_expand_success({ '$1 = function($2)\nend' }, { ' = function()', 'end' })
-- Show the completion menu.
feed('<C-n>')
-- Make sure no item is selected.
@@ -238,6 +240,50 @@ describe('vim.snippet', function()
-- Jump forward (the 2nd tabstop).
exec_lua('vim.snippet.jump(1)')
feed('foo')
- eq({ ' = function(foo)', '', 'end' }, buf_lines(0))
+ eq({ ' = function(foo)', 'end' }, buf_lines(0))
+ end)
+
+ it('correctly indents with newlines', function()
+ local curbuf = api.nvim_get_current_buf()
+ test_expand_success(
+ { 'function($2)\n\t$3\nend' },
+ { 'function()', ' ', 'end' },
+ [[
+ vim.opt.sw = 2
+ vim.opt.expandtab = true
+ ]]
+ )
+ api.nvim_buf_set_lines(curbuf, 0, -1, false, {})
+ test_expand_success(
+ { 'function($2)\n$3\nend' },
+ { 'function()', '', 'end' },
+ [[
+ vim.opt.sw = 2
+ vim.opt.expandtab = true
+ ]]
+ )
+ api.nvim_buf_set_lines(curbuf, 0, -1, false, {})
+ test_expand_success(
+ { 'func main() {\n\t$1\n}' },
+ { 'func main() {', '\t', '}' },
+ [[
+ vim.opt.sw = 4
+ vim.opt.ts = 4
+ vim.opt.expandtab = false
+ ]]
+ )
+ api.nvim_buf_set_lines(curbuf, 0, -1, false, {})
+ test_expand_success(
+ { '${1:name} :: ${2}\n${1:name} ${3}= ${0:undefined}' },
+ {
+ 'name :: ',
+ 'name = undefined',
+ },
+ [[
+ vim.opt.sw = 4
+ vim.opt.ts = 4
+ vim.opt.expandtab = false
+ ]]
+ )
end)
end)
diff --git a/test/functional/lua/spell_spec.lua b/test/functional/lua/spell_spec.lua
index e82dd7b4a0..af7d08b390 100644
--- a/test/functional/lua/spell_spec.lua
+++ b/test/functional/lua/spell_spec.lua
@@ -1,8 +1,10 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local pcall_err = helpers.pcall_err
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local pcall_err = t.pcall_err
describe('vim.spell', function()
before_each(function()
diff --git a/test/functional/lua/system_spec.lua b/test/functional/lua/system_spec.lua
index cb561f0771..e72a009d2e 100644
--- a/test/functional/lua/system_spec.lua
+++ b/test/functional/lua/system_spec.lua
@@ -1,7 +1,9 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
local function system_sync(cmd, opts)
return exec_lua(
diff --git a/test/functional/lua/text_spec.lua b/test/functional/lua/text_spec.lua
index e31aa63768..9e77953c8c 100644
--- a/test/functional/lua/text_spec.lua
+++ b/test/functional/lua/text_spec.lua
@@ -1,6 +1,8 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local eq = helpers.eq
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local eq = t.eq
describe('vim.text', function()
before_each(clear)
diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua
index c1981e19d4..780057b580 100644
--- a/test/functional/lua/thread_spec.lua
+++ b/test/functional/lua/thread_spec.lua
@@ -1,13 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local assert_alive = helpers.assert_alive
-local clear = helpers.clear
-local feed = helpers.feed
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local next_msg = helpers.next_msg
+
+local assert_alive = n.assert_alive
+local clear = n.clear
+local feed = n.feed
+local eq = t.eq
+local exec_lua = n.exec_lua
+local next_msg = n.next_msg
local NIL = vim.NIL
-local pcall_err = helpers.pcall_err
+local pcall_err = t.pcall_err
describe('thread', function()
local screen
@@ -166,7 +168,7 @@ describe('thread', function()
]]
local msg = next_msg()
- eq(msg[1], 'notification')
+ eq('notification', msg[1])
assert(tonumber(msg[2]) >= 72961)
end)
@@ -327,7 +329,7 @@ describe('threadpool', function()
]]
local msg = next_msg()
- eq(msg[1], 'notification')
+ eq('notification', msg[1])
assert(tonumber(msg[2]) >= 72961)
end)
diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua
index 3e46018682..1e80c88403 100644
--- a/test/functional/lua/ui_event_spec.lua
+++ b/test/functional/lua/ui_event_spec.lua
@@ -1,10 +1,16 @@
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local clear = helpers.clear
-local feed = helpers.feed
-local fn = helpers.fn
+
+local eq = t.eq
+local exec_lua = n.exec_lua
+local clear = n.clear
+local feed = n.feed
+local fn = n.fn
+local assert_log = t.assert_log
+local check_close = n.check_close
+
+local testlog = 'Xtest_lua_ui_event_log'
describe('vim.ui_attach', function()
local screen
@@ -108,7 +114,7 @@ describe('vim.ui_attach', function()
it('does not crash on exit', function()
fn.system({
- helpers.nvim_prog,
+ n.nvim_prog,
'-u',
'NONE',
'-i',
@@ -120,7 +126,7 @@ describe('vim.ui_attach', function()
'--cmd',
'quitall!',
})
- eq(0, helpers.eval('v:shell_error'))
+ eq(0, n.eval('v:shell_error'))
end)
it('can receive accurate message kinds even if they are history', function()
@@ -149,4 +155,56 @@ describe('vim.ui_attach', function()
},
}, actual, vim.inspect(actual))
end)
+
+ it('ui_refresh() activates correct capabilities without remote UI', function()
+ screen:detach()
+ exec_lua('vim.ui_attach(ns, { ext_cmdline = true }, on_event)')
+ eq(1, n.api.nvim_get_option_value('cmdheight', {}))
+ exec_lua('vim.ui_detach(ns)')
+ exec_lua('vim.ui_attach(ns, { ext_messages = true }, on_event)')
+ n.api.nvim_set_option_value('cmdheight', 1, {})
+ screen:attach()
+ eq(1, n.api.nvim_get_option_value('cmdheight', {}))
+ end)
+
+ it("ui_refresh() sets 'cmdheight' for all open tabpages with ext_messages", function()
+ exec_lua('vim.cmd.tabnew()')
+ exec_lua('vim.ui_attach(ns, { ext_messages = true }, on_event)')
+ exec_lua('vim.cmd.tabnext()')
+ eq(0, n.api.nvim_get_option_value('cmdheight', {}))
+ end)
+
+ it('avoids recursive flushing and invalid memory access with :redraw', function()
+ exec_lua([[
+ _G.cmdline = 0
+ vim.ui_attach(ns, { ext_messages = true }, function(ev)
+ vim.cmd.redraw()
+ _G.cmdline = _G.cmdline + (ev == 'cmdline_show' and 1 or 0)
+ end
+ )]])
+ feed(':')
+ eq(1, exec_lua('return _G.cmdline'))
+ n.assert_alive()
+ feed('version<CR><CR>v<Esc>')
+ n.assert_alive()
+ end)
+end)
+
+describe('vim.ui_attach', function()
+ after_each(function()
+ check_close()
+ os.remove(testlog)
+ end)
+
+ it('error in callback is logged', function()
+ clear({ env = { NVIM_LOG_FILE = testlog } })
+ local screen = Screen.new()
+ screen:attach()
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace('testspace')
+ vim.ui_attach(ns, { ext_popupmenu = true }, function() error(42) end)
+ ]])
+ feed('ifoo<CR>foobar<CR>fo<C-X><C-N>')
+ assert_log('Error executing UI event callback: Error executing lua: .*: 42', testlog, 100)
+ end)
end)
diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua
index e769843b19..d69e893c96 100644
--- a/test/functional/lua/ui_spec.lua
+++ b/test/functional/lua/ui_spec.lua
@@ -1,13 +1,15 @@
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local matches = helpers.matches
-local exec_lua = helpers.exec_lua
-local clear = helpers.clear
-local feed = helpers.feed
-local eval = helpers.eval
-local is_ci = helpers.is_ci
-local is_os = helpers.is_os
-local poke_eventloop = helpers.poke_eventloop
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local eq = t.eq
+local ok = t.ok
+local exec_lua = n.exec_lua
+local clear = n.clear
+local feed = n.feed
+local eval = n.eval
+local is_ci = t.is_ci
+local is_os = t.is_os
+local poke_eventloop = n.poke_eventloop
describe('vim.ui', function()
before_each(function()
@@ -138,13 +140,12 @@ describe('vim.ui', function()
describe('open()', function()
it('validation', function()
if is_os('win') or not is_ci('github') then
- exec_lua [[vim.system = function() return { wait=function() return { code=3} end } end]]
+ exec_lua [[vim.system = function() return { wait=function() return { code=3 } end } end]]
end
if not is_os('bsd') then
- matches(
- 'vim.ui.open: command failed %(%d%): { "[^"]+", .*"non%-existent%-file" }',
- exec_lua [[local _, err = vim.ui.open('non-existent-file') ; return err]]
- )
+ local rv =
+ exec_lua [[local cmd = vim.ui.open('non-existent-file'); return cmd:wait(100).code]]
+ ok(type(rv) == 'number' and rv ~= 0, 'nonzero exit code', rv)
end
exec_lua [[
@@ -152,7 +153,7 @@ describe('vim.ui', function()
vim.fn.executable = function() return 0 end
]]
eq(
- 'vim.ui.open: no handler found (tried: explorer.exe, xdg-open)',
+ 'vim.ui.open: no handler found (tried: wslview, explorer.exe, xdg-open)',
exec_lua [[local _, err = vim.ui.open('foo') ; return err]]
)
end)
diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua
index dacaf95867..553afb35d3 100644
--- a/test/functional/lua/uri_spec.lua
+++ b/test/functional/lua/uri_spec.lua
@@ -1,10 +1,12 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local is_os = helpers.is_os
-local skip = helpers.skip
-local write_file = require('test.helpers').write_file
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local is_os = t.is_os
+local skip = t.skip
+local write_file = t.write_file
describe('URI methods', function()
before_each(function()
@@ -206,7 +208,7 @@ describe('URI methods', function()
it('Windows paths should not be treated as uris', function()
skip(not is_os('win'), 'Not applicable on non-Windows')
- local file = helpers.tmpname()
+ local file = t.tmpname()
write_file(file, 'Test content')
local test_case = string.format(
[[
diff --git a/test/functional/lua/version_spec.lua b/test/functional/lua/version_spec.lua
index 3bc9e26d41..4ce8fb8dfe 100644
--- a/test/functional/lua/version_spec.lua
+++ b/test/functional/lua/version_spec.lua
@@ -1,10 +1,13 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local eq = helpers.eq
-local ok = helpers.ok
-local exec_lua = helpers.exec_lua
-local matches = helpers.matches
-local pcall_err = helpers.pcall_err
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local eq = t.eq
+local ok = t.ok
+local exec_lua = n.exec_lua
+local matches = t.matches
+local pcall_err = t.pcall_err
+local fn = n.fn
local function v(ver)
return vim.version._version(ver)
@@ -17,7 +20,7 @@ describe('version', function()
end)
it('version() returns Nvim version', function()
- local expected = exec_lua('return vim.fn.api_info().version')
+ local expected = fn.api_info().version
local actual = exec_lua('return vim.version()')
eq(expected.major, actual.major)
eq(expected.minor, actual.minor)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index a262d239e8..c8f94c6ffa 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -1,32 +1,33 @@
-- Test suite for testing interactions with API bindings
-local helpers = require('test.functional.helpers')(after_each)
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
-local nvim_prog = helpers.nvim_prog
-local fn = helpers.fn
-local api = helpers.api
-local command = helpers.command
-local dedent = helpers.dedent
-local insert = helpers.insert
-local clear = helpers.clear
-local eq = helpers.eq
-local ok = helpers.ok
+local nvim_prog = n.nvim_prog
+local fn = n.fn
+local api = n.api
+local command = n.command
+local dedent = t.dedent
+local insert = n.insert
+local clear = n.clear
+local eq = t.eq
+local ok = t.ok
local pesc = vim.pesc
-local eval = helpers.eval
-local feed = helpers.feed
-local pcall_err = helpers.pcall_err
-local exec_lua = helpers.exec_lua
-local matches = helpers.matches
-local exec = helpers.exec
+local eval = n.eval
+local feed = n.feed
+local pcall_err = t.pcall_err
+local exec_lua = n.exec_lua
+local matches = t.matches
+local exec = n.exec
local NIL = vim.NIL
-local retry = helpers.retry
-local next_msg = helpers.next_msg
-local remove_trace = helpers.remove_trace
-local mkdir_p = helpers.mkdir_p
-local rmdir = helpers.rmdir
-local write_file = helpers.write_file
-local poke_eventloop = helpers.poke_eventloop
-local assert_alive = helpers.assert_alive
+local retry = t.retry
+local next_msg = n.next_msg
+local remove_trace = t.remove_trace
+local mkdir_p = n.mkdir_p
+local rmdir = n.rmdir
+local write_file = t.write_file
+local poke_eventloop = n.poke_eventloop
+local assert_alive = n.assert_alive
describe('lua stdlib', function()
before_each(clear)
@@ -128,63 +129,62 @@ describe('lua stdlib', function()
eq(1, fn.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
end)
- local function test_vim_deprecate(current_version)
+ --- @param prerel string | nil
+ local function test_vim_deprecate(prerel)
-- vim.deprecate(name, alternative, version, plugin, backtrace)
-- See MAINTAIN.md for the soft/hard deprecation policy
- describe(('vim.deprecate [current_version = %s]'):format(current_version), function()
- before_each(function()
- -- mock vim.version() behavior, should be pinned for consistent testing
- exec_lua(
- [[
- local current_version_mock = vim.version.parse(...)
- getmetatable(vim.version).__call = function()
- return current_version_mock
- end
- ]],
- current_version
- )
- end)
+ 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'
- it('when plugin = nil', function()
+ it('plugin=nil, same message skipped', function()
eq(
- dedent [[
- foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated
- This feature will be removed in Nvim version 0.10]],
- exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10')
+ dedent(
+ [[
+ foo.bar() is deprecated. Run ":checkhealth vim.deprecated" for more information]]
+ ):format(curstr),
+ exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', curstr)
)
- -- Same message, skipped.
- eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10'))
+ -- Same message as above; skipped this time.
+ eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', curstr))
+ end)
- -- Don't show error if not hard-deprecated (only soft-deprecated)
+ it('plugin=nil, no error if soft-deprecated', function()
eq(
vim.NIL,
- exec_lua('return vim.deprecate(...)', 'foo.baz()', 'foo.better_baz()', '0.12.0')
+ exec_lua('return vim.deprecate(...)', 'foo.baz()', 'foo.better_baz()', '0.99.0')
)
+ end)
- -- Show error if hard-deprecated
+ it('plugin=nil, show error if hard-deprecated', function()
eq(
- dedent [[
- foo.hard_dep() is deprecated, use vim.new_api() instead. :help deprecated
- This feature will be removed in Nvim version 0.11]],
- exec_lua('return vim.deprecate(...)', 'foo.hard_dep()', 'vim.new_api()', '0.11')
+ dedent(
+ [[
+ foo.hard_dep() is deprecated. Run ":checkhealth vim.deprecated" for more information]]
+ ):format(was_removed, nextver),
+ exec_lua('return vim.deprecate(...)', 'foo.hard_dep()', 'vim.new_api()', nextver)
)
+ end)
- -- To be deleted in the next major version (1.0)
+ it('plugin=nil, to be deleted in the next major version (1.0)', function()
eq(
dedent [[
- foo.baz() is deprecated. :help deprecated
- This feature will be removed in Nvim version 1.0]],
+ foo.baz() is deprecated. Run ":checkhealth vim.deprecated" for more information]],
exec_lua [[ return vim.deprecate('foo.baz()', nil, '1.0') ]]
)
end)
- it('when plugin is specified', function()
+ it('plugin specified', function()
-- 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]],
+ Feature will be removed in my-plugin.nvim 0.3.0]],
exec_lua(
'return vim.deprecate(...)',
'foo.bar()',
@@ -199,7 +199,7 @@ describe('lua stdlib', function()
eq(
dedent [[
foo.bar() is deprecated, use zub.wooo{ok=yay} instead.
- This feature will be removed in my-plugin.nvim version 0.11.0]],
+ Feature will be removed in my-plugin.nvim 0.11.0]],
exec_lua(
'return vim.deprecate(...)',
'foo.bar()',
@@ -213,8 +213,8 @@ describe('lua stdlib', function()
end)
end
- test_vim_deprecate('0.10')
- test_vim_deprecate('0.10-dev+g0000000')
+ test_vim_deprecate()
+ test_vim_deprecate('-dev+g0000000')
it('vim.startswith', function()
eq(true, fn.luaeval('vim.startswith("123", "1")'))
@@ -592,8 +592,8 @@ describe('lua stdlib', function()
{ 'x*yz*oo*l', '*', true, false, { 'x', 'yz', 'oo', 'l' } },
}
- for _, t in ipairs(tests) do
- eq(t[5], vim.split(t[1], t[2], { plain = t[3], trimempty = t[4] }), t[1])
+ for _, q in ipairs(tests) do
+ eq(q[5], vim.split(q[1], q[2], { plain = q[3], trimempty = q[4] }), q[1])
end
-- Test old signature
@@ -603,8 +603,8 @@ describe('lua stdlib', function()
{ 'abc', '.-' },
}
- for _, t in ipairs(loops) do
- matches('Infinite loop detected', pcall_err(vim.split, t[1], t[2]))
+ for _, q in ipairs(loops) do
+ matches('Infinite loop detected', pcall_err(vim.split, q[1], q[2]))
end
-- Validates args.
@@ -626,8 +626,8 @@ describe('lua stdlib', function()
{ 'r\n', 'r' },
}
- for _, t in ipairs(trims) do
- assert(t[2], trim(t[1]))
+ for _, q in ipairs(trims) do
+ assert(q[2], trim(q[1]))
end
-- Validates args.
@@ -636,8 +636,8 @@ describe('lua stdlib', function()
it('vim.inspect', function()
-- just make sure it basically works, it has its own test suite
- local inspect = function(t, opts)
- return exec_lua('return vim.inspect(...)', t, opts)
+ local inspect = function(q, opts)
+ return exec_lua('return vim.inspect(...)', q, opts)
end
eq('2', inspect(2))
@@ -670,21 +670,21 @@ describe('lua stdlib', function()
local a = {}
local b = vim.deepcopy(a)
- return vim.tbl_islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b)
+ return vim.islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b)
]]))
ok(exec_lua([[
local a = vim.empty_dict()
local b = vim.deepcopy(a)
- return not vim.tbl_islist(b) and vim.tbl_count(b) == 0
+ return not vim.islist(b) and vim.tbl_count(b) == 0
]]))
ok(exec_lua([[
local a = {x = vim.empty_dict(), y = {}}
local b = vim.deepcopy(a)
- return not vim.tbl_islist(b.x) and vim.tbl_islist(b.y)
+ return not vim.islist(b.x) and vim.islist(b.y)
and vim.tbl_count(b) == 2
and tostring(a) ~= tostring(b)
]]))
@@ -822,30 +822,30 @@ 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})'))
+ it('vim.isarray', function()
+ eq(true, exec_lua('return vim.isarray({})'))
+ eq(false, exec_lua('return vim.isarray(vim.empty_dict())'))
+ eq(true, exec_lua("return vim.isarray({'a', 'b', 'c'})"))
+ eq(false, exec_lua("return vim.isarray({'a', '32', a='hello', b='baz'})"))
+ eq(false, exec_lua("return vim.isarray({1, a='hello', b='baz'})"))
+ eq(false, exec_lua("return vim.isarray({a='hello', b='baz', 1})"))
+ eq(false, exec_lua("return vim.isarray({1, 2, nil, a='hello'})"))
+ eq(true, exec_lua('return vim.isarray({1, 2, nil, 4})'))
+ eq(true, exec_lua('return vim.isarray({nil, 2, 3, 4})'))
+ eq(false, exec_lua('return vim.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())'))
- eq(true, exec_lua("return vim.tbl_islist({'a', 'b', 'c'})"))
- eq(false, exec_lua("return vim.tbl_islist({'a', '32', a='hello', b='baz'})"))
- 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})'))
+ it('vim.islist', function()
+ eq(true, exec_lua('return vim.islist({})'))
+ eq(false, exec_lua('return vim.islist(vim.empty_dict())'))
+ eq(true, exec_lua("return vim.islist({'a', 'b', 'c'})"))
+ eq(false, exec_lua("return vim.islist({'a', '32', a='hello', b='baz'})"))
+ eq(false, exec_lua("return vim.islist({1, a='hello', b='baz'})"))
+ eq(false, exec_lua("return vim.islist({a='hello', b='baz', 1})"))
+ eq(false, exec_lua("return vim.islist({1, 2, nil, a='hello'})"))
+ eq(false, exec_lua('return vim.islist({1, 2, nil, 4})'))
+ eq(false, exec_lua('return vim.islist({nil, 2, 3, 4})'))
+ eq(false, exec_lua('return vim.islist({1, [1.5]=2, [3]=3})'))
end)
it('vim.tbl_isempty', function()
@@ -918,7 +918,7 @@ describe('lua stdlib', function()
local b = {}
local c = vim.tbl_extend("keep", a, b)
- return not vim.tbl_islist(c) and vim.tbl_count(c) == 0
+ return not vim.islist(c) and vim.tbl_count(c) == 0
]]))
ok(exec_lua([[
@@ -926,7 +926,7 @@ describe('lua stdlib', function()
local b = vim.empty_dict()
local c = vim.tbl_extend("keep", a, b)
- return vim.tbl_islist(c) and vim.tbl_count(c) == 0
+ return vim.islist(c) and vim.tbl_count(c) == 0
]]))
ok(exec_lua([[
@@ -1026,7 +1026,7 @@ describe('lua stdlib', function()
local count = 0
for _ in pairs(c) do count = count + 1 end
- return not vim.tbl_islist(c) and count == 0
+ return not vim.islist(c) and count == 0
]]))
ok(exec_lua([[
@@ -1037,7 +1037,7 @@ describe('lua stdlib', function()
local count = 0
for _ in pairs(c) do count = count + 1 end
- return vim.tbl_islist(c) and count == 0
+ return vim.islist(c) and count == 0
]]))
eq(
@@ -1282,7 +1282,7 @@ describe('lua stdlib', function()
vim.rpcrequest(chan, 'nvim_exec', 'let xx = {}\nlet yy = []', false)
local dict = vim.rpcrequest(chan, 'nvim_eval', 'xx')
local list = vim.rpcrequest(chan, 'nvim_eval', 'yy')
- return {dict, list, vim.tbl_islist(dict), vim.tbl_islist(list)}
+ return {dict, list, vim.islist(dict), vim.islist(list)}
]])
)
@@ -1355,7 +1355,7 @@ describe('lua stdlib', function()
vim.api.nvim_set_var('dicty', vim.empty_dict())
local listy = vim.fn.eval("listy")
local dicty = vim.fn.eval("dicty")
- return {vim.tbl_islist(listy), vim.tbl_islist(dicty), next(listy) == nil, next(dicty) == nil}
+ return {vim.islist(listy), vim.islist(dicty), next(listy) == nil, next(dicty) == nil}
]])
)
@@ -1569,7 +1569,7 @@ describe('lua stdlib', function()
eq(NIL, exec_lua([[return vim.g.Unknown_script_func]]))
-- Check if autoload works properly
- local pathsep = helpers.get_pathsep()
+ local pathsep = n.get_pathsep()
local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
local xdata = 'Xhome' .. pathsep .. 'Xdata'
local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep)
@@ -2016,7 +2016,7 @@ describe('lua stdlib', function()
vim.opt.scrolloff = 10
return vim.o.scrolloff
]]
- eq(scrolloff, 10)
+ eq(10, scrolloff)
end)
pending('should handle STUPID window things', function()
@@ -2037,7 +2037,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = { 'hello', 'world' }
return vim.o.wildignore
]]
- eq(wildignore, 'hello,world')
+ eq('hello,world', wildignore)
end)
it('should allow setting tables with shortnames', function()
@@ -2045,7 +2045,7 @@ describe('lua stdlib', function()
vim.opt.wig = { 'hello', 'world' }
return vim.o.wildignore
]]
- eq(wildignore, 'hello,world')
+ eq('hello,world', wildignore)
end)
it('should error when you attempt to set string values to numeric options', function()
@@ -2451,13 +2451,13 @@ describe('lua stdlib', function()
vim.opt.wildignore = 'foo'
return vim.o.wildignore
]]
- eq(wildignore, 'foo')
+ eq('foo', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
end)
it('should handle adding duplicates', function()
@@ -2465,19 +2465,19 @@ describe('lua stdlib', function()
vim.opt.wildignore = 'foo'
return vim.o.wildignore
]]
- eq(wildignore, 'foo')
+ eq('foo', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
end)
it('should allow adding multiple times', function()
@@ -2486,7 +2486,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz'
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
end)
it('should remove values when you use minus', function()
@@ -2494,19 +2494,19 @@ describe('lua stdlib', function()
vim.opt.wildignore = 'foo'
return vim.o.wildignore
]]
- eq(wildignore, 'foo')
+ eq('foo', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore - 'bar'
return vim.o.wildignore
]]
- eq(wildignore, 'foo,baz')
+ eq('foo,baz', wildignore)
end)
it('should prepend values when using ^', function()
@@ -2521,7 +2521,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = vim.opt.wildignore ^ 'super_first'
return vim.o.wildignore
]]
- eq(wildignore, 'super_first,first,foo')
+ eq('super_first,first,foo', wildignore)
end)
it('should not remove duplicates from wildmode: #14708', function()
@@ -2530,7 +2530,7 @@ describe('lua stdlib', function()
return vim.o.wildmode
]]
- eq(wildmode, 'full,list,full')
+ eq('full,list,full', wildmode)
end)
describe('option types', function()
@@ -2738,7 +2738,7 @@ describe('lua stdlib', function()
return vim.go.whichwrap
]]
- eq(ww, 'b,s')
+ eq('b,s', ww)
eq(
'b,s,<,>,[,]',
exec_lua [[
@@ -3007,25 +3007,65 @@ describe('lua stdlib', function()
end)
describe('vim.on_key', function()
- it('tracks keystrokes', function()
+ it('tracks Unicode input', function()
insert([[hello world ]])
exec_lua [[
keys = {}
+ typed = {}
- vim.on_key(function(buf)
+ vim.on_key(function(buf, typed_buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
+ if typed_buf:byte() == 27 then
+ typed_buf = "<ESC>"
+ end
table.insert(keys, buf)
+ table.insert(typed, typed_buf)
end)
]]
- insert([[next 🤦 lines å ]])
+ insert([[next 🤦 lines å …]])
-- It has escape in the keys pressed
- eq('inext 🤦 lines å <ESC>', exec_lua [[return table.concat(keys, '')]])
+ eq('inext 🤦 lines å …<ESC>', exec_lua [[return table.concat(keys, '')]])
+ eq('inext 🤦 lines å …<ESC>', exec_lua [[return table.concat(typed, '')]])
+ end)
+
+ it('tracks input with modifiers', function()
+ exec_lua [[
+ keys = {}
+ typed = {}
+
+ vim.on_key(function(buf, typed_buf)
+ table.insert(keys, vim.fn.keytrans(buf))
+ table.insert(typed, vim.fn.keytrans(typed_buf))
+ end)
+ ]]
+
+ feed([[i<C-V><C-;><C-V><C-…><Esc>]])
+
+ eq('i<C-V><C-;><C-V><C-…><Esc>', exec_lua [[return table.concat(keys, '')]])
+ eq('i<C-V><C-;><C-V><C-…><Esc>', exec_lua [[return table.concat(typed, '')]])
+ end)
+
+ it('works with character find and Select mode', function()
+ insert('12345')
+
+ exec_lua [[
+ typed = {}
+
+ vim.cmd('snoremap # @')
+
+ vim.on_key(function(buf, typed_buf)
+ table.insert(typed, vim.fn.keytrans(typed_buf))
+ end)
+ ]]
+
+ feed('F3gHβγδεζ<Esc>gH…<Esc>gH#$%^')
+ eq('F3gHβγδεζ<Esc>gH…<Esc>gH#$%^', exec_lua [[return table.concat(typed, '')]])
end)
it('allows removing on_key listeners', function()
@@ -3087,23 +3127,29 @@ describe('lua stdlib', function()
eq('inext l', exec_lua [[ return table.concat(keys, '') ]])
end)
- it('processes mapped keys, not unmapped keys', function()
+ it('argument 1 is keys after mapping, argument 2 is typed keys', function()
exec_lua [[
keys = {}
+ typed = {}
vim.cmd("inoremap hello world")
- vim.on_key(function(buf)
+ vim.on_key(function(buf, typed_buf)
if buf:byte() == 27 then
buf = "<ESC>"
end
+ if typed_buf:byte() == 27 then
+ typed_buf = "<ESC>"
+ end
table.insert(keys, buf)
+ table.insert(typed, typed_buf)
end)
]]
insert('hello')
eq('iworld<ESC>', exec_lua [[return table.concat(keys, '')]])
+ eq('ihello<ESC>', exec_lua [[return table.concat(typed, '')]])
end)
it('can call vim.fn functions on Ctrl-C #17273', function()
@@ -3664,6 +3710,20 @@ describe('lua stdlib', function()
]]
)
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')
+
+ -- Without vim-patch:8.2.3862, this gives E36, despite just the 1st tabpage being full.
+ exec_lua('vim.api.nvim_win_call(..., 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.iconv', function()
@@ -4011,7 +4071,7 @@ describe('vim.keymap', function()
feed('asdf\n')
eq(1, exec_lua [[return GlobalCount]])
- eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
+ eq('\nNo mapping found', n.exec_capture('nmap asdf'))
end)
it('works with buffer-local mappings', function()
@@ -4035,7 +4095,7 @@ describe('vim.keymap', function()
feed('asdf\n')
eq(1, exec_lua [[return GlobalCount]])
- eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
+ eq('\nNo mapping found', n.exec_capture('nmap asdf'))
end)
it('does not mutate the opts parameter', function()
diff --git a/test/functional/lua/watch_spec.lua b/test/functional/lua/watch_spec.lua
index 115fee8091..bd8faadf5b 100644
--- a/test/functional/lua/watch_spec.lua
+++ b/test/functional/lua/watch_spec.lua
@@ -1,15 +1,17 @@
-local helpers = require('test.functional.helpers')(after_each)
-local eq = helpers.eq
-local exec_lua = helpers.exec_lua
-local clear = helpers.clear
-local is_ci = helpers.is_ci
-local is_os = helpers.is_os
-local skip = helpers.skip
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local eq = t.eq
+local exec_lua = n.exec_lua
+local clear = n.clear
+local is_ci = t.is_ci
+local is_os = t.is_os
+local skip = t.skip
-- Create a file via a rename to avoid multiple
-- events which can happen with some backends on some platforms
local function touch(path)
- local tmp = helpers.tmpname()
+ local tmp = t.tmpname()
io.open(tmp, 'w'):close()
assert(vim.uv.fs_rename(tmp, path))
end
@@ -22,15 +24,13 @@ describe('vim._watch', function()
local function run(watchfunc)
it('detects file changes (watchfunc=' .. watchfunc .. '())', function()
if watchfunc == 'fswatch' then
- skip(is_os('mac'), 'flaky test on mac')
- skip(
- not is_ci() and helpers.fn.executable('fswatch') == 0,
- 'fswatch not installed and not on CI'
- )
skip(is_os('win'), 'not supported on windows')
+ skip(is_os('mac'), 'flaky test on mac')
+ skip(not is_ci() and n.fn.executable('fswatch') == 0, 'fswatch not installed and not on CI')
end
if watchfunc == 'watch' then
+ skip(is_os('mac'), 'flaky test on mac')
skip(is_os('bsd'), 'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38')
else
skip(
@@ -39,7 +39,7 @@ describe('vim._watch', function()
)
end
- local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(helpers.tmpname()) .. '/nvim_XXXXXXXXXX')
+ local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(t.tmpname()) .. '/nvim_XXXXXXXXXX')
local expected_events = 0
diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua
index c21309c2e4..d5589c1f13 100644
--- a/test/functional/lua/xdiff_spec.lua
+++ b/test/functional/lua/xdiff_spec.lua
@@ -1,8 +1,10 @@
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local pcall_err = helpers.pcall_err
+local t = require('test.testutil')
+local n = require('test.functional.testnvim')()
+
+local clear = n.clear
+local exec_lua = n.exec_lua
+local eq = t.eq
+local pcall_err = t.pcall_err
describe('xdiff bindings', function()
before_each(function()