diff options
Diffstat (limited to 'test/functional/api')
-rw-r--r-- | test/functional/api/autocmd_spec.lua | 1093 | ||||
-rw-r--r-- | test/functional/api/buffer_spec.lua | 1598 | ||||
-rw-r--r-- | test/functional/api/buffer_updates_spec.lua | 544 | ||||
-rw-r--r-- | test/functional/api/command_spec.lua | 985 | ||||
-rw-r--r-- | test/functional/api/extmark_spec.lua | 1046 | ||||
-rw-r--r-- | test/functional/api/highlight_spec.lua | 530 | ||||
-rw-r--r-- | test/functional/api/keymap_spec.lua | 997 | ||||
-rw-r--r-- | test/functional/api/menu_spec.lua | 29 | ||||
-rw-r--r-- | test/functional/api/proc_spec.lua | 36 | ||||
-rw-r--r-- | test/functional/api/rpc_fixture.lua | 10 | ||||
-rw-r--r-- | test/functional/api/server_notifications_spec.lua | 67 | ||||
-rw-r--r-- | test/functional/api/server_requests_spec.lua | 203 | ||||
-rw-r--r-- | test/functional/api/tabpage_spec.lua | 150 | ||||
-rw-r--r-- | test/functional/api/ui_spec.lua | 98 | ||||
-rw-r--r-- | test/functional/api/version_spec.lua | 191 | ||||
-rw-r--r-- | test/functional/api/vim_spec.lua | 3895 | ||||
-rw-r--r-- | test/functional/api/window_spec.lua | 1908 |
17 files changed, 7830 insertions, 5550 deletions
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua index fd46a1dcfa..e89abf6c64 100644 --- a/test/functional/api/autocmd_spec.lua +++ b/test/functional/api/autocmd_spec.lua @@ -6,7 +6,7 @@ local eq = helpers.eq local neq = helpers.neq local exec_lua = helpers.exec_lua local matches = helpers.matches -local meths = helpers.meths +local api = helpers.api local source = helpers.source local pcall_err = helpers.pcall_err @@ -15,43 +15,74 @@ before_each(clear) describe('autocmd api', function() describe('nvim_create_autocmd', function() it('validation', function() - eq("Cannot use both 'callback' and 'command'", pcall_err(meths.create_autocmd, 'BufReadPost', { - pattern = '*.py,*.pyi', - command = "echo 'Should Have Errored", - callback = 'NotAllowed', - })) - eq("Cannot use both 'pattern' and 'buffer' for the same autocmd", pcall_err(meths.create_autocmd, 'FileType', { - command = 'let g:called = g:called + 1', - buffer = 0, - pattern = '*.py', - })) - eq("Required: 'event'", pcall_err(meths.create_autocmd, {}, { - command = 'ls', - })) - eq("Required: 'command' or 'callback'", pcall_err(meths.create_autocmd, 'FileType', { - })) - eq("Invalid 'desc': expected String, got Integer", pcall_err(meths.create_autocmd, 'FileType', { - command = 'ls', - desc = 42, - })) - eq("Invalid 'callback': expected Lua function or Vim function name, got Integer", pcall_err(meths.create_autocmd, 'FileType', { - callback = 0, - })) - eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.create_autocmd, - {'FileType', {}}, {})) - eq("Invalid 'group': 0", pcall_err(meths.create_autocmd, 'FileType', { - group = 0, - command = 'ls', - })) - - eq("Invalid 'event': 'foo'", pcall_err(meths.create_autocmd, 'foo', { command = '' })) - eq("Invalid 'event': 'VimEnter '", pcall_err(meths.create_autocmd, 'VimEnter ', { command = '' })) - eq("Invalid 'event': 'VimEnter foo'", pcall_err(meths.create_autocmd, 'VimEnter foo', { command = '' })) - eq("Invalid 'event': 'BufAdd,BufDelete'", pcall_err(meths.create_autocmd, 'BufAdd,BufDelete', { command = '' })) + eq( + "Cannot use both 'callback' and 'command'", + pcall_err(api.nvim_create_autocmd, 'BufReadPost', { + pattern = '*.py,*.pyi', + command = "echo 'Should Have Errored", + callback = 'NotAllowed', + }) + ) + eq( + "Cannot use both 'pattern' and 'buffer' for the same autocmd", + pcall_err(api.nvim_create_autocmd, 'FileType', { + command = 'let g:called = g:called + 1', + buffer = 0, + pattern = '*.py', + }) + ) + eq( + "Required: 'event'", + pcall_err(api.nvim_create_autocmd, {}, { + command = 'ls', + }) + ) + eq("Required: 'command' or 'callback'", pcall_err(api.nvim_create_autocmd, 'FileType', {})) + eq( + "Invalid 'desc': expected String, got Integer", + pcall_err(api.nvim_create_autocmd, 'FileType', { + command = 'ls', + desc = 42, + }) + ) + eq( + "Invalid 'callback': expected Lua function or Vim function name, got Integer", + pcall_err(api.nvim_create_autocmd, 'FileType', { + callback = 0, + }) + ) + eq( + "Invalid 'event' item: expected String, got Array", + pcall_err(api.nvim_create_autocmd, { 'FileType', {} }, {}) + ) + eq( + "Invalid 'group': 0", + pcall_err(api.nvim_create_autocmd, 'FileType', { + group = 0, + command = 'ls', + }) + ) + + eq("Invalid 'event': 'foo'", pcall_err(api.nvim_create_autocmd, 'foo', { command = '' })) + eq( + "Invalid 'event': 'VimEnter '", + pcall_err(api.nvim_create_autocmd, 'VimEnter ', { command = '' }) + ) + eq( + "Invalid 'event': 'VimEnter foo'", + pcall_err(api.nvim_create_autocmd, 'VimEnter foo', { command = '' }) + ) + eq( + "Invalid 'event': 'BufAdd,BufDelete'", + pcall_err(api.nvim_create_autocmd, 'BufAdd,BufDelete', { command = '' }) + ) end) it('doesnt leak when you use ++once', function() - eq(1, exec_lua([[ + eq( + 1, + exec_lua( + [[ local count = 0 vim.api.nvim_create_autocmd("FileType", { @@ -64,30 +95,33 @@ describe('autocmd api', function() vim.cmd "set filetype=python" return count - ]], {})) + ]], + {} + ) + ) end) it('allows passing buffer by key', function() - meths.set_var('called', 0) + api.nvim_set_var('called', 0) - meths.create_autocmd("FileType", { - command = "let g:called = g:called + 1", + api.nvim_create_autocmd('FileType', { + command = 'let g:called = g:called + 1', buffer = 0, }) - meths.command "set filetype=txt" - eq(1, meths.get_var('called')) + command 'set filetype=txt' + eq(1, api.nvim_get_var('called')) -- switch to a new buffer - meths.command "new" - meths.command "set filetype=python" + command 'new' + command 'set filetype=python' - eq(1, meths.get_var('called')) + eq(1, api.nvim_get_var('called')) end) it('does not allow passing invalid buffers', function() - local ok, msg = pcall(meths.create_autocmd, 'FileType', { - command = "let g:called = g:called + 1", + local ok, msg = pcall(api.nvim_create_autocmd, 'FileType', { + command = 'let g:called = g:called + 1', buffer = -1, }) @@ -96,60 +130,66 @@ describe('autocmd api', function() end) it('errors on non-functions for cb', function() - eq(false, pcall(exec_lua, [[ + eq( + false, + pcall( + exec_lua, + [[ vim.api.nvim_create_autocmd("BufReadPost", { pattern = "*.py,*.pyi", callback = 5, }) - ]])) + ]] + ) + ) end) it('allow passing pattern and <buffer> in same pattern', function() - local ok = pcall(meths.create_autocmd, "BufReadPost", { - pattern = "*.py,<buffer>", - command = "echo 'Should Not Error'" + local ok = pcall(api.nvim_create_autocmd, 'BufReadPost', { + pattern = '*.py,<buffer>', + command = "echo 'Should Not Error'", }) eq(true, ok) end) it('should handle multiple values as comma separated list', function() - meths.create_autocmd("BufReadPost", { - pattern = "*.py,*.pyi", - command = "echo 'Should Not Have Errored'" + api.nvim_create_autocmd('BufReadPost', { + pattern = '*.py,*.pyi', + command = "echo 'Should Not Have Errored'", }) -- We should have one autocmd for *.py and one for *.pyi - eq(2, #meths.get_autocmds { event = "BufReadPost" }) + eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) it('should handle multiple values as array', function() - meths.create_autocmd("BufReadPost", { - pattern = { "*.py", "*.pyi", }, - command = "echo 'Should Not Have Errored'" + api.nvim_create_autocmd('BufReadPost', { + pattern = { '*.py', '*.pyi' }, + command = "echo 'Should Not Have Errored'", }) -- We should have one autocmd for *.py and one for *.pyi - eq(2, #meths.get_autocmds { event = "BufReadPost" }) + eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) describe('desc', function() it('can add description to one autocmd', function() - local cmd = "echo 'Should Not Have Errored'" - local desc = "Can show description" - meths.create_autocmd("BufReadPost", { - pattern = "*.py", + local cmd = "echo 'Should Not Have Errored'" + local desc = 'Can show description' + api.nvim_create_autocmd('BufReadPost', { + pattern = '*.py', command = cmd, desc = desc, }) - eq(desc, meths.get_autocmds { event = "BufReadPost" }[1].desc) - eq(cmd, meths.get_autocmds { event = "BufReadPost" }[1].command) + eq(desc, api.nvim_get_autocmds { event = 'BufReadPost' }[1].desc) + eq(cmd, api.nvim_get_autocmds { event = 'BufReadPost' }[1].command) end) it('can add description to one autocmd that uses a callback', function() local desc = 'Can show description' - meths.set_var('desc', desc) + api.nvim_set_var('desc', desc) local result = exec_lua([[ local callback = function() print 'Should Not Have Errored' end @@ -178,38 +218,38 @@ describe('autocmd api', function() }) ]]) - eq(nil, meths.get_autocmds({ event = 'BufReadPost' })[1].desc) + eq(nil, api.nvim_get_autocmds({ event = 'BufReadPost' })[1].desc) end) it('can add description to multiple autocmd', function() - meths.create_autocmd("BufReadPost", { - pattern = {"*.py", "*.pyi"}, + api.nvim_create_autocmd('BufReadPost', { + pattern = { '*.py', '*.pyi' }, command = "echo 'Should Not Have Errored'", - desc = "Can show description", + desc = 'Can show description', }) - local aus = meths.get_autocmds { event = "BufReadPost" } + local aus = api.nvim_get_autocmds { event = 'BufReadPost' } eq(2, #aus) - eq("Can show description", aus[1].desc) - eq("Can show description", aus[2].desc) + eq('Can show description', aus[1].desc) + eq('Can show description', aus[2].desc) end) end) pending('script and verbose settings', function() it('marks API client', function() - meths.create_autocmd("BufReadPost", { - pattern = "*.py", + api.nvim_create_autocmd('BufReadPost', { + pattern = '*.py', command = "echo 'Should Not Have Errored'", - desc = "Can show description", + desc = 'Can show description', }) - local aus = meths.get_autocmds { event = "BufReadPost" } + local aus = api.nvim_get_autocmds { event = 'BufReadPost' } eq(1, #aus, aus) end) end) it('removes an autocommand if the callback returns true', function() - meths.set_var("some_condition", false) + api.nvim_set_var('some_condition', false) exec_lua [[ vim.api.nvim_create_autocmd("User", { @@ -221,21 +261,21 @@ describe('autocmd api', function() }) ]] - meths.exec_autocmds("User", {pattern = "Test"}) + api.nvim_exec_autocmds('User', { pattern = 'Test' }) - local aus = meths.get_autocmds({ event = 'User', pattern = 'Test' }) + local aus = api.nvim_get_autocmds({ event = 'User', pattern = 'Test' }) local first = aus[1] eq(true, first.id > 0) - meths.set_var("some_condition", true) - meths.exec_autocmds("User", {pattern = "Test"}) - eq({}, meths.get_autocmds({event = "User", pattern = "Test"})) + api.nvim_set_var('some_condition', true) + api.nvim_exec_autocmds('User', { pattern = 'Test' }) + eq({}, api.nvim_get_autocmds({ event = 'User', pattern = 'Test' })) end) it('receives an args table', function() - local group_id = meths.create_augroup("TestGroup", {}) + local group_id = api.nvim_create_augroup('TestGroup', {}) -- Having an existing autocmd calling expand("<afile>") shouldn't change args #18964 - meths.create_autocmd('User', { + api.nvim_create_autocmd('User', { group = 'TestGroup', pattern = 'Te*', command = 'call expand("<afile>")', @@ -251,15 +291,15 @@ describe('autocmd api', function() }) ]] - meths.exec_autocmds("User", {pattern = "Test pattern"}) + api.nvim_exec_autocmds('User', { pattern = 'Test pattern' }) eq({ id = autocmd_id, group = group_id, - event = "User", - match = "Test pattern", - file = "Test pattern", + event = 'User', + match = 'Test pattern', + file = 'Test pattern', buf = 1, - }, meths.get_var("autocmd_args")) + }, api.nvim_get_var('autocmd_args')) -- Test without a group autocmd_id = exec_lua [[ @@ -271,20 +311,23 @@ describe('autocmd api', function() }) ]] - meths.exec_autocmds("User", {pattern = "some_pat"}) + api.nvim_exec_autocmds('User', { pattern = 'some_pat' }) eq({ id = autocmd_id, group = nil, - event = "User", - match = "some_pat", - file = "some_pat", + event = 'User', + match = 'some_pat', + file = 'some_pat', buf = 1, - }, meths.get_var("autocmd_args")) + }, api.nvim_get_var('autocmd_args')) end) it('can receive arbitrary data', function() local function test(data) - eq(data, exec_lua([[ + eq( + data, + exec_lua( + [[ local input = ... local output vim.api.nvim_create_autocmd("User", { @@ -300,40 +343,64 @@ describe('autocmd api', function() }) return output - ]], data)) + ]], + data + ) + ) end - test("Hello") + test('Hello') test(42) test(true) - test({ "list" }) - test({ foo = "bar" }) + test({ 'list' }) + test({ foo = 'bar' }) end) end) describe('nvim_get_autocmds', function() it('validation', function() - eq("Invalid 'group': 9997999", pcall_err(meths.get_autocmds, { - group = 9997999, - })) - eq("Invalid 'group': 'bogus'", pcall_err(meths.get_autocmds, { - group = 'bogus', - })) - eq("Invalid 'group': 0", pcall_err(meths.get_autocmds, { - group = 0, - })) - eq("Invalid 'group': expected String or Integer, got Array", pcall_err(meths.get_autocmds, { - group = {}, - })) - eq("Invalid 'buffer': expected Integer or Array, got Boolean", pcall_err(meths.get_autocmds, { - buffer = true, - })) - eq("Invalid 'event': expected String or Array", pcall_err(meths.get_autocmds, { - event = true, - })) - eq("Invalid 'pattern': expected String or Array, got Boolean", pcall_err(meths.get_autocmds, { - pattern = true, - })) + eq( + "Invalid 'group': 9997999", + pcall_err(api.nvim_get_autocmds, { + group = 9997999, + }) + ) + eq( + "Invalid 'group': 'bogus'", + pcall_err(api.nvim_get_autocmds, { + group = 'bogus', + }) + ) + eq( + "Invalid 'group': 0", + pcall_err(api.nvim_get_autocmds, { + group = 0, + }) + ) + eq( + "Invalid 'group': expected String or Integer, got Array", + pcall_err(api.nvim_get_autocmds, { + group = {}, + }) + ) + eq( + "Invalid 'buffer': expected Integer or Array, got Boolean", + pcall_err(api.nvim_get_autocmds, { + buffer = true, + }) + ) + eq( + "Invalid 'event': expected String or Array", + pcall_err(api.nvim_get_autocmds, { + event = true, + }) + ) + eq( + "Invalid 'pattern': expected String or Array, got Boolean", + pcall_err(api.nvim_get_autocmds, { + pattern = true, + }) + ) end) describe('events', function() @@ -341,7 +408,7 @@ describe('autocmd api', function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "1"]] - local aus = meths.get_autocmds { event = "InsertEnter" } + local aus = api.nvim_get_autocmds { event = 'InsertEnter' } eq(1, #aus) end) @@ -350,7 +417,7 @@ describe('autocmd api', function() command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "2"]] - local aus = meths.get_autocmds { event = "InsertEnter" } + local aus = api.nvim_get_autocmds { event = 'InsertEnter' } eq(2, #aus) end) @@ -359,8 +426,8 @@ describe('autocmd api', function() command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "2"]] - local string_aus = meths.get_autocmds { event = "InsertEnter" } - local array_aus = meths.get_autocmds { event = { "InsertEnter" } } + local string_aus = api.nvim_get_autocmds { event = 'InsertEnter' } + local array_aus = api.nvim_get_autocmds { event = { 'InsertEnter' } } eq(string_aus, array_aus) end) @@ -370,7 +437,7 @@ describe('autocmd api', function() command [[au InsertEnter * :echo "1"]] command [[au InsertEnter * :echo "2"]] - local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } + local aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } } eq(2, #aus) end) @@ -384,7 +451,7 @@ describe('autocmd api', function() \ }) ]] - local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } + local aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } } local first = aus[1] eq(first.id, nil) @@ -392,8 +459,8 @@ describe('autocmd api', function() local second = aus[2] neq(second.id, nil) - meths.del_autocmd(second.id) - local new_aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } + api.nvim_del_autocmd(second.id) + local new_aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } } eq(1, #new_aus) eq(first, new_aus[1]) end) @@ -402,8 +469,16 @@ describe('autocmd api', function() command [[au! InsertEnter]] command [[au InsertEnter * :echo "1"]] - local aus = meths.get_autocmds { event = "InsertEnter" } - eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus) + local aus = api.nvim_get_autocmds { event = 'InsertEnter' } + eq({ + { + buflocal = false, + command = ':echo "1"', + event = 'InsertEnter', + once = false, + pattern = '*', + }, + }, aus) end) it('works with buffer numbers', function() @@ -412,77 +487,96 @@ describe('autocmd api', function() command [[au InsertEnter <buffer=1> :echo "1"]] command [[au InsertEnter <buffer=2> :echo "2"]] - local aus = meths.get_autocmds { event = "InsertEnter", buffer = 0 } - eq({{ - buffer = 2, - buflocal = true, - command = ':echo "2"', - event = 'InsertEnter', - once = false, - pattern = '<buffer=2>', - }}, aus) - - aus = meths.get_autocmds { event = "InsertEnter", buffer = 1 } - eq({{ - buffer = 1, - buflocal = true, - command = ':echo "1"', - event = "InsertEnter", - once = false, - pattern = "<buffer=1>", - }}, aus) - - aus = meths.get_autocmds { event = "InsertEnter", buffer = { 1, 2 } } - eq({{ - buffer = 1, - buflocal = true, - command = ':echo "1"', - event = "InsertEnter", - once = false, - pattern = "<buffer=1>", - }, { - buffer = 2, - buflocal = true, - command = ':echo "2"', - event = "InsertEnter", - once = false, - pattern = "<buffer=2>", - }}, aus) - - eq("Invalid 'buffer': expected Integer or Array, got String", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" })) - eq("Invalid 'buffer': expected Integer, got String", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } })) - eq("Invalid buffer id: 42", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { 42 } })) + local aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = 0 } + eq({ + { + buffer = 2, + buflocal = true, + command = ':echo "2"', + event = 'InsertEnter', + once = false, + pattern = '<buffer=2>', + }, + }, aus) + + aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = 1 } + eq({ + { + buffer = 1, + buflocal = true, + command = ':echo "1"', + event = 'InsertEnter', + once = false, + pattern = '<buffer=1>', + }, + }, aus) + + aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = { 1, 2 } } + eq({ + { + buffer = 1, + buflocal = true, + command = ':echo "1"', + event = 'InsertEnter', + once = false, + pattern = '<buffer=1>', + }, + { + buffer = 2, + buflocal = true, + command = ':echo "2"', + event = 'InsertEnter', + once = false, + pattern = '<buffer=2>', + }, + }, aus) + + eq( + "Invalid 'buffer': expected Integer or Array, got String", + pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = 'foo' }) + ) + eq( + "Invalid 'buffer': expected Integer, got String", + pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = { 'foo', 42 } }) + ) + eq( + 'Invalid buffer id: 42', + pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = { 42 } }) + ) local bufs = {} for _ = 1, 257 do - table.insert(bufs, meths.create_buf(true, false)) + table.insert(bufs, api.nvim_create_buf(true, false)) end - eq("Too many buffers (maximum of 256)", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs })) + eq( + 'Too many buffers (maximum of 256)', + pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = bufs }) + ) end) it('returns autocmds when group is specified by id', function() - local auid = meths.create_augroup("nvim_test_augroup", { clear = true }) - meths.create_autocmd("FileType", { group = auid, command = 'echo "1"' }) - meths.create_autocmd("FileType", { group = auid, command = 'echo "2"' }) + local auid = api.nvim_create_augroup('nvim_test_augroup', { clear = true }) + api.nvim_create_autocmd('FileType', { group = auid, command = 'echo "1"' }) + api.nvim_create_autocmd('FileType', { group = auid, command = 'echo "2"' }) - local aus = meths.get_autocmds { group = auid } + local aus = api.nvim_get_autocmds { group = auid } eq(2, #aus) - local aus2 = meths.get_autocmds { group = auid, event = "InsertEnter" } + local aus2 = api.nvim_get_autocmds { group = auid, event = 'InsertEnter' } eq(0, #aus2) end) it('returns autocmds when group is specified by name', function() - local auname = "nvim_test_augroup" - meths.create_augroup(auname, { clear = true }) - meths.create_autocmd("FileType", { group = auname, command = 'echo "1"' }) - meths.create_autocmd("FileType", { group = auname, command = 'echo "2"' }) + local auname = 'nvim_test_augroup' + api.nvim_create_augroup(auname, { clear = true }) + api.nvim_create_autocmd('FileType', { group = auname, command = 'echo "1"' }) + api.nvim_create_autocmd('FileType', { group = auname, command = 'echo "2"' }) - local aus = meths.get_autocmds { group = auname } + local aus = api.nvim_get_autocmds { group = auname } eq(2, #aus) - local aus2 = meths.get_autocmds { group = auname, event = "InsertEnter" } + local aus2 = api.nvim_get_autocmds { group = auname, event = 'InsertEnter' } eq(0, #aus2) end) @@ -510,12 +604,12 @@ describe('autocmd api', function() -- 1 for the first buffer -- 2 for First.md -- 3-7 for the 5 we make in the autocmd - eq({1, 2, 3, 4, 5, 6, 7}, bufs) + eq({ 1, 2, 3, 4, 5, 6, 7 }, bufs) end) it('can retrieve a callback from an autocmd', function() local content = 'I Am A Callback' - meths.set_var('content', content) + api.nvim_set_var('content', content) local result = exec_lua([[ local cb = function() return vim.g.content end @@ -534,12 +628,14 @@ describe('autocmd api', function() } ]]) - eq("function", result.cb.type) + eq('function', result.cb.type) eq(true, result.cb.can_retrieve) end) - it('will return an empty string as the command for an autocmd that uses a callback', function() - local result = exec_lua([[ + it( + 'will return an empty string as the command for an autocmd that uses a callback', + function() + local result = exec_lua([[ local callback = function() print 'I Am A Callback' end vim.api.nvim_create_autocmd("BufWritePost", { pattern = "*.py", @@ -553,8 +649,9 @@ describe('autocmd api', function() } ]]) - eq({ command = "", cbtype = 'function' }, result) - end) + eq({ command = '', cbtype = 'function' }, result) + end + ) end) describe('groups', function() @@ -574,7 +671,7 @@ describe('autocmd api', function() end) it('returns all groups if no group is specified', function() - local aus = meths.get_autocmds { event = "InsertEnter" } + local aus = api.nvim_get_autocmds { event = 'InsertEnter' } if #aus ~= 4 then eq({}, aus) end @@ -583,33 +680,34 @@ describe('autocmd api', function() end) it('returns only the group specified', function() - local aus = meths.get_autocmds { - event = "InsertEnter", - group = "GroupOne", + local aus = api.nvim_get_autocmds { + event = 'InsertEnter', + group = 'GroupOne', } eq(1, #aus) eq([[:echo "GroupOne:1"]], aus[1].command) - eq("GroupOne", aus[1].group_name) + eq('GroupOne', aus[1].group_name) end) it('returns only the group specified, multiple values', function() - local aus = meths.get_autocmds { - event = "InsertEnter", - group = "GroupTwo", + local aus = api.nvim_get_autocmds { + event = 'InsertEnter', + group = 'GroupTwo', } eq(2, #aus) eq([[:echo "GroupTwo:2"]], aus[1].command) - eq("GroupTwo", aus[1].group_name) + eq('GroupTwo', aus[1].group_name) eq([[:echo "GroupTwo:3"]], aus[2].command) - eq("GroupTwo", aus[2].group_name) + eq('GroupTwo', aus[2].group_name) end) end) describe('groups: 2', function() it('raises error for undefined augroup name', function() - local success, code = unpack(meths.exec_lua([[ + local success, code = unpack(api.nvim_exec_lua( + [[ return {pcall(function() vim.api.nvim_create_autocmd("FileType", { pattern = "*", @@ -617,14 +715,17 @@ describe('autocmd api', function() command = "echo 'hello'", }) end)} - ]], {})) + ]], + {} + )) eq(false, success) matches("Invalid 'group': 'NotDefined'", code) end) it('raises error for undefined augroup id', function() - local success, code = unpack(meths.exec_lua([[ + local success, code = unpack(api.nvim_exec_lua( + [[ return {pcall(function() -- Make sure the augroup is deleted vim.api.nvim_del_augroup_by_id(1) @@ -635,14 +736,17 @@ describe('autocmd api', function() command = "echo 'hello'", }) end)} - ]], {})) + ]], + {} + )) eq(false, success) matches("Invalid 'group': 1", code) end) it('raises error for invalid group type', function() - local success, code = unpack(meths.exec_lua([[ + local success, code = unpack(api.nvim_exec_lua( + [[ return {pcall(function() vim.api.nvim_create_autocmd("FileType", { pattern = "*", @@ -650,21 +754,26 @@ describe('autocmd api', function() command = "echo 'hello'", }) end)} - ]], {})) + ]], + {} + )) eq(false, success) matches("Invalid 'group': expected String or Integer, got Boolean", code) end) it('raises error for invalid pattern array', function() - local success, code = unpack(meths.exec_lua([[ + local success, code = unpack(api.nvim_exec_lua( + [[ return {pcall(function() vim.api.nvim_create_autocmd("FileType", { pattern = {{}}, command = "echo 'hello'", }) end)} - ]], {})) + ]], + {} + )) eq(false, success) matches("Invalid 'pattern' item: expected String, got Array", code) @@ -683,9 +792,9 @@ describe('autocmd api', function() end) it('returns for literal match', function() - local aus = meths.get_autocmds { - event = "InsertEnter", - pattern = "*" + local aus = api.nvim_get_autocmds { + event = 'InsertEnter', + pattern = '*', } eq(1, #aus) @@ -694,9 +803,9 @@ describe('autocmd api', function() it('returns for multiple matches', function() -- vim.api.nvim_get_autocmds - local aus = meths.get_autocmds { - event = "InsertEnter", - pattern = { "*.one", "*.two" }, + local aus = api.nvim_get_autocmds { + event = 'InsertEnter', + pattern = { '*.one', '*.two' }, } eq(3, #aus) @@ -706,19 +815,19 @@ describe('autocmd api', function() end) it('should work for buffer autocmds', function() - local normalized_aus = meths.get_autocmds { - event = "InsertEnter", - pattern = "<buffer=1>", + local normalized_aus = api.nvim_get_autocmds { + event = 'InsertEnter', + pattern = '<buffer=1>', } - local raw_aus = meths.get_autocmds { - event = "InsertEnter", - pattern = "<buffer>", + local raw_aus = api.nvim_get_autocmds { + event = 'InsertEnter', + pattern = '<buffer>', } - local zero_aus = meths.get_autocmds { - event = "InsertEnter", - pattern = "<buffer=0>", + local zero_aus = api.nvim_get_autocmds { + event = 'InsertEnter', + pattern = '<buffer=0>', } eq(normalized_aus, raw_aus) @@ -730,165 +839,186 @@ describe('autocmd api', function() describe('nvim_exec_autocmds', function() it('validation', function() - eq("Invalid 'group': 9997999", pcall_err(meths.exec_autocmds, 'FileType', { - group = 9997999, - })) - eq("Invalid 'group': 'bogus'", pcall_err(meths.exec_autocmds, 'FileType', { - group = 'bogus', - })) - eq("Invalid 'group': expected String or Integer, got Array", pcall_err(meths.exec_autocmds, 'FileType', { - group = {}, - })) - eq("Invalid 'group': 0", pcall_err(meths.exec_autocmds, 'FileType', { - group = 0, - })) - eq("Invalid 'buffer': expected Buffer, got Array", pcall_err(meths.exec_autocmds, 'FileType', { - buffer = {}, - })) - eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.exec_autocmds, - {'FileType', {}}, {})) + eq( + "Invalid 'group': 9997999", + pcall_err(api.nvim_exec_autocmds, 'FileType', { + group = 9997999, + }) + ) + eq( + "Invalid 'group': 'bogus'", + pcall_err(api.nvim_exec_autocmds, 'FileType', { + group = 'bogus', + }) + ) + eq( + "Invalid 'group': expected String or Integer, got Array", + pcall_err(api.nvim_exec_autocmds, 'FileType', { + group = {}, + }) + ) + eq( + "Invalid 'group': 0", + pcall_err(api.nvim_exec_autocmds, 'FileType', { + group = 0, + }) + ) + eq( + "Invalid 'buffer': expected Buffer, got Array", + pcall_err(api.nvim_exec_autocmds, 'FileType', { + buffer = {}, + }) + ) + eq( + "Invalid 'event' item: expected String, got Array", + pcall_err(api.nvim_exec_autocmds, { 'FileType', {} }, {}) + ) end) - it("can trigger builtin autocmds", function() - meths.set_var("autocmd_executed", false) + it('can trigger builtin autocmds', function() + api.nvim_set_var('autocmd_executed', false) - meths.create_autocmd("BufReadPost", { - pattern = "*", - command = "let g:autocmd_executed = v:true", + api.nvim_create_autocmd('BufReadPost', { + pattern = '*', + command = 'let g:autocmd_executed = v:true', }) - eq(false, meths.get_var("autocmd_executed")) - meths.exec_autocmds("BufReadPost", {}) - eq(true, meths.get_var("autocmd_executed")) + eq(false, api.nvim_get_var('autocmd_executed')) + api.nvim_exec_autocmds('BufReadPost', {}) + eq(true, api.nvim_get_var('autocmd_executed')) end) - it("can trigger multiple patterns", function() - meths.set_var("autocmd_executed", 0) + it('can trigger multiple patterns', function() + api.nvim_set_var('autocmd_executed', 0) - meths.create_autocmd("BufReadPost", { - pattern = "*", - command = "let g:autocmd_executed += 1", + api.nvim_create_autocmd('BufReadPost', { + pattern = '*', + command = 'let g:autocmd_executed += 1', }) - meths.exec_autocmds("BufReadPost", { pattern = { "*.lua", "*.vim" } }) - eq(2, meths.get_var("autocmd_executed")) + api.nvim_exec_autocmds('BufReadPost', { pattern = { '*.lua', '*.vim' } }) + eq(2, api.nvim_get_var('autocmd_executed')) - meths.create_autocmd("BufReadPre", { - pattern = { "bar", "foo" }, - command = "let g:autocmd_executed += 10", + api.nvim_create_autocmd('BufReadPre', { + pattern = { 'bar', 'foo' }, + command = 'let g:autocmd_executed += 10', }) - meths.exec_autocmds("BufReadPre", { pattern = { "foo", "bar", "baz", "frederick" }}) - eq(22, meths.get_var("autocmd_executed")) + api.nvim_exec_autocmds('BufReadPre', { pattern = { 'foo', 'bar', 'baz', 'frederick' } }) + eq(22, api.nvim_get_var('autocmd_executed')) end) - it("can pass the buffer", function() - meths.set_var("buffer_executed", -1) - eq(-1, meths.get_var("buffer_executed")) + it('can pass the buffer', function() + api.nvim_set_var('buffer_executed', -1) + eq(-1, api.nvim_get_var('buffer_executed')) - meths.create_autocmd("BufLeave", { - pattern = "*", + api.nvim_create_autocmd('BufLeave', { + pattern = '*', command = 'let g:buffer_executed = +expand("<abuf>")', }) -- Doesn't execute for other non-matching events - meths.exec_autocmds("CursorHold", { buffer = 1 }) - eq(-1, meths.get_var("buffer_executed")) + api.nvim_exec_autocmds('CursorHold', { buffer = 1 }) + eq(-1, api.nvim_get_var('buffer_executed')) - meths.exec_autocmds("BufLeave", { buffer = 1 }) - eq(1, meths.get_var("buffer_executed")) + api.nvim_exec_autocmds('BufLeave', { buffer = 1 }) + eq(1, api.nvim_get_var('buffer_executed')) end) - it("can pass the filename, pattern match", function() - meths.set_var("filename_executed", 'none') - eq('none', meths.get_var("filename_executed")) + it('can pass the filename, pattern match', function() + api.nvim_set_var('filename_executed', 'none') + eq('none', api.nvim_get_var('filename_executed')) - meths.create_autocmd("BufEnter", { - pattern = "*.py", + api.nvim_create_autocmd('BufEnter', { + pattern = '*.py', command = 'let g:filename_executed = expand("<afile>")', }) -- Doesn't execute for other non-matching events - meths.exec_autocmds("CursorHold", { buffer = 1 }) - eq('none', meths.get_var("filename_executed")) + api.nvim_exec_autocmds('CursorHold', { buffer = 1 }) + eq('none', api.nvim_get_var('filename_executed')) - meths.command('edit __init__.py') - eq('__init__.py', meths.get_var("filename_executed")) + command('edit __init__.py') + eq('__init__.py', api.nvim_get_var('filename_executed')) end) it('cannot pass buf and fname', function() - local ok = pcall(meths.exec_autocmds, "BufReadPre", { pattern = "literally_cannot_error.rs", buffer = 1 }) + local ok = pcall( + api.nvim_exec_autocmds, + 'BufReadPre', + { pattern = 'literally_cannot_error.rs', buffer = 1 } + ) eq(false, ok) end) - it("can pass the filename, exact match", function() - meths.set_var("filename_executed", 'none') - eq('none', meths.get_var("filename_executed")) + it('can pass the filename, exact match', function() + api.nvim_set_var('filename_executed', 'none') + eq('none', api.nvim_get_var('filename_executed')) - meths.command('edit other_file.txt') - meths.command('edit __init__.py') - eq('none', meths.get_var("filename_executed")) + command('edit other_file.txt') + command('edit __init__.py') + eq('none', api.nvim_get_var('filename_executed')) - meths.create_autocmd("CursorHoldI", { - pattern = "__init__.py", + api.nvim_create_autocmd('CursorHoldI', { + pattern = '__init__.py', command = 'let g:filename_executed = expand("<afile>")', }) -- Doesn't execute for other non-matching events - meths.exec_autocmds("CursorHoldI", { buffer = 1 }) - eq('none', meths.get_var("filename_executed")) + api.nvim_exec_autocmds('CursorHoldI', { buffer = 1 }) + eq('none', api.nvim_get_var('filename_executed')) - meths.exec_autocmds("CursorHoldI", { buffer = meths.get_current_buf() }) - eq('__init__.py', meths.get_var("filename_executed")) + api.nvim_exec_autocmds('CursorHoldI', { buffer = api.nvim_get_current_buf() }) + eq('__init__.py', api.nvim_get_var('filename_executed')) -- Reset filename - meths.set_var("filename_executed", 'none') + api.nvim_set_var('filename_executed', 'none') - meths.exec_autocmds("CursorHoldI", { pattern = '__init__.py' }) - eq('__init__.py', meths.get_var("filename_executed")) + api.nvim_exec_autocmds('CursorHoldI', { pattern = '__init__.py' }) + eq('__init__.py', api.nvim_get_var('filename_executed')) end) - it("works with user autocmds", function() - meths.set_var("matched", 'none') + it('works with user autocmds', function() + api.nvim_set_var('matched', 'none') - meths.create_autocmd("User", { - pattern = "TestCommand", - command = 'let g:matched = "matched"' + api.nvim_create_autocmd('User', { + pattern = 'TestCommand', + command = 'let g:matched = "matched"', }) - meths.exec_autocmds("User", { pattern = "OtherCommand" }) - eq('none', meths.get_var('matched')) - meths.exec_autocmds("User", { pattern = "TestCommand" }) - eq('matched', meths.get_var('matched')) + api.nvim_exec_autocmds('User', { pattern = 'OtherCommand' }) + eq('none', api.nvim_get_var('matched')) + api.nvim_exec_autocmds('User', { pattern = 'TestCommand' }) + eq('matched', api.nvim_get_var('matched')) end) it('can pass group by id', function() - meths.set_var("group_executed", false) + api.nvim_set_var('group_executed', false) - local auid = meths.create_augroup("nvim_test_augroup", { clear = true }) - meths.create_autocmd("FileType", { + local auid = api.nvim_create_augroup('nvim_test_augroup', { clear = true }) + api.nvim_create_autocmd('FileType', { group = auid, command = 'let g:group_executed = v:true', }) - eq(false, meths.get_var("group_executed")) - meths.exec_autocmds("FileType", { group = auid }) - eq(true, meths.get_var("group_executed")) + eq(false, api.nvim_get_var('group_executed')) + api.nvim_exec_autocmds('FileType', { group = auid }) + eq(true, api.nvim_get_var('group_executed')) end) it('can pass group by name', function() - meths.set_var("group_executed", false) + api.nvim_set_var('group_executed', false) - local auname = "nvim_test_augroup" - meths.create_augroup(auname, { clear = true }) - meths.create_autocmd("FileType", { + local auname = 'nvim_test_augroup' + api.nvim_create_augroup(auname, { clear = true }) + api.nvim_create_autocmd('FileType', { group = auname, command = 'let g:group_executed = v:true', }) - eq(false, meths.get_var("group_executed")) - meths.exec_autocmds("FileType", { group = auname }) - eq(true, meths.get_var("group_executed")) + eq(false, api.nvim_get_var('group_executed')) + api.nvim_exec_autocmds('FileType', { group = auname }) + eq(true, api.nvim_get_var('group_executed')) end) end) @@ -896,39 +1026,39 @@ describe('autocmd api', function() before_each(function() clear() - meths.set_var('executed', 0) + api.nvim_set_var('executed', 0) end) local make_counting_autocmd = function(opts) opts = opts or {} local resulting = { - pattern = "*", - command = "let g:executed = g:executed + 1", + pattern = '*', + command = 'let g:executed = g:executed + 1', } resulting.group = opts.group resulting.once = opts.once - meths.create_autocmd("FileType", resulting) + api.nvim_create_autocmd('FileType', resulting) end local set_ft = function(ft) - ft = ft or "txt" - source(string.format("set filetype=%s", ft)) + ft = ft or 'txt' + source(string.format('set filetype=%s', ft)) end local get_executed_count = function() - return meths.get_var('executed') + return api.nvim_get_var('executed') end it('can be added in a group', function() - local augroup = "TestGroup" - meths.create_augroup(augroup, { clear = true }) + local augroup = 'TestGroup' + api.nvim_create_augroup(augroup, { clear = true }) make_counting_autocmd { group = augroup } - set_ft("txt") - set_ft("python") + set_ft('txt') + set_ft('python') eq(2, get_executed_count()) end) @@ -943,7 +1073,7 @@ describe('autocmd api', function() end) it('handles ++once', function() - make_counting_autocmd {once = true} + make_counting_autocmd { once = true } set_ft('txt') set_ft('help') set_ft('txt') @@ -953,9 +1083,9 @@ describe('autocmd api', function() end) it('errors on unexpected keys', function() - local success, code = pcall(meths.create_autocmd, "FileType", { - pattern = "*", - not_a_valid_key = "NotDefined", + local success, code = pcall(api.nvim_create_autocmd, 'FileType', { + pattern = '*', + not_a_valid_key = 'NotDefined', }) eq(false, success) @@ -963,24 +1093,35 @@ describe('autocmd api', function() end) it('can execute simple callback', function() - exec_lua([[ + exec_lua( + [[ vim.g.executed = false vim.api.nvim_create_autocmd("FileType", { pattern = "*", callback = function() vim.g.executed = true end, }) - ]], {}) - - - eq(true, exec_lua([[ + ]], + {} + ) + + eq( + true, + exec_lua( + [[ vim.cmd "set filetype=txt" return vim.g.executed - ]], {})) + ]], + {} + ) + ) end) it('calls multiple lua callbacks for the same autocmd execution', function() - eq(4, exec_lua([[ + eq( + 4, + exec_lua( + [[ local count = 0 local counter = function() count = count + 1 @@ -1000,7 +1141,10 @@ describe('autocmd api', function() vim.cmd "set filetype=txt" return count - ]], {})) + ]], + {} + ) + ) end) it('properly releases functions with ++once', function() @@ -1030,108 +1174,112 @@ describe('autocmd api', function() command [[set filetype=txt]] eq(1, exec_lua([[return OnceCount]], {})) - eq(0, exec_lua([[ + eq( + 0, + exec_lua([[ local count = 0 for _ in pairs(WeakTable) do count = count + 1 end return count - ]]), "Should have no keys remaining") + ]]), + 'Should have no keys remaining' + ) end) it('groups can be cleared', function() - local augroup = "TestGroup" - meths.create_augroup(augroup, { clear = true }) - meths.create_autocmd("FileType", { + local augroup = 'TestGroup' + api.nvim_create_augroup(augroup, { clear = true }) + api.nvim_create_autocmd('FileType', { group = augroup, - command = "let g:executed = g:executed + 1" + command = 'let g:executed = g:executed + 1', }) - set_ft("txt") - set_ft("txt") - eq(2, get_executed_count(), "should only count twice") + set_ft('txt') + set_ft('txt') + eq(2, get_executed_count(), 'should only count twice') - meths.create_augroup(augroup, { clear = true }) - eq({}, meths.get_autocmds { group = augroup }) + api.nvim_create_augroup(augroup, { clear = true }) + eq({}, api.nvim_get_autocmds { group = augroup }) - set_ft("txt") - set_ft("txt") - eq(2, get_executed_count(), "No additional counts") + set_ft('txt') + set_ft('txt') + eq(2, get_executed_count(), 'No additional counts') end) it('can delete non-existent groups with pcall', function() - eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_name, 'noexist')]]) - eq('Vim:E367: No such group: "noexist"', pcall_err(meths.del_augroup_by_name, 'noexist')) + eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_name, 'noexist')]]) + eq('Vim:E367: No such group: "noexist"', pcall_err(api.nvim_del_augroup_by_name, 'noexist')) - eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, -12342)]]) - eq('Vim:E367: No such group: "--Deleted--"', pcall_err(meths.del_augroup_by_id, -12312)) + eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, -12342)]]) + eq('Vim:E367: No such group: "--Deleted--"', pcall_err(api.nvim_del_augroup_by_id, -12312)) - eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, 0)]]) - eq('Vim:E367: No such group: "[NULL]"', pcall_err(meths.del_augroup_by_id, 0)) + eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, 0)]]) + eq('Vim:E367: No such group: "[NULL]"', pcall_err(api.nvim_del_augroup_by_id, 0)) - eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, 12342)]]) - eq('Vim:E367: No such group: "[NULL]"', pcall_err(meths.del_augroup_by_id, 12312)) + eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, 12342)]]) + eq('Vim:E367: No such group: "[NULL]"', pcall_err(api.nvim_del_augroup_by_id, 12312)) end) it('groups work with once', function() - local augroup = "TestGroup" + local augroup = 'TestGroup' - meths.create_augroup(augroup, { clear = true }) + api.nvim_create_augroup(augroup, { clear = true }) make_counting_autocmd { group = augroup, once = true } - set_ft("txt") - set_ft("python") + set_ft('txt') + set_ft('python') eq(1, get_executed_count()) end) it('autocmds can be registered multiple times.', function() - local augroup = "TestGroup" + local augroup = 'TestGroup' - meths.create_augroup(augroup, { clear = true }) + api.nvim_create_augroup(augroup, { clear = true }) make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false } make_counting_autocmd { group = augroup, once = false } - set_ft("txt") - set_ft("python") + set_ft('txt') + set_ft('python') eq(3 * 2, get_executed_count()) end) it('can be deleted', function() - local augroup = "WillBeDeleted" + local augroup = 'WillBeDeleted' - meths.create_augroup(augroup, { clear = true }) - meths.create_autocmd({"FileType"}, { - pattern = "*", + api.nvim_create_augroup(augroup, { clear = true }) + api.nvim_create_autocmd({ 'FileType' }, { + pattern = '*', command = "echo 'does not matter'", }) -- Clears the augroup from before, which erases the autocmd - meths.create_augroup(augroup, { clear = true }) + api.nvim_create_augroup(augroup, { clear = true }) - local result = #meths.get_autocmds { group = augroup } + local result = #api.nvim_get_autocmds { group = augroup } eq(0, result) end) it('can be used for buffer local autocmds', function() - local augroup = "WillBeDeleted" + local augroup = 'WillBeDeleted' - meths.set_var("value_set", false) + api.nvim_set_var('value_set', false) - meths.create_augroup(augroup, { clear = true }) - meths.create_autocmd("FileType", { - pattern = "<buffer>", - command = "let g:value_set = v:true", + api.nvim_create_augroup(augroup, { clear = true }) + api.nvim_create_autocmd('FileType', { + pattern = '<buffer>', + command = 'let g:value_set = v:true', }) - command "new" - command "set filetype=python" + command 'new' + command 'set filetype=python' - eq(false, meths.get_var("value_set")) + eq(false, api.nvim_get_var('value_set')) end) it('can accept vimscript functions', function() @@ -1154,118 +1302,124 @@ describe('autocmd api', function() set filetype=txt ]] - eq(2, meths.get_var("vimscript_executed")) + eq(2, api.nvim_get_var('vimscript_executed')) end) end) describe('augroup!', function() it('legacy: should clear and not return any autocmds for delete groups', function() - command('augroup TEMP_A') - command(' autocmd! BufReadPost *.py :echo "Hello"') - command('augroup END') + command('augroup TEMP_A') + command(' autocmd! BufReadPost *.py :echo "Hello"') + command('augroup END') - command('augroup! TEMP_A') + command('augroup! TEMP_A') - eq(false, pcall(meths.get_autocmds, { group = 'TEMP_A' })) + eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_A' })) - -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild - -- but we managed to keep this behavior. - eq(1, #meths.get_autocmds { event = 'BufReadPost' }) + -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild + -- but we managed to keep this behavior. + eq(1, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) it('legacy: remove augroups that have no autocmds', function() - command('augroup TEMP_AB') - command('augroup END') + command('augroup TEMP_AB') + command('augroup END') - command('augroup! TEMP_AB') + command('augroup! TEMP_AB') - eq(false, pcall(meths.get_autocmds, { group = 'TEMP_AB' })) - eq(0, #meths.get_autocmds { event = 'BufReadPost' }) + eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_AB' })) + eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) it('legacy: multiple remove and add augroup', function() - command('augroup TEMP_ABC') - command(' au!') - command(' autocmd BufReadPost *.py echo "Hello"') - command('augroup END') + command('augroup TEMP_ABC') + command(' au!') + command(' autocmd BufReadPost *.py echo "Hello"') + command('augroup END') - command('augroup! TEMP_ABC') + command('augroup! TEMP_ABC') - -- Should still have one autocmd :'( - local aus = meths.get_autocmds { event = 'BufReadPost' } - eq(1, #aus, aus) + -- Should still have one autocmd :'( + local aus = api.nvim_get_autocmds { event = 'BufReadPost' } + eq(1, #aus, aus) - command('augroup TEMP_ABC') - command(' au!') - command(' autocmd BufReadPost *.py echo "Hello"') - command('augroup END') + command('augroup TEMP_ABC') + command(' au!') + command(' autocmd BufReadPost *.py echo "Hello"') + command('augroup END') - -- Should now have two autocmds :'( - aus = meths.get_autocmds { event = 'BufReadPost' } - eq(2, #aus, aus) + -- Should now have two autocmds :'( + aus = api.nvim_get_autocmds { event = 'BufReadPost' } + eq(2, #aus, aus) - command('augroup! TEMP_ABC') + command('augroup! TEMP_ABC') - eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABC' })) - eq(2, #meths.get_autocmds { event = 'BufReadPost' }) + eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABC' })) + eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) it('api: should clear and not return any autocmds for delete groups by id', function() - command('augroup TEMP_ABCD') - command('autocmd! BufReadPost *.py :echo "Hello"') - command('augroup END') + command('augroup TEMP_ABCD') + command('autocmd! BufReadPost *.py :echo "Hello"') + command('augroup END') - local augroup_id = meths.create_augroup("TEMP_ABCD", { clear = false }) - meths.del_augroup_by_id(augroup_id) + local augroup_id = api.nvim_create_augroup('TEMP_ABCD', { clear = false }) + api.nvim_del_augroup_by_id(augroup_id) - -- For good reason, we kill all the autocmds from del_augroup, - -- so now this works as expected - eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCD' })) - eq(0, #meths.get_autocmds { event = 'BufReadPost' }) + -- For good reason, we kill all the autocmds from del_augroup, + -- so now this works as expected + eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABCD' })) + eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) it('api: should clear and not return any autocmds for delete groups by name', function() - command('augroup TEMP_ABCDE') - command('autocmd! BufReadPost *.py :echo "Hello"') - command('augroup END') + command('augroup TEMP_ABCDE') + command('autocmd! BufReadPost *.py :echo "Hello"') + command('augroup END') - meths.del_augroup_by_name("TEMP_ABCDE") + api.nvim_del_augroup_by_name('TEMP_ABCDE') - -- For good reason, we kill all the autocmds from del_augroup, - -- so now this works as expected - eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCDE' })) - eq(0, #meths.get_autocmds { event = 'BufReadPost' }) + -- For good reason, we kill all the autocmds from del_augroup, + -- so now this works as expected + eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABCDE' })) + eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' }) end) end) describe('nvim_clear_autocmds', function() it('validation', function() - eq("Cannot use both 'pattern' and 'buffer'", pcall_err(meths.clear_autocmds, { - pattern = '*', - buffer = 42, - })) - eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.clear_autocmds, { - event = {'FileType', {}} - })) - eq("Invalid 'group': 0", pcall_err(meths.clear_autocmds, {group = 0})) + eq( + "Cannot use both 'pattern' and 'buffer'", + pcall_err(api.nvim_clear_autocmds, { + pattern = '*', + buffer = 42, + }) + ) + eq( + "Invalid 'event' item: expected String, got Array", + pcall_err(api.nvim_clear_autocmds, { + event = { 'FileType', {} }, + }) + ) + eq("Invalid 'group': 0", pcall_err(api.nvim_clear_autocmds, { group = 0 })) end) it('should clear based on event + pattern', function() command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"') command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"') - local search = { event = "InsertEnter", pattern = "*.txt" } - local before_delete = meths.get_autocmds(search) + local search = { event = 'InsertEnter', pattern = '*.txt' } + local before_delete = api.nvim_get_autocmds(search) eq(1, #before_delete) - local before_delete_all = meths.get_autocmds { event = search.event } + local before_delete_all = api.nvim_get_autocmds { event = search.event } eq(2, #before_delete_all) - meths.clear_autocmds(search) - local after_delete = meths.get_autocmds(search) + api.nvim_clear_autocmds(search) + local after_delete = api.nvim_get_autocmds(search) eq(0, #after_delete) - local after_delete_all = meths.get_autocmds { event = search.event } + local after_delete_all = api.nvim_get_autocmds { event = search.event } eq(1, #after_delete_all) end) @@ -1273,12 +1427,12 @@ describe('autocmd api', function() command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"') command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"') - local search = { event = "InsertEnter"} - local before_delete = meths.get_autocmds(search) + local search = { event = 'InsertEnter' } + local before_delete = api.nvim_get_autocmds(search) eq(2, #before_delete) - meths.clear_autocmds(search) - local after_delete = meths.get_autocmds(search) + api.nvim_clear_autocmds(search) + local after_delete = api.nvim_get_autocmds(search) eq(0, #after_delete) end) @@ -1288,17 +1442,18 @@ describe('autocmd api', function() command('autocmd InsertEnter *.TestPat2 :echo "Enter 2"') command('autocmd InsertLeave *.TestPat2 :echo "Leave 2"') - local search = { pattern = "*.TestPat1"} - local before_delete = meths.get_autocmds(search) + local search = { pattern = '*.TestPat1' } + local before_delete = api.nvim_get_autocmds(search) eq(2, #before_delete) - local before_delete_events = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } + local before_delete_events = + api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } } eq(4, #before_delete_events) - meths.clear_autocmds(search) - local after_delete = meths.get_autocmds(search) + api.nvim_clear_autocmds(search) + local after_delete = api.nvim_get_autocmds(search) eq(0, #after_delete) - local after_delete_events = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } } + local after_delete_events = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } } eq(2, #after_delete_events) end) @@ -1307,14 +1462,14 @@ describe('autocmd api', function() command('autocmd InsertEnter <buffer> :echo "Enter Buffer"') command('autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"') - local search = { event = "InsertEnter" } - local before_delete = meths.get_autocmds(search) + local search = { event = 'InsertEnter' } + local before_delete = api.nvim_get_autocmds(search) eq(2, #before_delete) - meths.clear_autocmds { buffer = 0 } - local after_delete = meths.get_autocmds(search) + api.nvim_clear_autocmds { buffer = 0 } + local after_delete = api.nvim_get_autocmds(search) eq(1, #after_delete) - eq("*.TestPat1", after_delete[1].pattern) + eq('*.TestPat1', after_delete[1].pattern) end) it('should allow clearing by buffer and group', function() @@ -1324,18 +1479,18 @@ describe('autocmd api', function() command(' autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"') command('augroup END') - local search = { event = "InsertEnter", group = "TestNvimClearAutocmds" } - local before_delete = meths.get_autocmds(search) + local search = { event = 'InsertEnter', group = 'TestNvimClearAutocmds' } + local before_delete = api.nvim_get_autocmds(search) eq(2, #before_delete) -- Doesn't clear without passing group. - meths.clear_autocmds { buffer = 0 } - local without_group = meths.get_autocmds(search) + api.nvim_clear_autocmds { buffer = 0 } + local without_group = api.nvim_get_autocmds(search) eq(2, #without_group) -- Doesn't clear with passing group. - meths.clear_autocmds { buffer = 0, group = search.group } - local with_group = meths.get_autocmds(search) + api.nvim_clear_autocmds { buffer = 0, group = search.group } + local with_group = api.nvim_get_autocmds(search) eq(1, #with_group) end) end) diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 6ed9aa574a..78d220ff57 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -1,19 +1,18 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer -local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq -local curbufmeths, ok = helpers.curbufmeths, helpers.ok +local clear = helpers.clear +local eq = helpers.eq +local ok = helpers.ok local describe_lua_and_rpc = helpers.describe_lua_and_rpc(describe) -local meths = helpers.meths -local funcs = helpers.funcs +local api = helpers.api +local fn = helpers.fn local request = helpers.request local exc_exec = helpers.exc_exec local exec_lua = helpers.exec_lua local feed_command = helpers.feed_command local insert = helpers.insert -local NIL = helpers.NIL +local NIL = vim.NIL local command = helpers.command -local bufmeths = helpers.bufmeths local feed = helpers.feed local pcall_err = helpers.pcall_err local assert_alive = helpers.assert_alive @@ -23,16 +22,15 @@ describe('api/buf', function() -- access deprecated functions local function curbuf_depr(method, ...) - return request('buffer_'..method, 0, ...) + return request('buffer_' .. method, 0, ...) end - describe('nvim_buf_set_lines, nvim_buf_line_count', function() it('deprecated forms', function() eq(1, curbuf_depr('line_count')) - curbuf_depr('insert', -1, {'line'}) + curbuf_depr('insert', -1, { 'line' }) eq(2, curbuf_depr('line_count')) - curbuf_depr('insert', -1, {'line'}) + curbuf_depr('insert', -1, { 'line' }) eq(3, curbuf_depr('line_count')) curbuf_depr('del_line', -1) eq(2, curbuf_depr('line_count')) @@ -43,108 +41,114 @@ describe('api/buf', function() end) it("doesn't crash just after set undolevels=1 #24894", function() - local buf = meths.create_buf(false, true) - meths.buf_set_option(buf, 'undolevels', -1) - meths.buf_set_lines(buf, 0, 1, false, { }) + local buf = api.nvim_create_buf(false, true) + api.nvim_buf_set_option(buf, 'undolevels', -1) + api.nvim_buf_set_lines(buf, 0, 1, false, {}) assert_alive() end) it('cursor position is maintained after lines are inserted #9961', function() -- replace the buffer contents with these three lines. - request('nvim_buf_set_lines', 0, 0, -1, 1, {"line1", "line2", "line3", "line4"}) + api.nvim_buf_set_lines(0, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' }) -- Set the current cursor to {3, 2}. - curwin('set_cursor', {3, 2}) + api.nvim_win_set_cursor(0, { 3, 2 }) -- add 2 lines and delete 1 line above the current cursor position. - request('nvim_buf_set_lines', 0, 1, 2, 1, {"line5", "line6"}) + api.nvim_buf_set_lines(0, 1, 2, true, { 'line5', 'line6' }) -- check the current set of lines in the buffer. - eq({"line1", "line5", "line6", "line3", "line4"}, buffer('get_lines', 0, 0, -1, 1)) + eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, api.nvim_buf_get_lines(0, 0, -1, true)) -- cursor should be moved below by 1 line. - eq({4, 2}, curwin('get_cursor')) + eq({ 4, 2 }, api.nvim_win_get_cursor(0)) -- add a line after the current cursor position. - request('nvim_buf_set_lines', 0, 5, 5, 1, {"line7"}) + api.nvim_buf_set_lines(0, 5, 5, true, { 'line7' }) -- check the current set of lines in the buffer. - eq({"line1", "line5", "line6", "line3", "line4", "line7"}, buffer('get_lines', 0, 0, -1, 1)) + eq( + { 'line1', 'line5', 'line6', 'line3', 'line4', 'line7' }, + api.nvim_buf_get_lines(0, 0, -1, true) + ) -- cursor position is unchanged. - eq({4, 2}, curwin('get_cursor')) + eq({ 4, 2 }, api.nvim_win_get_cursor(0)) -- overwrite current cursor line. - request('nvim_buf_set_lines', 0, 3, 5, 1, {"line8", "line9"}) + api.nvim_buf_set_lines(0, 3, 5, true, { 'line8', 'line9' }) -- check the current set of lines in the buffer. - eq({"line1", "line5", "line6", "line8", "line9", "line7"}, buffer('get_lines', 0, 0, -1, 1)) + eq( + { 'line1', 'line5', 'line6', 'line8', 'line9', 'line7' }, + api.nvim_buf_get_lines(0, 0, -1, true) + ) -- cursor position is unchanged. - eq({4, 2}, curwin('get_cursor')) + eq({ 4, 2 }, api.nvim_win_get_cursor(0)) -- delete current cursor line. - request('nvim_buf_set_lines', 0, 3, 5, 1, {}) + api.nvim_buf_set_lines(0, 3, 5, true, {}) -- check the current set of lines in the buffer. - eq({"line1", "line5", "line6", "line7"}, buffer('get_lines', 0, 0, -1, 1)) + eq({ 'line1', 'line5', 'line6', 'line7' }, api.nvim_buf_get_lines(0, 0, -1, true)) -- cursor position is unchanged. - eq({4, 2}, curwin('get_cursor')) + eq({ 4, 2 }, api.nvim_win_get_cursor(0)) end) it('cursor position is maintained in non-current window', function() - meths.buf_set_lines(0, 0, -1, 1, {"line1", "line2", "line3", "line4"}) - meths.win_set_cursor(0, {3, 2}) - local win = meths.get_current_win() - local buf = meths.get_current_buf() + api.nvim_buf_set_lines(0, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' }) + api.nvim_win_set_cursor(0, { 3, 2 }) + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('new') - meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"}) - eq({"line1", "line5", "line6", "line3", "line4"}, meths.buf_get_lines(buf, 0, -1, true)) - eq({4, 2}, meths.win_get_cursor(win)) + api.nvim_buf_set_lines(buf, 1, 2, true, { 'line5', 'line6' }) + eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, api.nvim_buf_get_lines(buf, 0, -1, true)) + eq({ 4, 2 }, api.nvim_win_get_cursor(win)) end) it('cursor position is maintained in TWO non-current windows', function() - meths.buf_set_lines(0, 0, -1, 1, {"line1", "line2", "line3", "line4"}) - meths.win_set_cursor(0, {3, 2}) - local win = meths.get_current_win() - local buf = meths.get_current_buf() + api.nvim_buf_set_lines(0, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' }) + api.nvim_win_set_cursor(0, { 3, 2 }) + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('split') - meths.win_set_cursor(0, {4, 2}) - local win2 = meths.get_current_win() + api.nvim_win_set_cursor(0, { 4, 2 }) + local win2 = api.nvim_get_current_win() -- set current window to third one with another buffer - command("new") + command('new') - meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"}) - eq({"line1", "line5", "line6", "line3", "line4"}, meths.buf_get_lines(buf, 0, -1, true)) - eq({4, 2}, meths.win_get_cursor(win)) - eq({5, 2}, meths.win_get_cursor(win2)) + api.nvim_buf_set_lines(buf, 1, 2, true, { 'line5', 'line6' }) + eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, api.nvim_buf_get_lines(buf, 0, -1, true)) + eq({ 4, 2 }, api.nvim_win_get_cursor(win)) + eq({ 5, 2 }, api.nvim_win_get_cursor(win2)) end) it('line_count has defined behaviour for unloaded buffers', function() -- we'll need to know our bufnr for when it gets unloaded - local bufnr = curbuf('get_number') + local bufnr = api.nvim_buf_get_number(0) -- replace the buffer contents with these three lines - request('nvim_buf_set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"}) + api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' }) -- check the line count is correct - eq(4, request('nvim_buf_line_count', bufnr)) + eq(4, api.nvim_buf_line_count(bufnr)) -- force unload the buffer (this will discard changes) command('new') - command('bunload! '..bufnr) + command('bunload! ' .. bufnr) -- line count for an unloaded buffer should always be 0 - eq(0, request('nvim_buf_line_count', bufnr)) + eq(0, api.nvim_buf_line_count(bufnr)) end) it('get_lines has defined behaviour for unloaded buffers', function() -- we'll need to know our bufnr for when it gets unloaded - local bufnr = curbuf('get_number') + local bufnr = api.nvim_buf_get_number(0) -- replace the buffer contents with these three lines - buffer('set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"}) + api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' }) -- confirm that getting lines works - eq({"line2", "line3"}, buffer('get_lines', bufnr, 1, 3, 1)) + eq({ 'line2', 'line3' }, api.nvim_buf_get_lines(bufnr, 1, 3, true)) -- force unload the buffer (this will discard changes) command('new') - command('bunload! '..bufnr) + command('bunload! ' .. bufnr) -- attempting to get lines now always gives empty list - eq({}, buffer('get_lines', bufnr, 1, 3, 1)) + eq({}, api.nvim_buf_get_lines(bufnr, 1, 3, true)) -- it's impossible to get out-of-bounds errors for an unloaded buffer - eq({}, buffer('get_lines', bufnr, 8888, 9999, 1)) + eq({}, api.nvim_buf_get_lines(bufnr, 8888, 9999, true)) end) describe('handles topline', function() @@ -152,28 +156,32 @@ describe('api/buf', function() before_each(function() screen = Screen.new(20, 12) screen:set_default_attr_ids { - [1] = {bold = true, foreground = Screen.colors.Blue1}; - [2] = {reverse = true, bold = true}; - [3] = {reverse = true}; + [1] = { bold = true, foreground = Screen.colors.Blue1 }, + [2] = { reverse = true, bold = true }, + [3] = { reverse = true }, } screen:attach() - meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"}) - meths.set_option_value('modified', false, {}) + api.nvim_buf_set_lines( + 0, + 0, + -1, + true, + { 'aaa', 'bbb', 'ccc', 'ddd', 'www', 'xxx', 'yyy', 'zzz' } + ) + api.nvim_set_option_value('modified', false, {}) end) it('of current window', function() - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('new | wincmd w') - meths.win_set_cursor(win, {8,0}) + api.nvim_win_set_cursor(win, { 8, 0 }) - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| www | xxx | @@ -181,15 +189,14 @@ describe('api/buf', function() ^zzz | {2:[No Name] }| | - ]]} + ]], + } - meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 0, 2, true, { 'aaabbb' }) + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| www | xxx | @@ -197,16 +204,15 @@ describe('api/buf', function() ^zzz | {2:[No Name] [+] }| | - ]]} + ]], + } -- replacing topline keeps it the topline - meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 3, 4, true, { 'wwweeee' }) + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| wwweeee | xxx | @@ -214,16 +220,15 @@ describe('api/buf', function() ^zzz | {2:[No Name] [+] }| | - ]]} + ]], + } -- inserting just before topline does not scroll up if cursor would be moved - meths.buf_set_lines(buf, 3, 3, true, {"mmm"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' }) + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| wwweeee | xxx | @@ -231,15 +236,15 @@ describe('api/buf', function() ^zzz | {2:[No Name] [+] }| | - ]], unchanged=true} + ]], + unchanged = true, + } - meths.win_set_cursor(0, {7, 0}) - screen:expect{grid=[[ + api.nvim_win_set_cursor(0, { 7, 0 }) + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| wwweeee | xxx | @@ -247,15 +252,14 @@ describe('api/buf', function() zzz | {2:[No Name] [+] }| | - ]]} + ]], + } - meths.buf_set_lines(buf, 4, 4, true, {"mmmeeeee"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 4, 4, true, { 'mmmeeeee' }) + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| mmmeeeee | wwweeee | @@ -263,22 +267,21 @@ describe('api/buf', function() ^yyy | {2:[No Name] [+] }| | - ]]} + ]], + } end) it('of non-current window', function() - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('new') - meths.win_set_cursor(win, {8,0}) + api.nvim_win_set_cursor(win, { 8, 0 }) - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {2:[No Name] }| www | xxx | @@ -286,15 +289,14 @@ describe('api/buf', function() zzz | {3:[No Name] }| | - ]]} + ]], + } - meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 0, 2, true, { 'aaabbb' }) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {2:[No Name] }| www | xxx | @@ -302,16 +304,15 @@ describe('api/buf', function() zzz | {3:[No Name] [+] }| | - ]]} + ]], + } -- replacing topline keeps it the topline - meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 3, 4, true, { 'wwweeee' }) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {2:[No Name] }| wwweeee | xxx | @@ -319,16 +320,15 @@ describe('api/buf', function() zzz | {3:[No Name] [+] }| | - ]]} + ]], + } -- inserting just before topline scrolls up - meths.buf_set_lines(buf, 3, 3, true, {"mmm"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' }) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {2:[No Name] }| mmm | wwweeee | @@ -336,18 +336,20 @@ describe('api/buf', function() yyy | {3:[No Name] [+] }| | - ]]} + ]], + } end) it('of split windows with same buffer', function() - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('split') - meths.win_set_cursor(win, {8,0}) - meths.win_set_cursor(0, {1,0}) + api.nvim_win_set_cursor(win, { 8, 0 }) + api.nvim_win_set_cursor(0, { 1, 0 }) - screen:expect{grid=[[ + screen:expect { + grid = [[ ^aaa | bbb | ccc | @@ -360,10 +362,12 @@ describe('api/buf', function() zzz | {3:[No Name] }| | - ]]} - meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"}) + ]], + } + api.nvim_buf_set_lines(buf, 0, 2, true, { 'aaabbb' }) - screen:expect{grid=[[ + screen:expect { + grid = [[ ^aaabbb | ccc | ddd | @@ -376,11 +380,13 @@ describe('api/buf', function() zzz | {3:[No Name] [+] }| | - ]]} + ]], + } -- replacing topline keeps it the topline - meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 3, 4, true, { 'wwweeee' }) + screen:expect { + grid = [[ ^aaabbb | ccc | ddd | @@ -393,11 +399,13 @@ describe('api/buf', function() zzz | {3:[No Name] [+] }| | - ]]} + ]], + } -- inserting just before topline scrolls up - meths.buf_set_lines(buf, 3, 3, true, {"mmm"}) - screen:expect{grid=[[ + api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' }) + screen:expect { + grid = [[ ^aaabbb | ccc | ddd | @@ -410,20 +418,21 @@ describe('api/buf', function() yyy | {3:[No Name] [+] }| | - ]]} + ]], + } end) end) it('handles clearing out non-current buffer #24911', function() - local buf = meths.get_current_buf() - meths.buf_set_lines(buf, 0, -1, true, {"aaa", "bbb", "ccc"}) - command("new") + local buf = api.nvim_get_current_buf() + api.nvim_buf_set_lines(buf, 0, -1, true, { 'aaa', 'bbb', 'ccc' }) + command('new') - meths.buf_set_lines(0, 0, -1, true, {"xxx", "yyy", "zzz"}) + api.nvim_buf_set_lines(0, 0, -1, true, { 'xxx', 'yyy', 'zzz' }) - meths.buf_set_lines(buf, 0, -1, true, {}) - eq({"xxx", "yyy", "zzz"}, meths.buf_get_lines(0, 0, -1, true)) - eq({''}, meths.buf_get_lines(buf, 0, -1, true)) + api.nvim_buf_set_lines(buf, 0, -1, true, {}) + eq({ 'xxx', 'yyy', 'zzz' }, api.nvim_buf_get_lines(0, 0, -1, true)) + eq({ '' }, api.nvim_buf_get_lines(buf, 0, -1, true)) end) end) @@ -461,8 +470,8 @@ describe('api/buf', function() describe('deprecated: {get,set}_line_slice', function() it('get_line_slice: out-of-bounds returns empty array', function() - curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity + curbuf_depr('set_line_slice', 0, 0, true, true, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity eq({}, curbuf_depr('get_line_slice', 2, 3, false, true)) eq({}, curbuf_depr('get_line_slice', 3, 9, true, true)) @@ -472,62 +481,73 @@ describe('api/buf', function() end) it('set_line_slice: out-of-bounds extends past end', function() - curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity + curbuf_depr('set_line_slice', 0, 0, true, true, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity - eq({'c'}, curbuf_depr('get_line_slice', -1, 4, true, true)) - eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 5, true, true)) - curbuf_depr('set_line_slice', 4, 5, true, true, {'d'}) - eq({'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true)) - curbuf_depr('set_line_slice', -4, -5, true, true, {'e'}) - eq({'e', 'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true)) + eq({ 'c' }, curbuf_depr('get_line_slice', -1, 4, true, true)) + eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, 5, true, true)) + curbuf_depr('set_line_slice', 4, 5, true, true, { 'd' }) + eq({ 'a', 'b', 'c', 'd' }, curbuf_depr('get_line_slice', 0, 5, true, true)) + curbuf_depr('set_line_slice', -4, -5, true, true, { 'e' }) + eq({ 'e', 'a', 'b', 'c', 'd' }, curbuf_depr('get_line_slice', 0, 5, true, true)) end) it('works', function() - eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true)) + eq({ '' }, curbuf_depr('get_line_slice', 0, -1, true, true)) -- Replace buffer - curbuf_depr('set_line_slice', 0, -1, true, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true)) - eq({'b', 'c'}, curbuf_depr('get_line_slice', 1, -1, true, true)) - eq({'b'}, curbuf_depr('get_line_slice', 1, 2, true, false)) + curbuf_depr('set_line_slice', 0, -1, true, true, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true)) + eq({ 'b', 'c' }, curbuf_depr('get_line_slice', 1, -1, true, true)) + eq({ 'b' }, curbuf_depr('get_line_slice', 1, 2, true, false)) eq({}, curbuf_depr('get_line_slice', 1, 1, true, false)) - eq({'a', 'b'}, curbuf_depr('get_line_slice', 0, -1, true, false)) - eq({'b'}, curbuf_depr('get_line_slice', 1, -1, true, false)) - eq({'b', 'c'}, curbuf_depr('get_line_slice', -2, -1, true, true)) - curbuf_depr('set_line_slice', 1, 2, true, false, {'a', 'b', 'c'}) - eq({'a', 'a', 'b', 'c', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true)) - curbuf_depr('set_line_slice', -1, -1, true, true, {'a', 'b', 'c'}) - eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'}, - curbuf_depr('get_line_slice', 0, -1, true, true)) + eq({ 'a', 'b' }, curbuf_depr('get_line_slice', 0, -1, true, false)) + eq({ 'b' }, curbuf_depr('get_line_slice', 1, -1, true, false)) + eq({ 'b', 'c' }, curbuf_depr('get_line_slice', -2, -1, true, true)) + curbuf_depr('set_line_slice', 1, 2, true, false, { 'a', 'b', 'c' }) + eq({ 'a', 'a', 'b', 'c', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true)) + curbuf_depr('set_line_slice', -1, -1, true, true, { 'a', 'b', 'c' }) + eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true)) curbuf_depr('set_line_slice', 0, -3, true, false, {}) - eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true)) + eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true)) curbuf_depr('set_line_slice', 0, -1, true, true, {}) - eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true)) + eq({ '' }, curbuf_depr('get_line_slice', 0, -1, true, true)) end) end) - describe_lua_and_rpc('nvim_buf_get_lines, nvim_buf_set_lines', function(api) - local get_lines = api.curbufmeths.get_lines - local set_lines = api.curbufmeths.set_lines - local line_count = api.curbufmeths.line_count + describe_lua_and_rpc('nvim_buf_get_lines, nvim_buf_set_lines', function(lua_or_rpc) + local function get_lines(...) + return lua_or_rpc.nvim_buf_get_lines(0, ...) + end + + local function set_lines(...) + return lua_or_rpc.nvim_buf_set_lines(0, ...) + end + + local function line_count() + return lua_or_rpc.nvim_buf_line_count(0) + end it('fails correctly when input is not valid', function() - eq(1, api.curbufmeths.get_number()) - eq([['replacement string' item contains newlines]], - pcall_err(bufmeths.set_lines, 1, 1, 2, false, {'b\na'})) + eq(1, lua_or_rpc.nvim_buf_get_number(0)) + eq( + [['replacement string' item contains newlines]], + pcall_err(lua_or_rpc.nvim_buf_set_lines, 1, 1, 2, false, { 'b\na' }) + ) end) it("fails if 'nomodifiable'", function() command('set nomodifiable') - eq([[Buffer is not 'modifiable']], - pcall_err(api.bufmeths.set_lines, 1, 1, 2, false, {'a','b'})) + eq( + [[Buffer is not 'modifiable']], + pcall_err(lua_or_rpc.nvim_buf_set_lines, 1, 1, 2, false, { 'a', 'b' }) + ) end) it('has correct line_count when inserting and deleting', function() eq(1, line_count()) - set_lines(-1, -1, true, {'line'}) + set_lines(-1, -1, true, { 'line' }) eq(2, line_count()) - set_lines(-1, -1, true, {'line'}) + set_lines(-1, -1, true, { 'line' }) eq(3, line_count()) set_lines(-2, -1, true, {}) eq(2, line_count()) @@ -538,81 +558,80 @@ describe('api/buf', function() end) it('can get, set and delete a single line', function() - eq({''}, get_lines(0, 1, true)) - set_lines(0, 1, true, {'line1'}) - eq({'line1'}, get_lines(0, 1, true)) - set_lines(0, 1, true, {'line2'}) - eq({'line2'}, get_lines(0, 1, true)) + eq({ '' }, get_lines(0, 1, true)) + set_lines(0, 1, true, { 'line1' }) + eq({ 'line1' }, get_lines(0, 1, true)) + set_lines(0, 1, true, { 'line2' }) + eq({ 'line2' }, get_lines(0, 1, true)) set_lines(0, 1, true, {}) - eq({''}, get_lines(0, 1, true)) + eq({ '' }, get_lines(0, 1, true)) end) it('can get a single line with strict indexing', function() - set_lines(0, 1, true, {'line1.a'}) + set_lines(0, 1, true, { 'line1.a' }) eq(1, line_count()) -- sanity eq('Index out of bounds', pcall_err(get_lines, 1, 2, true)) eq('Index out of bounds', pcall_err(get_lines, -3, -2, true)) end) it('can get a single line with non-strict indexing', function() - set_lines(0, 1, true, {'line1.a'}) + set_lines(0, 1, true, { 'line1.a' }) eq(1, line_count()) -- sanity eq({}, get_lines(1, 2, false)) eq({}, get_lines(-3, -2, false)) end) it('can set and delete a single line with strict indexing', function() - set_lines(0, 1, true, {'line1.a'}) - eq('Index out of bounds', pcall_err(set_lines, 1, 2, true, {'line1.b'})) - eq('Index out of bounds', pcall_err(set_lines, -3, -2, true, {'line1.c'})) - eq({'line1.a'}, get_lines(0, -1, true)) + set_lines(0, 1, true, { 'line1.a' }) + eq('Index out of bounds', pcall_err(set_lines, 1, 2, true, { 'line1.b' })) + eq('Index out of bounds', pcall_err(set_lines, -3, -2, true, { 'line1.c' })) + eq({ 'line1.a' }, get_lines(0, -1, true)) eq('Index out of bounds', pcall_err(set_lines, 1, 2, true, {})) eq('Index out of bounds', pcall_err(set_lines, -3, -2, true, {})) - eq({'line1.a'}, get_lines(0, -1, true)) + eq({ 'line1.a' }, get_lines(0, -1, true)) end) it('can set and delete a single line with non-strict indexing', function() - set_lines(0, 1, true, {'line1.a'}) - set_lines(1, 2, false, {'line1.b'}) - set_lines(-4, -3, false, {'line1.c'}) - eq({'line1.c', 'line1.a', 'line1.b'}, get_lines(0, -1, true)) + set_lines(0, 1, true, { 'line1.a' }) + set_lines(1, 2, false, { 'line1.b' }) + set_lines(-4, -3, false, { 'line1.c' }) + eq({ 'line1.c', 'line1.a', 'line1.b' }, get_lines(0, -1, true)) set_lines(3, 4, false, {}) set_lines(-5, -4, false, {}) - eq({'line1.c', 'line1.a', 'line1.b'}, get_lines(0, -1, true)) + eq({ 'line1.c', 'line1.a', 'line1.b' }, get_lines(0, -1, true)) end) it('can handle NULs', function() - set_lines(0, 1, true, {'ab\0cd'}) - eq({'ab\0cd'}, get_lines(0, -1, true)) + set_lines(0, 1, true, { 'ab\0cd' }) + eq({ 'ab\0cd' }, get_lines(0, -1, true)) end) it('works with multiple lines', function() - eq({''}, get_lines(0, -1, true)) + eq({ '' }, get_lines(0, -1, true)) -- Replace buffer - for _, mode in pairs({false, true}) do - set_lines(0, -1, mode, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, get_lines(0, -1, mode)) - eq({'b', 'c'}, get_lines(1, -1, mode)) - eq({'b'}, get_lines(1, 2, mode)) + for _, mode in pairs({ false, true }) do + set_lines(0, -1, mode, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode)) + eq({ 'b', 'c' }, get_lines(1, -1, mode)) + eq({ 'b' }, get_lines(1, 2, mode)) eq({}, get_lines(1, 1, mode)) - eq({'a', 'b'}, get_lines(0, -2, mode)) - eq({'b'}, get_lines(1, -2, mode)) - eq({'b', 'c'}, get_lines(-3, -1, mode)) - set_lines(1, 2, mode, {'a', 'b', 'c'}) - eq({'a', 'a', 'b', 'c', 'c'}, get_lines(0, -1, mode)) - set_lines(-2, -1, mode, {'a', 'b', 'c'}) - eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'}, - get_lines(0, -1, mode)) + eq({ 'a', 'b' }, get_lines(0, -2, mode)) + eq({ 'b' }, get_lines(1, -2, mode)) + eq({ 'b', 'c' }, get_lines(-3, -1, mode)) + set_lines(1, 2, mode, { 'a', 'b', 'c' }) + eq({ 'a', 'a', 'b', 'c', 'c' }, get_lines(0, -1, mode)) + set_lines(-2, -1, mode, { 'a', 'b', 'c' }) + eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, get_lines(0, -1, mode)) set_lines(0, -4, mode, {}) - eq({'a', 'b', 'c'}, get_lines(0, -1, mode)) + eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode)) set_lines(0, -1, mode, {}) - eq({''}, get_lines(0, -1, mode)) + eq({ '' }, get_lines(0, -1, mode)) end end) it('can get line ranges with non-strict indexing', function() - set_lines(0, -1, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity + set_lines(0, -1, true, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, get_lines(0, -1, true)) --sanity eq({}, get_lines(3, 4, false)) eq({}, get_lines(3, 10, false)) @@ -622,8 +641,8 @@ describe('api/buf', function() end) it('can get line ranges with strict indexing', function() - set_lines(0, -1, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity + set_lines(0, -1, true, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, get_lines(0, -1, true)) --sanity eq('Index out of bounds', pcall_err(get_lines, 3, 4, true)) eq('Index out of bounds', pcall_err(get_lines, 3, 10, true)) @@ -634,20 +653,20 @@ describe('api/buf', function() end) it('set_lines: out-of-bounds can extend past end', function() - set_lines(0, -1, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity + set_lines(0, -1, true, { 'a', 'b', 'c' }) + eq({ 'a', 'b', 'c' }, get_lines(0, -1, true)) --sanity - eq({'c'}, get_lines(-2, 5, false)) - eq({'a', 'b', 'c'}, get_lines(0, 6, false)) - eq('Index out of bounds', pcall_err(set_lines, 4, 6, true, {'d'})) - set_lines(4, 6, false, {'d'}) - eq({'a', 'b', 'c', 'd'}, get_lines(0, -1, true)) - eq('Index out of bounds', pcall_err(set_lines, -6, -6, true, {'e'})) - set_lines(-6, -6, false, {'e'}) - eq({'e', 'a', 'b', 'c', 'd'}, get_lines(0, -1, true)) + eq({ 'c' }, get_lines(-2, 5, false)) + eq({ 'a', 'b', 'c' }, get_lines(0, 6, false)) + eq('Index out of bounds', pcall_err(set_lines, 4, 6, true, { 'd' })) + set_lines(4, 6, false, { 'd' }) + eq({ 'a', 'b', 'c', 'd' }, get_lines(0, -1, true)) + eq('Index out of bounds', pcall_err(set_lines, -6, -6, true, { 'e' })) + set_lines(-6, -6, false, { 'e' }) + eq({ 'e', 'a', 'b', 'c', 'd' }, get_lines(0, -1, true)) end) - it("set_lines on alternate buffer does not access invalid line (E315)", function() + it('set_lines on alternate buffer does not access invalid line (E315)', function() feed_command('set hidden') insert('Initial file') command('enew') @@ -667,8 +686,8 @@ describe('api/buf', function() it("set_lines of invisible buffer doesn't move cursor in current window", function() local screen = Screen.new(20, 5) screen:set_default_attr_ids({ - [1] = {bold = true, foreground = Screen.colors.Blue1}, - [2] = {bold = true}, + [1] = { bold = true, foreground = Screen.colors.Blue1 }, + [2] = { bold = true }, }) screen:attach() @@ -676,7 +695,7 @@ describe('api/buf', function() Who would win? A real window with proper text]]) - local buf = api.meths.create_buf(false,true) + local buf = lua_or_rpc.nvim_create_buf(false, true) screen:expect([[ Who would win? | A real window | @@ -685,7 +704,7 @@ describe('api/buf', function() | ]]) - api.meths.buf_set_lines(buf, 0, -1, true, {'or some', 'scratchy text'}) + lua_or_rpc.nvim_buf_set_lines(buf, 0, -1, true, { 'or some', 'scratchy text' }) feed('i') -- provoke redraw screen:expect([[ Who would win? | @@ -701,37 +720,42 @@ describe('api/buf', function() visible buffer line 1 line 2 ]]) - local hiddenbuf = api.meths.create_buf(false,true) + local hiddenbuf = lua_or_rpc.nvim_create_buf(false, true) command('vsplit') command('vsplit') feed('<c-w>l<c-w>l<c-w>l') - eq(3, funcs.winnr()) + eq(3, fn.winnr()) feed('<c-w>h') - eq(2, funcs.winnr()) - api.meths.buf_set_lines(hiddenbuf, 0, -1, true, - {'hidden buffer line 1', 'line 2'}) + eq(2, fn.winnr()) + lua_or_rpc.nvim_buf_set_lines(hiddenbuf, 0, -1, true, { 'hidden buffer line 1', 'line 2' }) feed('<c-w>p') - eq(3, funcs.winnr()) + eq(3, fn.winnr()) end) it('set_lines on unloaded buffer #8659 #22670', function() - local bufnr = curbuf('get_number') - meths.buf_set_lines(bufnr, 0, -1, false, {'a', 'b', 'c'}) - meths.buf_set_name(bufnr, 'set_lines') + local bufnr = api.nvim_get_current_buf() + lua_or_rpc.nvim_buf_set_lines(bufnr, 0, -1, false, { 'a', 'b', 'c' }) + lua_or_rpc.nvim_buf_set_name(bufnr, 'set_lines') finally(function() os.remove('set_lines') end) command('write!') command('new') - command('bunload! '..bufnr) - local new_bufnr = funcs.bufnr('set_lines', true) - meths.buf_set_lines(new_bufnr, 0, -1, false, {}) - eq({''}, meths.buf_get_lines(new_bufnr, 0, -1, false)) + command('bunload! ' .. bufnr) + local new_bufnr = fn.bufnr('set_lines', true) + lua_or_rpc.nvim_buf_set_lines(new_bufnr, 0, -1, false, {}) + eq({ '' }, lua_or_rpc.nvim_buf_get_lines(new_bufnr, 0, -1, false)) end) end) describe('nvim_buf_set_text', function() - local get_lines, set_text = curbufmeths.get_lines, curbufmeths.set_text + local function get_lines(...) + return api.nvim_buf_get_lines(0, ...) + end + + local function set_text(...) + return api.nvim_buf_set_text(0, ...) + end it('works', function() insert([[ @@ -739,70 +763,69 @@ describe('api/buf', function() text ]]) - eq({'hello foo!'}, get_lines(0, 1, true)) - + eq({ 'hello foo!' }, get_lines(0, 1, true)) -- can replace a single word - set_text(0, 6, 0, 9, {'world'}) - eq({'hello world!', 'text'}, get_lines(0, 2, true)) + set_text(0, 6, 0, 9, { 'world' }) + eq({ 'hello world!', 'text' }, get_lines(0, 2, true)) -- can insert text - set_text(0, 0, 0, 0, {'well '}) - eq({'well hello world!', 'text'}, get_lines(0, 2, true)) + set_text(0, 0, 0, 0, { 'well ' }) + eq({ 'well hello world!', 'text' }, get_lines(0, 2, true)) -- can delete text - set_text(0, 0, 0, 5, {''}) - eq({'hello world!', 'text'}, get_lines(0, 2, true)) + set_text(0, 0, 0, 5, { '' }) + eq({ 'hello world!', 'text' }, get_lines(0, 2, true)) -- can replace with multiple lines - set_text(0, 6, 0, 11, {'foo', 'wo', 'more'}) - eq({'hello foo', 'wo', 'more!', 'text'}, get_lines(0, 4, true)) + set_text(0, 6, 0, 11, { 'foo', 'wo', 'more' }) + eq({ 'hello foo', 'wo', 'more!', 'text' }, get_lines(0, 4, true)) -- will join multiple lines if needed - set_text(0, 6, 3, 4, {'bar'}) - eq({'hello bar'}, get_lines(0, 1, true)) + set_text(0, 6, 3, 4, { 'bar' }) + eq({ 'hello bar' }, get_lines(0, 1, true)) -- can use negative line numbers - set_text(-2, 0, -2, 5, {'goodbye'}) - eq({'goodbye bar', ''}, get_lines(0, -1, true)) + set_text(-2, 0, -2, 5, { 'goodbye' }) + eq({ 'goodbye bar', '' }, get_lines(0, -1, true)) - set_text(-1, 0, -1, 0, {'text'}) - eq({'goodbye bar', 'text'}, get_lines(0, 2, true)) + set_text(-1, 0, -1, 0, { 'text' }) + eq({ 'goodbye bar', 'text' }, get_lines(0, 2, true)) -- can append to a line - set_text(1, 4, -1, 4, {' and', 'more'}) - eq({'goodbye bar', 'text and', 'more'}, get_lines(0, 3, true)) + set_text(1, 4, -1, 4, { ' and', 'more' }) + eq({ 'goodbye bar', 'text and', 'more' }, get_lines(0, 3, true)) -- can use negative column numbers - set_text(0, -5, 0, -1, {'!'}) - eq({'goodbye!'}, get_lines(0, 1, true)) + set_text(0, -5, 0, -1, { '!' }) + eq({ 'goodbye!' }, get_lines(0, 1, true)) end) it('works with undo', function() - insert([[ + insert([[ hello world! foo bar ]]) - -- setting text - set_text(0, 0, 0, 0, {'well '}) - feed('u') - eq({'hello world!'}, get_lines(0, 1, true)) + -- setting text + set_text(0, 0, 0, 0, { 'well ' }) + feed('u') + eq({ 'hello world!' }, get_lines(0, 1, true)) - -- deleting text - set_text(0, 0, 0, 6, {''}) - feed('u') - eq({'hello world!'}, get_lines(0, 1, true)) + -- deleting text + set_text(0, 0, 0, 6, { '' }) + feed('u') + eq({ 'hello world!' }, get_lines(0, 1, true)) - -- inserting newlines - set_text(0, 0, 0, 0, {'hello', 'mr '}) - feed('u') - eq({'hello world!'}, get_lines(0, 1, true)) + -- inserting newlines + set_text(0, 0, 0, 0, { 'hello', 'mr ' }) + feed('u') + eq({ 'hello world!' }, get_lines(0, 1, true)) - -- deleting newlines - set_text(0, 0, 1, 4, {'hello'}) - feed('u') - eq({'hello world!'}, get_lines(0, 1, true)) + -- deleting newlines + set_text(0, 0, 1, 4, { 'hello' }) + feed('u') + eq({ 'hello world!' }, get_lines(0, 1, true)) end) it('updates the cursor position', function() @@ -811,12 +834,12 @@ describe('api/buf', function() ]]) -- position the cursor on `!` - curwin('set_cursor', {1, 11}) + api.nvim_win_set_cursor(0, { 1, 11 }) -- replace 'world' with 'foo' - set_text(0, 6, 0, 11, {'foo'}) + set_text(0, 6, 0, 11, { 'foo' }) eq('hello foo!', curbuf_depr('get_line', 0)) -- cursor should be moved left by two columns (replacement is shorter by 2 chars) - eq({1, 9}, curwin('get_cursor')) + eq({ 1, 9 }, api.nvim_win_get_cursor(0)) end) it('updates the cursor position in non-current window', function() @@ -824,18 +847,18 @@ describe('api/buf', function() hello world!]]) -- position the cursor on `!` - meths.win_set_cursor(0, {1, 11}) + api.nvim_win_set_cursor(0, { 1, 11 }) - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() - command("new") + command('new') -- replace 'world' with 'foo' - meths.buf_set_text(buf, 0, 6, 0, 11, {'foo'}) - eq({'hello foo!'}, meths.buf_get_lines(buf, 0, -1, true)) + api.nvim_buf_set_text(buf, 0, 6, 0, 11, { 'foo' }) + eq({ 'hello foo!' }, api.nvim_buf_get_lines(buf, 0, -1, true)) -- cursor should be moved left by two columns (replacement is shorter by 2 chars) - eq({1, 9}, meths.win_get_cursor(win)) + eq({ 1, 9 }, api.nvim_win_get_cursor(win)) end) it('updates the cursor position in TWO non-current windows', function() @@ -843,24 +866,24 @@ describe('api/buf', function() hello world!]]) -- position the cursor on `!` - meths.win_set_cursor(0, {1, 11}) - local win = meths.get_current_win() - local buf = meths.get_current_buf() + api.nvim_win_set_cursor(0, { 1, 11 }) + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() - command("split") - local win2 = meths.get_current_win() + command('split') + local win2 = api.nvim_get_current_win() -- position the cursor on `w` - meths.win_set_cursor(0, {1, 6}) + api.nvim_win_set_cursor(0, { 1, 6 }) - command("new") + command('new') -- replace 'hello' with 'foo' - meths.buf_set_text(buf, 0, 0, 0, 5, {'foo'}) - eq({'foo world!'}, meths.buf_get_lines(buf, 0, -1, true)) + api.nvim_buf_set_text(buf, 0, 0, 0, 5, { 'foo' }) + eq({ 'foo world!' }, api.nvim_buf_get_lines(buf, 0, -1, true)) -- both cursors should be moved left by two columns (replacement is shorter by 2 chars) - eq({1, 9}, meths.win_get_cursor(win)) - eq({1, 4}, meths.win_get_cursor(win2)) + eq({ 1, 9 }, api.nvim_win_get_cursor(win)) + eq({ 1, 4 }, api.nvim_win_get_cursor(win2)) end) describe('when text is being added right at cursor position #22526', function() @@ -869,12 +892,12 @@ describe('api/buf', function() abcd]]) -- position the cursor on 'c' - curwin('set_cursor', {1, 2}) + api.nvim_win_set_cursor(0, { 1, 2 }) -- add 'xxx' before 'c' - set_text(0, 2, 0, 2, {'xxx'}) - eq({'abxxxcd'}, get_lines(0, -1, true)) + set_text(0, 2, 0, 2, { 'xxx' }) + eq({ 'abxxxcd' }, get_lines(0, -1, true)) -- cursor should be on 'c' - eq({1, 5}, curwin('get_cursor')) + eq({ 1, 5 }, api.nvim_win_get_cursor(0)) end) it('updates the cursor position only in non-current window when in INSERT mode', function() @@ -882,23 +905,23 @@ describe('api/buf', function() abcd]]) -- position the cursor on 'c' - curwin('set_cursor', {1, 2}) + api.nvim_win_set_cursor(0, { 1, 2 }) -- open vertical split feed('<c-w>v') -- get into INSERT mode to treat cursor -- as being after 'b', not on 'c' feed('i') -- add 'xxx' between 'b' and 'c' - set_text(0, 2, 0, 2, {'xxx'}) - eq({'abxxxcd'}, get_lines(0, -1, true)) + set_text(0, 2, 0, 2, { 'xxx' }) + eq({ 'abxxxcd' }, get_lines(0, -1, true)) -- in the current window cursor should stay after 'b' - eq({1, 2}, curwin('get_cursor')) + eq({ 1, 2 }, api.nvim_win_get_cursor(0)) -- quit INSERT mode feed('<esc>') -- close current window feed('<c-w>c') -- in another window cursor should be on 'c' - eq({1, 5}, curwin('get_cursor')) + eq({ 1, 5 }, api.nvim_win_get_cursor(0)) end) end) @@ -908,20 +931,20 @@ describe('api/buf', function() abcd]]) -- position the cursor on 'b' - curwin('set_cursor', {1, 1}) + api.nvim_win_set_cursor(0, { 1, 1 }) -- delete 'b' set_text(0, 1, 0, 2, {}) - eq({'acd'}, get_lines(0, -1, true)) + eq({ 'acd' }, get_lines(0, -1, true)) -- cursor is now on 'c' - eq({1, 1}, curwin('get_cursor')) + eq({ 1, 1 }, api.nvim_win_get_cursor(0)) end) - it('leaves cursor at the same position in INSERT mode in current and non-current window', function() + it('maintains INSERT-mode cursor position current/non-current window', function() insert([[ abcd]]) -- position the cursor on 'b' - curwin('set_cursor', {1, 1}) + api.nvim_win_set_cursor(0, { 1, 1 }) -- open vertical split feed('<c-w>v') -- get into INSERT mode to treat cursor @@ -929,27 +952,27 @@ describe('api/buf', function() feed('i') -- delete 'b' set_text(0, 1, 0, 2, {}) - eq({'acd'}, get_lines(0, -1, true)) + eq({ 'acd' }, get_lines(0, -1, true)) -- cursor in the current window should stay after 'a' - eq({1, 1}, curwin('get_cursor')) + eq({ 1, 1 }, api.nvim_win_get_cursor(0)) -- quit INSERT mode feed('<esc>') -- close current window feed('<c-w>c') -- cursor in non-current window should stay on 'c' - eq({1, 1}, curwin('get_cursor')) + eq({ 1, 1 }, api.nvim_win_get_cursor(0)) end) end) describe('when cursor is inside replaced row range', function() - it('keeps cursor at the same position if cursor is at start_row, but before start_col', function() + it('maintains cursor position if at start_row, but before start_col', function() insert([[ This should be first then there is a line we do not want and finally the last one]]) -- position the cursor on ' ' before 'first' - curwin('set_cursor', {1, 14}) + api.nvim_win_set_cursor(0, { 1, 14 }) set_text(0, 15, 2, 11, { 'the line we do not want', @@ -961,17 +984,17 @@ describe('api/buf', function() 'but hopefully the last one', }, get_lines(0, -1, true)) -- cursor should stay at the same position - eq({1, 14}, curwin('get_cursor')) + eq({ 1, 14 }, api.nvim_win_get_cursor(0)) end) - it('keeps cursor at the same position if cursor is at start_row and column is still valid', function() + it('maintains cursor position if at start_row and column is still valid', function() insert([[ This should be first then there is a line we do not want and finally the last one]]) -- position the cursor on 'f' in 'first' - curwin('set_cursor', {1, 15}) + api.nvim_win_set_cursor(0, { 1, 15 }) set_text(0, 15, 2, 11, { 'the line we do not want', @@ -983,7 +1006,7 @@ describe('api/buf', function() 'but hopefully the last one', }, get_lines(0, -1, true)) -- cursor should stay at the same position - eq({1, 15}, curwin('get_cursor')) + eq({ 1, 15 }, api.nvim_win_get_cursor(0)) end) it('adjusts cursor column to keep it valid if start_row got smaller', function() @@ -993,7 +1016,7 @@ describe('api/buf', function() and finally the last one]]) -- position the cursor on 't' in 'first' - curwin('set_cursor', {1, 19}) + api.nvim_win_set_cursor(0, { 1, 19 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 24, {'last'}) @@ -1002,19 +1025,19 @@ describe('api/buf', function() eq({ 'This should be last' }, get_lines(0, -1, true)) -- cursor should end up on 't' in 'last' - eq({1, 18}, curwin('get_cursor')) + eq({ 1, 18 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 18}, cursor) + eq({ 1, 18 }, cursor) end) - it('adjusts cursor column to keep it valid if start_row got smaller in INSERT mode', function() + it('adjusts cursor column to keep it valid if start_row decreased in INSERT mode', function() insert([[ This should be first then there is a line we do not want and finally the last one]]) -- position the cursor on 't' in 'first' - curwin('set_cursor', {1, 19}) + api.nvim_win_set_cursor(0, { 1, 19 }) -- enter INSERT mode to treat cursor as being after 't' feed('a') @@ -1025,19 +1048,19 @@ describe('api/buf', function() eq({ 'This should be last' }, get_lines(0, -1, true)) -- cursor should end up after 't' in 'last' - eq({1, 19}, curwin('get_cursor')) + eq({ 1, 19 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 19}, cursor) + eq({ 1, 19 }, cursor) end) - it('adjusts cursor column to keep it valid in a row after start_row if it got smaller', function() + it('adjusts cursor to valid column in row after start_row if it got smaller', function() insert([[ This should be first then there is a line we do not want and finally the last one]]) -- position the cursor on 'w' in 'want' - curwin('set_cursor', {2, 31}) + api.nvim_win_set_cursor(0, { 2, 31 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { @@ -1054,23 +1077,25 @@ describe('api/buf', function() 'and then the last one', }, get_lines(0, -1, true)) -- cursor column should end up at the end of a row - eq({2, 5}, curwin('get_cursor')) + eq({ 2, 5 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({2, 5}, cursor) + eq({ 2, 5 }, cursor) end) - it('adjusts cursor column to keep it valid in a row after start_row if it got smaller in INSERT mode', function() - insert([[ + it( + 'adjusts cursor to valid column in row after start_row if it got smaller in INSERT mode', + function() + insert([[ This should be first then there is a line we do not want and finally the last one]]) - -- position the cursor on 'w' in 'want' - curwin('set_cursor', {2, 31}) - -- enter INSERT mode - feed('a') + -- position the cursor on 'w' in 'want' + api.nvim_win_set_cursor(0, { 2, 31 }) + -- enter INSERT mode + feed('a') - local cursor = exec_lua([[ + local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { '1', 'then 2', @@ -1079,16 +1104,17 @@ describe('api/buf', function() return vim.api.nvim_win_get_cursor(0) ]]) - eq({ - 'This should be 1', - 'then 2', - 'and then the last one', - }, get_lines(0, -1, true)) - -- cursor column should end up at the end of a row - eq({2, 6}, curwin('get_cursor')) - -- immediate call to nvim_win_get_cursor should have returned the same position - eq({2, 6}, cursor) - end) + eq({ + 'This should be 1', + 'then 2', + 'and then the last one', + }, get_lines(0, -1, true)) + -- cursor column should end up at the end of a row + eq({ 2, 6 }, api.nvim_win_get_cursor(0)) + -- immediate call to nvim_win_get_cursor should have returned the same position + eq({ 2, 6 }, cursor) + end + ) it('adjusts cursor line and column to keep it inside replacement range', function() insert([[ @@ -1097,7 +1123,7 @@ describe('api/buf', function() and finally the last one]]) -- position the cursor on 'n' in 'finally' - curwin('set_cursor', {3, 6}) + api.nvim_win_set_cursor(0, { 3, 6 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { @@ -1113,9 +1139,9 @@ describe('api/buf', function() }, get_lines(0, -1, true)) -- cursor should end up on 'y' in 'hopefully' -- to stay in the range, because it got smaller - eq({2, 12}, curwin('get_cursor')) + eq({ 2, 12 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({2, 12}, cursor) + eq({ 2, 12 }, cursor) end) it('adjusts cursor line and column if replacement is empty', function() @@ -1125,7 +1151,7 @@ describe('api/buf', function() and finally the last one]]) -- position the cursor on 'r' in 'there' - curwin('set_cursor', {2, 8}) + api.nvim_win_set_cursor(0, { 2, 8 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 12, {}) @@ -1134,9 +1160,9 @@ describe('api/buf', function() eq({ 'This should be the last one' }, get_lines(0, -1, true)) -- cursor should end up on the next column after deleted range - eq({1, 15}, curwin('get_cursor')) + eq({ 1, 15 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 15}, cursor) + eq({ 1, 15 }, cursor) end) it('adjusts cursor line and column if replacement is empty and start_col == 0', function() @@ -1146,7 +1172,7 @@ describe('api/buf', function() and finally the last one]]) -- position the cursor on 'r' in 'there' - curwin('set_cursor', {2, 8}) + api.nvim_win_set_cursor(0, { 2, 8 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 0, 2, 4, {}) @@ -1155,9 +1181,9 @@ describe('api/buf', function() eq({ 'finally the last one' }, get_lines(0, -1, true)) -- cursor should end up in column 0 - eq({1, 0}, curwin('get_cursor')) + eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 0}, cursor) + eq({ 1, 0 }, cursor) end) it('adjusts cursor column if replacement ends at cursor row, after cursor column', function() @@ -1167,7 +1193,7 @@ describe('api/buf', function() and finally the last one]]) -- position the cursor on 'y' in 'finally' - curwin('set_cursor', {3, 10}) + api.nvim_win_set_cursor(0, { 3, 10 }) set_text(0, 15, 2, 11, { '1', 'this 2', 'and then' }) eq({ @@ -1176,29 +1202,32 @@ describe('api/buf', function() 'and then the last one', }, get_lines(0, -1, true)) -- cursor should end up on 'n' in 'then' - eq({3, 7}, curwin('get_cursor')) + eq({ 3, 7 }, api.nvim_win_get_cursor(0)) end) - it('adjusts cursor column if replacement ends at cursor row, at cursor column in INSERT mode', function() - insert([[ + it( + 'adjusts cursor column if replacement ends at cursor row, at cursor column in INSERT mode', + function() + insert([[ This should be first then there is a line we do not want and finally the last one]]) - -- position the cursor on 'y' at 'finally' - curwin('set_cursor', {3, 10}) - -- enter INSERT mode to treat cursor as being between 'l' and 'y' - feed('i') - set_text(0, 15, 2, 11, { '1', 'this 2', 'and then' }) + -- position the cursor on 'y' at 'finally' + api.nvim_win_set_cursor(0, { 3, 10 }) + -- enter INSERT mode to treat cursor as being between 'l' and 'y' + feed('i') + set_text(0, 15, 2, 11, { '1', 'this 2', 'and then' }) - eq({ - 'This should be 1', - 'this 2', - 'and then the last one', - }, get_lines(0, -1, true)) - -- cursor should end up after 'n' in 'then' - eq({3, 8}, curwin('get_cursor')) - end) + eq({ + 'This should be 1', + 'this 2', + 'and then the last one', + }, get_lines(0, -1, true)) + -- cursor should end up after 'n' in 'then' + eq({ 3, 8 }, api.nvim_win_get_cursor(0)) + end + ) it('adjusts cursor column if replacement is inside of a single line', function() insert([[ @@ -1207,7 +1236,7 @@ describe('api/buf', function() and finally the last one]]) -- position the cursor on 'y' in 'finally' - curwin('set_cursor', {3, 10}) + api.nvim_win_set_cursor(0, { 3, 10 }) set_text(2, 4, 2, 11, { 'then' }) eq({ @@ -1216,7 +1245,7 @@ describe('api/buf', function() 'and then the last one', }, get_lines(0, -1, true)) -- cursor should end up on 'n' in 'then' - eq({3, 7}, curwin('get_cursor')) + eq({ 3, 7 }, api.nvim_win_get_cursor(0)) end) it('does not move cursor column after end of a line', function() @@ -1225,7 +1254,7 @@ describe('api/buf', function() !!!]]) -- position cursor on the last '1' - curwin('set_cursor', {2, 2}) + api.nvim_win_set_cursor(0, { 2, 2 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 33, 1, 3, {}) @@ -1234,16 +1263,16 @@ describe('api/buf', function() eq({ 'This should be the only line here' }, get_lines(0, -1, true)) -- cursor should end up on '!' - eq({1, 32}, curwin('get_cursor')) + eq({ 1, 32 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 32}, cursor) + eq({ 1, 32 }, cursor) end) it('does not move cursor column before start of a line', function() insert('\n!!!') -- position cursor on the last '1' - curwin('set_cursor', {2, 2}) + api.nvim_win_set_cursor(0, { 2, 2 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 0, 1, 3, {}) @@ -1252,20 +1281,20 @@ describe('api/buf', function() eq({ '' }, get_lines(0, -1, true)) -- cursor should end up on '!' - eq({1, 0}, curwin('get_cursor')) + eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 0}, cursor) + eq({ 1, 0 }, cursor) end) describe('with virtualedit', function() - it('adjusts cursor line and column to keep it inside replacement range if cursor is not after eol', function() + it('adjusts cursor line/col to keep inside replacement range if not after eol', function() insert([[ This should be first then there is a line we do not want and finally the last one]]) -- position cursor on 't' in 'want' - curwin('set_cursor', {2, 34}) + api.nvim_win_set_cursor(0, { 2, 34 }) -- turn on virtualedit command('set virtualedit=all') @@ -1283,23 +1312,26 @@ describe('api/buf', function() }, get_lines(0, -1, true)) -- cursor should end up on 'y' in 'hopefully' -- to stay in the range - eq({2, 12}, curwin('get_cursor')) + eq({ 2, 12 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({2, 12}, cursor) + eq({ 2, 12 }, cursor) -- coladd should be 0 - eq(0, exec_lua([[ + eq( + 0, + exec_lua([[ return vim.fn.winsaveview().coladd - ]])) + ]]) + ) end) - it('does not change cursor screen column when cursor is after eol and row got shorter', function() + it('does not change cursor screen column when cursor >EOL and row got shorter', function() insert([[ This should be first then there is a line we do not want and finally the last one]]) -- position cursor on 't' in 'want' - curwin('set_cursor', {2, 34}) + api.nvim_win_set_cursor(0, { 2, 34 }) -- turn on virtualedit command('set virtualedit=all') -- move cursor after eol @@ -1320,31 +1352,36 @@ describe('api/buf', function() 'but hopefully the last one', }, get_lines(0, -1, true)) -- cursor should end up at eol of a new row - eq({2, 26}, curwin('get_cursor')) + eq({ 2, 26 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({2, 26}, cursor) + eq({ 2, 26 }, cursor) -- coladd should be increased so that cursor stays in the same screen column - eq(13, exec_lua([[ + eq( + 13, + exec_lua([[ return vim.fn.winsaveview().coladd - ]])) + ]]) + ) end) - it('does not change cursor screen column when cursor is after eol and row got longer', function() - insert([[ + it( + 'does not change cursor screen column when cursor is after eol and row got longer', + function() + insert([[ This should be first then there is a line we do not want and finally the last one]]) - -- position cursor on 't' in 'first' - curwin('set_cursor', {1, 19}) - -- turn on virtualedit - command('set virtualedit=all') - -- move cursor after eol - exec_lua([[ + -- position cursor on 't' in 'first' + api.nvim_win_set_cursor(0, { 1, 19 }) + -- turn on virtualedit + command('set virtualedit=all') + -- move cursor after eol + exec_lua([[ vim.fn.winrestview({ coladd = 21 }) ]]) - local cursor = exec_lua([[ + local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { 'the line we do not want', 'but hopefully', @@ -1352,36 +1389,42 @@ describe('api/buf', function() return vim.api.nvim_win_get_cursor(0) ]]) - eq({ - 'This should be the line we do not want', - 'but hopefully the last one', - }, get_lines(0, -1, true)) - -- cursor should end up at eol of a new row - eq({1, 38}, curwin('get_cursor')) - -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 38}, cursor) - -- coladd should be increased so that cursor stays in the same screen column - eq(2, exec_lua([[ + eq({ + 'This should be the line we do not want', + 'but hopefully the last one', + }, get_lines(0, -1, true)) + -- cursor should end up at eol of a new row + eq({ 1, 38 }, api.nvim_win_get_cursor(0)) + -- immediate call to nvim_win_get_cursor should have returned the same position + eq({ 1, 38 }, cursor) + -- coladd should be increased so that cursor stays in the same screen column + eq( + 2, + exec_lua([[ return vim.fn.winsaveview().coladd - ]])) - end) - - it('does not change cursor screen column when cursor is after eol and row extended past cursor column', function() - insert([[ + ]]) + ) + end + ) + + it( + 'does not change cursor screen column when cursor is after eol and row extended past cursor column', + function() + insert([[ This should be first then there is a line we do not want and finally the last one]]) - -- position cursor on 't' in 'first' - curwin('set_cursor', {1, 19}) - -- turn on virtualedit - command('set virtualedit=all') - -- move cursor after eol just a bit - exec_lua([[ + -- position cursor on 't' in 'first' + api.nvim_win_set_cursor(0, { 1, 19 }) + -- turn on virtualedit + command('set virtualedit=all') + -- move cursor after eol just a bit + exec_lua([[ vim.fn.winrestview({ coladd = 3 }) ]]) - local cursor = exec_lua([[ + local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, { 'the line we do not want', 'but hopefully', @@ -1389,37 +1432,43 @@ describe('api/buf', function() return vim.api.nvim_win_get_cursor(0) ]]) - eq({ - 'This should be the line we do not want', - 'but hopefully the last one', - }, get_lines(0, -1, true)) - -- cursor should stay at the same screen column - eq({1, 22}, curwin('get_cursor')) - -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 22}, cursor) - -- coladd should become 0 - eq(0, exec_lua([[ + eq({ + 'This should be the line we do not want', + 'but hopefully the last one', + }, get_lines(0, -1, true)) + -- cursor should stay at the same screen column + eq({ 1, 22 }, api.nvim_win_get_cursor(0)) + -- immediate call to nvim_win_get_cursor should have returned the same position + eq({ 1, 22 }, cursor) + -- coladd should become 0 + eq( + 0, + exec_lua([[ return vim.fn.winsaveview().coladd - ]])) - end) - - it('does not change cursor screen column when cursor is after eol and row range decreased', function() - insert([[ + ]]) + ) + end + ) + + it( + 'does not change cursor screen column when cursor is after eol and row range decreased', + function() + insert([[ This should be first then there is a line we do not want and one more and finally the last one]]) - -- position cursor on 'e' in 'more' - curwin('set_cursor', {3, 11}) - -- turn on virtualedit - command('set virtualedit=all') - -- move cursor after eol - exec_lua([[ + -- position cursor on 'e' in 'more' + api.nvim_win_set_cursor(0, { 3, 11 }) + -- turn on virtualedit + command('set virtualedit=all') + -- move cursor after eol + exec_lua([[ vim.fn.winrestview({ coladd = 28 }) ]]) - local cursor = exec_lua([[ + local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 15, 3, 11, { 'the line we do not want', 'but hopefully', @@ -1427,19 +1476,23 @@ describe('api/buf', function() return vim.api.nvim_win_get_cursor(0) ]]) - eq({ - 'This should be the line we do not want', - 'but hopefully the last one', - }, get_lines(0, -1, true)) - -- cursor should end up at eol of a new row - eq({2, 26}, curwin('get_cursor')) - -- immediate call to nvim_win_get_cursor should have returned the same position - eq({2, 26}, cursor) - -- coladd should be increased so that cursor stays in the same screen column - eq(13, exec_lua([[ + eq({ + 'This should be the line we do not want', + 'but hopefully the last one', + }, get_lines(0, -1, true)) + -- cursor should end up at eol of a new row + eq({ 2, 26 }, api.nvim_win_get_cursor(0)) + -- immediate call to nvim_win_get_cursor should have returned the same position + eq({ 2, 26 }, cursor) + -- coladd should be increased so that cursor stays in the same screen column + eq( + 13, + exec_lua([[ return vim.fn.winsaveview().coladd - ]])) - end) + ]]) + ) + end + ) end) end) @@ -1451,80 +1504,86 @@ describe('api/buf', function() line]]) -- position the cursor on 'i' - curwin('set_cursor', {3, 2}) + api.nvim_win_set_cursor(0, { 3, 2 }) set_text(1, 6, 2, 0, {}) - eq({'first line', 'second line'}, get_lines(0, -1, true)) + eq({ 'first line', 'second line' }, get_lines(0, -1, true)) -- cursor should stay on 'i' - eq({2, 8}, curwin('get_cursor')) + eq({ 2, 8 }, api.nvim_win_get_cursor(0)) -- add a newline back - set_text(1, 6, 1, 6, {'', ''}) - eq({'first line', 'second', ' line'}, get_lines(0, -1, true)) + set_text(1, 6, 1, 6, { '', '' }) + eq({ 'first line', 'second', ' line' }, get_lines(0, -1, true)) -- cursor should return back to the original position - eq({3, 2}, curwin('get_cursor')) + eq({ 3, 2 }, api.nvim_win_get_cursor(0)) end) - it('adjusts cursor column if the range is not bound to either start or end of a line', function() - insert([[ + it( + 'adjusts cursor column if the range is not bound to either start or end of a line', + function() + insert([[ This should be first then there is a line we do not want and finally the last one]]) - -- position the cursor on 'h' in 'the' - curwin('set_cursor', {3, 13}) - set_text(0, 14, 2, 11, {}) - eq({'This should be the last one'}, get_lines(0, -1, true)) - -- cursor should stay on 'h' - eq({1, 16}, curwin('get_cursor')) - -- add deleted lines back - set_text(0, 14, 0, 14, { - ' first', - 'then there is a line we do not want', - 'and finally', - }) - eq({ - 'This should be first', - 'then there is a line we do not want', - 'and finally the last one', - }, get_lines(0, -1, true)) - -- cursor should return back to the original position - eq({3, 13}, curwin('get_cursor')) - end) - - it('adjusts cursor column if replacing lines in range, not just deleting and adding', function() - insert([[ + -- position the cursor on 'h' in 'the' + api.nvim_win_set_cursor(0, { 3, 13 }) + set_text(0, 14, 2, 11, {}) + eq({ 'This should be the last one' }, get_lines(0, -1, true)) + -- cursor should stay on 'h' + eq({ 1, 16 }, api.nvim_win_get_cursor(0)) + -- add deleted lines back + set_text(0, 14, 0, 14, { + ' first', + 'then there is a line we do not want', + 'and finally', + }) + eq({ + 'This should be first', + 'then there is a line we do not want', + 'and finally the last one', + }, get_lines(0, -1, true)) + -- cursor should return back to the original position + eq({ 3, 13 }, api.nvim_win_get_cursor(0)) + end + ) + + it( + 'adjusts cursor column if replacing lines in range, not just deleting and adding', + function() + insert([[ This should be first then there is a line we do not want and finally the last one]]) - -- position the cursor on 's' in 'last' - curwin('set_cursor', {3, 18}) - set_text(0, 15, 2, 11, { - 'the line we do not want', - 'but hopefully', - }) + -- position the cursor on 's' in 'last' + api.nvim_win_set_cursor(0, { 3, 18 }) + set_text(0, 15, 2, 11, { + 'the line we do not want', + 'but hopefully', + }) - eq({ - 'This should be the line we do not want', - 'but hopefully the last one', - }, get_lines(0, -1, true)) - -- cursor should stay on 's' - eq({2, 20}, curwin('get_cursor')) + eq({ + 'This should be the line we do not want', + 'but hopefully the last one', + }, get_lines(0, -1, true)) + -- cursor should stay on 's' + eq({ 2, 20 }, api.nvim_win_get_cursor(0)) - set_text(0, 15, 1, 13, { - 'first', - 'then there is a line we do not want', - 'and finally', - }) + set_text(0, 15, 1, 13, { + 'first', + 'then there is a line we do not want', + 'and finally', + }) - eq({ - 'This should be first', - 'then there is a line we do not want', - 'and finally the last one', - }, get_lines(0, -1, true)) - -- cursor should return back to the original position - eq({3, 18}, curwin('get_cursor')) - end) + eq({ + 'This should be first', + 'then there is a line we do not want', + 'and finally the last one', + }, get_lines(0, -1, true)) + -- cursor should return back to the original position + eq({ 3, 18 }, api.nvim_win_get_cursor(0)) + end + ) it('does not move cursor column after end of a line', function() insert([[ @@ -1532,7 +1591,7 @@ describe('api/buf', function() ]]) -- position cursor at the empty line - curwin('set_cursor', {2, 0}) + api.nvim_win_set_cursor(0, { 2, 0 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 33, 1, 0, {'!'}) @@ -1541,9 +1600,9 @@ describe('api/buf', function() eq({ 'This should be the only line here!' }, get_lines(0, -1, true)) -- cursor should end up on '!' - eq({1, 33}, curwin('get_cursor')) + eq({ 1, 33 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 33}, cursor) + eq({ 1, 33 }, cursor) end) it('does not move cursor column before start of a line', function() @@ -1552,7 +1611,7 @@ describe('api/buf', function() eq({ '', '' }, get_lines(0, -1, true)) -- position cursor on the last '1' - curwin('set_cursor', {2, 2}) + api.nvim_win_set_cursor(0, { 2, 2 }) local cursor = exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 0, 1, 0, {''}) @@ -1561,61 +1620,61 @@ describe('api/buf', function() eq({ '' }, get_lines(0, -1, true)) -- cursor should end up on '!' - eq({1, 0}, curwin('get_cursor')) + eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- immediate call to nvim_win_get_cursor should have returned the same position - eq({1, 0}, cursor) + eq({ 1, 0 }, cursor) end) end) it('can handle NULs', function() - set_text(0, 0, 0, 0, {'ab\0cd'}) + set_text(0, 0, 0, 0, { 'ab\0cd' }) eq('ab\0cd', curbuf_depr('get_line', 0)) end) it('adjusts extmarks', function() - local ns = request('nvim_create_namespace', "my-fancy-plugin") + local ns = api.nvim_create_namespace('my-fancy-plugin') insert([[ foo bar baz ]]) - local id1 = curbufmeths.set_extmark(ns, 0, 1, {}) - local id2 = curbufmeths.set_extmark(ns, 0, 7, {}) - local id3 = curbufmeths.set_extmark(ns, 1, 1, {}) - set_text(0, 4, 0, 7, {"q"}) + local id1 = api.nvim_buf_set_extmark(0, ns, 0, 1, {}) + local id2 = api.nvim_buf_set_extmark(0, ns, 0, 7, {}) + local id3 = api.nvim_buf_set_extmark(0, ns, 1, 1, {}) + set_text(0, 4, 0, 7, { 'q' }) - eq({'foo q', 'baz'}, get_lines(0, 2, true)) + eq({ 'foo q', 'baz' }, get_lines(0, 2, true)) -- mark before replacement point is unaffected - eq({0, 1}, curbufmeths.get_extmark_by_id(ns, id1, {})) + eq({ 0, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {})) -- mark gets shifted back because the replacement was shorter - eq({0, 5}, curbufmeths.get_extmark_by_id(ns, id2, {})) + eq({ 0, 5 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {})) -- mark on the next line is unaffected - eq({1, 1}, curbufmeths.get_extmark_by_id(ns, id3, {})) + eq({ 1, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {})) -- replacing the text spanning two lines will adjust the mark on the next line - set_text(0, 3, 1, 3, {"qux"}) - eq({'fooqux', ''}, get_lines(0, 2, true)) - eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id3, {})) + set_text(0, 3, 1, 3, { 'qux' }) + eq({ 'fooqux', '' }, get_lines(0, 2, true)) + eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {})) -- but mark before replacement point is still unaffected - eq({0, 1}, curbufmeths.get_extmark_by_id(ns, id1, {})) + eq({ 0, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {})) -- and the mark in the middle was shifted to the end of the insertion - eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id2, {})) + eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {})) -- marks should be put back into the same place after undoing - set_text(0, 0, 0, 2, {''}) + set_text(0, 0, 0, 2, { '' }) feed('u') - eq({0, 1}, curbufmeths.get_extmark_by_id(ns, id1, {})) - eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id2, {})) - eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id3, {})) + eq({ 0, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {})) + eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {})) + eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {})) -- marks should be shifted over by the correct number of bytes for multibyte -- chars - set_text(0, 0, 0, 0, {'Ø'}) - eq({0, 3}, curbufmeths.get_extmark_by_id(ns, id1, {})) - eq({0, 8}, curbufmeths.get_extmark_by_id(ns, id2, {})) - eq({0, 8}, curbufmeths.get_extmark_by_id(ns, id3, {})) + set_text(0, 0, 0, 0, { 'Ø' }) + eq({ 0, 3 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {})) + eq({ 0, 8 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {})) + eq({ 0, 8 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {})) end) - it("correctly marks changed region for redraw #13890", function() + it('correctly marks changed region for redraw #13890', function() local screen = Screen.new(20, 5) screen:attach() @@ -1624,7 +1683,7 @@ describe('api/buf', function() BBB ]]) - curbufmeths.set_text(0, 0, 1, 3, {'XXX', 'YYY'}) + api.nvim_buf_set_text(0, 0, 0, 1, 3, { 'XXX', 'YYY' }) screen:expect([[ XXX | @@ -1657,14 +1716,14 @@ describe('api/buf', function() end) it('no heap-use-after-free when called consecutively #19643', function() - set_text(0, 0, 0, 0, {'one', '', '', 'two'}) - eq({'one', '', '', 'two'}, get_lines(0, 4, true)) - meths.win_set_cursor(0, {1, 0}) + set_text(0, 0, 0, 0, { 'one', '', '', 'two' }) + eq({ 'one', '', '', 'two' }, get_lines(0, 4, true)) + api.nvim_win_set_cursor(0, { 1, 0 }) exec_lua([[ vim.api.nvim_buf_set_text(0, 0, 3, 1, 0, {''}) vim.api.nvim_buf_set_text(0, 0, 3, 1, 0, {''}) ]]) - eq({'one', 'two'}, get_lines(0, 2, true)) + eq({ 'one', 'two' }, get_lines(0, 2, true)) end) describe('handles topline', function() @@ -1672,28 +1731,32 @@ describe('api/buf', function() before_each(function() screen = Screen.new(20, 12) screen:set_default_attr_ids { - [1] = {bold = true, foreground = Screen.colors.Blue1}; - [2] = {reverse = true, bold = true}; - [3] = {reverse = true}; + [1] = { bold = true, foreground = Screen.colors.Blue1 }, + [2] = { reverse = true, bold = true }, + [3] = { reverse = true }, } screen:attach() - meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"}) - meths.set_option_value('modified', false, {}) + api.nvim_buf_set_lines( + 0, + 0, + -1, + true, + { 'aaa', 'bbb', 'ccc', 'ddd', 'www', 'xxx', 'yyy', 'zzz' } + ) + api.nvim_set_option_value('modified', false, {}) end) it('of current window', function() - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('new | wincmd w') - meths.win_set_cursor(win, {8,0}) + api.nvim_win_set_cursor(win, { 8, 0 }) - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| www | xxx | @@ -1701,15 +1764,14 @@ describe('api/buf', function() ^zzz | {2:[No Name] }| | - ]]} - meths.buf_set_text(buf, 0,3, 1,0, {"X"}) + ]], + } + api.nvim_buf_set_text(buf, 0, 3, 1, 0, { 'X' }) - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {3:[No Name] }| www | xxx | @@ -1717,22 +1779,21 @@ describe('api/buf', function() ^zzz | {2:[No Name] [+] }| | - ]]} + ]], + } end) it('of non-current window', function() - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('new') - meths.win_set_cursor(win, {8,0}) + api.nvim_win_set_cursor(win, { 8, 0 }) - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {2:[No Name] }| www | xxx | @@ -1740,15 +1801,14 @@ describe('api/buf', function() zzz | {3:[No Name] }| | - ]]} + ]], + } - meths.buf_set_text(buf, 0,3, 1,0, {"X"}) - screen:expect{grid=[[ + api.nvim_buf_set_text(buf, 0, 3, 1, 0, { 'X' }) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| - {1:~ }| - {1:~ }| + {1:~ }|*4 {2:[No Name] }| www | xxx | @@ -1756,18 +1816,20 @@ describe('api/buf', function() zzz | {3:[No Name] [+] }| | - ]]} + ]], + } end) it('of split windows with same buffer', function() - local win = meths.get_current_win() - local buf = meths.get_current_buf() + local win = api.nvim_get_current_win() + local buf = api.nvim_get_current_buf() command('split') - meths.win_set_cursor(win, {8,0}) - meths.win_set_cursor(0, {1,1}) + api.nvim_win_set_cursor(win, { 8, 0 }) + api.nvim_win_set_cursor(0, { 1, 1 }) - screen:expect{grid=[[ + screen:expect { + grid = [[ a^aa | bbb | ccc | @@ -1780,10 +1842,12 @@ describe('api/buf', function() zzz | {3:[No Name] }| | - ]]} - meths.buf_set_text(buf, 0,3, 1,0, {"X"}) + ]], + } + api.nvim_buf_set_text(buf, 0, 3, 1, 0, { 'X' }) - screen:expect{grid=[[ + screen:expect { + grid = [[ a^aaXbbb | ccc | ddd | @@ -1796,13 +1860,14 @@ describe('api/buf', function() zzz | {3:[No Name] [+] }| | - ]]} + ]], + } end) end) end) - describe_lua_and_rpc('nvim_buf_get_text', function(api) - local get_text = api.curbufmeths.get_text + describe_lua_and_rpc('nvim_buf_get_text', function(lua_or_rpc) + local get_text = lua_or_rpc.nvim_buf_get_text before_each(function() insert([[ hello foo! @@ -1811,119 +1876,118 @@ describe('api/buf', function() end) it('works', function() - eq({'hello'}, get_text(0, 0, 0, 5, {})) - eq({'hello foo!'}, get_text(0, 0, 0, 42, {})) - eq({'foo!'}, get_text(0, 6, 0, 10, {})) - eq({'foo!', 'tex'}, get_text(0, 6, 1, 3, {})) - eq({'foo!', 'tex'}, get_text(-3, 6, -2, 3, {})) - eq({''}, get_text(0, 18, 0, 20, {})) - eq({'ext'}, get_text(-2, 1, -2, 4, {})) - eq({'hello foo!', 'text', 'm'}, get_text(0, 0, 2, 1, {})) + eq({ 'hello' }, get_text(0, 0, 0, 0, 5, {})) + eq({ 'hello foo!' }, get_text(0, 0, 0, 0, 42, {})) + eq({ 'foo!' }, get_text(0, 0, 6, 0, 10, {})) + eq({ 'foo!', 'tex' }, get_text(0, 0, 6, 1, 3, {})) + eq({ 'foo!', 'tex' }, get_text(0, -3, 6, -2, 3, {})) + eq({ '' }, get_text(0, 0, 18, 0, 20, {})) + eq({ 'ext' }, get_text(0, -2, 1, -2, 4, {})) + eq({ 'hello foo!', 'text', 'm' }, get_text(0, 0, 0, 2, 1, {})) end) it('errors on out-of-range', function() - eq('Index out of bounds', pcall_err(get_text, 2, 0, 4, 0, {})) - eq('Index out of bounds', pcall_err(get_text, -4, 0, 0, 0, {})) - eq('Index out of bounds', pcall_err(get_text, 0, 0, 3, 0, {})) - eq('Index out of bounds', pcall_err(get_text, 0, 0, -4, 0, {})) + eq('Index out of bounds', pcall_err(get_text, 0, 2, 0, 4, 0, {})) + eq('Index out of bounds', pcall_err(get_text, 0, -4, 0, 0, 0, {})) + eq('Index out of bounds', pcall_err(get_text, 0, 0, 0, 3, 0, {})) + eq('Index out of bounds', pcall_err(get_text, 0, 0, 0, -4, 0, {})) -- no ml_get errors should happen #19017 - eq('', meths.get_vvar('errmsg')) + eq('', api.nvim_get_vvar('errmsg')) end) it('errors when start is greater than end', function() - eq("'start' is higher than 'end'", pcall_err(get_text, 1, 0, 0, 0, {})) - eq('start_col must be less than end_col', pcall_err(get_text, 0, 1, 0, 0, {})) + eq("'start' is higher than 'end'", pcall_err(get_text, 0, 1, 0, 0, 0, {})) + eq('start_col must be less than end_col', pcall_err(get_text, 0, 0, 1, 0, 0, {})) end) end) describe('nvim_buf_get_offset', function() - local get_offset = curbufmeths.get_offset + local get_offset = api.nvim_buf_get_offset it('works', function() - curbufmeths.set_lines(0,-1,true,{'Some\r','exa\000mple', '', 'buf\rfer', 'text'}) - eq(5, curbufmeths.line_count()) - eq(0, get_offset(0)) - eq(6, get_offset(1)) - eq(15, get_offset(2)) - eq(16, get_offset(3)) - eq(24, get_offset(4)) - eq(29, get_offset(5)) - eq('Index out of bounds', pcall_err(get_offset, 6)) - eq('Index out of bounds', pcall_err(get_offset, -1)) - - meths.set_option_value('eol', false, {}) - meths.set_option_value('fixeol', false, {}) - eq(28, get_offset(5)) + api.nvim_buf_set_lines(0, 0, -1, true, { 'Some\r', 'exa\000mple', '', 'buf\rfer', 'text' }) + eq(5, api.nvim_buf_line_count(0)) + eq(0, get_offset(0, 0)) + eq(6, get_offset(0, 1)) + eq(15, get_offset(0, 2)) + eq(16, get_offset(0, 3)) + eq(24, get_offset(0, 4)) + eq(29, get_offset(0, 5)) + eq('Index out of bounds', pcall_err(get_offset, 0, 6)) + eq('Index out of bounds', pcall_err(get_offset, 0, -1)) + + api.nvim_set_option_value('eol', false, {}) + api.nvim_set_option_value('fixeol', false, {}) + eq(28, get_offset(0, 5)) -- fileformat is ignored - meths.set_option_value('fileformat', 'dos', {}) - eq(0, get_offset(0)) - eq(6, get_offset(1)) - eq(15, get_offset(2)) - eq(16, get_offset(3)) - eq(24, get_offset(4)) - eq(28, get_offset(5)) - meths.set_option_value('eol', true, {}) - eq(29, get_offset(5)) - - command("set hidden") - command("enew") - eq(6, bufmeths.get_offset(1,1)) - command("bunload! 1") - eq(-1, bufmeths.get_offset(1,1)) - eq(-1, bufmeths.get_offset(1,0)) + api.nvim_set_option_value('fileformat', 'dos', {}) + eq(0, get_offset(0, 0)) + eq(6, get_offset(0, 1)) + eq(15, get_offset(0, 2)) + eq(16, get_offset(0, 3)) + eq(24, get_offset(0, 4)) + eq(28, get_offset(0, 5)) + api.nvim_set_option_value('eol', true, {}) + eq(29, get_offset(0, 5)) + + command('set hidden') + command('enew') + eq(6, api.nvim_buf_get_offset(1, 1)) + command('bunload! 1') + eq(-1, api.nvim_buf_get_offset(1, 1)) + eq(-1, api.nvim_buf_get_offset(1, 0)) end) it('works in empty buffer', function() - eq(0, get_offset(0)) - eq(1, get_offset(1)) + eq(0, get_offset(0, 0)) + eq(1, get_offset(0, 1)) + eq(-1, fn.line2byte('$')) end) it('works in buffer with one line inserted', function() feed('itext') - eq(0, get_offset(0)) - eq(5, get_offset(1)) + eq(0, get_offset(0, 0)) + eq(5, get_offset(0, 1)) end) end) describe('nvim_buf_get_var, nvim_buf_set_var, nvim_buf_del_var', function() it('works', function() - curbuf('set_var', 'lua', {1, 2, {['3'] = 1}}) - eq({1, 2, {['3'] = 1}}, curbuf('get_var', 'lua')) - eq({1, 2, {['3'] = 1}}, nvim('eval', 'b:lua')) - eq(1, funcs.exists('b:lua')) - curbufmeths.del_var('lua') - eq(0, funcs.exists('b:lua')) - eq( 'Key not found: lua', pcall_err(curbufmeths.del_var, 'lua')) - curbufmeths.set_var('lua', 1) + api.nvim_buf_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } }) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_buf_get_var(0, 'lua')) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('b:lua')) + eq(1, fn.exists('b:lua')) + api.nvim_buf_del_var(0, 'lua') + eq(0, fn.exists('b:lua')) + eq('Key not found: lua', pcall_err(api.nvim_buf_del_var, 0, 'lua')) + api.nvim_buf_set_var(0, 'lua', 1) command('lockvar b:lua') - eq('Key is locked: lua', pcall_err(curbufmeths.del_var, 'lua')) - eq('Key is locked: lua', pcall_err(curbufmeths.set_var, 'lua', 1)) - eq('Key is read-only: changedtick', - pcall_err(curbufmeths.del_var, 'changedtick')) - eq('Key is read-only: changedtick', - pcall_err(curbufmeths.set_var, 'changedtick', 1)) + eq('Key is locked: lua', pcall_err(api.nvim_buf_del_var, 0, 'lua')) + eq('Key is locked: lua', pcall_err(api.nvim_buf_set_var, 0, 'lua', 1)) + eq('Key is read-only: changedtick', pcall_err(api.nvim_buf_del_var, 0, 'changedtick')) + eq('Key is read-only: changedtick', pcall_err(api.nvim_buf_set_var, 0, 'changedtick', 1)) end) end) describe('nvim_buf_get_changedtick', function() it('works', function() - eq(2, curbufmeths.get_changedtick()) - curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'}) - eq(3, curbufmeths.get_changedtick()) - eq(3, curbufmeths.get_var('changedtick')) + eq(2, api.nvim_buf_get_changedtick(0)) + api.nvim_buf_set_lines(0, 0, 1, false, { 'abc\0', '\0def', 'ghi' }) + eq(3, api.nvim_buf_get_changedtick(0)) + eq(3, api.nvim_buf_get_var(0, 'changedtick')) end) it('buffer_set_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } eq(NIL, request('buffer_set_var', 0, 'lua', val1)) eq(val1, request('buffer_set_var', 0, 'lua', val2)) end) it('buffer_del_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} - eq(NIL, request('buffer_set_var', 0, 'lua', val1)) + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } + eq(NIL, request('buffer_set_var', 0, 'lua', val1)) eq(val1, request('buffer_set_var', 0, 'lua', val2)) eq(val2, request('buffer_del_var', 0, 'lua')) end) @@ -1931,33 +1995,33 @@ describe('api/buf', function() describe('nvim_get_option_value, nvim_set_option_value', function() it('works', function() - eq(8, nvim('get_option_value', 'shiftwidth', {})) - nvim('set_option_value', 'shiftwidth', 4, {}) - eq(4, nvim('get_option_value', 'shiftwidth', {})) + eq(8, api.nvim_get_option_value('shiftwidth', {})) + api.nvim_set_option_value('shiftwidth', 4, {}) + eq(4, api.nvim_get_option_value('shiftwidth', {})) -- global-local option - nvim('set_option_value', 'define', 'test', {buf = 0}) - eq('test', nvim('get_option_value', 'define', {buf = 0})) + api.nvim_set_option_value('define', 'test', { buf = 0 }) + eq('test', api.nvim_get_option_value('define', { buf = 0 })) -- Doesn't change the global value - eq("", nvim('get_option_value', 'define', {scope='global'})) + eq('', api.nvim_get_option_value('define', { scope = 'global' })) end) it('returns values for unset local options', function() -- 'undolevels' is only set to its "unset" value when a new buffer is -- created command('enew') - eq(-123456, nvim('get_option_value', 'undolevels', {buf=0})) + eq(-123456, api.nvim_get_option_value('undolevels', { buf = 0 })) end) end) describe('nvim_buf_get_name, nvim_buf_set_name', function() it('works', function() - nvim('command', 'new') - eq('', curbuf('get_name')) - local new_name = nvim('eval', 'resolve(tempname())') - curbuf('set_name', new_name) - eq(new_name, curbuf('get_name')) - nvim('command', 'w!') - eq(1, funcs.filereadable(new_name)) + command('new') + eq('', api.nvim_buf_get_name(0)) + local new_name = api.nvim_eval('resolve(tempname())') + api.nvim_buf_set_name(0, new_name) + eq(new_name, api.nvim_buf_get_name(0)) + command('w!') + eq(1, fn.filereadable(new_name)) os.remove(new_name) end) end) @@ -1965,119 +2029,121 @@ describe('api/buf', function() describe('nvim_buf_is_loaded', function() it('works', function() -- record our buffer number for when we unload it - local bufnr = curbuf('get_number') + local bufnr = api.nvim_buf_get_number(0) -- api should report that the buffer is loaded - ok(buffer('is_loaded', bufnr)) + ok(api.nvim_buf_is_loaded(bufnr)) -- hide the current buffer by switching to a new empty buffer -- Careful! we need to modify the buffer first or vim will just reuse it - buffer('set_lines', bufnr, 0, -1, 1, {'line1'}) + api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'line1' }) command('hide enew') -- confirm the buffer is hidden, but still loaded - local infolist = nvim('eval', 'getbufinfo('..bufnr..')') + local infolist = api.nvim_eval('getbufinfo(' .. bufnr .. ')') eq(1, #infolist) eq(1, infolist[1].hidden) eq(1, infolist[1].loaded) -- now force unload the buffer - command('bunload! '..bufnr) + command('bunload! ' .. bufnr) -- confirm the buffer is unloaded - infolist = nvim('eval', 'getbufinfo('..bufnr..')') + infolist = api.nvim_eval('getbufinfo(' .. bufnr .. ')') eq(0, infolist[1].loaded) -- nvim_buf_is_loaded() should also report the buffer as unloaded - eq(false, buffer('is_loaded', bufnr)) + eq(false, api.nvim_buf_is_loaded(bufnr)) end) end) describe('nvim_buf_is_valid', function() it('works', function() - nvim('command', 'new') - local b = nvim('get_current_buf') - ok(buffer('is_valid', b)) - nvim('command', 'bw!') - ok(not buffer('is_valid', b)) + command('new') + local b = api.nvim_get_current_buf() + ok(api.nvim_buf_is_valid(b)) + command('bw!') + ok(not api.nvim_buf_is_valid(b)) end) end) describe('nvim_buf_delete', function() it('allows for just deleting', function() - nvim('command', 'new') - local b = nvim('get_current_buf') - ok(buffer('is_valid', b)) - nvim('buf_delete', b, {}) - ok(not buffer('is_loaded', b)) - ok(not buffer('is_valid', b)) + command('new') + local b = api.nvim_get_current_buf() + ok(api.nvim_buf_is_valid(b)) + api.nvim_buf_delete(b, {}) + ok(not api.nvim_buf_is_loaded(b)) + ok(not api.nvim_buf_is_valid(b)) end) it('allows for just unloading', function() - nvim('command', 'new') - local b = nvim('get_current_buf') - ok(buffer('is_valid', b)) - nvim('buf_delete', b, { unload = true }) - ok(not buffer('is_loaded', b)) - ok(buffer('is_valid', b)) + command('new') + local b = api.nvim_get_current_buf() + ok(api.nvim_buf_is_valid(b)) + api.nvim_buf_delete(b, { unload = true }) + ok(not api.nvim_buf_is_loaded(b)) + ok(api.nvim_buf_is_valid(b)) end) end) describe('nvim_buf_get_mark', function() it('works', function() - curbuf('set_lines', -1, -1, true, {'a', 'bit of', 'text'}) - curwin('set_cursor', {3, 4}) - nvim('command', 'mark v') - eq({3, 0}, curbuf('get_mark', 'v')) + api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' }) + api.nvim_win_set_cursor(0, { 3, 4 }) + command('mark v') + eq({ 3, 0 }, api.nvim_buf_get_mark(0, 'v')) end) end) describe('nvim_buf_set_mark', function() it('works with buffer local marks', function() - curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - eq(true, curbufmeths.set_mark('z', 1, 1, {})) - eq({1, 1}, curbufmeths.get_mark('z')) + api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' }) + eq(true, api.nvim_buf_set_mark(0, 'z', 1, 1, {})) + eq({ 1, 1 }, api.nvim_buf_get_mark(0, 'z')) + eq({ 0, 1, 2, 0 }, fn.getpos("'z")) end) it('works with file/uppercase marks', function() - curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - eq(true, curbufmeths.set_mark('Z', 3, 1, {})) - eq({3, 1}, curbufmeths.get_mark('Z')) + api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' }) + eq(true, api.nvim_buf_set_mark(0, 'Z', 3, 2, {})) + eq({ 3, 2 }, api.nvim_buf_get_mark(0, 'Z')) + eq({ api.nvim_get_current_buf(), 3, 3, 0 }, fn.getpos("'Z")) end) it('fails when invalid marks names are used', function() - eq(false, pcall(curbufmeths.set_mark, '!', 1, 0, {})) - eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0, {})) + eq(false, pcall(api.nvim_buf_set_mark, 0, '!', 1, 0, {})) + eq(false, pcall(api.nvim_buf_set_mark, 0, 'fail', 1, 0, {})) end) it('fails when invalid buffer number is used', function() - eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1, {})) + eq(false, pcall(api.nvim_buf_set_mark, 99, 'a', 1, 1, {})) end) end) describe('nvim_buf_del_mark', function() it('works with buffer local marks', function() - curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - curbufmeths.set_mark('z', 3, 1, {}) - eq(true, curbufmeths.del_mark('z')) - eq({0, 0}, curbufmeths.get_mark('z')) + api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' }) + api.nvim_buf_set_mark(0, 'z', 3, 1, {}) + eq(true, api.nvim_buf_del_mark(0, 'z')) + eq({ 0, 0 }, api.nvim_buf_get_mark(0, 'z')) end) it('works with file/uppercase marks', function() - curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - curbufmeths.set_mark('Z', 3, 3, {}) - eq(true, curbufmeths.del_mark('Z')) - eq({0, 0}, curbufmeths.get_mark('Z')) + api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' }) + api.nvim_buf_set_mark(0, 'Z', 3, 3, {}) + eq(true, api.nvim_buf_del_mark(0, 'Z')) + eq({ 0, 0 }, api.nvim_buf_get_mark(0, 'Z')) end) it('returns false in marks not set in this buffer', function() - local abuf = meths.create_buf(false,true) - bufmeths.set_lines(abuf, -1, -1, true, {'a', 'bit of', 'text'}) - bufmeths.set_mark(abuf, 'A', 2, 2, {}) - eq(false, curbufmeths.del_mark('A')) - eq({2, 2}, bufmeths.get_mark(abuf, 'A')) + local abuf = api.nvim_create_buf(false, true) + api.nvim_buf_set_lines(abuf, -1, -1, true, { 'a', 'bit of', 'text' }) + api.nvim_buf_set_mark(abuf, 'A', 2, 2, {}) + eq(false, api.nvim_buf_del_mark(0, 'A')) + eq({ 2, 2 }, api.nvim_buf_get_mark(abuf, 'A')) end) it('returns false if mark was not deleted', function() - curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'}) - curbufmeths.set_mark('z', 3, 1, {}) - eq(true, curbufmeths.del_mark('z')) - eq(false, curbufmeths.del_mark('z')) -- Mark was already deleted + api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' }) + api.nvim_buf_set_mark(0, 'z', 3, 1, {}) + eq(true, api.nvim_buf_del_mark(0, 'z')) + eq(false, api.nvim_buf_del_mark(0, 'z')) -- Mark was already deleted end) it('fails when invalid marks names are used', function() - eq(false, pcall(curbufmeths.del_mark, '!')) - eq(false, pcall(curbufmeths.del_mark, 'fail')) + eq(false, pcall(api.nvim_buf_del_mark, 0, '!')) + eq(false, pcall(api.nvim_buf_del_mark, 0, 'fail')) end) it('fails when invalid buffer number is used', function() - eq(false, pcall(meths.buf_del_mark, 99, 'a')) + eq(false, pcall(api.nvim_buf_del_mark, 99, 'a')) end) end) end) diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua index 80e29c1ff2..262ca40e28 100644 --- a/test/functional/api/buffer_updates_spec.lua +++ b/test/functional/api/buffer_updates_spec.lua @@ -1,39 +1,43 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq, ok = helpers.eq, helpers.ok -local buffer, command, eval, nvim, next_msg = helpers.buffer, - helpers.command, helpers.eval, helpers.nvim, helpers.next_msg +local fn = helpers.fn +local api = helpers.api +local command, eval, next_msg = helpers.command, helpers.eval, helpers.next_msg local nvim_prog = helpers.nvim_prog local pcall_err = helpers.pcall_err -local sleep = helpers.sleep +local sleep = vim.uv.sleep local write_file = helpers.write_file -local origlines = {"original line 1", - "original line 2", - "original line 3", - "original line 4", - "original line 5", - "original line 6"} +local origlines = { + 'original line 1', + 'original line 2', + 'original line 3', + 'original line 4', + 'original line 5', + 'original line 6', +} local function expectn(name, args) -- expect the next message to be the specified notification event - eq({'notification', name, args}, next_msg()) + eq({ 'notification', name, args }, next_msg()) end local function sendkeys(keys) - nvim('input', keys) + api.nvim_input(keys) -- give nvim some time to process msgpack requests before possibly sending -- more key presses - otherwise they all pile up in the queue and get -- processed at once local ntime = os.clock() + 0.1 - repeat until os.clock() > ntime + repeat + until os.clock() > ntime end local function open(activate, lines) local filename = helpers.tmpname() - write_file(filename, table.concat(lines, "\n").."\n", true) + write_file(filename, table.concat(lines, '\n') .. '\n', true) command('edit ' .. filename) - local b = nvim('get_current_buf') + local b = api.nvim_get_current_buf() -- what is the value of b:changedtick? local tick = eval('b:changedtick') @@ -41,8 +45,8 @@ local function open(activate, lines) -- arrive as expected if activate then local firstline = 0 - ok(buffer('attach', b, true, {})) - expectn('nvim_buf_lines_event', {b, tick, firstline, -1, lines, false}) + ok(api.nvim_buf_attach(b, true, {})) + expectn('nvim_buf_lines_event', { b, tick, firstline, -1, lines, false }) end return b, tick, filename @@ -58,14 +62,14 @@ local function editoriginal(activate, lines) end local function reopen(buf, expectedlines) - ok(buffer('detach', buf)) - expectn('nvim_buf_detach_event', {buf}) + ok(api.nvim_buf_detach(buf)) + expectn('nvim_buf_detach_event', { buf }) -- for some reason the :edit! increments tick by 2 command('edit!') local tick = eval('b:changedtick') - ok(buffer('attach', buf, true, {})) + ok(api.nvim_buf_attach(buf, true, {})) local firstline = 0 - expectn('nvim_buf_lines_event', {buf, tick, firstline, -1, expectedlines, false}) + expectn('nvim_buf_lines_event', { buf, tick, firstline, -1, expectedlines, false }) command('normal! gg') return tick end @@ -80,18 +84,36 @@ local function reopenwithfolds(b) -- add a fold command('2,4fold') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2/*{{{*/', - 'original line 3', - 'original line 4/*}}}*/'}, false}) + expectn('nvim_buf_lines_event', { + b, + tick, + 1, + 4, + { + 'original line 2/*{{{*/', + 'original line 3', + 'original line 4/*}}}*/', + }, + false, + }) -- make a new fold that wraps lines 1-6 command('1,6fold') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 6, {'original line 1/*{{{*/', - 'original line 2/*{{{*/', - 'original line 3', - 'original line 4/*}}}*/', - 'original line 5', - 'original line 6/*}}}*/'}, false}) + expectn('nvim_buf_lines_event', { + b, + tick, + 0, + 6, + { + 'original line 1/*{{{*/', + 'original line 2/*{{{*/', + 'original line 3', + 'original line 4/*}}}*/', + 'original line 5', + 'original line 6/*}}}*/', + }, + false, + }) return tick end @@ -104,97 +126,105 @@ describe('API: buffer events:', function() -- add a new line at the start of the buffer command('normal! GyyggP') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 0, {'original line 6'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 0, { 'original line 6' }, false }) -- add multiple lines at the start of the file command('normal! GkkyGggP') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 0, {'original line 4', - 'original line 5', - 'original line 6'}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 0, 0, { 'original line 4', 'original line 5', 'original line 6' }, false } + ) -- add one line to the middle of the file, several times command('normal! ggYjjp') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 3, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 3, { 'original line 4' }, false }) command('normal! p') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 4, 4, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 4, 4, { 'original line 4' }, false }) command('normal! p') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 5, 5, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 5, 5, { 'original line 4' }, false }) -- add multiple lines to the middle of the file command('normal! gg4Yjjp') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 3, {'original line 4', - 'original line 5', - 'original line 6', - 'original line 4'}, false}) + expectn('nvim_buf_lines_event', { + b, + tick, + 3, + 3, + { + 'original line 4', + 'original line 5', + 'original line 6', + 'original line 4', + }, + false, + }) -- add one line to the end of the file command('normal! ggYGp') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 17, 17, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 17, 17, { 'original line 4' }, false }) -- add one line to the end of the file, several times command('normal! ggYGppp') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 18, 18, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 18, 18, { 'original line 4' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 19, 19, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 19, 19, { 'original line 4' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 20, 20, {'original line 4'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 20, 20, { 'original line 4' }, false }) -- add several lines to the end of the file, several times command('normal! gg4YGp') command('normal! Gp') command('normal! Gp') - local firstfour = {'original line 4', - 'original line 5', - 'original line 6', - 'original line 4'} + local firstfour = { 'original line 4', 'original line 5', 'original line 6', 'original line 4' } tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 21, 21, firstfour, false}) + expectn('nvim_buf_lines_event', { b, tick, 21, 21, firstfour, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 25, 25, firstfour, false}) + expectn('nvim_buf_lines_event', { b, tick, 25, 25, firstfour, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 29, 29, firstfour, false}) + expectn('nvim_buf_lines_event', { b, tick, 29, 29, firstfour, false }) -- delete the current buffer to turn off buffer events command('bdelete!') - expectn('nvim_buf_detach_event', {b}) + expectn('nvim_buf_detach_event', { b }) -- add a line at the start of an empty file command('enew') tick = eval('b:changedtick') - local b2 = nvim('get_current_buf') - ok(buffer('attach', b2, true, {})) - expectn('nvim_buf_lines_event', {b2, tick, 0, -1, {""}, false}) + local b2 = api.nvim_get_current_buf() + ok(api.nvim_buf_attach(b2, true, {})) + expectn('nvim_buf_lines_event', { b2, tick, 0, -1, { '' }, false }) eval('append(0, ["new line 1"])') tick = tick + 1 - expectn('nvim_buf_lines_event', {b2, tick, 0, 0, {'new line 1'}, false}) + expectn('nvim_buf_lines_event', { b2, tick, 0, 0, { 'new line 1' }, false }) -- turn off buffer events manually - buffer('detach', b2) - expectn('nvim_buf_detach_event', {b2}) + api.nvim_buf_detach(b2) + expectn('nvim_buf_detach_event', { b2 }) -- add multiple lines to a blank file command('enew!') - local b3 = nvim('get_current_buf') - ok(buffer('attach', b3, true, {})) + local b3 = api.nvim_get_current_buf() + ok(api.nvim_buf_attach(b3, true, {})) tick = eval('b:changedtick') - expectn('nvim_buf_lines_event', {b3, tick, 0, -1, {""}, false}) + expectn('nvim_buf_lines_event', { b3, tick, 0, -1, { '' }, false }) eval('append(0, ["new line 1", "new line 2", "new line 3"])') tick = tick + 1 - expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {'new line 1', - 'new line 2', - 'new line 3'}, false}) + expectn( + 'nvim_buf_lines_event', + { b3, tick, 0, 0, { 'new line 1', 'new line 2', 'new line 3' }, false } + ) -- use the API itself to add a line to the start of the buffer - buffer('set_lines', b3, 0, 0, true, {'New First Line'}) + api.nvim_buf_set_lines(b3, 0, 0, true, { 'New First Line' }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {"New First Line"}, false}) + expectn('nvim_buf_lines_event', { b3, tick, 0, 0, { 'New First Line' }, false }) end) it('when lines are removed', function() @@ -203,37 +233,37 @@ describe('API: buffer events:', function() -- remove one line from start of file command('normal! dd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, {}, false }) -- remove multiple lines from the start of the file command('normal! 4dd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 4, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 4, {}, false }) -- remove multiple lines from middle of file tick = reopen(b, origlines) command('normal! jj3dd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 5, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 2, 5, {}, false }) -- remove one line from the end of the file tick = reopen(b, origlines) command('normal! Gdd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 5, 6, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 5, 6, {}, false }) -- remove multiple lines from the end of the file tick = reopen(b, origlines) command('normal! 4G3dd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 6, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 6, {}, false }) -- pretend to remove heaps lines from the end of the file but really -- just remove two tick = reopen(b, origlines) command('normal! Gk5dd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 4, 6, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 4, 6, {}, false }) end) it('when text is changed', function() @@ -242,53 +272,56 @@ describe('API: buffer events:', function() -- some normal text editing command('normal! A555') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'original line 1555'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'original line 1555' }, false }) command('normal! jj8X') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'origin3'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'origin3' }, false }) -- modify multiple lines at once using visual block mode tick = reopen(b, origlines) command('normal! jjw') sendkeys('<C-v>jjllx') tick = tick + 1 - expectn('nvim_buf_lines_event', - {b, tick, 2, 5, {'original e 3', 'original e 4', 'original e 5'}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 2, 5, { 'original e 3', 'original e 4', 'original e 5' }, false } + ) -- replace part of a line line using :s tick = reopen(b, origlines) command('3s/line 3/foo/') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'original foo'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'original foo' }, false }) -- replace parts of several lines line using :s tick = reopen(b, origlines) command('%s/line [35]/foo/') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 5, {'original foo', - 'original line 4', - 'original foo'}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 2, 5, { 'original foo', 'original line 4', 'original foo' }, false } + ) -- type text into the first line of a blank file, one character at a time command('bdelete!') tick = 2 - expectn('nvim_buf_detach_event', {b}) - local bnew = nvim('get_current_buf') - ok(buffer('attach', bnew, true, {})) - expectn('nvim_buf_lines_event', {bnew, tick, 0, -1, {''}, false}) + expectn('nvim_buf_detach_event', { b }) + local bnew = api.nvim_get_current_buf() + ok(api.nvim_buf_attach(bnew, true, {})) + expectn('nvim_buf_lines_event', { bnew, tick, 0, -1, { '' }, false }) sendkeys('i') sendkeys('h') sendkeys('e') sendkeys('l') sendkeys('l') sendkeys('o\nworld') - expectn('nvim_buf_lines_event', {bnew, tick + 1, 0, 1, {'h'}, false}) - expectn('nvim_buf_lines_event', {bnew, tick + 2, 0, 1, {'he'}, false}) - expectn('nvim_buf_lines_event', {bnew, tick + 3, 0, 1, {'hel'}, false}) - expectn('nvim_buf_lines_event', {bnew, tick + 4, 0, 1, {'hell'}, false}) - expectn('nvim_buf_lines_event', {bnew, tick + 5, 0, 1, {'hello'}, false}) - expectn('nvim_buf_lines_event', {bnew, tick + 6, 0, 1, {'hello', ''}, false}) - expectn('nvim_buf_lines_event', {bnew, tick + 7, 1, 2, {'world'}, false}) + expectn('nvim_buf_lines_event', { bnew, tick + 1, 0, 1, { 'h' }, false }) + expectn('nvim_buf_lines_event', { bnew, tick + 2, 0, 1, { 'he' }, false }) + expectn('nvim_buf_lines_event', { bnew, tick + 3, 0, 1, { 'hel' }, false }) + expectn('nvim_buf_lines_event', { bnew, tick + 4, 0, 1, { 'hell' }, false }) + expectn('nvim_buf_lines_event', { bnew, tick + 5, 0, 1, { 'hello' }, false }) + expectn('nvim_buf_lines_event', { bnew, tick + 6, 0, 1, { 'hello', '' }, false }) + expectn('nvim_buf_lines_event', { bnew, tick + 7, 1, 2, { 'world' }, false }) end) it('when lines are replaced', function() @@ -297,169 +330,179 @@ describe('API: buffer events:', function() -- blast away parts of some lines with visual mode command('normal! jjwvjjllx') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'original '}, false}) + expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'original ' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 4, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 4, {}, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 4, {'e 5'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 4, { 'e 5' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'original e 5'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'original e 5' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 4, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 4, {}, false }) -- blast away a few lines using :g tick = reopen(b, origlines) command('global/line [35]/delete') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 2, 3, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 2, 3, {}, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 4, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 4, {}, false }) + end) + + it('visual paste split empty line', function() + local b, tick = editoriginal(true, { 'abc', '{', 'def', '}' }) + command('normal! ggyyjjvi{p') + expectn('nvim_buf_lines_event', { b, tick + 1, 2, 3, { '' }, false }) + expectn('nvim_buf_lines_event', { b, tick + 2, 2, 3, { '}' }, false }) + expectn('nvim_buf_lines_event', { b, tick + 3, 3, 4, {}, false }) + expectn('nvim_buf_lines_event', { b, tick + 3, 2, 3, { '' }, false }) + expectn('nvim_buf_lines_event', { b, tick + 4, 3, 3, { 'abc', '}' }, false }) end) it('when lines are filtered', function() -- Test filtering lines with !cat - local b, tick = editoriginal(true, {"A", "C", "E", "B", "D", "F"}) + local b, tick = editoriginal(true, { 'A', 'C', 'E', 'B', 'D', 'F' }) command('silent 2,5!cat') -- the change comes through as two changes: -- 1) addition of the new lines after the filtered lines -- 2) removal of the original lines tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 5, 5, {"C", "E", "B", "D"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 5, 5, { 'C', 'E', 'B', 'D' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 5, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 5, {}, false }) end) it('when you use "o"', function() - local b, tick = editoriginal(true, {'AAA', 'BBB'}) + local b, tick = editoriginal(true, { 'AAA', 'BBB' }) command('set noautoindent nosmartindent') -- use 'o' to start a new line from a line with no indent command('normal! o') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 1, {""}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 1, { '' }, false }) -- undo the change, indent line 1 a bit, and try again command('undo') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 2, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 2, {}, false }) tick = tick + 1 - expectn('nvim_buf_changedtick_event', {b, tick}) + expectn('nvim_buf_changedtick_event', { b, tick }) command('set autoindent') command('normal! >>') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {"\tAAA"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { '\tAAA' }, false }) command('normal! ommm') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 1, {"\t"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 1, { '\t' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 2, {"\tmmm"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 2, { '\tmmm' }, false }) -- undo the change, and try again with 'O' command('undo') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 2, {'\t'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 2, { '\t' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 2, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 2, {}, false }) tick = tick + 1 - expectn('nvim_buf_changedtick_event', {b, tick}) + expectn('nvim_buf_changedtick_event', { b, tick }) command('normal! ggOmmm') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 0, {"\t"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 0, { '\t' }, false }) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {"\tmmm"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { '\tmmm' }, false }) end) it('deactivates if the buffer is changed externally', function() -- Test changing file from outside vim and reloading using :edit - local lines = {"Line 1", "Line 2"}; + local lines = { 'Line 1', 'Line 2' } local b, tick, filename = editoriginal(true, lines) command('normal! x') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'ine 1'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'ine 1' }, false }) command('undo') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'Line 1'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'Line 1' }, false }) tick = tick + 1 - expectn('nvim_buf_changedtick_event', {b, tick}) + expectn('nvim_buf_changedtick_event', { b, tick }) -- change the file directly - write_file(filename, "another line\n", true, true) + write_file(filename, 'another line\n', true, true) -- reopen the file and watch buffer events shut down command('edit') - expectn('nvim_buf_detach_event', {b}) + expectn('nvim_buf_detach_event', { b }) end) it('channel can watch many buffers at once', function() -- edit 3 buffers, make sure they all have windows visible so that when we -- move between buffers, none of them are unloaded - local b1, tick1 = editoriginal(true, {'A1', 'A2'}) + local b1, tick1 = editoriginal(true, { 'A1', 'A2' }) local b1nr = eval('bufnr("")') command('split') - local b2, tick2 = open(true, {'B1', 'B2'}) + local b2, tick2 = open(true, { 'B1', 'B2' }) local b2nr = eval('bufnr("")') command('split') - local b3, tick3 = open(true, {'C1', 'C2'}) + local b3, tick3 = open(true, { 'C1', 'C2' }) local b3nr = eval('bufnr("")') -- make a new window for moving between buffers command('split') - command('b'..b1nr) + command('b' .. b1nr) command('normal! x') tick1 = tick1 + 1 - expectn('nvim_buf_lines_event', {b1, tick1, 0, 1, {'1'}, false}) + expectn('nvim_buf_lines_event', { b1, tick1, 0, 1, { '1' }, false }) command('undo') tick1 = tick1 + 1 - expectn('nvim_buf_lines_event', {b1, tick1, 0, 1, {'A1'}, false}) + expectn('nvim_buf_lines_event', { b1, tick1, 0, 1, { 'A1' }, false }) tick1 = tick1 + 1 - expectn('nvim_buf_changedtick_event', {b1, tick1}) + expectn('nvim_buf_changedtick_event', { b1, tick1 }) - command('b'..b2nr) + command('b' .. b2nr) command('normal! x') tick2 = tick2 + 1 - expectn('nvim_buf_lines_event', {b2, tick2, 0, 1, {'1'}, false}) + expectn('nvim_buf_lines_event', { b2, tick2, 0, 1, { '1' }, false }) command('undo') tick2 = tick2 + 1 - expectn('nvim_buf_lines_event', {b2, tick2, 0, 1, {'B1'}, false}) + expectn('nvim_buf_lines_event', { b2, tick2, 0, 1, { 'B1' }, false }) tick2 = tick2 + 1 - expectn('nvim_buf_changedtick_event', {b2, tick2}) + expectn('nvim_buf_changedtick_event', { b2, tick2 }) - command('b'..b3nr) + command('b' .. b3nr) command('normal! x') tick3 = tick3 + 1 - expectn('nvim_buf_lines_event', {b3, tick3, 0, 1, {'1'}, false}) + expectn('nvim_buf_lines_event', { b3, tick3, 0, 1, { '1' }, false }) command('undo') tick3 = tick3 + 1 - expectn('nvim_buf_lines_event', {b3, tick3, 0, 1, {'C1'}, false}) + expectn('nvim_buf_lines_event', { b3, tick3, 0, 1, { 'C1' }, false }) tick3 = tick3 + 1 - expectn('nvim_buf_changedtick_event', {b3, tick3}) + expectn('nvim_buf_changedtick_event', { b3, tick3 }) end) it('does not get confused if enabled/disabled many times', function() - local channel = nvim('get_api_info')[1] + local channel = api.nvim_get_chan_info(0).id local b, tick = editoriginal(false) -- Enable buffer events many times. - ok(buffer('attach', b, true, {})) - ok(buffer('attach', b, true, {})) - ok(buffer('attach', b, true, {})) - ok(buffer('attach', b, true, {})) - ok(buffer('attach', b, true, {})) - expectn('nvim_buf_lines_event', {b, tick, 0, -1, origlines, false}) - eval('rpcnotify('..channel..', "Hello There")') + ok(api.nvim_buf_attach(b, true, {})) + ok(api.nvim_buf_attach(b, true, {})) + ok(api.nvim_buf_attach(b, true, {})) + ok(api.nvim_buf_attach(b, true, {})) + ok(api.nvim_buf_attach(b, true, {})) + expectn('nvim_buf_lines_event', { b, tick, 0, -1, origlines, false }) + eval('rpcnotify(' .. channel .. ', "Hello There")') expectn('Hello There', {}) -- Disable buffer events many times. - ok(buffer('detach', b)) - ok(buffer('detach', b)) - ok(buffer('detach', b)) - ok(buffer('detach', b)) - ok(buffer('detach', b)) - expectn('nvim_buf_detach_event', {b}) - eval('rpcnotify('..channel..', "Hello Again")') + ok(api.nvim_buf_detach(b)) + ok(api.nvim_buf_detach(b)) + ok(api.nvim_buf_detach(b)) + ok(api.nvim_buf_detach(b)) + ok(api.nvim_buf_detach(b)) + expectn('nvim_buf_detach_event', { b }) + eval('rpcnotify(' .. channel .. ', "Hello Again")') expectn('Hello Again', {}) end) @@ -469,7 +512,7 @@ describe('API: buffer events:', function() -- create several new sessions, in addition to our main API local sessions = {} local pipe = helpers.new_pipename() - eval("serverstart('"..pipe.."')") + eval("serverstart('" .. pipe .. "')") sessions[1] = helpers.connect(pipe) sessions[2] = helpers.connect(pipe) sessions[3] = helpers.connect(pipe) @@ -484,109 +527,105 @@ describe('API: buffer events:', function() local function wantn(sessionid, name, args) local session = sessions[sessionid] - eq({'notification', name, args}, session:next_message(10000)) + eq({ 'notification', name, args }, session:next_message(10000)) end -- Edit a new file, but don't enable buffer events. - local lines = {'AAA', 'BBB'} + local lines = { 'AAA', 'BBB' } local b, tick = open(false, lines) -- Enable buffer events for sessions 1, 2 and 3. ok(request(1, 'nvim_buf_attach', b, true, {})) ok(request(2, 'nvim_buf_attach', b, true, {})) ok(request(3, 'nvim_buf_attach', b, true, {})) - wantn(1, 'nvim_buf_lines_event', {b, tick, 0, -1, lines, false}) - wantn(2, 'nvim_buf_lines_event', {b, tick, 0, -1, lines, false}) - wantn(3, 'nvim_buf_lines_event', {b, tick, 0, -1, lines, false}) + wantn(1, 'nvim_buf_lines_event', { b, tick, 0, -1, lines, false }) + wantn(2, 'nvim_buf_lines_event', { b, tick, 0, -1, lines, false }) + wantn(3, 'nvim_buf_lines_event', { b, tick, 0, -1, lines, false }) -- Change the buffer. command('normal! x') tick = tick + 1 - wantn(1, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) - wantn(2, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) - wantn(3, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + wantn(1, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) + wantn(2, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) + wantn(3, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) -- Stop watching on channel 1. ok(request(1, 'nvim_buf_detach', b)) - wantn(1, 'nvim_buf_detach_event', {b}) + wantn(1, 'nvim_buf_detach_event', { b }) -- Undo the change to buffer 1. command('undo') tick = tick + 1 - wantn(2, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false}) - wantn(3, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false}) + wantn(2, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false }) + wantn(3, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false }) tick = tick + 1 - wantn(2, 'nvim_buf_changedtick_event', {b, tick}) - wantn(3, 'nvim_buf_changedtick_event', {b, tick}) + wantn(2, 'nvim_buf_changedtick_event', { b, tick }) + wantn(3, 'nvim_buf_changedtick_event', { b, tick }) -- make sure there are no other pending nvim_buf_lines_event messages going to -- channel 1 - local channel1 = request(1, 'nvim_get_api_info')[1] - eval('rpcnotify('..channel1..', "Hello")') + local channel1 = request(1, 'nvim_get_chan_info', 0).id + eval('rpcnotify(' .. channel1 .. ', "Hello")') wantn(1, 'Hello', {}) -- close the buffer and channels 2 and 3 should get a nvim_buf_detach_event -- notification command('edit') - wantn(2, 'nvim_buf_detach_event', {b}) - wantn(3, 'nvim_buf_detach_event', {b}) + wantn(2, 'nvim_buf_detach_event', { b }) + wantn(3, 'nvim_buf_detach_event', { b }) -- make sure there are no other pending nvim_buf_lines_event messages going to -- channel 1 - channel1 = request(1, 'nvim_get_api_info')[1] - eval('rpcnotify('..channel1..', "Hello Again")') + channel1 = request(1, 'nvim_get_chan_info', 0).id + eval('rpcnotify(' .. channel1 .. ', "Hello Again")') wantn(1, 'Hello Again', {}) end) it('works with :diffput and :diffget', function() - local b1, tick1 = editoriginal(true, {"AAA", "BBB"}) - local channel = nvim('get_api_info')[1] + local b1, tick1 = editoriginal(true, { 'AAA', 'BBB' }) + local channel = api.nvim_get_chan_info(0).id command('diffthis') command('rightbelow vsplit') - local b2, tick2 = open(true, {"BBB", "CCC"}) + local b2, tick2 = open(true, { 'BBB', 'CCC' }) command('diffthis') -- go back to first buffer, and push the 'AAA' line to the second buffer command('1wincmd w') command('normal! gg') command('diffput') tick2 = tick2 + 1 - expectn('nvim_buf_lines_event', {b2, tick2, 0, 0, {"AAA"}, false}) + expectn('nvim_buf_lines_event', { b2, tick2, 0, 0, { 'AAA' }, false }) -- use :diffget to grab the other change from buffer 2 command('normal! G') command('diffget') tick1 = tick1 + 1 - expectn('nvim_buf_lines_event', {b1, tick1, 2, 2, {"CCC"}, false}) + expectn('nvim_buf_lines_event', { b1, tick1, 2, 2, { 'CCC' }, false }) - eval('rpcnotify('..channel..', "Goodbye")') + eval('rpcnotify(' .. channel .. ', "Goodbye")') expectn('Goodbye', {}) end) it('works with :sort', function() -- test for :sort - local b, tick = editoriginal(true, {"B", "D", "C", "A", "E"}) + local b, tick = editoriginal(true, { 'B', 'D', 'C', 'A', 'E' }) command('%sort') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 5, {"A", "B", "C", "D", "E"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 5, { 'A', 'B', 'C', 'D', 'E' }, false }) end) it('works with :left', function() - local b, tick = editoriginal(true, {" A", " B", "B", "\tB", "\t\tC"}) + local b, tick = editoriginal(true, { ' A', ' B', 'B', '\tB', '\t\tC' }) command('2,4left') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 4, {"B", "B", "B"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 4, { 'B', 'B', 'B' }, false }) end) it('works with :right', function() - local b, tick = editoriginal(true, {" A", - "\t B", - "\t \tBB", - " \tB", - "\t\tC"}) + local b, tick = editoriginal(true, { ' A', '\t B', '\t \tBB', ' \tB', '\t\tC' }) command('set ts=2 et') command('2,4retab') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 4, {" B", " BB", " B"}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 4, { ' B', ' BB', ' B' }, false }) end) it('works with :move', function() @@ -594,19 +633,23 @@ describe('API: buffer events:', function() -- move text down towards the end of the file command('2,3move 4') tick = tick + 2 - expectn('nvim_buf_lines_event', {b, tick, 4, 4, {"original line 2", - "original line 3"}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 4, 4, { 'original line 2', 'original line 3' }, false } + ) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 3, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 1, 3, {}, false }) -- move text up towards the start of the file tick = reopen(b, origlines) command('4,5move 2') tick = tick + 2 - expectn('nvim_buf_lines_event', {b, tick, 2, 2, {"original line 4", - "original line 5"}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 2, 2, { 'original line 4', 'original line 5' }, false } + ) tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 5, 7, {}, false}) + expectn('nvim_buf_lines_event', { b, tick, 5, 7, {}, false }) end) it('when you manually add/remove folds', function() @@ -616,13 +659,14 @@ describe('API: buffer events:', function() -- delete the inner fold command('normal! zR3Gzd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2', - 'original line 3', - 'original line 4'}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 1, 4, { 'original line 2', 'original line 3', 'original line 4' }, false } + ) -- delete the outer fold command('normal! zd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 6, origlines, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 6, origlines, false }) -- discard changes and put the folds back tick = reopenwithfolds(b) @@ -630,7 +674,7 @@ describe('API: buffer events:', function() -- remove both folds at once command('normal! ggzczD') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 6, origlines, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 6, origlines, false }) -- discard changes and put the folds back tick = reopenwithfolds(b) @@ -638,101 +682,102 @@ describe('API: buffer events:', function() -- now delete all folds at once command('normal! zE') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 6, origlines, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 6, origlines, false }) -- create a fold from line 4 to the end of the file command('normal! 4GA/*{{{*/') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 4, {'original line 4/*{{{*/'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 3, 4, { 'original line 4/*{{{*/' }, false }) -- delete the fold which only has one marker command('normal! Gzd') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 3, 6, {'original line 4', - 'original line 5', - 'original line 6'}, false}) + expectn( + 'nvim_buf_lines_event', + { b, tick, 3, 6, { 'original line 4', 'original line 5', 'original line 6' }, false } + ) end) it('detaches if the buffer is closed', function() - local b, tick = editoriginal(true, {'AAA'}) - local channel = nvim('get_api_info')[1] + local b, tick = editoriginal(true, { 'AAA' }) + local channel = api.nvim_get_chan_info(0).id -- Test that buffer events are working. command('normal! x') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) command('undo') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false }) tick = tick + 1 - expectn('nvim_buf_changedtick_event', {b, tick}) + expectn('nvim_buf_changedtick_event', { b, tick }) -- close our buffer and create a new one command('bdelete') command('enew') - expectn('nvim_buf_detach_event', {b}) + expectn('nvim_buf_detach_event', { b }) -- Reopen the original buffer, make sure there are no buffer events sent. command('b1') command('normal! x') - eval('rpcnotify('..channel..', "Hello There")') + eval('rpcnotify(' .. channel .. ', "Hello There")') expectn('Hello There', {}) end) it(':edit! (reload) causes detach #9642', function() - local b, tick = editoriginal(true, {'AAA', 'BBB'}) + local b, tick = editoriginal(true, { 'AAA', 'BBB' }) command('set undoreload=1') command('normal! x') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) command('edit!') - expectn('nvim_buf_detach_event', {b}) + expectn('nvim_buf_detach_event', { b }) end) it(':enew! does not detach hidden buffer', function() - local b, tick = editoriginal(true, {'AAA', 'BBB'}) - local channel = nvim('get_api_info')[1] + local b, tick = editoriginal(true, { 'AAA', 'BBB' }) + local channel = api.nvim_get_chan_info(0).id command('set undoreload=1 hidden') command('normal! x') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) command('enew!') - eval('rpcnotify('..channel..', "Hello There")') + eval('rpcnotify(' .. channel .. ', "Hello There")') expectn('Hello There', {}) end) it('stays attached if the buffer is hidden', function() - local b, tick = editoriginal(true, {'AAA'}) - local channel = nvim('get_api_info')[1] + local b, tick = editoriginal(true, { 'AAA' }) + local channel = api.nvim_get_chan_info(0).id -- Test that buffer events are working. command('normal! x') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) command('undo') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false }) tick = tick + 1 - expectn('nvim_buf_changedtick_event', {b, tick}) + expectn('nvim_buf_changedtick_event', { b, tick }) -- Close our buffer by creating a new one. command('set hidden') command('enew') -- Assert that no nvim_buf_detach_event is sent. - eval('rpcnotify('..channel..', "Hello There")') + eval('rpcnotify(' .. channel .. ', "Hello There")') expectn('Hello There', {}) -- Reopen the original buffer, assert that buffer events are still active. command('b1') command('normal! x') tick = tick + 1 - expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false}) + expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false }) end) it('detaches if the buffer is unloaded/deleted/wiped', function() @@ -740,29 +785,29 @@ describe('API: buffer events:', function() clear() -- need to make a new window with a buffer because :bunload doesn't let you -- unload the last buffer - for _, cmd in ipairs({'bunload', 'bdelete', 'bwipeout'}) do + for _, cmd in ipairs({ 'bunload', 'bdelete', 'bwipeout' }) do command('new') -- open a brand spanking new file - local b = open(true, {'AAA'}) + local b = open(true, { 'AAA' }) -- call :bunload or whatever the command is, and then check that we -- receive a nvim_buf_detach_event command(cmd) - expectn('nvim_buf_detach_event', {b}) + expectn('nvim_buf_detach_event', { b }) end end) it('does not send the buffer content if not requested', function() clear() local b, tick = editoriginal(false) - ok(buffer('attach', b, false, {})) - expectn('nvim_buf_changedtick_event', {b, tick}) + ok(api.nvim_buf_attach(b, false, {})) + expectn('nvim_buf_changedtick_event', { b, tick }) end) it('returns a proper error on nonempty options dict', function() clear() local b = editoriginal(false) - eq("Invalid 'opts' key: 'builtin'", pcall_err(buffer, 'attach', b, false, {builtin="asfd"})) + eq("Invalid key: 'builtin'", pcall_err(api.nvim_buf_attach, b, false, { builtin = 'asfd' })) end) it('nvim_buf_attach returns response after delay #8634', function() @@ -772,11 +817,13 @@ describe('API: buffer events:', function() eq(true, helpers.request('nvim_buf_attach', 0, false, {})) -- notification eq({ - [1] = 'notification', - [2] = 'nvim_buf_changedtick_event', - [3] = { - [1] = { id = 1 }, - [2] = 2 }, }, next_msg()) + [1] = 'notification', + [2] = 'nvim_buf_changedtick_event', + [3] = { + [1] = 1, + [2] = 2, + }, + }, next_msg()) end) end) @@ -786,7 +833,7 @@ describe('API: buffer events:', function() end) local function lines_subset(first, second) - for i = 1,#first do + for i = 1, #first do -- need to ignore trailing spaces if first[i]:gsub(' +$', '') ~= second[i]:gsub(' +$', '') then return false @@ -802,7 +849,7 @@ describe('API: buffer events:', function() local function assert_match_somewhere(expected_lines, buffer_lines) local msg = next_msg() - while(msg ~= nil) do + while msg ~= nil do local event = msg[2] if event == 'nvim_buf_lines_event' then local args = msg[3] @@ -813,7 +860,7 @@ describe('API: buffer events:', function() -- with the test setup. Note updates are contiguous. assert(#newlines <= 23) - for i = 1,#newlines do + for i = 1, #newlines do buffer_lines[starts + i] = newlines[i] end -- we don't compare the msg area of the embedded nvim, it's too flakey @@ -832,36 +879,35 @@ describe('API: buffer events:', function() it('when :terminal lines change', function() local buffer_lines = {} local expected_lines = {} - command('terminal "'..nvim_prog..'" -u NONE -i NONE -n -c "set shortmess+=A"') - local b = nvim('get_current_buf') - ok(buffer('attach', b, true, {})) + fn.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '-n', '-c', 'set shortmess+=A' }, { + env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, + }) - for _ = 1,22 do - table.insert(expected_lines,'~') + local b = api.nvim_get_current_buf() + ok(api.nvim_buf_attach(b, true, {})) + + for _ = 1, 22 do + table.insert(expected_lines, '~') end expected_lines[1] = '' - expected_lines[22] = ('tmp_terminal_nvim'..(' '):rep(45) - ..'0,0-1 All') + expected_lines[22] = ('tmp_terminal_nvim' .. (' '):rep(45) .. '0,0-1 All') sendkeys('i:e tmp_terminal_nvim<Enter>') assert_match_somewhere(expected_lines, buffer_lines) expected_lines[1] = 'Blarg' - expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41) - ..'1,6 All') + expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '1,6 All') sendkeys('iBlarg') assert_match_somewhere(expected_lines, buffer_lines) - for i = 1,21 do + for i = 1, 21 do expected_lines[i] = 'xyz' end - expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41) - ..'31,4 Bot') + expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '31,4 Bot') local s = string.rep('\nxyz', 30) sendkeys(s) assert_match_somewhere(expected_lines, buffer_lines) end) - end) diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua index 1ddb289ded..f73b9c8b13 100644 --- a/test/functional/api/command_spec.lua +++ b/test/functional/api/command_spec.lua @@ -1,76 +1,177 @@ local helpers = require('test.functional.helpers')(after_each) -local NIL = helpers.NIL +local NIL = vim.NIL local clear = helpers.clear local command = helpers.command -local curbufmeths = helpers.curbufmeths local eq = helpers.eq -local meths = helpers.meths -local bufmeths = helpers.bufmeths +local api = helpers.api local matches = helpers.matches local source = helpers.source local pcall_err = helpers.pcall_err local exec_lua = helpers.exec_lua local assert_alive = helpers.assert_alive local feed = helpers.feed -local funcs = helpers.funcs +local fn = helpers.fn describe('nvim_get_commands', function() - local cmd_dict = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='echo "Hello World"', name='Hello', nargs='1', preview=false, range=NIL, register=false, keepscript=false, script_id=0, } - local cmd_dict2 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='pwd', name='Pwd', nargs='?', preview=false, range=NIL, register=false, keepscript=false, script_id=0, } + local cmd_dict = { + addr = NIL, + bang = false, + bar = false, + complete = NIL, + complete_arg = NIL, + count = NIL, + definition = 'echo "Hello World"', + name = 'Hello', + nargs = '1', + preview = false, + range = NIL, + register = false, + keepscript = false, + script_id = 0, + } + local cmd_dict2 = { + addr = NIL, + bang = false, + bar = false, + complete = NIL, + complete_arg = NIL, + count = NIL, + definition = 'pwd', + name = 'Pwd', + nargs = '?', + preview = false, + range = NIL, + register = false, + keepscript = false, + script_id = 0, + } before_each(clear) it('gets empty list if no commands were defined', function() - eq({}, meths.get_commands({builtin=false})) + eq({}, api.nvim_get_commands({ builtin = false })) end) it('validation', function() - eq('builtin=true not implemented', pcall_err(meths.get_commands, - {builtin=true})) - eq("Invalid key: 'foo'", pcall_err(meths.get_commands, - {foo='blah'})) + eq('builtin=true not implemented', pcall_err(api.nvim_get_commands, { builtin = true })) + eq("Invalid key: 'foo'", pcall_err(api.nvim_get_commands, { foo = 'blah' })) end) it('gets global user-defined commands', function() -- Define a command. command('command -nargs=1 Hello echo "Hello World"') - eq({Hello=cmd_dict}, meths.get_commands({builtin=false})) + eq({ Hello = cmd_dict }, api.nvim_get_commands({ builtin = false })) -- Define another command. - command('command -nargs=? Pwd pwd'); - eq({Hello=cmd_dict, Pwd=cmd_dict2}, meths.get_commands({builtin=false})) + command('command -nargs=? Pwd pwd') + eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, api.nvim_get_commands({ builtin = false })) -- Delete a command. command('delcommand Pwd') - eq({Hello=cmd_dict}, meths.get_commands({builtin=false})) + eq({ Hello = cmd_dict }, api.nvim_get_commands({ builtin = false })) end) it('gets buffer-local user-defined commands', function() -- Define a buffer-local command. command('command -buffer -nargs=1 Hello echo "Hello World"') - eq({Hello=cmd_dict}, curbufmeths.get_commands({builtin=false})) + eq({ Hello = cmd_dict }, api.nvim_buf_get_commands(0, { builtin = false })) -- Define another buffer-local command. command('command -buffer -nargs=? Pwd pwd') - eq({Hello=cmd_dict, Pwd=cmd_dict2}, curbufmeths.get_commands({builtin=false})) + eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, api.nvim_buf_get_commands(0, { builtin = false })) -- Delete a command. command('delcommand Pwd') - eq({Hello=cmd_dict}, curbufmeths.get_commands({builtin=false})) + eq({ Hello = cmd_dict }, api.nvim_buf_get_commands(0, { builtin = false })) -- {builtin=true} always returns empty for buffer-local case. - eq({}, curbufmeths.get_commands({builtin=true})) + eq({}, api.nvim_buf_get_commands(0, { builtin = true })) end) it('gets various command attributes', function() - local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', preview=false, range='10', register=false, keepscript=false, script_id=0, } - local cmd1 = { addr=NIL, bang=false, bar=false, complete='custom', complete_arg='ListUsers', count=NIL, definition='!finger <args>', name='Finger', nargs='+', preview=false, range=NIL, register=false, keepscript=false, script_id=1, } - local cmd2 = { addr=NIL, bang=true, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R2_foo(<q-args>)', name='Cmd2', nargs='*', preview=false, range=NIL, register=false, keepscript=false, script_id=2, } - local cmd3 = { addr=NIL, bang=false, bar=true, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R3_ohyeah()', name='Cmd3', nargs='0', preview=false, range=NIL, register=false, keepscript=false, script_id=3, } - local cmd4 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R4_just_great()', name='Cmd4', nargs='0', preview=false, range=NIL, register=true, keepscript=false, script_id=4, } + local cmd0 = { + addr = 'arguments', + bang = false, + bar = false, + complete = 'dir', + complete_arg = NIL, + count = '10', + definition = 'pwd <args>', + name = 'TestCmd', + nargs = '1', + preview = false, + range = '10', + register = false, + keepscript = false, + script_id = 0, + } + local cmd1 = { + addr = NIL, + bang = false, + bar = false, + complete = 'custom', + complete_arg = 'ListUsers', + count = NIL, + definition = '!finger <args>', + name = 'Finger', + nargs = '+', + preview = false, + range = NIL, + register = false, + keepscript = false, + script_id = 1, + } + local cmd2 = { + addr = NIL, + bang = true, + bar = false, + complete = NIL, + complete_arg = NIL, + count = NIL, + definition = 'call \128\253R2_foo(<q-args>)', + name = 'Cmd2', + nargs = '*', + preview = false, + range = NIL, + register = false, + keepscript = false, + script_id = 2, + } + local cmd3 = { + addr = NIL, + bang = false, + bar = true, + complete = NIL, + complete_arg = NIL, + count = NIL, + definition = 'call \128\253R3_ohyeah()', + name = 'Cmd3', + nargs = '0', + preview = false, + range = NIL, + register = false, + keepscript = false, + script_id = 3, + } + local cmd4 = { + addr = NIL, + bang = false, + bar = false, + complete = NIL, + complete_arg = NIL, + count = NIL, + definition = 'call \128\253R4_just_great()', + name = 'Cmd4', + nargs = '0', + preview = false, + range = NIL, + register = true, + keepscript = false, + script_id = 4, + } source([[ let s:foo = 1 command -complete=custom,ListUsers -nargs=+ Finger !finger <args> ]]) - eq({Finger=cmd1}, meths.get_commands({builtin=false})) + eq({ Finger = cmd1 }, api.nvim_get_commands({ builtin = false })) command('command -nargs=1 -complete=dir -addr=arguments -count=10 TestCmd pwd <args>') - eq({Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false})) + eq({ Finger = cmd1, TestCmd = cmd0 }, api.nvim_get_commands({ builtin = false })) source([[ function! s:foo() abort @@ -88,7 +189,10 @@ describe('nvim_get_commands', function() command -register Cmd4 call <SID>just_great() ]]) -- TODO(justinmk): Order is stable but undefined. Sort before return? - eq({Cmd2=cmd2, Cmd3=cmd3, Cmd4=cmd4, Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false})) + eq( + { Cmd2 = cmd2, Cmd3 = cmd3, Cmd4 = cmd4, Finger = cmd1, TestCmd = cmd0 }, + api.nvim_get_commands({ builtin = false }) + ) end) end) @@ -96,9 +200,9 @@ describe('nvim_create_user_command', function() before_each(clear) it('works with strings', function() - meths.create_user_command('SomeCommand', 'let g:command_fired = <args>', {nargs = 1}) - meths.command('SomeCommand 42') - eq(42, meths.eval('g:command_fired')) + api.nvim_create_user_command('SomeCommand', 'let g:command_fired = <args>', { nargs = 1 }) + command('SomeCommand 42') + eq(42, api.nvim_eval('g:command_fired')) end) it('works with Lua functions', function() @@ -113,227 +217,245 @@ describe('nvim_create_user_command', function() }) ]] - eq({ - name = "CommandWithLuaCallback", - args = [[this\ is a\ test]], - fargs = {"this ", "is", "a test"}, - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + eq( + { + name = 'CommandWithLuaCallback', + args = [[this\ is a\ test]], + fargs = { 'this ', 'is', 'a test' }, + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [=[ + exec_lua [=[ vim.api.nvim_command([[CommandWithLuaCallback this\ is a\ test]]) return result - ]=]) - - eq({ - name = "CommandWithLuaCallback", - args = [[this includes\ a backslash: \\]], - fargs = {"this", "includes a", "backslash:", "\\"}, - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + ]=] + ) + + eq( + { + name = 'CommandWithLuaCallback', + args = [[this includes\ a backslash: \\]], + fargs = { 'this', 'includes a', 'backslash:', '\\' }, + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [=[ + exec_lua [=[ vim.api.nvim_command([[CommandWithLuaCallback this includes\ a backslash: \\]]) return result - ]=]) - - eq({ - name = "CommandWithLuaCallback", - args = "a\\b", - fargs = {"a\\b"}, - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + ]=] + ) + + eq( + { + name = 'CommandWithLuaCallback', + args = 'a\\b', + fargs = { 'a\\b' }, + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [=[ + exec_lua [=[ vim.api.nvim_command('CommandWithLuaCallback a\\b') return result - ]=]) - - eq({ - name = "CommandWithLuaCallback", - args = 'h\tey ', - fargs = {[[h]], [[ey]]}, - bang = true, - line1 = 10, - line2 = 10, - mods = "confirm unsilent botright horizontal", - smods = { - browse = false, - confirm = true, - emsg_silent = false, - hide = false, - horizontal = true, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "botright", - tab = -1, - unsilent = true, - verbose = -1, - vertical = false, + ]=] + ) + + eq( + { + name = 'CommandWithLuaCallback', + args = 'h\tey ', + fargs = { [[h]], [[ey]] }, + bang = true, + line1 = 10, + line2 = 10, + mods = 'confirm unsilent botright horizontal', + smods = { + browse = false, + confirm = true, + emsg_silent = false, + hide = false, + horizontal = true, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = 'botright', + tab = -1, + unsilent = true, + verbose = -1, + vertical = false, + }, + range = 1, + count = 10, + reg = '', }, - range = 1, - count = 10, - reg = "", - }, exec_lua [=[ + exec_lua [=[ vim.api.nvim_command('unsilent horizontal botright confirm 10CommandWithLuaCallback! h\tey ') return result - ]=]) - - eq({ - name = "CommandWithLuaCallback", - args = "h", - fargs = {"h"}, - bang = false, - line1 = 1, - line2 = 42, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + ]=] + ) + + eq( + { + name = 'CommandWithLuaCallback', + args = 'h', + fargs = { 'h' }, + bang = false, + line1 = 1, + line2 = 42, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 1, + count = 42, + reg = '', }, - range = 1, - count = 42, - reg = "", - }, exec_lua [[ + exec_lua [[ vim.api.nvim_command('CommandWithLuaCallback 42 h') return result - ]]) - - eq({ - name = "CommandWithLuaCallback", - args = "", - fargs = {}, -- fargs works without args - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + ]] + ) + + eq( + { + name = 'CommandWithLuaCallback', + args = '', + fargs = {}, -- fargs works without args + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [[ + exec_lua [[ vim.api.nvim_command('CommandWithLuaCallback') return result - ]]) + ]] + ) -- f-args doesn't split when command nargs is 1 or "?" exec_lua [[ @@ -347,80 +469,86 @@ describe('nvim_create_user_command', function() }) ]] - eq({ - name = "CommandWithOneOrNoArg", - args = "hello I'm one argument", - fargs = {"hello I'm one argument"}, -- Doesn't split args - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + eq( + { + name = 'CommandWithOneOrNoArg', + args = "hello I'm one argument", + fargs = { "hello I'm one argument" }, -- Doesn't split args + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [[ + exec_lua [[ vim.api.nvim_command('CommandWithOneOrNoArg hello I\'m one argument') return result - ]]) + ]] + ) -- f-args is an empty table if no args were passed - eq({ - name = "CommandWithOneOrNoArg", - args = "", - fargs = {}, - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + eq( + { + name = 'CommandWithOneOrNoArg', + args = '', + fargs = {}, + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [[ + exec_lua [[ vim.api.nvim_command('CommandWithOneOrNoArg') return result - ]]) + ]] + ) -- f-args is an empty table when the command nargs=0 exec_lua [[ @@ -434,88 +562,93 @@ describe('nvim_create_user_command', function() register = true, }) ]] - eq({ - name = "CommandWithNoArgs", - args = "", - fargs = {}, - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + eq( + { + name = 'CommandWithNoArgs', + args = '', + fargs = {}, + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '', }, - range = 0, - count = 2, - reg = "", - }, exec_lua [[ + exec_lua [[ vim.cmd('CommandWithNoArgs') return result - ]]) + ]] + ) -- register can be specified - eq({ - name = "CommandWithNoArgs", - args = "", - fargs = {}, - bang = false, - line1 = 1, - line2 = 1, - mods = "", - smods = { - browse = false, - confirm = false, - emsg_silent = false, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "", - tab = -1, - unsilent = false, - verbose = -1, - vertical = false, + eq( + { + name = 'CommandWithNoArgs', + args = '', + fargs = {}, + bang = false, + line1 = 1, + line2 = 1, + mods = '', + smods = { + browse = false, + confirm = false, + emsg_silent = false, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = '', + tab = -1, + unsilent = false, + verbose = -1, + vertical = false, + }, + range = 0, + count = 2, + reg = '+', }, - range = 0, - count = 2, - reg = "+", - }, exec_lua [[ + exec_lua [[ vim.cmd('CommandWithNoArgs +') return result - ]]) - + ]] + ) end) it('can define buffer-local commands', function() - local bufnr = meths.create_buf(false, false) - bufmeths.create_user_command(bufnr, "Hello", "", {}) - matches("Not an editor command: Hello", pcall_err(meths.command, "Hello")) - meths.set_current_buf(bufnr) - meths.command("Hello") + local bufnr = api.nvim_create_buf(false, false) + api.nvim_buf_create_user_command(bufnr, 'Hello', '', {}) + matches('Not an editor command: Hello', pcall_err(command, 'Hello')) + api.nvim_set_current_buf(bufnr) + command('Hello') assert_alive() end) @@ -537,58 +670,88 @@ describe('nvim_create_user_command', function() ]] feed(':Test a<Tab>') - eq('Test aaa', funcs.getcmdline()) + eq('Test aaa', fn.getcmdline()) feed('<C-U>Test b<Tab>') - eq('Test bbb', funcs.getcmdline()) + eq('Test bbb', fn.getcmdline()) end) it('does not allow invalid command names', function() - eq("Invalid command name (must start with uppercase): 'test'", pcall_err(exec_lua, [[ + eq( + "Invalid command name (must start with uppercase): 'test'", + pcall_err( + exec_lua, + [[ vim.api.nvim_create_user_command('test', 'echo "hi"', {}) - ]])) - eq("Invalid command name: 't@'", pcall_err(exec_lua, [[ + ]] + ) + ) + eq( + "Invalid command name: 't@'", + pcall_err( + exec_lua, + [[ vim.api.nvim_create_user_command('t@', 'echo "hi"', {}) - ]])) - eq("Invalid command name: 'T@st'", pcall_err(exec_lua, [[ + ]] + ) + ) + eq( + "Invalid command name: 'T@st'", + pcall_err( + exec_lua, + [[ vim.api.nvim_create_user_command('T@st', 'echo "hi"', {}) - ]])) - eq("Invalid command name: 'Test!'", pcall_err(exec_lua, [[ + ]] + ) + ) + eq( + "Invalid command name: 'Test!'", + pcall_err( + exec_lua, + [[ vim.api.nvim_create_user_command('Test!', 'echo "hi"', {}) - ]])) - eq("Invalid command name: '💩'", pcall_err(exec_lua, [[ + ]] + ) + ) + eq( + "Invalid command name: '💩'", + pcall_err( + exec_lua, + [[ vim.api.nvim_create_user_command('💩', 'echo "hi"', {}) - ]])) + ]] + ) + ) end) it('smods can be used with nvim_cmd', function() - exec_lua[[ + exec_lua [[ vim.api.nvim_create_user_command('MyEcho', function(opts) vim.api.nvim_cmd({ cmd = 'echo', args = { '&verbose' }, mods = opts.smods }, {}) end, {}) ]] - eq("3", meths.cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true })) + eq('3', api.nvim_cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true })) - eq(1, #meths.list_tabpages()) - exec_lua[[ + eq(1, #api.nvim_list_tabpages()) + exec_lua [[ vim.api.nvim_create_user_command('MySplit', function(opts) vim.api.nvim_cmd({ cmd = 'split', mods = opts.smods }, {}) end, {}) ]] - meths.cmd({ cmd = 'MySplit' }, {}) - eq(1, #meths.list_tabpages()) - eq(2, #meths.list_wins()) - meths.cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {}) - eq(2, #meths.list_tabpages()) - eq(2, funcs.tabpagenr()) - meths.cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {}) - eq(3, #meths.list_tabpages()) - eq(2, funcs.tabpagenr()) - meths.cmd({ cmd = 'MySplit', mods = { tab = 3 } }, {}) - eq(4, #meths.list_tabpages()) - eq(4, funcs.tabpagenr()) - meths.cmd({ cmd = 'MySplit', mods = { tab = 0 } }, {}) - eq(5, #meths.list_tabpages()) - eq(1, funcs.tabpagenr()) + api.nvim_cmd({ cmd = 'MySplit' }, {}) + eq(1, #api.nvim_list_tabpages()) + eq(2, #api.nvim_list_wins()) + api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {}) + eq(2, #api.nvim_list_tabpages()) + eq(2, fn.tabpagenr()) + api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {}) + eq(3, #api.nvim_list_tabpages()) + eq(2, fn.tabpagenr()) + api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 3 } }, {}) + eq(4, #api.nvim_list_tabpages()) + eq(4, fn.tabpagenr()) + api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 0 } }, {}) + eq(5, #api.nvim_list_tabpages()) + eq(1, fn.tabpagenr()) end) end) @@ -596,16 +759,16 @@ describe('nvim_del_user_command', function() before_each(clear) it('can delete global commands', function() - meths.create_user_command('Hello', 'echo "Hi"', {}) - meths.command('Hello') - meths.del_user_command('Hello') - matches("Not an editor command: Hello", pcall_err(meths.command, "Hello")) + api.nvim_create_user_command('Hello', 'echo "Hi"', {}) + command('Hello') + api.nvim_del_user_command('Hello') + matches('Not an editor command: Hello', pcall_err(command, 'Hello')) end) it('can delete buffer-local commands', function() - bufmeths.create_user_command(0, 'Hello', 'echo "Hi"', {}) - meths.command('Hello') - bufmeths.del_user_command(0, 'Hello') - matches("Not an editor command: Hello", pcall_err(meths.command, "Hello")) + api.nvim_buf_create_user_command(0, 'Hello', 'echo "Hi"', {}) + command('Hello') + api.nvim_buf_del_user_command(0, 'Hello') + matches('Not an editor command: Hello', pcall_err(command, 'Hello')) end) end) diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua index 44a151cf6a..2acfbfc949 100644 --- a/test/functional/api/extmark_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -4,15 +4,13 @@ local Screen = require('test.functional.ui.screen') local request = helpers.request local eq = helpers.eq local ok = helpers.ok -local curbufmeths = helpers.curbufmeths -local bufmeths = helpers.bufmeths local pcall_err = helpers.pcall_err local insert = helpers.insert local feed = helpers.feed local clear = helpers.clear local command = helpers.command local exec = helpers.exec -local meths = helpers.meths +local api = helpers.api local assert_alive = helpers.assert_alive local function expect(contents) @@ -26,32 +24,32 @@ local function set_extmark(ns_id, id, line, col, opts) if id ~= nil and id ~= 0 then opts.id = id end - return curbufmeths.set_extmark(ns_id, line, col, opts) + return api.nvim_buf_set_extmark(0, ns_id, line, col, opts) end local function get_extmarks(ns_id, start, end_, opts) if opts == nil then opts = {} end - return curbufmeths.get_extmarks(ns_id, start, end_, opts) + return api.nvim_buf_get_extmarks(0, ns_id, start, end_, opts) end local function get_extmark_by_id(ns_id, id, opts) if opts == nil then opts = {} end - return curbufmeths.get_extmark_by_id(ns_id, id, opts) + return api.nvim_buf_get_extmark_by_id(0, ns_id, id, opts) end local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end local rv = get_extmark_by_id(ns, mark) - eq({er, ec}, rv) - feed("u") + eq({ er, ec }, rv) + feed('u') rv = get_extmark_by_id(ns, mark) - eq({sr, sc}, rv) - feed("<c-r>") + eq({ sr, sc }, rv) + feed('<c-r>') rv = get_extmark_by_id(ns, mark) - eq({er, ec}, rv) + eq({ er, ec }, rv) end local function batch_set(ns_id, positions) @@ -64,20 +62,20 @@ end local function batch_check(ns_id, ids, positions) local actual, expected = {}, {} - for i,id in ipairs(ids) do + for i, id in ipairs(ids) do expected[id] = positions[i] end for _, mark in pairs(get_extmarks(ns_id, 0, -1, {})) do - actual[mark[1]] = {mark[2], mark[3]} + actual[mark[1]] = { mark[2], mark[3] } end eq(expected, actual) end local function batch_check_undo_redo(ns_id, ids, before, after) batch_check(ns_id, ids, after) - feed("u") + feed('u') batch_check(ns_id, ids, before) - feed("<c-r>") + feed('<c-r>') batch_check(ns_id, ids, after) end @@ -88,49 +86,78 @@ describe('API/extmarks', function() before_each(function() -- Initialize some namespaces and insert 12345 into a buffer - marks = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} - positions = {{0, 0,}, {0, 2}, {0, 3}} + marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 } + positions = { { 0, 0 }, { 0, 2 }, { 0, 3 } } - init_text = "12345" + init_text = '12345' row = 0 col = 2 clear() insert(init_text) - ns = request('nvim_create_namespace', "my-fancy-plugin") - ns2 = request('nvim_create_namespace', "my-fancy-plugin2") + ns = request('nvim_create_namespace', 'my-fancy-plugin') + ns2 = request('nvim_create_namespace', 'my-fancy-plugin2') end) it('validation', function() - eq("Invalid 'end_col': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 })) - eq("Invalid 'end_row': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} })) - eq("Invalid 'virt_text_pos': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 })) - eq("Invalid 'virt_text_pos': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' })) - eq("Invalid 'hl_mode': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 })) + eq( + "Invalid 'end_col': expected Integer, got Array", + pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 }) + ) + eq( + "Invalid 'end_row': expected Integer, got Array", + pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} }) + ) + eq( + "Invalid 'virt_text_pos': expected String, got Integer", + pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 }) + ) + eq( + "Invalid 'virt_text_pos': 'foo'", + pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' }) + ) + eq( + "Invalid 'hl_mode': expected String, got Integer", + pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 }) + ) eq("Invalid 'hl_mode': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 'foo' })) - eq("Invalid 'id': expected Integer, got Array", pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 })) - eq("Invalid mark position: expected 2 Integer items", pcall_err(get_extmarks, ns, {}, {-1, -1})) - eq("Invalid mark position: expected mark id Integer or 2-item Array", pcall_err(get_extmarks, ns, true, {-1, -1})) + eq( + "Invalid 'id': expected Integer, got Array", + pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 }) + ) + eq( + 'Invalid mark position: expected 2 Integer items', + pcall_err(get_extmarks, ns, {}, { -1, -1 }) + ) + eq( + 'Invalid mark position: expected mark id Integer or 2-item Array', + pcall_err(get_extmarks, ns, true, { -1, -1 }) + ) -- No memory leak with virt_text, virt_lines, sign_text - eq("right_gravity is not a boolean", pcall_err(set_extmark, ns, marks[2], 0, 0, { - virt_text = {{'foo', 'Normal'}}, - virt_lines = {{{'bar', 'Normal'}}}, - sign_text = 'a', - right_gravity = 'baz', - })) + eq( + 'right_gravity is not a boolean', + pcall_err(set_extmark, ns, marks[2], 0, 0, { + virt_text = { { 'foo', 'Normal' } }, + virt_lines = { { { 'bar', 'Normal' } } }, + sign_text = 'a', + right_gravity = 'baz', + }) + ) end) - it("can end extranges past final newline using end_col = 0", function() + it('can end extranges past final newline using end_col = 0', function() set_extmark(ns, marks[1], 0, 0, { end_col = 0, - end_row = 1 + end_row = 1, }) - eq("Invalid 'end_col': out of range", - pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 })) + eq( + "Invalid 'end_col': out of range", + pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }) + ) end) - it("can end extranges past final newline when strict mode is false", function() + it('can end extranges past final newline when strict mode is false', function() set_extmark(ns, marks[1], 0, 0, { end_col = 1, end_row = 1, @@ -138,7 +165,7 @@ describe('API/extmarks', function() }) end) - it("can end extranges past final column when strict mode is false", function() + it('can end extranges past final column when strict mode is false', function() set_extmark(ns, marks[1], 0, 0, { end_col = 6, end_row = 0, @@ -150,7 +177,7 @@ describe('API/extmarks', function() local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2]) eq(marks[1], rv) rv = get_extmark_by_id(ns, marks[1]) - eq({positions[1][1], positions[1][2]}, rv) + eq({ positions[1][1], positions[1][2] }, rv) -- Test adding a second mark on same row works rv = set_extmark(ns, marks[2], positions[2][1], positions[2][2]) eq(marks[2], rv) @@ -159,21 +186,21 @@ describe('API/extmarks', function() rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2]) eq(marks[1], rv) rv = get_extmark_by_id(ns, marks[2]) - eq({positions[2][1], positions[2][2]}, rv) + eq({ positions[2][1], positions[2][2] }, rv) -- Test an update, (new pos) row = positions[1][1] col = positions[1][2] + 1 rv = set_extmark(ns, marks[1], row, col) eq(marks[1], rv) rv = get_extmark_by_id(ns, marks[1]) - eq({row, col}, rv) + eq({ row, col }, rv) -- remove the test marks - eq(true, curbufmeths.del_extmark(ns, marks[1])) - eq(false, curbufmeths.del_extmark(ns, marks[1])) - eq(true, curbufmeths.del_extmark(ns, marks[2])) - eq(false, curbufmeths.del_extmark(ns, marks[3])) - eq(false, curbufmeths.del_extmark(ns, 1000)) + eq(true, api.nvim_buf_del_extmark(0, ns, marks[1])) + eq(false, api.nvim_buf_del_extmark(0, ns, marks[1])) + eq(true, api.nvim_buf_del_extmark(0, ns, marks[2])) + eq(false, api.nvim_buf_del_extmark(0, ns, marks[3])) + eq(false, api.nvim_buf_del_extmark(0, ns, 1000)) end) it('can clear a specific namespace range', function() @@ -181,15 +208,15 @@ describe('API/extmarks', function() set_extmark(ns2, 1, 0, 1) -- force a new undo buffer feed('o<esc>') - curbufmeths.clear_namespace(ns2, 0, -1) - eq({{1, 0, 1}}, get_extmarks(ns, {0, 0}, {-1, -1})) - eq({}, get_extmarks(ns2, {0, 0}, {-1, -1})) + api.nvim_buf_clear_namespace(0, ns2, 0, -1) + eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 })) feed('u') - eq({{1, 0, 1}}, get_extmarks(ns, {0, 0}, {-1, -1})) - eq({}, get_extmarks(ns2, {0, 0}, {-1, -1})) + eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 })) feed('<c-r>') - eq({{1, 0, 1}}, get_extmarks(ns, {0, 0}, {-1, -1})) - eq({}, get_extmarks(ns2, {0, 0}, {-1, -1})) + eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 })) end) it('can clear a namespace range using 0,-1', function() @@ -197,32 +224,32 @@ describe('API/extmarks', function() set_extmark(ns2, 1, 0, 1) -- force a new undo buffer feed('o<esc>') - curbufmeths.clear_namespace(-1, 0, -1) - eq({}, get_extmarks(ns, {0, 0}, {-1, -1})) - eq({}, get_extmarks(ns2, {0, 0}, {-1, -1})) + api.nvim_buf_clear_namespace(0, -1, 0, -1) + eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 })) feed('u') - eq({}, get_extmarks(ns, {0, 0}, {-1, -1})) - eq({}, get_extmarks(ns2, {0, 0}, {-1, -1})) + eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 })) feed('<c-r>') - eq({}, get_extmarks(ns, {0, 0}, {-1, -1})) - eq({}, get_extmarks(ns2, {0, 0}, {-1, -1})) + eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 })) end) it('can undo with extmarks (#25147)', function() feed('itest<esc>') set_extmark(ns, 1, 0, 0) set_extmark(ns, 2, 1, 0) - eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1})) + eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) feed('dd') - eq({ { 1, 1, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1})) - curbufmeths.clear_namespace(ns, 0, -1) - eq({}, get_extmarks(ns, {0, 0}, {-1, -1})) + eq({ { 1, 1, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + api.nvim_buf_clear_namespace(0, ns, 0, -1) + eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 })) set_extmark(ns, 1, 0, 0, { right_gravity = false }) set_extmark(ns, 2, 1, 0, { right_gravity = false }) - eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1})) + eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) feed('u') - eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1})) - curbufmeths.clear_namespace(ns, 0, -1) + eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 })) + api.nvim_buf_clear_namespace(0, ns, 0, -1) end) it('querying for information and ranges', function() @@ -237,112 +264,114 @@ describe('API/extmarks', function() end -- {0, 0} and {-1, -1} work as extreme values - eq({{1, 0, 0}}, get_extmarks(ns, {0, 0}, {0, 0})) - eq({}, get_extmarks(ns, {-1, -1}, {-1, -1})) - local rv = get_extmarks(ns, {0, 0}, {-1, -1}) + eq({ { 1, 0, 0 } }, get_extmarks(ns, { 0, 0 }, { 0, 0 })) + eq({}, get_extmarks(ns, { -1, -1 }, { -1, -1 })) + local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) for i, m in ipairs(marks) do if positions[i] ~= nil then - eq({m, positions[i][1], positions[i][2]}, rv[i]) + eq({ m, positions[i][1], positions[i][2] }, rv[i]) end end -- 0 and -1 works as short hand extreme values - eq({{1, 0, 0}}, get_extmarks(ns, 0, 0)) + eq({ { 1, 0, 0 } }, get_extmarks(ns, 0, 0)) eq({}, get_extmarks(ns, -1, -1)) rv = get_extmarks(ns, 0, -1) for i, m in ipairs(marks) do if positions[i] ~= nil then - eq({m, positions[i][1], positions[i][2]}, rv[i]) + eq({ m, positions[i][1], positions[i][2] }, rv[i]) end end -- next with mark id - rv = get_extmarks(ns, marks[1], {-1, -1}, {limit=1}) - eq({{marks[1], positions[1][1], positions[1][2]}}, rv) - rv = get_extmarks(ns, marks[2], {-1, -1}, {limit=1}) - eq({{marks[2], positions[2][1], positions[2][2]}}, rv) + rv = get_extmarks(ns, marks[1], { -1, -1 }, { limit = 1 }) + eq({ { marks[1], positions[1][1], positions[1][2] } }, rv) + rv = get_extmarks(ns, marks[2], { -1, -1 }, { limit = 1 }) + eq({ { marks[2], positions[2][1], positions[2][2] } }, rv) -- next with positional when mark exists at position - rv = get_extmarks(ns, positions[1], {-1, -1}, {limit=1}) - eq({{marks[1], positions[1][1], positions[1][2]}}, rv) + rv = get_extmarks(ns, positions[1], { -1, -1 }, { limit = 1 }) + eq({ { marks[1], positions[1][1], positions[1][2] } }, rv) -- next with positional index (no mark at position) - rv = get_extmarks(ns, {positions[1][1], positions[1][2] +1}, {-1, -1}, {limit=1}) - eq({{marks[2], positions[2][1], positions[2][2]}}, rv) + rv = get_extmarks(ns, { positions[1][1], positions[1][2] + 1 }, { -1, -1 }, { limit = 1 }) + eq({ { marks[2], positions[2][1], positions[2][2] } }, rv) -- next with Extremity index - rv = get_extmarks(ns, {0,0}, {-1, -1}, {limit=1}) - eq({{marks[1], positions[1][1], positions[1][2]}}, rv) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 }) + eq({ { marks[1], positions[1][1], positions[1][2] } }, rv) -- nextrange with mark id rv = get_extmarks(ns, marks[1], marks[3]) - eq({marks[1], positions[1][1], positions[1][2]}, rv[1]) - eq({marks[2], positions[2][1], positions[2][2]}, rv[2]) + eq({ marks[1], positions[1][1], positions[1][2] }, rv[1]) + eq({ marks[2], positions[2][1], positions[2][2] }, rv[2]) -- nextrange with `limit` - rv = get_extmarks(ns, marks[1], marks[3], {limit=2}) + rv = get_extmarks(ns, marks[1], marks[3], { limit = 2 }) eq(2, #rv) -- nextrange with positional when mark exists at position rv = get_extmarks(ns, positions[1], positions[3]) - eq({marks[1], positions[1][1], positions[1][2]}, rv[1]) - eq({marks[2], positions[2][1], positions[2][2]}, rv[2]) + eq({ marks[1], positions[1][1], positions[1][2] }, rv[1]) + eq({ marks[2], positions[2][1], positions[2][2] }, rv[2]) rv = get_extmarks(ns, positions[2], positions[3]) eq(2, #rv) -- nextrange with positional index (no mark at position) - local lower = {positions[1][1], positions[2][2] -1} - local upper = {positions[2][1], positions[3][2] - 1} + local lower = { positions[1][1], positions[2][2] - 1 } + local upper = { positions[2][1], positions[3][2] - 1 } rv = get_extmarks(ns, lower, upper) - eq({{marks[2], positions[2][1], positions[2][2]}}, rv) - lower = {positions[3][1], positions[3][2] + 1} - upper = {positions[3][1], positions[3][2] + 2} + eq({ { marks[2], positions[2][1], positions[2][2] } }, rv) + lower = { positions[3][1], positions[3][2] + 1 } + upper = { positions[3][1], positions[3][2] + 2 } rv = get_extmarks(ns, lower, upper) eq({}, rv) -- nextrange with extremity index - lower = {positions[2][1], positions[2][2]+1} - upper = {-1, -1} + lower = { positions[2][1], positions[2][2] + 1 } + upper = { -1, -1 } rv = get_extmarks(ns, lower, upper) - eq({{marks[3], positions[3][1], positions[3][2]}}, rv) + eq({ { marks[3], positions[3][1], positions[3][2] } }, rv) -- prev with mark id - rv = get_extmarks(ns, marks[3], {0, 0}, {limit=1}) - eq({{marks[3], positions[3][1], positions[3][2]}}, rv) - rv = get_extmarks(ns, marks[2], {0, 0}, {limit=1}) - eq({{marks[2], positions[2][1], positions[2][2]}}, rv) + rv = get_extmarks(ns, marks[3], { 0, 0 }, { limit = 1 }) + eq({ { marks[3], positions[3][1], positions[3][2] } }, rv) + rv = get_extmarks(ns, marks[2], { 0, 0 }, { limit = 1 }) + eq({ { marks[2], positions[2][1], positions[2][2] } }, rv) -- prev with positional when mark exists at position - rv = get_extmarks(ns, positions[3], {0, 0}, {limit=1}) - eq({{marks[3], positions[3][1], positions[3][2]}}, rv) + rv = get_extmarks(ns, positions[3], { 0, 0 }, { limit = 1 }) + eq({ { marks[3], positions[3][1], positions[3][2] } }, rv) -- prev with positional index (no mark at position) - rv = get_extmarks(ns, {positions[1][1], positions[1][2] +1}, {0, 0}, {limit=1}) - eq({{marks[1], positions[1][1], positions[1][2]}}, rv) + rv = get_extmarks(ns, { positions[1][1], positions[1][2] + 1 }, { 0, 0 }, { limit = 1 }) + eq({ { marks[1], positions[1][1], positions[1][2] } }, rv) -- prev with Extremity index - rv = get_extmarks(ns, {-1,-1}, {0,0}, {limit=1}) - eq({{marks[3], positions[3][1], positions[3][2]}}, rv) + rv = get_extmarks(ns, { -1, -1 }, { 0, 0 }, { limit = 1 }) + eq({ { marks[3], positions[3][1], positions[3][2] } }, rv) -- prevrange with mark id rv = get_extmarks(ns, marks[3], marks[1]) - eq({marks[3], positions[3][1], positions[3][2]}, rv[1]) - eq({marks[2], positions[2][1], positions[2][2]}, rv[2]) - eq({marks[1], positions[1][1], positions[1][2]}, rv[3]) + eq({ marks[3], positions[3][1], positions[3][2] }, rv[1]) + eq({ marks[2], positions[2][1], positions[2][2] }, rv[2]) + eq({ marks[1], positions[1][1], positions[1][2] }, rv[3]) -- prevrange with limit - rv = get_extmarks(ns, marks[3], marks[1], {limit=2}) + rv = get_extmarks(ns, marks[3], marks[1], { limit = 2 }) eq(2, #rv) -- prevrange with positional when mark exists at position rv = get_extmarks(ns, positions[3], positions[1]) - eq({{marks[3], positions[3][1], positions[3][2]}, - {marks[2], positions[2][1], positions[2][2]}, - {marks[1], positions[1][1], positions[1][2]}}, rv) + eq({ + { marks[3], positions[3][1], positions[3][2] }, + { marks[2], positions[2][1], positions[2][2] }, + { marks[1], positions[1][1], positions[1][2] }, + }, rv) rv = get_extmarks(ns, positions[2], positions[1]) eq(2, #rv) -- prevrange with positional index (no mark at position) - lower = {positions[2][1], positions[2][2] + 1} - upper = {positions[3][1], positions[3][2] + 1} + lower = { positions[2][1], positions[2][2] + 1 } + upper = { positions[3][1], positions[3][2] + 1 } rv = get_extmarks(ns, upper, lower) - eq({{marks[3], positions[3][1], positions[3][2]}}, rv) - lower = {positions[3][1], positions[3][2] + 1} - upper = {positions[3][1], positions[3][2] + 2} + eq({ { marks[3], positions[3][1], positions[3][2] } }, rv) + lower = { positions[3][1], positions[3][2] + 1 } + upper = { positions[3][1], positions[3][2] + 2 } rv = get_extmarks(ns, upper, lower) eq({}, rv) -- prevrange with extremity index - lower = {0,0} - upper = {positions[2][1], positions[2][2] - 1} + lower = { 0, 0 } + upper = { positions[2][1], positions[2][2] - 1 } rv = get_extmarks(ns, upper, lower) - eq({{marks[1], positions[1][1], positions[1][2]}}, rv) + eq({ { marks[1], positions[1][1], positions[1][2] } }, rv) end) it('querying for information with limit', function() @@ -354,34 +383,34 @@ describe('API/extmarks', function() end end - local rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=1}) + local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 }) eq(1, #rv) - rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=2}) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 2 }) eq(2, #rv) - rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=3}) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 3 }) eq(3, #rv) -- now in reverse - rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=1}) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 }) eq(1, #rv) - rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=2}) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 2 }) eq(2, #rv) - rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=3}) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 3 }) eq(3, #rv) end) it('get_marks works when mark col > upper col', function() feed('A<cr>12345<esc>') feed('A<cr>12345<esc>') - set_extmark(ns, 10, 0, 2) -- this shouldn't be found - set_extmark(ns, 11, 2, 1) -- this shouldn't be found + set_extmark(ns, 10, 0, 2) -- this shouldn't be found + set_extmark(ns, 11, 2, 1) -- this shouldn't be found set_extmark(ns, marks[1], 0, 4) -- check col > our upper bound set_extmark(ns, marks[2], 1, 1) -- check col < lower bound set_extmark(ns, marks[3], 2, 0) -- check is inclusive - eq({{marks[1], 0, 4}, - {marks[2], 1, 1}, - {marks[3], 2, 0}}, - get_extmarks(ns, {0, 3}, {2, 0})) + eq( + { { marks[1], 0, 4 }, { marks[2], 1, 1 }, { marks[3], 2, 0 } }, + get_extmarks(ns, { 0, 3 }, { 2, 0 }) + ) end) it('get_marks works in reverse when mark col < lower col', function() @@ -392,28 +421,24 @@ describe('API/extmarks', function() set_extmark(ns, marks[1], 2, 1) -- check col < our lower bound set_extmark(ns, marks[2], 1, 4) -- check col > upper bound set_extmark(ns, marks[3], 0, 2) -- check is inclusive - local rv = get_extmarks(ns, {2, 3}, {0, 2}) - eq({{marks[1], 2, 1}, - {marks[2], 1, 4}, - {marks[3], 0, 2}}, - rv) + local rv = get_extmarks(ns, { 2, 3 }, { 0, 2 }) + eq({ { marks[1], 2, 1 }, { marks[2], 1, 4 }, { marks[3], 0, 2 } }, rv) end) it('get_marks limit=0 returns nothing', function() set_extmark(ns, marks[1], positions[1][1], positions[1][2]) - local rv = get_extmarks(ns, {-1, -1}, {-1, -1}, {limit=0}) + local rv = get_extmarks(ns, { -1, -1 }, { -1, -1 }, { limit = 0 }) eq({}, rv) end) - it('marks move with line insertations', function() set_extmark(ns, marks[1], 0, 0) - feed("yyP") + feed('yyP') check_undo_redo(ns, marks[1], 0, 0, 1, 0) end) it('marks move with multiline insertations', function() - feed("a<cr>22<cr>33<esc>") + feed('a<cr>22<cr>33<esc>') set_extmark(ns, marks[1], 1, 1) feed('ggVGyP') check_undo_redo(ns, marks[1], 1, 1, 4, 1) @@ -421,7 +446,7 @@ describe('API/extmarks', function() it('marks move with line join', function() -- do_join in ops.c - feed("a<cr>222<esc>") + feed('a<cr>222<esc>') set_extmark(ns, marks[1], 1, 0) feed('ggJ') check_undo_redo(ns, marks[1], 1, 0, 0, 6) @@ -430,40 +455,33 @@ describe('API/extmarks', function() it('join works when no marks are present', function() screen = Screen.new(15, 10) screen:attach() - feed("a<cr>1<esc>") + feed('a<cr>1<esc>') feed('kJ') -- This shouldn't seg fault screen:expect([[ 12345^ 1 | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | + ~ |*8 | ]]) end) it('marks move with multiline join', function() -- do_join in ops.c - feed("a<cr>222<cr>333<cr>444<esc>") + feed('a<cr>222<cr>333<cr>444<esc>') set_extmark(ns, marks[1], 3, 0) feed('2GVGJ') check_undo_redo(ns, marks[1], 3, 0, 1, 8) end) it('marks move with line deletes', function() - feed("a<cr>222<cr>333<cr>444<esc>") + feed('a<cr>222<cr>333<cr>444<esc>') set_extmark(ns, marks[1], 2, 1) feed('ggjdd') check_undo_redo(ns, marks[1], 2, 1, 1, 1) end) it('marks move with multiline deletes', function() - feed("a<cr>222<cr>333<cr>444<esc>") + feed('a<cr>222<cr>333<cr>444<esc>') set_extmark(ns, marks[1], 3, 0) feed('gg2dd') check_undo_redo(ns, marks[1], 3, 0, 1, 0) @@ -475,7 +493,7 @@ describe('API/extmarks', function() it('marks move with open line', function() -- open_line in change.c -- testing marks below are also moved - feed("yyP") + feed('yyP') set_extmark(ns, marks[1], 0, 4) set_extmark(ns, marks[2], 1, 4) feed('1G<s-o><esc>') @@ -495,18 +513,11 @@ describe('API/extmarks', function() insert('abc') screen:expect([[ ab^c12345 | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | - ~ | + ~ |*8 | ]]) local rv = get_extmark_by_id(ns, marks[1]) - eq({0, 6}, rv) + eq({ 0, 6 }, rv) check_undo_redo(ns, marks[1], 0, 3, 0, 6) end) @@ -515,12 +526,12 @@ describe('API/extmarks', function() -- insertchar in edit.c (the ins_str branch) set_extmark(ns, marks[1], 0, 2) feed('03l') - insert("X") + insert('X') check_undo_redo(ns, marks[1], 0, 2, 0, 2) -- check multibyte chars feed('03l<esc>') - insert("~~") + insert('~~') check_undo_redo(ns, marks[1], 0, 2, 0, 2) end) @@ -544,7 +555,7 @@ describe('API/extmarks', function() it('marks move with line splits (using enter)', function() -- open_line in change.c -- testing marks below are also moved - feed("yyP") + feed('yyP') set_extmark(ns, marks[1], 0, 4) set_extmark(ns, marks[2], 1, 4) feed('1Gla<cr><esc>') @@ -561,16 +572,16 @@ describe('API/extmarks', function() it('yet again marks move with line splits', function() -- the first test above wasn't catching all errors.. - feed("A67890<esc>") + feed('A67890<esc>') set_extmark(ns, marks[1], 0, 4) - feed("04li<cr><esc>") + feed('04li<cr><esc>') check_undo_redo(ns, marks[1], 0, 4, 1, 0) end) it('and one last time line splits...', function() set_extmark(ns, marks[1], 0, 1) set_extmark(ns, marks[2], 0, 2) - feed("02li<cr><esc>") + feed('02li<cr><esc>') check_undo_redo(ns, marks[1], 0, 1, 0, 1) check_undo_redo(ns, marks[2], 0, 2, 1, 0) end) @@ -578,7 +589,7 @@ describe('API/extmarks', function() it('multiple marks move with mark splits', function() set_extmark(ns, marks[1], 0, 1) set_extmark(ns, marks[2], 0, 3) - feed("0li<cr><esc>") + feed('0li<cr><esc>') check_undo_redo(ns, marks[1], 0, 1, 1, 0) check_undo_redo(ns, marks[2], 0, 3, 1, 2) end) @@ -670,11 +681,11 @@ describe('API/extmarks', function() feed('0vx<esc>') check_undo_redo(ns, marks[1], 0, 3, 0, 2) - feed("u") + feed('u') feed('0vlx<esc>') check_undo_redo(ns, marks[1], 0, 3, 0, 1) - feed("u") + feed('u') feed('0v2lx<esc>') check_undo_redo(ns, marks[1], 0, 3, 0, 0) @@ -689,16 +700,16 @@ describe('API/extmarks', function() feed('0x<esc>') check_undo_redo(ns, marks[1], 0, 3, 0, 2) - feed("u") + feed('u') feed('02x<esc>') check_undo_redo(ns, marks[1], 0, 3, 0, 1) - feed("u") + feed('u') feed('0v3lx<esc>') check_undo_redo(ns, marks[1], 0, 3, 0, 0) -- from the other side (nothing should happen) - feed("u") + feed('u') feed('$vx') check_undo_redo(ns, marks[1], 0, 3, 0, 3) end) @@ -756,27 +767,44 @@ describe('API/extmarks', function() it('delete', function() local pos1 = { - {2, 4}, {2, 12}, {2, 13}, {2, 14}, {2, 25}, - {4, 8}, {4, 10}, {4, 20}, - {5, 3}, {6, 10} + { 2, 4 }, + { 2, 12 }, + { 2, 13 }, + { 2, 14 }, + { 2, 25 }, + { 4, 8 }, + { 4, 10 }, + { 4, 20 }, + { 5, 3 }, + { 6, 10 }, } local ids = batch_set(ns, pos1) batch_check(ns, ids, pos1) feed('3Gfiv2+ftd') batch_check_undo_redo(ns, ids, pos1, { - {2, 4}, {2, 12}, {2, 13}, {2, 13}, {2, 13}, - {2, 13}, {2, 15}, {2, 25}, - {3, 3}, {4, 10} + { 2, 4 }, + { 2, 12 }, + { 2, 13 }, + { 2, 13 }, + { 2, 13 }, + { 2, 13 }, + { 2, 15 }, + { 2, 25 }, + { 3, 3 }, + { 4, 10 }, }) end) it('can get overlapping extmarks', function() - set_extmark(ns, 1, 0, 0, {end_row = 5, end_col=0}) - set_extmark(ns, 2, 2, 5, {end_row = 2, end_col=30}) - set_extmark(ns, 3, 0, 5, {end_row = 2, end_col=10}) - set_extmark(ns, 4, 0, 0, {end_row = 1, end_col=0}) - eq({{ 2, 2, 5 }}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=false })) - eq({{ 1, 0, 0 }, { 3, 0, 5}, {2, 2, 5}}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=true })) + set_extmark(ns, 1, 0, 0, { end_row = 5, end_col = 0 }) + set_extmark(ns, 2, 2, 5, { end_row = 2, end_col = 30 }) + set_extmark(ns, 3, 0, 5, { end_row = 2, end_col = 10 }) + set_extmark(ns, 4, 0, 0, { end_row = 1, end_col = 0 }) + eq({ { 2, 2, 5 } }, get_extmarks(ns, { 2, 0 }, { 2, -1 }, { overlap = false })) + eq( + { { 1, 0, 0 }, { 3, 0, 5 }, { 2, 2, 5 } }, + get_extmarks(ns, { 2, 0 }, { 2, -1 }, { overlap = true }) + ) end) end) @@ -876,33 +904,40 @@ describe('API/extmarks', function() set_extmark(ns, marks[2], 0, -1) set_extmark(ns, marks[3], 0, -1) - feed("u") - local rv = get_extmarks(ns, {0, 0}, {-1, -1}) + feed('u') + local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) eq(3, #rv) - feed("<c-r>") - rv = get_extmarks(ns, {0, 0}, {-1, -1}) + feed('<c-r>') + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) eq(3, #rv) -- Test updates feed('o<esc>') set_extmark(ns, marks[1], positions[1][1], positions[1][2]) - rv = get_extmarks(ns, marks[1], marks[1], {limit=1}) + rv = get_extmarks(ns, marks[1], marks[1], { limit = 1 }) eq(1, #rv) - feed("u") - feed("<c-r>") + feed('u') + feed('<c-r>') -- old value is NOT kept in history - check_undo_redo(ns, marks[1], positions[1][1], positions[1][2], positions[1][1], positions[1][2]) + check_undo_redo( + ns, + marks[1], + positions[1][1], + positions[1][2], + positions[1][1], + positions[1][2] + ) -- Test unset feed('o<esc>') - curbufmeths.del_extmark(ns, marks[3]) - feed("u") - rv = get_extmarks(ns, {0, 0}, {-1, -1}) + api.nvim_buf_del_extmark(0, ns, marks[3]) + feed('u') + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) -- undo does NOT restore deleted marks eq(2, #rv) - feed("<c-r>") - rv = get_extmarks(ns, {0, 0}, {-1, -1}) + feed('<c-r>') + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) eq(2, #rv) end) @@ -919,9 +954,9 @@ describe('API/extmarks', function() eq(1, rv) rv = set_extmark(ns2, marks[1], positions[1][1], positions[1][2]) eq(1, rv) - rv = get_extmarks(ns, {0, 0}, {-1, -1}) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) eq(1, #rv) - rv = get_extmarks(ns2, {0, 0}, {-1, -1}) + rv = get_extmarks(ns2, { 0, 0 }, { -1, -1 }) eq(1, #rv) -- Set more marks for testing the ranges @@ -931,14 +966,14 @@ describe('API/extmarks', function() set_extmark(ns2, marks[3], positions[3][1], positions[3][2]) -- get_next (limit set) - rv = get_extmarks(ns, {0, 0}, positions[2], {limit=1}) + rv = get_extmarks(ns, { 0, 0 }, positions[2], { limit = 1 }) eq(1, #rv) - rv = get_extmarks(ns2, {0, 0}, positions[2], {limit=1}) + rv = get_extmarks(ns2, { 0, 0 }, positions[2], { limit = 1 }) eq(1, #rv) -- get_prev (limit set) - rv = get_extmarks(ns, positions[1], {0, 0}, {limit=1}) + rv = get_extmarks(ns, positions[1], { 0, 0 }, { limit = 1 }) eq(1, #rv) - rv = get_extmarks(ns2, positions[1], {0, 0}, {limit=1}) + rv = get_extmarks(ns2, positions[1], { 0, 0 }, { limit = 1 }) eq(1, #rv) -- get_next (no limit) @@ -952,11 +987,11 @@ describe('API/extmarks', function() rv = get_extmarks(ns2, positions[2], positions[1]) eq(2, #rv) - curbufmeths.del_extmark(ns, marks[1]) - rv = get_extmarks(ns, {0, 0}, {-1, -1}) + api.nvim_buf_del_extmark(0, ns, marks[1]) + rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }) eq(2, #rv) - curbufmeths.del_extmark(ns2, marks[1]) - rv = get_extmarks(ns2, {0, 0}, {-1, -1}) + api.nvim_buf_del_extmark(0, ns2, marks[1]) + rv = get_extmarks(ns2, { 0, 0 }, { -1, -1 }) eq(2, #rv) end) @@ -980,16 +1015,16 @@ describe('API/extmarks', function() feed(':set cindent<cr><esc>') feed(':set autoindent<cr><esc>') feed(':set shiftwidth=2<cr><esc>') - feed("0iint <esc>A {1M1<esc>b<esc>") + feed('0iint <esc>A {1M1<esc>b<esc>') -- Set the mark on the M, should move.. set_extmark(ns, marks[1], 0, 12) -- Set the mark before the cursor, should stay there set_extmark(ns, marks[2], 0, 10) - feed("i<cr><esc>") + feed('i<cr><esc>') local rv = get_extmark_by_id(ns, marks[1]) - eq({1, 3}, rv) + eq({ 1, 3 }, rv) rv = get_extmark_by_id(ns, marks[2]) - eq({0, 10}, rv) + eq({ 0, 10 }, rv) check_undo_redo(ns, marks[1], 0, 12, 1, 3) end) @@ -998,39 +1033,39 @@ describe('API/extmarks', function() feed(':set autoindent<cr><esc>') feed(':set shiftwidth=2<cr><esc>') -- <c-f> will force an indent of 2 - feed("0iint <esc>A {<cr><esc>0i1M1<esc>") + feed('0iint <esc>A {<cr><esc>0i1M1<esc>') set_extmark(ns, marks[1], 1, 1) - feed("0i<c-f><esc>") + feed('0i<c-f><esc>') local rv = get_extmark_by_id(ns, marks[1]) - eq({1, 3}, rv) + eq({ 1, 3 }, rv) check_undo_redo(ns, marks[1], 1, 1, 1, 3) -- now check when cursor at eol - feed("uA<c-f><esc>") + feed('uA<c-f><esc>') rv = get_extmark_by_id(ns, marks[1]) - eq({1, 3}, rv) + eq({ 1, 3 }, rv) end) it('removing auto indenting with <C-D> works', function() feed(':set cindent<cr><esc>') feed(':set autoindent<cr><esc>') feed(':set shiftwidth=2<cr><esc>') - feed("0i<tab><esc>") + feed('0i<tab><esc>') set_extmark(ns, marks[1], 0, 3) - feed("bi<c-d><esc>") + feed('bi<c-d><esc>') local rv = get_extmark_by_id(ns, marks[1]) - eq({0, 1}, rv) + eq({ 0, 1 }, rv) check_undo_redo(ns, marks[1], 0, 3, 0, 1) -- check when cursor at eol - feed("uA<c-d><esc>") + feed('uA<c-d><esc>') rv = get_extmark_by_id(ns, marks[1]) - eq({0, 1}, rv) + eq({ 0, 1 }, rv) end) it('indenting multiple lines with = works', function() feed(':set cindent<cr><esc>') feed(':set autoindent<cr><esc>') feed(':set shiftwidth=2<cr><esc>') - feed("0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>") + feed('0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>') set_extmark(ns, marks[1], 1, 1) set_extmark(ns, marks[2], 2, 1) feed('=gg') @@ -1152,7 +1187,7 @@ describe('API/extmarks', function() check_undo_redo(ns, marks[5], 2, 0, 3, 0) feed('u') feed([[:1,2s:3:\rxx<cr>]]) - eq({1, 3}, get_extmark_by_id(ns, marks[3])) + eq({ 1, 3 }, get_extmark_by_id(ns, marks[3])) end) it('substitutes over multiple lines with replace in substitution', function() @@ -1388,8 +1423,11 @@ describe('API/extmarks', function() it('throws consistent error codes', function() local ns_invalid = ns2 + 1 - eq("Invalid 'ns_id': 3", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2])) - eq("Invalid 'ns_id': 3", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1])) + eq( + "Invalid 'ns_id': 3", + pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]) + ) + eq("Invalid 'ns_id': 3", pcall_err(api.nvim_buf_del_extmark, 0, ns_invalid, marks[1])) eq("Invalid 'ns_id': 3", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2])) eq("Invalid 'ns_id': 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1])) end) @@ -1397,11 +1435,11 @@ describe('API/extmarks', function() it('when col = line-length, set the mark on eol', function() set_extmark(ns, marks[1], 0, -1) local rv = get_extmark_by_id(ns, marks[1]) - eq({0, init_text:len()}, rv) + eq({ 0, init_text:len() }, rv) -- Test another set_extmark(ns, marks[1], 0, -1) rv = get_extmark_by_id(ns, marks[1]) - eq({0, init_text:len()}, rv) + eq({ 0, init_text:len() }, rv) end) it('when col = line-length, set the mark on eol', function() @@ -1412,7 +1450,10 @@ describe('API/extmarks', function() it('fails when line > line_count', function() local invalid_col = init_text:len() + 1 local invalid_lnum = 3 - eq("Invalid 'line': out of range", pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col)) + eq( + "Invalid 'line': out of range", + pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col) + ) eq({}, get_extmark_by_id(ns, marks[1])) end) @@ -1428,17 +1469,17 @@ describe('API/extmarks', function() end) it('in read-only buffer', function() - command("view! runtime/doc/help.txt") - eq(true, meths.get_option_value('ro', {})) + command('view! runtime/doc/help.txt') + eq(true, api.nvim_get_option_value('ro', {})) local id = set_extmark(ns, 0, 0, 2) - eq({{id, 0, 2}}, get_extmarks(ns,0, -1)) + eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1)) end) it('can set a mark to other buffer', function() local buf = request('nvim_create_buf', 0, 1) - request('nvim_buf_set_lines', buf, 0, -1, 1, {"", ""}) - local id = bufmeths.set_extmark(buf, ns, 1, 0, {}) - eq({{id, 1, 0}}, bufmeths.get_extmarks(buf, ns, 0, -1, {})) + request('nvim_buf_set_lines', buf, 0, -1, 1, { '', '' }) + local id = api.nvim_buf_set_extmark(buf, ns, 1, 0, {}) + eq({ { id, 1, 0 } }, api.nvim_buf_get_extmarks(buf, ns, 0, -1, {})) end) it('does not crash with append/delete/undo sequence', function() @@ -1454,210 +1495,274 @@ describe('API/extmarks', function() it('works with left and right gravity', function() -- right gravity should move with inserted text, while -- left gravity should stay in place. - curbufmeths.set_extmark(ns, 0, 5, {right_gravity = false}) - curbufmeths.set_extmark(ns, 0, 5, {right_gravity = true}) + api.nvim_buf_set_extmark(0, ns, 0, 5, { right_gravity = false }) + api.nvim_buf_set_extmark(0, ns, 0, 5, { right_gravity = true }) feed([[Aasdfasdf]]) - eq({ {1, 0, 5}, {2, 0, 13} }, - curbufmeths.get_extmarks(ns, 0, -1, {})) + eq({ { 1, 0, 5 }, { 2, 0, 13 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {})) -- but both move when text is inserted before feed([[<esc>Iasdf<esc>]]) - -- eq({}, curbufmeths.get_lines(0, -1, true)) - eq({ {1, 0, 9}, {2, 0, 17} }, - curbufmeths.get_extmarks(ns, 0, -1, {})) + -- eq({}, api.nvim_buf_get_lines(0, 0, -1, true)) + eq({ { 1, 0, 9 }, { 2, 0, 17 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {})) -- clear text - curbufmeths.set_text(0, 0, 0, 17, {}) + api.nvim_buf_set_text(0, 0, 0, 0, 17, {}) -- handles set_text correctly as well - eq({ {1, 0, 0}, {2, 0, 0} }, - meths.buf_get_extmarks(0, ns, 0, -1, {})) - curbufmeths.set_text(0, 0, 0, 0, {'asdfasdf'}) - eq({ {1, 0, 0}, {2, 0, 8} }, - curbufmeths.get_extmarks(ns, 0, -1, {})) + eq({ { 1, 0, 0 }, { 2, 0, 0 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {})) + api.nvim_buf_set_text(0, 0, 0, 0, 0, { 'asdfasdf' }) + eq({ { 1, 0, 0 }, { 2, 0, 8 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {})) feed('u') -- handles pasting exec([[let @a='asdfasdf']]) feed([["ap]]) - eq({ {1, 0, 0}, {2, 0, 8} }, - meths.buf_get_extmarks(0, ns, 0, -1, {})) + eq({ { 1, 0, 0 }, { 2, 0, 8 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {})) end) it('can accept "end_row" or "end_line" #16548', function() set_extmark(ns, marks[1], 0, 0, { end_col = 0, - end_line = 1 + end_line = 1, }) - eq({ {1, 0, 0, { - ns_id = 1, - end_col = 0, - end_row = 1, - right_gravity = true, - end_right_gravity = false, - }} }, get_extmarks(ns, 0, -1, {details=true})) + eq({ + { + 1, + 0, + 0, + { + ns_id = 1, + end_col = 0, + end_row = 1, + right_gravity = true, + end_right_gravity = false, + }, + }, + }, get_extmarks(ns, 0, -1, { details = true })) end) it('in prompt buffer', function() feed('dd') local id = set_extmark(ns, marks[1], 0, 0, {}) - meths.set_option_value('buftype', 'prompt', {}) + api.nvim_set_option_value('buftype', 'prompt', {}) feed('i<esc>') - eq({{id, 0, 2}}, get_extmarks(ns, 0, -1)) + eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1)) end) it('can get details', function() set_extmark(ns, marks[1], 0, 0, { - conceal = "c", - cursorline_hl_group = "Statement", + conceal = 'c', + cursorline_hl_group = 'Statement', end_col = 0, end_right_gravity = true, end_row = 1, hl_eol = true, - hl_group = "String", - hl_mode = "blend", - line_hl_group = "Statement", - number_hl_group = "Statement", + hl_group = 'String', + hl_mode = 'blend', + line_hl_group = 'Statement', + number_hl_group = 'Statement', priority = 0, right_gravity = false, - sign_hl_group = "Statement", - sign_text = ">>", + sign_hl_group = 'Statement', + sign_text = '>>', spell = true, virt_lines = { - { { "lines", "Macro" }, { "???" } }, - { { "stack", { "Type", "Search" } }, { "!!!" } }, + { { 'lines', 'Macro' }, { '???' } }, + { { 'stack', { 'Type', 'Search' } }, { '!!!' } }, }, virt_lines_above = true, virt_lines_leftcol = true, - virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } }, + virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } }, virt_text_hide = true, - virt_text_pos = "right_align", + virt_text_pos = 'right_align', }) set_extmark(ns, marks[2], 0, 0, { priority = 0, - virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } }, + virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } }, virt_text_win_col = 1, }) - eq({0, 0, { - conceal = "c", - cursorline_hl_group = "Statement", - end_col = 0, - end_right_gravity = true, - end_row = 1, - hl_eol = true, - hl_group = "String", - hl_mode = "blend", - line_hl_group = "Statement", - ns_id = 1, - number_hl_group = "Statement", - priority = 0, - right_gravity = false, - sign_hl_group = "Statement", - sign_text = ">>", + eq({ + 0, + 0, + { + conceal = 'c', + cursorline_hl_group = 'Statement', + end_col = 0, + end_right_gravity = true, + end_row = 1, + hl_eol = true, + hl_group = 'String', + hl_mode = 'blend', + line_hl_group = 'Statement', + ns_id = 1, + number_hl_group = 'Statement', + priority = 0, + right_gravity = false, + sign_hl_group = 'Statement', + sign_text = '>>', + spell = true, + virt_lines = { + { { 'lines', 'Macro' }, { '???' } }, + { { 'stack', { 'Type', 'Search' } }, { '!!!' } }, + }, + virt_lines_above = true, + virt_lines_leftcol = true, + virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } }, + virt_text_repeat_linebreak = false, + virt_text_hide = true, + virt_text_pos = 'right_align', + }, + }, get_extmark_by_id(ns, marks[1], { details = true })) + eq({ + 0, + 0, + { + ns_id = 1, + right_gravity = true, + priority = 0, + virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } }, + virt_text_repeat_linebreak = false, + virt_text_hide = false, + virt_text_pos = 'win_col', + virt_text_win_col = 1, + }, + }, get_extmark_by_id(ns, marks[2], { details = true })) + set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = 'Statement' }) + eq({ + 0, + 0, + { + ns_id = 1, + cursorline_hl_group = 'Statement', + priority = 4096, + right_gravity = true, + }, + }, get_extmark_by_id(ns, marks[3], { details = true })) + set_extmark(ns, marks[4], 0, 0, { + end_col = 1, + conceal = 'a', spell = true, - virt_lines = { - { { "lines", "Macro" }, { "???" } }, - { { "stack", { "Type", "Search" } }, { "!!!" } }, + }) + eq({ + 0, + 0, + { + conceal = 'a', + end_col = 1, + end_right_gravity = false, + end_row = 0, + ns_id = 1, + right_gravity = true, + spell = true, }, - virt_lines_above = true, - virt_lines_leftcol = true, - virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } }, - virt_text_hide = true, - virt_text_pos = "right_align", - } }, get_extmark_by_id(ns, marks[1], { details = true })) - eq({0, 0, { - ns_id = 1, - right_gravity = true, - priority = 0, - virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } }, - virt_text_hide = false, - virt_text_pos = "win_col", - virt_text_win_col = 1, - } }, get_extmark_by_id(ns, marks[2], { details = true })) - set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = "Statement" }) - eq({0, 0, { - ns_id = 1, - cursorline_hl_group = "Statement", - priority = 4096, - right_gravity = true, - } }, get_extmark_by_id(ns, marks[3], { details = true })) - curbufmeths.clear_namespace(ns, 0, -1) + }, get_extmark_by_id(ns, marks[4], { details = true })) + set_extmark(ns, marks[5], 0, 0, { + end_col = 1, + spell = false, + }) + eq({ + 0, + 0, + { + end_col = 1, + end_right_gravity = false, + end_row = 0, + ns_id = 1, + right_gravity = true, + spell = false, + }, + }, get_extmark_by_id(ns, marks[5], { details = true })) + api.nvim_buf_clear_namespace(0, ns, 0, -1) -- legacy sign mark includes sign name command('sign define sign1 text=s1 texthl=Title linehl=LineNR numhl=Normal culhl=CursorLine') command('sign place 1 name=sign1 line=1') - eq({ {1, 0, 0, { - cursorline_hl_group = 'CursorLine', - invalidate = true, - line_hl_group = 'LineNr', - ns_id = 0, - number_hl_group = 'Normal', - priority = 10, - right_gravity = true, - sign_hl_group = 'Title', - sign_name = 'sign1', - sign_text = 's1', - undo_restore = false - } } }, get_extmarks(-1, 0, -1, { details = true })) + eq({ + { + 1, + 0, + 0, + { + cursorline_hl_group = 'CursorLine', + invalidate = true, + line_hl_group = 'LineNr', + ns_id = 0, + number_hl_group = 'Normal', + priority = 10, + right_gravity = true, + sign_hl_group = 'Title', + sign_name = 'sign1', + sign_text = 's1', + undo_restore = false, + }, + }, + }, get_extmarks(-1, 0, -1, { details = true })) end) it('can get marks from anonymous namespaces', function() - ns = request('nvim_create_namespace', "") - ns2 = request('nvim_create_namespace', "") + ns = request('nvim_create_namespace', '') + ns2 = request('nvim_create_namespace', '') set_extmark(ns, 1, 0, 0, {}) set_extmark(ns2, 2, 1, 0, {}) - eq({{ 1, 0, 0, { ns_id = ns, right_gravity = true }}, - { 2, 1, 0, { ns_id = ns2, right_gravity = true }}}, - get_extmarks(-1, 0, -1, { details = true })) + eq({ + { 1, 0, 0, { ns_id = ns, right_gravity = true } }, + { 2, 1, 0, { ns_id = ns2, right_gravity = true } }, + }, get_extmarks(-1, 0, -1, { details = true })) end) it('can filter by extmark properties', function() set_extmark(ns, 1, 0, 0, {}) set_extmark(ns, 2, 0, 0, { hl_group = 'Normal' }) set_extmark(ns, 3, 0, 0, { sign_text = '>>' }) - set_extmark(ns, 4, 0, 0, { virt_text = {{'text', 'Normal'}}}) - set_extmark(ns, 5, 0, 0, { virt_lines = {{{ 'line', 'Normal' }}}}) + set_extmark(ns, 4, 0, 0, { virt_text = { { 'text', 'Normal' } } }) + set_extmark(ns, 5, 0, 0, { virt_lines = { { { 'line', 'Normal' } } } }) eq(5, #get_extmarks(-1, 0, -1, {})) - eq({{ 2, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'highlight' })) - eq({{ 3, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'sign' })) - eq({{ 4, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'virt_text' })) - eq({{ 5, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'virt_lines' })) + eq({ { 2, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'highlight' })) + eq({ { 3, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'sign' })) + eq({ { 4, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'virt_text' })) + eq({ { 5, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'virt_lines' })) end) - it("invalidated marks are deleted", function() + it('invalidated marks are deleted', function() screen = Screen.new(40, 6) screen:attach() feed('dd6iaaa bbb ccc<CR><ESC>gg') - set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1' }) - set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2' }) + api.nvim_set_option_value('signcolumn', 'auto:2', {}) + set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1', end_row = 1 }) + set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2', end_row = 2 }) -- mark with invalidate is removed - command('d') + command('d2') screen:expect([[ S2^aaa bbb ccc | - aaa bbb ccc | - aaa bbb ccc | - aaa bbb ccc | - aaa bbb ccc | - | + aaa bbb ccc |*3 + |*2 ]]) -- mark is restored with undo_restore == true command('silent undo') screen:expect([[ - S1^aaa bbb ccc | - S2aaa bbb ccc | - aaa bbb ccc | - aaa bbb ccc | - aaa bbb ccc | + S1 ^aaa bbb ccc | + S1S2aaa bbb ccc | + S2 aaa bbb ccc | + aaa bbb ccc |*2 | ]]) + -- decor is not removed twice + command('d3') + api.nvim_buf_del_extmark(0, ns, 1) + command('silent undo') -- mark is deleted with undo_restore == false set_extmark(ns, 1, 0, 0, { invalidate = true, undo_restore = false, sign_text = 'S1' }) set_extmark(ns, 2, 1, 0, { invalidate = true, undo_restore = false, sign_text = 'S2' }) command('1d 2') eq(0, #get_extmarks(-1, 0, -1, {})) -- mark is not removed when deleting bytes before the range - set_extmark(ns, 3, 0, 4, { invalidate = true, undo_restore = false, - hl_group = 'Error', end_col = 7 }) + set_extmark( + ns, + 3, + 0, + 4, + { invalidate = true, undo_restore = false, hl_group = 'Error', end_col = 7 } + ) feed('dw') eq(3, get_extmark_by_id(ns, 3, { details = true })[3].end_col) -- mark is not removed when deleting bytes at the start of the range @@ -1665,22 +1770,64 @@ describe('API/extmarks', function() eq(2, get_extmark_by_id(ns, 3, { details = true })[3].end_col) -- mark is not removed when deleting bytes from the end of the range feed('lx') - eq(1, get_extmark_by_id(ns, 3, { details = true})[3].end_col) + eq(1, get_extmark_by_id(ns, 3, { details = true })[3].end_col) -- mark is not removed when deleting bytes beyond end of the range feed('x') - eq(1, get_extmark_by_id(ns, 3, { details = true})[3].end_col) + eq(1, get_extmark_by_id(ns, 3, { details = true })[3].end_col) -- mark is removed when all bytes in the range are deleted feed('hx') eq({}, get_extmark_by_id(ns, 3, {})) -- multiline mark is not removed when start of its range is deleted - set_extmark(ns, 4, 1, 4, { undo_restore = false, invalidate = true, - hl_group = 'Error', end_col = 7, end_row = 3 }) + set_extmark( + ns, + 4, + 1, + 4, + { undo_restore = false, invalidate = true, hl_group = 'Error', end_col = 7, end_row = 3 } + ) feed('ddDdd') - eq({0, 0}, get_extmark_by_id(ns, 4, {})) + eq({ 0, 0 }, get_extmark_by_id(ns, 4, {})) -- multiline mark is removed when entirety of its range is deleted feed('vj2ed') eq({}, get_extmark_by_id(ns, 4, {})) end) + + it('can set a URL', function() + set_extmark(ns, 1, 0, 0, { url = 'https://example.com', end_col = 3 }) + local extmarks = get_extmarks(ns, 0, -1, { details = true }) + eq(1, #extmarks) + eq('https://example.com', extmarks[1][4].url) + end) + + it('respects priority', function() + screen = Screen.new(15, 10) + screen:attach() + + set_extmark(ns, marks[1], 0, 0, { + hl_group = 'Comment', + end_col = 2, + priority = 20, + }) + + -- Extmark defined after first extmark but has lower priority, first extmark "wins" + set_extmark(ns, marks[2], 0, 0, { + hl_group = 'String', + end_col = 2, + priority = 10, + }) + + screen:expect { + grid = [[ + {1:12}34^5 | + {2:~ }|*8 + | + ]], + attr_ids = { + [1] = { foreground = Screen.colors.Blue1 }, + [2] = { foreground = Screen.colors.Blue1, bold = true }, + }, + } + end) end) describe('Extmarks buffer api with many marks', function() @@ -1689,29 +1836,28 @@ describe('Extmarks buffer api with many marks', function() local ns_marks = {} before_each(function() clear() - ns1 = request('nvim_create_namespace', "ns1") - ns2 = request('nvim_create_namespace', "ns2") - ns_marks = {[ns1]={}, [ns2]={}} + ns1 = request('nvim_create_namespace', 'ns1') + ns2 = request('nvim_create_namespace', 'ns2') + ns_marks = { [ns1] = {}, [ns2] = {} } local lines = {} - for i = 1,30 do - lines[#lines+1] = string.rep("x ",i) + for i = 1, 30 do + lines[#lines + 1] = string.rep('x ', i) end - curbufmeths.set_lines(0, -1, true, lines) + api.nvim_buf_set_lines(0, 0, -1, true, lines) local ns = ns1 local q = 0 - for i = 0,29 do - for j = 0,i do - local id = set_extmark(ns,0, i,j) + for i = 0, 29 do + for j = 0, i do + local id = set_extmark(ns, 0, i, j) eq(nil, ns_marks[ns][id]) ok(id > 0) - ns_marks[ns][id] = {i,j} - ns = ns1+ns2-ns + ns_marks[ns][id] = { i, j } + ns = ns1 + ns2 - ns q = q + 1 end end eq(233, #ns_marks[ns1]) eq(232, #ns_marks[ns2]) - end) local function get_marks(ns) @@ -1719,28 +1865,28 @@ describe('Extmarks buffer api with many marks', function() local marks = {} for _, mark in ipairs(mark_list) do local id, row, col = unpack(mark) - eq(nil, marks[id], "duplicate mark") - marks[id] = {row,col} + eq(nil, marks[id], 'duplicate mark') + marks[id] = { row, col } end return marks end - it("can get marks", function() + it('can get marks', function() eq(ns_marks[ns1], get_marks(ns1)) eq(ns_marks[ns2], get_marks(ns2)) end) - it("can clear all marks in ns", function() - curbufmeths.clear_namespace(ns1, 0, -1) + it('can clear all marks in ns', function() + api.nvim_buf_clear_namespace(0, ns1, 0, -1) eq({}, get_marks(ns1)) eq(ns_marks[ns2], get_marks(ns2)) - curbufmeths.clear_namespace(ns2, 0, -1) + api.nvim_buf_clear_namespace(0, ns2, 0, -1) eq({}, get_marks(ns1)) eq({}, get_marks(ns2)) end) - it("can clear line range", function() - curbufmeths.clear_namespace(ns1, 10, 20) + it('can clear line range', function() + api.nvim_buf_clear_namespace(0, ns1, 10, 20) for id, mark in pairs(ns_marks[ns1]) do if 10 <= mark[1] and mark[1] < 20 then ns_marks[ns1][id] = nil @@ -1750,12 +1896,12 @@ describe('Extmarks buffer api with many marks', function() eq(ns_marks[ns2], get_marks(ns2)) end) - it("can delete line", function() + it('can delete line', function() feed('10Gdd') for _, marks in pairs(ns_marks) do for id, mark in pairs(marks) do if mark[1] == 9 then - marks[id] = {9,0} + marks[id] = { 9, 0 } elseif mark[1] >= 10 then mark[1] = mark[1] - 1 end @@ -1765,12 +1911,12 @@ describe('Extmarks buffer api with many marks', function() eq(ns_marks[ns2], get_marks(ns2)) end) - it("can delete lines", function() + it('can delete lines', function() feed('10G10dd') for _, marks in pairs(ns_marks) do for id, mark in pairs(marks) do if 9 <= mark[1] and mark[1] < 19 then - marks[id] = {9,0} + marks[id] = { 9, 0 } elseif mark[1] >= 19 then mark[1] = mark[1] - 10 end @@ -1780,7 +1926,7 @@ describe('Extmarks buffer api with many marks', function() eq(ns_marks[ns2], get_marks(ns2)) end) - it("can wipe buffer", function() + it('can wipe buffer', function() command('bwipe!') eq({}, get_marks(ns1)) eq({}, get_marks(ns2)) @@ -1794,17 +1940,17 @@ describe('API/win_extmark', function() before_each(function() -- Initialize some namespaces and insert text into a buffer - marks = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} + marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 } - line1 = "non ui-watched line" - line2 = "ui-watched line" + line1 = 'non ui-watched line' + line2 = 'ui-watched line' clear() insert(line1) - feed("o<esc>") + feed('o<esc>') insert(line2) - ns = request('nvim_create_namespace', "extmark-ui") + ns = request('nvim_create_namespace', 'extmark-ui') end) it('sends and only sends ui-watched marks to ui', function() @@ -1824,8 +1970,8 @@ describe('API/win_extmark', function() extmarks = { [2] = { -- positioned at the end of the 2nd line - { {id = 1000}, 1, 1, 1, 16 }, - } + { 1000, ns, marks[1], 1, 16 }, + }, }, }) end) @@ -1833,35 +1979,45 @@ describe('API/win_extmark', function() it('sends multiple ui-watched marks to ui', function() screen = Screen.new(20, 4) screen:attach() + feed('15A!<Esc>') -- should send all of these - set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = "overlay" }) - set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = "overlay" }) - set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = "overlay" }) - set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = "overlay" }) + set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = 'overlay' }) + set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = 'overlay' }) + set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = 'overlay' }) + set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = 'overlay' }) set_extmark(ns, marks[5], 1, 8, { ui_watched = true }) screen:expect({ grid = [[ non ui-watched line | - ui-watched lin^e | - ~ | + ui-watched line!!!!!| + !!!!!!!!!^! | | ]], extmarks = { [2] = { - -- earlier notifications - { {id = 1000}, 1, 1, 1, 0 }, - { {id = 1000}, 1, 1, 1, 0 }, { {id = 1000}, 1, 2, 1, 2 }, - { {id = 1000}, 1, 1, 1, 0 }, { {id = 1000}, 1, 2, 1, 2 }, { {id = 1000}, 1, 3, 1, 4 }, - { {id = 1000}, 1, 1, 1, 0 }, { {id = 1000}, 1, 2, 1, 2 }, { {id = 1000}, 1, 3, 1, 4 }, { {id = 1000}, 1, 4, 1, 6 }, + -- notification from 1st call + { 1000, ns, marks[1], 1, 0 }, + -- notifications from 2nd call + { 1000, ns, marks[1], 1, 0 }, + { 1000, ns, marks[2], 1, 2 }, + -- notifications from 3rd call + { 1000, ns, marks[1], 1, 0 }, + { 1000, ns, marks[2], 1, 2 }, + { 1000, ns, marks[3], 1, 4 }, + -- notifications from 4th call + { 1000, ns, marks[1], 1, 0 }, + { 1000, ns, marks[2], 1, 2 }, + { 1000, ns, marks[3], 1, 4 }, + { 1000, ns, marks[4], 1, 6 }, -- final -- overlay - { {id = 1000}, 1, 1, 1, 0 }, - { {id = 1000}, 1, 2, 1, 2 }, - { {id = 1000}, 1, 3, 1, 4 }, - { {id = 1000}, 1, 4, 1, 6 }, + { 1000, ns, marks[1], 1, 0 }, + { 1000, ns, marks[2], 1, 2 }, + { 1000, ns, marks[3], 1, 4 }, + { 1000, ns, marks[4], 1, 6 }, -- eol - { {id = 1000}, 1, 5, 1, 16 }, - } + { 1000, ns, marks[5], 2, 11 }, + }, }, }) end) @@ -1874,7 +2030,7 @@ describe('API/win_extmark', function() -- should not send this set_extmark(ns, marks[2], 0, 0, { ui_watched = false }) -- make some changes - insert(" update") + insert(' update') screen:expect({ grid = [[ non ui-watched line | @@ -1885,13 +2041,13 @@ describe('API/win_extmark', function() extmarks = { [2] = { -- positioned at the end of the 2nd line - { {id = 1000}, 1, 1, 1, 16 }, + { 1000, ns, marks[1], 1, 16 }, -- updated and wrapped to 3rd line - { {id = 1000}, 1, 1, 2, 2 }, - } - } + { 1000, ns, marks[1], 2, 2 }, + }, + }, }) - feed("<c-e>") + feed('<c-e>') screen:expect({ grid = [[ ui-watched linupdat^e| @@ -1902,18 +2058,18 @@ describe('API/win_extmark', function() extmarks = { [2] = { -- positioned at the end of the 2nd line - { {id = 1000}, 1, 1, 1, 16 }, + { 1000, ns, marks[1], 1, 16 }, -- updated and wrapped to 3rd line - { {id = 1000}, 1, 1, 2, 2 }, + { 1000, ns, marks[1], 2, 2 }, -- scrolled up one line, should be handled by grid scroll - } - } + }, + }, }) end) it('sends ui-watched to splits', function() screen = Screen.new(20, 8) - screen:attach({ext_multigrid=true}) + screen:attach({ ext_multigrid = true }) -- should send this set_extmark(ns, marks[1], 1, 0, { ui_watched = true }) -- should not send this @@ -1922,12 +2078,9 @@ describe('API/win_extmark', function() screen:expect({ grid = [[ ## grid 1 - [4:--------------------]| - [4:--------------------]| - [4:--------------------]| + [4:--------------------]|*3 [No Name] [+] | - [2:--------------------]| - [2:--------------------]| + [2:--------------------]|*2 [No Name] [+] | [3:--------------------]| ## grid 2 @@ -1943,27 +2096,24 @@ describe('API/win_extmark', function() extmarks = { [2] = { -- positioned at the end of the 2nd line - { {id = 1000}, 1, 1, 1, 16 }, + { 1000, ns, marks[1], 1, 16 }, -- updated after split - { {id = 1000}, 1, 1, 1, 16 }, + { 1000, ns, marks[1], 1, 16 }, }, [4] = { -- only after split - { {id = 1001}, 1, 1, 1, 16 }, - } - } + { 1001, ns, marks[1], 1, 16 }, + }, + }, }) -- make some changes - insert(" update") + insert(' update') screen:expect({ grid = [[ ## grid 1 - [4:--------------------]| - [4:--------------------]| - [4:--------------------]| + [4:--------------------]|*3 [No Name] [+] | - [2:--------------------]| - [2:--------------------]| + [2:--------------------]|*2 [No Name] [+] | [3:--------------------]| ## grid 2 @@ -1979,16 +2129,16 @@ describe('API/win_extmark', function() extmarks = { [2] = { -- positioned at the end of the 2nd line - { {id = 1000}, 1, 1, 1, 16 }, + { 1000, ns, marks[1], 1, 16 }, -- updated after split - { {id = 1000}, 1, 1, 1, 16 }, + { 1000, ns, marks[1], 1, 16 }, }, [4] = { - { {id = 1001}, 1, 1, 1, 16 }, + { 1001, ns, marks[1], 1, 16 }, -- updated - { {id = 1001}, 1, 1, 2, 2 }, - } - } + { 1001, ns, marks[1], 2, 2 }, + }, + }, }) end) end) diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua index 7d7d07e30e..1973d3e1c7 100644 --- a/test/functional/api/highlight_spec.lua +++ b/test/functional/api/highlight_spec.lua @@ -1,16 +1,16 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, nvim = helpers.clear, helpers.nvim +local clear = helpers.clear local Screen = require('test.functional.ui.screen') local eq, eval = helpers.eq, helpers.eval local command = helpers.command local exec_capture = helpers.exec_capture -local meths = helpers.meths -local funcs = helpers.funcs +local api = helpers.api +local fn = helpers.fn local pcall_err = helpers.pcall_err local ok = helpers.ok local assert_alive = helpers.assert_alive -describe('API: highlight',function() +describe('API: highlight', function() clear() Screen.new() -- initialize Screen.colors @@ -45,127 +45,138 @@ describe('API: highlight',function() before_each(function() clear() - command("hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold") + command( + 'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold' + ) end) - it("nvim_get_hl_by_id", function() + it('nvim_get_hl_by_id', function() local hl_id = eval("hlID('NewHighlight')") - eq(expected_cterm, nvim("get_hl_by_id", hl_id, false)) + eq(expected_cterm, api.nvim_get_hl_by_id(hl_id, false)) hl_id = eval("hlID('NewHighlight')") -- Test valid id. - eq(expected_rgb, nvim("get_hl_by_id", hl_id, true)) + eq(expected_rgb, api.nvim_get_hl_by_id(hl_id, true)) -- Test invalid id. - eq('Invalid highlight id: 30000', pcall_err(meths.get_hl_by_id, 30000, false)) + eq('Invalid highlight id: 30000', pcall_err(api.nvim_get_hl_by_id, 30000, false)) -- Test all highlight properties. command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') - eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true)) + eq(expected_rgb2, api.nvim_get_hl_by_id(hl_id, true)) -- Test undercurl command('hi NewHighlight gui=undercurl') - eq(expected_undercurl, nvim("get_hl_by_id", hl_id, true)) + eq(expected_undercurl, api.nvim_get_hl_by_id(hl_id, true)) -- Test nil argument. - eq('Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer', - pcall_err(meths.get_hl_by_id, { nil }, false)) + eq( + 'Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer', + pcall_err(api.nvim_get_hl_by_id, { nil }, false) + ) -- Test 0 argument. - eq('Invalid highlight id: 0', pcall_err(meths.get_hl_by_id, 0, false)) + eq('Invalid highlight id: 0', pcall_err(api.nvim_get_hl_by_id, 0, false)) -- Test -1 argument. - eq('Invalid highlight id: -1', pcall_err(meths.get_hl_by_id, -1, false)) + eq('Invalid highlight id: -1', pcall_err(api.nvim_get_hl_by_id, -1, false)) -- Test highlight group without ctermbg value. command('hi Normal ctermfg=red ctermbg=yellow') command('hi NewConstant ctermfg=green guifg=white guibg=blue') hl_id = eval("hlID('NewConstant')") - eq({foreground = 10,}, meths.get_hl_by_id(hl_id, false)) + eq({ foreground = 10 }, api.nvim_get_hl_by_id(hl_id, false)) -- Test highlight group without ctermfg value. command('hi clear NewConstant') command('hi NewConstant ctermbg=Magenta guifg=white guibg=blue') - eq({background = 13,}, meths.get_hl_by_id(hl_id, false)) + eq({ background = 13 }, api.nvim_get_hl_by_id(hl_id, false)) -- Test highlight group with ctermfg and ctermbg values. command('hi clear NewConstant') command('hi NewConstant ctermfg=green ctermbg=Magenta guifg=white guibg=blue') - eq({foreground = 10, background = 13,}, meths.get_hl_by_id(hl_id, false)) + eq({ foreground = 10, background = 13 }, api.nvim_get_hl_by_id(hl_id, false)) end) - it("nvim_get_hl_by_name", function() - local expected_normal = { background = Screen.colors.Yellow, - foreground = Screen.colors.Red } + it('nvim_get_hl_by_name', function() + local expected_normal = { background = Screen.colors.Yellow, foreground = Screen.colors.Red } -- Test `Normal` default values. - eq({}, nvim("get_hl_by_name", 'Normal', true)) + eq({}, api.nvim_get_hl_by_name('Normal', true)) - eq(expected_cterm, nvim("get_hl_by_name", 'NewHighlight', false)) - eq(expected_rgb, nvim("get_hl_by_name", 'NewHighlight', true)) + eq(expected_cterm, api.nvim_get_hl_by_name('NewHighlight', false)) + eq(expected_rgb, api.nvim_get_hl_by_name('NewHighlight', true)) -- Test `Normal` modified values. command('hi Normal guifg=red guibg=yellow') - eq(expected_normal, nvim("get_hl_by_name", 'Normal', true)) + eq(expected_normal, api.nvim_get_hl_by_name('Normal', true)) -- Test invalid name. - eq("Invalid highlight name: 'unknown_highlight'", - pcall_err(meths.get_hl_by_name , 'unknown_highlight', false)) + eq( + "Invalid highlight name: 'unknown_highlight'", + pcall_err(api.nvim_get_hl_by_name, 'unknown_highlight', false) + ) -- Test nil argument. - eq('Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String', - pcall_err(meths.get_hl_by_name , { nil }, false)) + eq( + 'Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String', + pcall_err(api.nvim_get_hl_by_name, { nil }, false) + ) -- Test empty string argument. - eq('Invalid highlight name', - pcall_err(meths.get_hl_by_name , '', false)) + eq('Invalid highlight name', pcall_err(api.nvim_get_hl_by_name, '', false)) -- Test "standout" attribute. #8054 - eq({ underline = true, }, - meths.get_hl_by_name('cursorline', 0)); + eq({ underline = true }, api.nvim_get_hl_by_name('cursorline', 0)) command('hi CursorLine cterm=standout,underline term=standout,underline gui=standout,underline') command('set cursorline') - eq({ underline = true, standout = true, }, - meths.get_hl_by_name('cursorline', 0)); + eq({ underline = true, standout = true }, api.nvim_get_hl_by_name('cursorline', 0)) -- Test cterm & Normal values. #18024 (tail) & #18980 -- Ensure Normal, and groups that match Normal return their fg & bg cterm values - meths.set_hl(0, 'Normal', {ctermfg = 17, ctermbg = 213}) - meths.set_hl(0, 'NotNormal', {ctermfg = 17, ctermbg = 213, nocombine = true}) + api.nvim_set_hl(0, 'Normal', { ctermfg = 17, ctermbg = 213 }) + api.nvim_set_hl(0, 'NotNormal', { ctermfg = 17, ctermbg = 213, nocombine = true }) -- Note colors are "cterm" values, not rgb-as-ints - eq({foreground = 17, background = 213}, nvim("get_hl_by_name", 'Normal', false)) - eq({foreground = 17, background = 213, nocombine = true}, nvim("get_hl_by_name", 'NotNormal', false)) + eq({ foreground = 17, background = 213 }, api.nvim_get_hl_by_name('Normal', false)) + eq( + { foreground = 17, background = 213, nocombine = true }, + api.nvim_get_hl_by_name('NotNormal', false) + ) end) it('nvim_get_hl_id_by_name', function() -- precondition: use a hl group that does not yet exist - eq("Invalid highlight name: 'Shrubbery'", pcall_err(meths.get_hl_by_name, "Shrubbery", true)) - eq(0, funcs.hlID("Shrubbery")) + eq("Invalid highlight name: 'Shrubbery'", pcall_err(api.nvim_get_hl_by_name, 'Shrubbery', true)) + eq(0, fn.hlID('Shrubbery')) - local hl_id = meths.get_hl_id_by_name("Shrubbery") + local hl_id = api.nvim_get_hl_id_by_name('Shrubbery') ok(hl_id > 0) - eq(hl_id, funcs.hlID("Shrubbery")) + eq(hl_id, fn.hlID('Shrubbery')) command('hi Shrubbery guifg=#888888 guibg=#888888') - eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")}, - meths.get_hl_by_id(hl_id, true)) - eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")}, - meths.get_hl_by_name("Shrubbery", true)) + eq( + { foreground = tonumber('0x888888'), background = tonumber('0x888888') }, + api.nvim_get_hl_by_id(hl_id, true) + ) + eq( + { foreground = tonumber('0x888888'), background = tonumber('0x888888') }, + api.nvim_get_hl_by_name('Shrubbery', true) + ) end) it("nvim_buf_add_highlight to other buffer doesn't crash if undo is disabled #12873", function() command('vsplit file') - local err, _ = pcall(meths.set_option_value, 'undofile', false, { buf = 1 }) + local err, _ = pcall(api.nvim_set_option_value, 'undofile', false, { buf = 1 }) eq(true, err) - err, _ = pcall(meths.set_option_value, 'undolevels', -1, { buf = 1 }) + err, _ = pcall(api.nvim_set_option_value, 'undolevels', -1, { buf = 1 }) eq(true, err) - err, _ = pcall(meths.buf_add_highlight, 1, -1, 'Question', 0, 0, -1) + err, _ = pcall(api.nvim_buf_add_highlight, 1, -1, 'Question', 0, 0, -1) eq(true, err) assert_alive() end) end) -describe("API: set highlight", function() +describe('API: set highlight', function() local highlight_color = { fg = tonumber('0xff0000'), bg = tonumber('0x0032aa'), @@ -207,7 +218,7 @@ describe("API: set highlight", function() strikethrough = true, altfont = true, nocombine = true, - } + }, } local highlight3_result_gui = { background = highlight_color.bg, @@ -230,57 +241,61 @@ describe("API: set highlight", function() } local function get_ns() - local ns = meths.create_namespace('Test_set_hl') - meths.set_hl_ns(ns) + local ns = api.nvim_create_namespace('Test_set_hl') + api.nvim_set_hl_ns(ns) return ns end before_each(clear) it('validation', function() - eq("Invalid 'blend': out of range", - pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend=999})) - eq("Invalid 'blend': expected Integer, got Array", - pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend={}})) + eq( + "Invalid 'blend': out of range", + pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = 999 }) + ) + eq( + "Invalid 'blend': expected Integer, got Array", + pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = {} }) + ) end) - it("can set gui highlight", function() + it('can set gui highlight', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight1) - eq(highlight1, meths.get_hl_by_name('Test_hl', true)) + api.nvim_set_hl(ns, 'Test_hl', highlight1) + eq(highlight1, api.nvim_get_hl_by_name('Test_hl', true)) end) - it("can set cterm highlight", function() + it('can set cterm highlight', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight2_config) - eq(highlight2_result, meths.get_hl_by_name('Test_hl', false)) + api.nvim_set_hl(ns, 'Test_hl', highlight2_config) + eq(highlight2_result, api.nvim_get_hl_by_name('Test_hl', false)) end) - it("can set empty cterm attr", function() + it('can set empty cterm attr', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', { cterm = {} }) - eq({}, meths.get_hl_by_name('Test_hl', false)) + api.nvim_set_hl(ns, 'Test_hl', { cterm = {} }) + eq({}, api.nvim_get_hl_by_name('Test_hl', false)) end) - it("cterm attr defaults to gui attr", function() + it('cterm attr defaults to gui attr', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight1) + api.nvim_set_hl(ns, 'Test_hl', highlight1) eq({ bold = true, italic = true, - }, meths.get_hl_by_name('Test_hl', false)) + }, api.nvim_get_hl_by_name('Test_hl', false)) end) - it("can overwrite attr for cterm", function() + it('can overwrite attr for cterm', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight3_config) - eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true)) - eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false)) + api.nvim_set_hl(ns, 'Test_hl', highlight3_config) + eq(highlight3_result_gui, api.nvim_get_hl_by_name('Test_hl', true)) + eq(highlight3_result_cterm, api.nvim_get_hl_by_name('Test_hl', false)) end) - it("only allows one underline attribute #22371", function() + it('only allows one underline attribute #22371', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', { + api.nvim_set_hl(ns, 'Test_hl', { underdouble = true, underdotted = true, cterm = { @@ -288,84 +303,86 @@ describe("API: set highlight", function() undercurl = true, }, }) - eq({ undercurl = true }, meths.get_hl_by_name('Test_hl', false)) - eq({ underdotted = true }, meths.get_hl_by_name('Test_hl', true)) + eq({ undercurl = true }, api.nvim_get_hl_by_name('Test_hl', false)) + eq({ underdotted = true }, api.nvim_get_hl_by_name('Test_hl', true)) end) - it("can set a highlight in the global namespace", function() - meths.set_hl(0, 'Test_hl', highlight2_config) - eq('Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse', - exec_capture('highlight Test_hl')) + it('can set a highlight in the global namespace', function() + api.nvim_set_hl(0, 'Test_hl', highlight2_config) + eq( + 'Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse', + exec_capture('highlight Test_hl') + ) - meths.set_hl(0, 'Test_hl', { background = highlight_color.bg }) - eq('Test_hl xxx guibg=#0032aa', - exec_capture('highlight Test_hl')) + api.nvim_set_hl(0, 'Test_hl', { background = highlight_color.bg }) + eq('Test_hl xxx guibg=#0032aa', exec_capture('highlight Test_hl')) - meths.set_hl(0, 'Test_hl2', highlight3_config) - eq('Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa', - exec_capture('highlight Test_hl2')) + api.nvim_set_hl(0, 'Test_hl2', highlight3_config) + eq( + 'Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa', + exec_capture('highlight Test_hl2') + ) -- Colors are stored with the name they are defined, but -- with canonical casing - meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue'}) - eq('Test_hl3 xxx guifg=Blue guibg=Red', - exec_capture('highlight Test_hl3')) + api.nvim_set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' }) + eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3')) end) - it("can modify a highlight in the global namespace", function() - meths.set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue'}) - eq('Test_hl3 xxx guifg=Blue guibg=Red', - exec_capture('highlight Test_hl3')) + it('can modify a highlight in the global namespace', function() + api.nvim_set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue' }) + eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3')) - meths.set_hl(0, 'Test_hl3', { bg = 'red' }) - eq('Test_hl3 xxx guibg=Red', - exec_capture('highlight Test_hl3')) + api.nvim_set_hl(0, 'Test_hl3', { bg = 'red' }) + eq('Test_hl3 xxx guibg=Red', exec_capture('highlight Test_hl3')) - meths.set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12}) - eq('Test_hl3 xxx ctermfg=12 ctermbg=9', - exec_capture('highlight Test_hl3')) + api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12 }) + eq('Test_hl3 xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3')) - meths.set_hl(0, 'Test_hl3', { ctermbg = 'red' , ctermfg = 'blue'}) - eq('Test_hl3 xxx ctermfg=12 ctermbg=9', - exec_capture('highlight Test_hl3')) + api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 'red', ctermfg = 'blue' }) + eq('Test_hl3 xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3')) - meths.set_hl(0, 'Test_hl3', { ctermbg = 9 }) - eq('Test_hl3 xxx ctermbg=9', - exec_capture('highlight Test_hl3')) + api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 9 }) + eq('Test_hl3 xxx ctermbg=9', exec_capture('highlight Test_hl3')) - eq("Invalid highlight color: 'redd'", - pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='redd'})) + eq( + "Invalid highlight color: 'redd'", + pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = 'redd' }) + ) - eq("Invalid highlight color: 'bleu'", - pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='bleu'})) + eq( + "Invalid highlight color: 'bleu'", + pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { ctermfg = 'bleu' }) + ) - meths.set_hl(0, 'Test_hl3', {fg='#FF00FF'}) - eq('Test_hl3 xxx guifg=#ff00ff', - exec_capture('highlight Test_hl3')) + api.nvim_set_hl(0, 'Test_hl3', { fg = '#FF00FF' }) + eq('Test_hl3 xxx guifg=#ff00ff', exec_capture('highlight Test_hl3')) - eq("Invalid highlight color: '#FF00FF'", - pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='#FF00FF'})) + eq( + "Invalid highlight color: '#FF00FF'", + pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { ctermfg = '#FF00FF' }) + ) - for _, fg_val in ipairs{ nil, 'NONE', 'nOnE', '', -1 } do - meths.set_hl(0, 'Test_hl3', {fg = fg_val}) - eq('Test_hl3 xxx cleared', - exec_capture('highlight Test_hl3')) + for _, fg_val in ipairs { nil, 'NONE', 'nOnE', '', -1 } do + api.nvim_set_hl(0, 'Test_hl3', { fg = fg_val }) + eq('Test_hl3 xxx cleared', exec_capture('highlight Test_hl3')) end - meths.set_hl(0, 'Test_hl3', {fg='#FF00FF', blend=50}) - eq('Test_hl3 xxx guifg=#ff00ff blend=50', - exec_capture('highlight Test_hl3')) - + api.nvim_set_hl(0, 'Test_hl3', { fg = '#FF00FF', blend = 50 }) + eq('Test_hl3 xxx guifg=#ff00ff blend=50', exec_capture('highlight Test_hl3')) end) it("correctly sets 'Normal' internal properties", function() -- Normal has some special handling internally. #18024 - meths.set_hl(0, 'Normal', {fg='#000083', bg='#0000F3'}) - eq({foreground = 131, background = 243}, nvim("get_hl_by_name", 'Normal', true)) + api.nvim_set_hl(0, 'Normal', { fg = '#000083', bg = '#0000F3' }) + eq({ foreground = 131, background = 243 }, api.nvim_get_hl_by_name('Normal', true)) end) it('does not segfault on invalid group name #20009', function() - eq("Invalid highlight name: 'foo bar'", pcall_err(meths.set_hl, 0, 'foo bar', {bold = true})) + eq( + "Invalid highlight name: 'foo bar'", + pcall_err(api.nvim_set_hl, 0, 'foo bar', { bold = true }) + ) assert_alive() end) end) @@ -380,14 +397,16 @@ describe('API: get highlight', function() local highlight1 = { bg = highlight_color.bg, fg = highlight_color.fg, - bold = true, italic = true, - cterm = {bold = true, italic = true}, + bold = true, + italic = true, + cterm = { bold = true, italic = true }, } local highlight2 = { ctermbg = highlight_color.ctermbg, ctermfg = highlight_color.ctermfg, - underline = true, reverse = true, - cterm = {underline = true, reverse = true}, + underline = true, + reverse = true, + cterm = { underline = true, reverse = true }, } local highlight3_config = { bg = highlight_color.bg, @@ -413,20 +432,31 @@ describe('API: get highlight', function() fg = highlight_color.fg, ctermbg = highlight_color.ctermbg, ctermfg = highlight_color.ctermfg, - bold = true, italic = true, reverse = true, underdashed = true, strikethrough = true, altfont = true, - cterm = {italic = true, nocombine = true, reverse = true, strikethrough = true, altfont = true} + bold = true, + italic = true, + reverse = true, + underdashed = true, + strikethrough = true, + altfont = true, + cterm = { + italic = true, + nocombine = true, + reverse = true, + strikethrough = true, + altfont = true, + }, } local function get_ns() -- Test namespace filtering behavior - local ns2 = meths.create_namespace('Another_namespace') - meths.set_hl(ns2, 'Test_hl', { ctermfg = 23 }) - meths.set_hl(ns2, 'Test_another_hl', { link = 'Test_hl' }) - meths.set_hl(ns2, 'Test_hl_link', { link = 'Test_another_hl' }) - meths.set_hl(ns2, 'Test_another_hl_link', { link = 'Test_hl_link' }) + local ns2 = api.nvim_create_namespace('Another_namespace') + api.nvim_set_hl(ns2, 'Test_hl', { ctermfg = 23 }) + api.nvim_set_hl(ns2, 'Test_another_hl', { link = 'Test_hl' }) + api.nvim_set_hl(ns2, 'Test_hl_link', { link = 'Test_another_hl' }) + api.nvim_set_hl(ns2, 'Test_another_hl_link', { link = 'Test_hl_link' }) - local ns = meths.create_namespace('Test_set_hl') - meths.set_hl_ns(ns) + local ns = api.nvim_create_namespace('Test_set_hl') + api.nvim_set_hl_ns(ns) return ns end @@ -434,67 +464,69 @@ describe('API: get highlight', function() before_each(clear) it('validation', function() - eq("Invalid 'name': expected String, got Integer", - pcall_err(meths.get_hl, 0, { name = 177 })) - eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' })) + eq( + "Invalid 'name': expected String, got Integer", + pcall_err(api.nvim_get_hl, 0, { name = 177 }) + ) + eq('Highlight id out of bounds', pcall_err(api.nvim_get_hl, 0, { name = 'Test set hl' })) end) it('nvim_get_hl with create flag', function() - eq({}, nvim("get_hl", 0, {name = 'Foo', create = false})) - eq(0, funcs.hlexists('Foo')) - meths.get_hl(0, {name = 'Bar', create = true}) - eq(1, funcs.hlexists('Bar')) - meths.get_hl(0, {name = 'FooBar'}) - eq(1, funcs.hlexists('FooBar')) + eq({}, api.nvim_get_hl(0, { name = 'Foo', create = false })) + eq(0, fn.hlexists('Foo')) + api.nvim_get_hl(0, { name = 'Bar', create = true }) + eq(1, fn.hlexists('Bar')) + api.nvim_get_hl(0, { name = 'FooBar' }) + eq(1, fn.hlexists('FooBar')) end) it('can get all highlights in current namespace', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', { bg = '#B4BEFE' }) - meths.set_hl(ns, 'Test_hl_link', { link = 'Test_hl' }) + api.nvim_set_hl(ns, 'Test_hl', { bg = '#B4BEFE' }) + api.nvim_set_hl(ns, 'Test_hl_link', { link = 'Test_hl' }) eq({ Test_hl = { - bg = 11845374 + bg = 11845374, }, Test_hl_link = { - link = 'Test_hl' - } - }, meths.get_hl(ns, {})) + link = 'Test_hl', + }, + }, api.nvim_get_hl(ns, {})) end) it('can get gui highlight', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight1) - eq(highlight1, meths.get_hl(ns, { name = 'Test_hl' })) + api.nvim_set_hl(ns, 'Test_hl', highlight1) + eq(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' })) end) it('can get cterm highlight', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight2) - eq(highlight2, meths.get_hl(ns, { name = 'Test_hl' })) + api.nvim_set_hl(ns, 'Test_hl', highlight2) + eq(highlight2, api.nvim_get_hl(ns, { name = 'Test_hl' })) end) it('can get empty cterm attr', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', { cterm = {} }) - eq({}, meths.get_hl(ns, { name = 'Test_hl' })) + api.nvim_set_hl(ns, 'Test_hl', { cterm = {} }) + eq({}, api.nvim_get_hl(ns, { name = 'Test_hl' })) end) it('cterm attr defaults to gui attr', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight1) - eq(highlight1, meths.get_hl(ns, { name = 'Test_hl' })) + api.nvim_set_hl(ns, 'Test_hl', highlight1) + eq(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' })) end) it('can overwrite attr for cterm', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', highlight3_config) - eq(highlight3_result, meths.get_hl(ns, { name = 'Test_hl' })) + api.nvim_set_hl(ns, 'Test_hl', highlight3_config) + eq(highlight3_result, api.nvim_get_hl(ns, { name = 'Test_hl' })) end) it('only allows one underline attribute #22371', function() local ns = get_ns() - meths.set_hl(ns, 'Test_hl', { + api.nvim_set_hl(ns, 'Test_hl', { underdouble = true, underdotted = true, cterm = { @@ -502,154 +534,178 @@ describe('API: get highlight', function() undercurl = true, }, }) - eq({ underdotted = true, cterm = { undercurl = true} }, - meths.get_hl(ns, { name = 'Test_hl' })) + eq( + { underdotted = true, cterm = { undercurl = true } }, + api.nvim_get_hl(ns, { name = 'Test_hl' }) + ) end) it('can get a highlight in the global namespace', function() - meths.set_hl(0, 'Test_hl', highlight2) - eq(highlight2, meths.get_hl(0, { name = 'Test_hl' })) + api.nvim_set_hl(0, 'Test_hl', highlight2) + eq(highlight2, api.nvim_get_hl(0, { name = 'Test_hl' })) - meths.set_hl(0, 'Test_hl', { background = highlight_color.bg }) + api.nvim_set_hl(0, 'Test_hl', { background = highlight_color.bg }) eq({ bg = 12970, - }, meths.get_hl(0, { name = 'Test_hl' })) + }, api.nvim_get_hl(0, { name = 'Test_hl' })) - meths.set_hl(0, 'Test_hl2', highlight3_config) - eq(highlight3_result, meths.get_hl(0, { name = 'Test_hl2' })) + api.nvim_set_hl(0, 'Test_hl2', highlight3_config) + eq(highlight3_result, api.nvim_get_hl(0, { name = 'Test_hl2' })) -- Colors are stored with the name they are defined, but -- with canonical casing - meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' }) + api.nvim_set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' }) eq({ bg = 16711680, fg = 255, - }, meths.get_hl(0, { name = 'Test_hl3' })) + }, api.nvim_get_hl(0, { name = 'Test_hl3' })) end) it('nvim_get_hl by id', function() - local hl_id = meths.get_hl_id_by_name('NewHighlight') + local hl_id = api.nvim_get_hl_id_by_name('NewHighlight') command( 'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold' ) - eq({ fg = 16711680, bg = 16776960, sp = 255, bold = true, - ctermbg = 10, cterm = { underline = true }, - }, meths.get_hl(0, { id = hl_id })) + eq({ + fg = 16711680, + bg = 16776960, + sp = 255, + bold = true, + ctermbg = 10, + cterm = { underline = true }, + }, api.nvim_get_hl(0, { id = hl_id })) -- Test 0 argument - eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { id = 0 })) + eq('Highlight id out of bounds', pcall_err(api.nvim_get_hl, 0, { id = 0 })) eq( "Invalid 'id': expected Integer, got String", - pcall_err(meths.get_hl, 0, { id = 'Test_set_hl' }) + pcall_err(api.nvim_get_hl, 0, { id = 'Test_set_hl' }) ) -- Test all highlight properties. command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine') - eq({ fg = 16711680, bg = 16776960, sp = 255, - altfont = true, bold = true, italic = true, nocombine = true, reverse = true, strikethrough = true, underline = true, - ctermbg = 10, cterm = {underline = true}, - }, meths.get_hl(0, { id = hl_id })) + eq({ + fg = 16711680, + bg = 16776960, + sp = 255, + altfont = true, + bold = true, + italic = true, + nocombine = true, + reverse = true, + strikethrough = true, + underline = true, + ctermbg = 10, + cterm = { underline = true }, + }, api.nvim_get_hl(0, { id = hl_id })) -- Test undercurl command('hi NewHighlight gui=undercurl') - eq({ fg = 16711680, bg = 16776960, sp = 255, undercurl = true, - ctermbg = 10, - cterm = {underline = true}, - }, meths.get_hl(0, { id = hl_id })) + eq({ + fg = 16711680, + bg = 16776960, + sp = 255, + undercurl = true, + ctermbg = 10, + cterm = { underline = true }, + }, api.nvim_get_hl(0, { id = hl_id })) end) it('can correctly detect links', function() - command('hi String guifg=#a6e3a1') + command('hi String guifg=#a6e3a1 ctermfg=NONE') command('hi link @string string') command('hi link @string.cpp @string') - eq({ fg = 10937249 }, meths.get_hl(0, { name = 'String' })) - eq({ link = 'String' }, meths.get_hl(0, { name = '@string' })) - eq({ fg = 10937249 }, meths.get_hl(0, { name = '@string.cpp', link = false })) + eq({ fg = 10937249 }, api.nvim_get_hl(0, { name = 'String' })) + eq({ link = 'String' }, api.nvim_get_hl(0, { name = '@string' })) + eq({ fg = 10937249 }, api.nvim_get_hl(0, { name = '@string.cpp', link = false })) end) it('can get all attributes for a linked group', function() command('hi Bar guifg=red') command('hi Foo guifg=#00ff00 gui=bold,underline') command('hi! link Foo Bar') - eq({ link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true }, meths.get_hl(0, { name = 'Foo', link = true })) + eq( + { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true }, + api.nvim_get_hl(0, { name = 'Foo', link = true }) + ) end) it('can set link as well as other attributes', function() command('hi Bar guifg=red') local hl = { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, cterm = { bold = true } } - meths.set_hl(0, 'Foo', hl) - eq(hl, meths.get_hl(0, { name = 'Foo', link = true })) + api.nvim_set_hl(0, 'Foo', hl) + eq(hl, api.nvim_get_hl(0, { name = 'Foo', link = true })) end) it("doesn't contain unset groups", function() - local id = meths.get_hl_id_by_name "@foobar.hubbabubba" + local id = api.nvim_get_hl_id_by_name '@foobar.hubbabubba' ok(id > 0) - local data = meths.get_hl(0, {}) - eq(nil, data["@foobar.hubbabubba"]) - eq(nil, data["@foobar"]) + local data = api.nvim_get_hl(0, {}) + eq(nil, data['@foobar.hubbabubba']) + eq(nil, data['@foobar']) command 'hi @foobar.hubbabubba gui=bold' - data = meths.get_hl(0, {}) - eq({bold = true}, data["@foobar.hubbabubba"]) - eq(nil, data["@foobar"]) + data = api.nvim_get_hl(0, {}) + eq({ bold = true }, data['@foobar.hubbabubba']) + eq(nil, data['@foobar']) -- @foobar.hubbabubba was explicitly cleared and thus shows up -- but @foobar was never touched, and thus doesn't command 'hi clear @foobar.hubbabubba' - data = meths.get_hl(0, {}) - eq({}, data["@foobar.hubbabubba"]) - eq(nil, data["@foobar"]) + data = api.nvim_get_hl(0, {}) + eq({}, data['@foobar.hubbabubba']) + eq(nil, data['@foobar']) end) it('should return default flag', function() - meths.set_hl(0, 'Tried', { fg = "#00ff00", default = true }) - eq({ fg = tonumber('00ff00', 16), default = true }, meths.get_hl(0, { name = 'Tried' })) + api.nvim_set_hl(0, 'Tried', { fg = '#00ff00', default = true }) + eq({ fg = tonumber('00ff00', 16), default = true }, api.nvim_get_hl(0, { name = 'Tried' })) end) it('should not output empty gui and cterm #23474', function() - meths.set_hl(0, 'Foo', {default = true}) - meths.set_hl(0, 'Bar', { default = true, fg = '#ffffff' }) - meths.set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = {bold = true} }) - meths.set_hl(0, 'FooBarA', { default = true, fg = '#ffffff', cterm = {bold = true,italic = true}}) - - eq('Foo xxx cleared', - exec_capture('highlight Foo')) - eq({default = true}, meths.get_hl(0, {name = 'Foo'})) - eq('Bar xxx guifg=#ffffff', - exec_capture('highlight Bar')) - eq('FooBar xxx cterm=bold guifg=#ffffff', - exec_capture('highlight FooBar')) - eq('FooBarA xxx cterm=bold,italic guifg=#ffffff', - exec_capture('highlight FooBarA')) + api.nvim_set_hl(0, 'Foo', { default = true }) + api.nvim_set_hl(0, 'Bar', { default = true, fg = '#ffffff' }) + api.nvim_set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = { bold = true } }) + api.nvim_set_hl( + 0, + 'FooBarA', + { default = true, fg = '#ffffff', cterm = { bold = true, italic = true } } + ) + + eq('Foo xxx cleared', exec_capture('highlight Foo')) + eq({ default = true }, api.nvim_get_hl(0, { name = 'Foo' })) + eq('Bar xxx guifg=#ffffff', exec_capture('highlight Bar')) + eq('FooBar xxx cterm=bold guifg=#ffffff', exec_capture('highlight FooBar')) + eq('FooBarA xxx cterm=bold,italic guifg=#ffffff', exec_capture('highlight FooBarA')) end) it('can override exist highlight group by force #20323', function() local white = tonumber('ffffff', 16) local green = tonumber('00ff00', 16) - meths.set_hl(0, 'Foo', { fg=white }) - meths.set_hl(0, 'Foo', { fg=green, force = true }) - eq({ fg = green },meths.get_hl(0, {name = 'Foo'})) - meths.set_hl(0, 'Bar', {link = 'Comment', default = true}) - meths.set_hl(0, 'Bar', {link = 'Foo',default = true, force = true}) - eq({link ='Foo', default = true}, meths.get_hl(0, {name = 'Bar'})) + api.nvim_set_hl(0, 'Foo', { fg = white }) + api.nvim_set_hl(0, 'Foo', { fg = green, force = true }) + eq({ fg = green }, api.nvim_get_hl(0, { name = 'Foo' })) + api.nvim_set_hl(0, 'Bar', { link = 'Comment', default = true }) + api.nvim_set_hl(0, 'Bar', { link = 'Foo', default = true, force = true }) + eq({ link = 'Foo', default = true }, api.nvim_get_hl(0, { name = 'Bar' })) end) end) describe('API: set/get highlight namespace', function() it('set/get highlight namespace', function() - eq(0, meths.get_hl_ns({})) - local ns = meths.create_namespace('') - meths.set_hl_ns(ns) - eq(ns, meths.get_hl_ns({})) + eq(0, api.nvim_get_hl_ns({})) + local ns = api.nvim_create_namespace('') + api.nvim_set_hl_ns(ns) + eq(ns, api.nvim_get_hl_ns({})) end) it('set/get window highlight namespace', function() - eq(-1, meths.get_hl_ns({winid = 0})) - local ns = meths.create_namespace('') - meths.win_set_hl_ns(0, ns) - eq(ns, meths.get_hl_ns({winid = 0})) + eq(-1, api.nvim_get_hl_ns({ winid = 0 })) + local ns = api.nvim_create_namespace('') + api.nvim_win_set_hl_ns(0, ns) + eq(ns, api.nvim_get_hl_ns({ winid = 0 })) end) end) diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index 434f117956..0decd710e9 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -1,20 +1,18 @@ local helpers = require('test.functional.helpers')(after_each) -local bufmeths = helpers.bufmeths local clear = helpers.clear local command = helpers.command -local curbufmeths = helpers.curbufmeths local eq, neq = helpers.eq, helpers.neq local exec_lua = helpers.exec_lua local exec = helpers.exec local feed = helpers.feed -local funcs = helpers.funcs -local meths = helpers.meths +local fn = helpers.fn +local api = helpers.api local source = helpers.source local pcall_err = helpers.pcall_err local shallowcopy = helpers.shallowcopy -local sleep = helpers.sleep +local sleep = vim.uv.sleep local sid_api_client = -9 local sid_lua = -8 @@ -39,25 +37,25 @@ describe('nvim_get_keymap', function() -- Basic mapping and table to be used to describe results local foo_bar_string = 'nnoremap foo bar' local foo_bar_map_table = { - lhs='foo', - lhsraw='foo', - script=0, - silent=0, - rhs='bar', - expr=0, - sid=0, - scriptversion=1, - buffer=0, - nowait=0, - mode='n', - mode_bits=0x01, - abbr=0, - noremap=1, - lnum=0, + lhs = 'foo', + lhsraw = 'foo', + script = 0, + silent = 0, + rhs = 'bar', + expr = 0, + sid = 0, + scriptversion = 1, + buffer = 0, + nowait = 0, + mode = 'n', + mode_bits = 0x01, + abbr = 0, + noremap = 1, + lnum = 0, } it('returns empty list when no map', function() - eq({}, meths.get_keymap('n')) + eq({}, api.nvim_get_keymap('n')) end) it('returns list of all applicable mappings', function() @@ -66,10 +64,8 @@ describe('nvim_get_keymap', function() -- Should be the same as the dictionary we supplied earlier -- and the dictionary you would get from maparg -- since this is a global map, and not script local - eq({foo_bar_map_table}, meths.get_keymap('n')) - eq({funcs.maparg('foo', 'n', false, true)}, - meths.get_keymap('n') - ) + eq({ foo_bar_map_table }, api.nvim_get_keymap('n')) + eq({ fn.maparg('foo', 'n', false, true) }, api.nvim_get_keymap('n')) -- Add another mapping command('nnoremap foo_longer bar_longer') @@ -78,15 +74,11 @@ describe('nvim_get_keymap', function() foolong_bar_map_table['lhsraw'] = 'foo_longer' foolong_bar_map_table['rhs'] = 'bar_longer' - eq({foolong_bar_map_table, foo_bar_map_table}, - meths.get_keymap('n') - ) + eq({ foolong_bar_map_table, foo_bar_map_table }, api.nvim_get_keymap('n')) -- Remove a mapping command('unmap foo_longer') - eq({foo_bar_map_table}, - meths.get_keymap('n') - ) + eq({ foo_bar_map_table }, api.nvim_get_keymap('n')) end) it('works for other modes', function() @@ -100,7 +92,7 @@ describe('nvim_get_keymap', function() insert_table['mode'] = 'i' insert_table['mode_bits'] = 0x10 - eq({insert_table}, meths.get_keymap('i')) + eq({ insert_table }, api.nvim_get_keymap('i')) end) it('considers scope', function() @@ -117,8 +109,8 @@ describe('nvim_get_keymap', function() command('nnoremap <buffer> foo bar') -- The buffer mapping should not show up - eq({foolong_bar_map_table}, meths.get_keymap('n')) - eq({buffer_table}, curbufmeths.get_keymap('n')) + eq({ foolong_bar_map_table }, api.nvim_get_keymap('n')) + eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n')) end) it('considers scope for overlapping maps', function() @@ -129,12 +121,12 @@ describe('nvim_get_keymap', function() command('nnoremap <buffer> foo bar') - eq({foo_bar_map_table}, meths.get_keymap('n')) - eq({buffer_table}, curbufmeths.get_keymap('n')) + eq({ foo_bar_map_table }, api.nvim_get_keymap('n')) + eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n')) end) it('can retrieve mapping for different buffers', function() - local original_buffer = curbufmeths.get_number() + local original_buffer = api.nvim_buf_get_number(0) -- Place something in each of the buffers to make sure they stick around -- and set hidden so we can leave them command('set hidden') @@ -143,87 +135,124 @@ describe('nvim_get_keymap', function() command('new') command('normal! ihello 3') - local final_buffer = curbufmeths.get_number() + local final_buffer = api.nvim_buf_get_number(0) command('nnoremap <buffer> foo bar') -- Final buffer will have buffer mappings local buffer_table = shallowcopy(foo_bar_map_table) buffer_table['buffer'] = final_buffer - eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n')) - eq({buffer_table}, meths.buf_get_keymap(0, 'n')) + eq({ buffer_table }, api.nvim_buf_get_keymap(final_buffer, 'n')) + eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n')) command('buffer ' .. original_buffer) - eq(original_buffer, curbufmeths.get_number()) + eq(original_buffer, api.nvim_buf_get_number(0)) -- Original buffer won't have any mappings - eq({}, meths.get_keymap('n')) - eq({}, curbufmeths.get_keymap('n')) - eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n')) + eq({}, api.nvim_get_keymap('n')) + eq({}, api.nvim_buf_get_keymap(0, 'n')) + eq({ buffer_table }, api.nvim_buf_get_keymap(final_buffer, 'n')) end) -- Test toggle switches for basic options -- @param option The key represented in the `maparg()` result dict - local function global_and_buffer_test(map, - option, - option_token, - global_on_result, - buffer_on_result, - global_off_result, - buffer_off_result, - new_windows) - + local function global_and_buffer_test( + map, + option, + option_token, + global_on_result, + buffer_on_result, + global_off_result, + buffer_off_result, + new_windows + ) local function make_new_windows(number_of_windows) if new_windows == nil then return nil end - for _=1,number_of_windows do + for _ = 1, number_of_windows do command('new') end end - local mode = string.sub(map, 1,1) + local mode = string.sub(map, 1, 1) -- Don't run this for the <buffer> mapping, since it doesn't make sense if option_token ~= '<buffer>' then - it(string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)', - global_on_result, option, option_token, map, mode), function() - make_new_windows(new_windows) - command(map .. ' ' .. option_token .. ' foo bar') - local result = meths.get_keymap(mode)[1][option] - eq(global_on_result, result) - end) + it( + string.format( + 'returns %d for the key "%s" when %s is used globally with %s (%s)', + global_on_result, + option, + option_token, + map, + mode + ), + function() + make_new_windows(new_windows) + command(map .. ' ' .. option_token .. ' foo bar') + local result = api.nvim_get_keymap(mode)[1][option] + eq(global_on_result, result) + end + ) end - it(string.format('returns %d for the key "%s" when %s is used for buffers with %s (%s)', - buffer_on_result, option, option_token, map, mode), function() - make_new_windows(new_windows) - command(map .. ' <buffer> ' .. option_token .. ' foo bar') - local result = curbufmeths.get_keymap(mode)[1][option] - eq(buffer_on_result, result) - end) + it( + string.format( + 'returns %d for the key "%s" when %s is used for buffers with %s (%s)', + buffer_on_result, + option, + option_token, + map, + mode + ), + function() + make_new_windows(new_windows) + command(map .. ' <buffer> ' .. option_token .. ' foo bar') + local result = api.nvim_buf_get_keymap(0, mode)[1][option] + eq(buffer_on_result, result) + end + ) -- Don't run these for the <buffer> mapping, since it doesn't make sense if option_token ~= '<buffer>' then - it(string.format('returns %d for the key "%s" when %s is not used globally with %s (%s)', - global_off_result, option, option_token, map, mode), function() - make_new_windows(new_windows) - command(map .. ' baz bat') - local result = meths.get_keymap(mode)[1][option] - eq(global_off_result, result) - end) - - it(string.format('returns %d for the key "%s" when %s is not used for buffers with %s (%s)', - buffer_off_result, option, option_token, map, mode), function() - make_new_windows(new_windows) - command(map .. ' <buffer> foo bar') + it( + string.format( + 'returns %d for the key "%s" when %s is not used globally with %s (%s)', + global_off_result, + option, + option_token, + map, + mode + ), + function() + make_new_windows(new_windows) + command(map .. ' baz bat') + local result = api.nvim_get_keymap(mode)[1][option] + eq(global_off_result, result) + end + ) - local result = curbufmeths.get_keymap(mode)[1][option] - eq(buffer_off_result, result) - end) + it( + string.format( + 'returns %d for the key "%s" when %s is not used for buffers with %s (%s)', + buffer_off_result, + option, + option_token, + map, + mode + ), + function() + make_new_windows(new_windows) + command(map .. ' <buffer> foo bar') + + local result = api.nvim_buf_get_keymap(0, mode)[1][option] + eq(buffer_off_result, result) + end + ) end end -- Standard modes and returns the same values in the dictionary as maparg() - local mode_list = {'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap'} + local mode_list = { 'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap' } for mode in pairs(mode_list) do global_and_buffer_test(mode_list[mode], 'silent', '<silent>', 1, 1, 0, 0) global_and_buffer_test(mode_list[mode], 'nowait', '<nowait>', 1, 1, 0, 0) @@ -246,9 +275,9 @@ describe('nvim_get_keymap', function() nnoremap fizz :call <SID>maparg_test_function()<CR> ]]) - local sid_result = meths.get_keymap('n')[1]['sid'] + local sid_result = api.nvim_get_keymap('n')[1]['sid'] eq(1, sid_result) - eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) + eq('testing', api.nvim_call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) end) it('returns script numbers for buffer maps', function() @@ -259,29 +288,29 @@ describe('nvim_get_keymap', function() nnoremap <buffer> fizz :call <SID>maparg_test_function()<CR> ]]) - local sid_result = curbufmeths.get_keymap('n')[1]['sid'] + local sid_result = api.nvim_buf_get_keymap(0, 'n')[1]['sid'] eq(1, sid_result) - eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) + eq('testing', api.nvim_call_function('<SNR>' .. sid_result .. '_maparg_test_function', {})) end) it('works with <F12> and others', function() command('nnoremap <F12> :let g:maparg_test_var = 1<CR>') - eq('<F12>', meths.get_keymap('n')[1]['lhs']) - eq(':let g:maparg_test_var = 1<CR>', meths.get_keymap('n')[1]['rhs']) + eq('<F12>', api.nvim_get_keymap('n')[1]['lhs']) + eq(':let g:maparg_test_var = 1<CR>', api.nvim_get_keymap('n')[1]['rhs']) end) it('works correctly despite various &cpo settings', function() local cpo_table = { - script=0, - silent=0, - expr=0, - sid=0, - scriptversion=1, - buffer=0, - nowait=0, - abbr=0, - noremap=1, - lnum=0, + script = 0, + silent = 0, + expr = 0, + sid = 0, + scriptversion = 1, + buffer = 0, + nowait = 0, + abbr = 0, + noremap = 1, + lnum = 0, } local function cpomap(lhs, rhs, mode) local ret = shallowcopy(cpo_table) @@ -310,7 +339,7 @@ describe('nvim_get_keymap', function() -- wrapper around get_keymap() that drops "lhsraw" and "lhsrawalt" which are hard to check local function get_keymap_noraw(...) - local ret = meths.get_keymap(...) + local ret = api.nvim_get_keymap(...) for _, item in ipairs(ret) do item.lhsraw = nil item.lhsrawalt = nil @@ -323,103 +352,164 @@ describe('nvim_get_keymap', function() 'set cpo+=B', }) do command(cmd) - eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'), - cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')}, - get_keymap_noraw('n')) - eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), - cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')}, - get_keymap_noraw('x')) - eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'), - cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')}, - get_keymap_noraw('s')) - eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), - cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')}, - get_keymap_noraw('o')) + eq({ + cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'), + cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n'), + }, get_keymap_noraw('n')) + eq({ + cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), + cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x'), + }, get_keymap_noraw('x')) + eq({ + cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'), + cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's'), + }, get_keymap_noraw('s')) + eq({ + cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), + cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o'), + }, get_keymap_noraw('o')) end end) it('always uses space for space and bar for bar', function() local space_table = { - lhs='| |', - lhsraw='| |', - rhs='| |', - mode='n', - mode_bits=0x01, - abbr=0, - script=0, - silent=0, - expr=0, - sid=0, - scriptversion=1, - buffer=0, - nowait=0, - noremap=1, - lnum=0, + lhs = '| |', + lhsraw = '| |', + rhs = '| |', + mode = 'n', + mode_bits = 0x01, + abbr = 0, + script = 0, + silent = 0, + expr = 0, + sid = 0, + scriptversion = 1, + buffer = 0, + nowait = 0, + noremap = 1, + lnum = 0, } command('nnoremap \\|<Char-0x20><Char-32><Space><Bar> \\|<Char-0x20><Char-32><Space> <Bar>') - eq({space_table}, meths.get_keymap('n')) + eq({ space_table }, api.nvim_get_keymap('n')) end) it('can handle lua mappings', function() - eq(0, exec_lua([[ + eq( + 0, + exec_lua([[ GlobalCount = 0 vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]])) + ]]) + ) feed('asdf\n') eq(1, exec_lua([[return GlobalCount]])) - eq(2, exec_lua([[ + eq( + 2, + exec_lua([[ vim.api.nvim_get_keymap('n')[1].callback() return GlobalCount - ]])) + ]]) + ) exec([[ call nvim_get_keymap('n')[0].callback() ]]) eq(3, exec_lua([[return GlobalCount]])) - local mapargs = meths.get_keymap('n') + local mapargs = api.nvim_get_keymap('n') mapargs[1].callback = nil eq({ - lhs='asdf', - lhsraw='asdf', - script=0, - silent=0, - expr=0, - sid=sid_lua, - scriptversion=1, - buffer=0, - nowait=0, - mode='n', - mode_bits=0x01, - abbr=0, - noremap=0, - lnum=0, + lhs = 'asdf', + lhsraw = 'asdf', + script = 0, + silent = 0, + expr = 0, + sid = sid_lua, + scriptversion = 1, + buffer = 0, + nowait = 0, + mode = 'n', + mode_bits = 0x01, + abbr = 0, + noremap = 0, + lnum = 0, }, mapargs[1]) end) it('can handle map descriptions', function() - meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"}) + api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' }) eq({ - lhs='lhs', - lhsraw='lhs', - rhs='rhs', - script=0, - silent=0, - expr=0, - sid=sid_api_client, - scriptversion=1, - buffer=0, - nowait=0, - mode='n', - mode_bits=0x01, - abbr=0, - noremap=0, - lnum=0, - desc='map description' - }, meths.get_keymap('n')[1]) + lhs = 'lhs', + lhsraw = 'lhs', + rhs = 'rhs', + script = 0, + silent = 0, + expr = 0, + sid = sid_api_client, + scriptversion = 1, + buffer = 0, + nowait = 0, + mode = 'n', + mode_bits = 0x01, + abbr = 0, + noremap = 0, + lnum = 0, + desc = 'map description', + }, api.nvim_get_keymap('n')[1]) + end) + + it('can get abbreviations', function() + command('inoreabbr foo bar') + command('cnoreabbr <buffer> foo baz') + + local mapargs_i = { + abbr = 1, + buffer = 0, + expr = 0, + lhs = 'foo', + lhsraw = 'foo', + lnum = 0, + mode = 'i', + mode_bits = 0x10, + noremap = 1, + nowait = 0, + rhs = 'bar', + script = 0, + scriptversion = 1, + sid = 0, + silent = 0, + } + local mapargs_c = { + abbr = 1, + buffer = 1, + expr = 0, + lhs = 'foo', + lhsraw = 'foo', + lnum = 0, + mode = 'c', + mode_bits = 0x08, + noremap = 1, + nowait = 0, + rhs = 'baz', + script = 0, + scriptversion = 1, + sid = 0, + silent = 0, + } + + local curbuf = api.nvim_get_current_buf() + + eq({ mapargs_i }, api.nvim_get_keymap('ia')) + eq({}, api.nvim_buf_get_keymap(curbuf, 'ia')) + + eq({}, api.nvim_get_keymap('ca')) + eq({ mapargs_c }, api.nvim_buf_get_keymap(curbuf, 'ca')) + + eq({ mapargs_i }, api.nvim_get_keymap('!a')) + eq({ mapargs_c }, api.nvim_buf_get_keymap(curbuf, '!a')) end) end) @@ -472,7 +562,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function() -- Gets a maparg() dict from Nvim, if one exists. local function get_mapargs(mode, lhs) - local mapargs = funcs.maparg(lhs, normalize_mapmode(mode), mode:sub(-1) == 'a', true) + local mapargs = fn.maparg(lhs, normalize_mapmode(mode), mode:sub(-1) == 'a', true) -- drop "lhsraw" and "lhsrawalt" which are hard to check mapargs.lhsraw = nil mapargs.lhsrawalt = nil @@ -481,238 +571,239 @@ describe('nvim_set_keymap, nvim_del_keymap', function() it('error on empty LHS', function() -- escape parentheses in lua string, else comparison fails erroneously - eq('Invalid (empty) LHS', pcall_err(meths.set_keymap, '', '', 'rhs', {})) - eq('Invalid (empty) LHS', pcall_err(meths.set_keymap, '', '', '', {})) - eq('Invalid (empty) LHS', pcall_err(meths.del_keymap, '', '')) + eq('Invalid (empty) LHS', pcall_err(api.nvim_set_keymap, '', '', 'rhs', {})) + eq('Invalid (empty) LHS', pcall_err(api.nvim_set_keymap, '', '', '', {})) + eq('Invalid (empty) LHS', pcall_err(api.nvim_del_keymap, '', '')) end) it('error if LHS longer than MAXMAPLEN', function() -- assume MAXMAPLEN of 50 chars, as declared in mapping_defs.h local MAXMAPLEN = 50 local lhs = '' - for i=1,MAXMAPLEN do - lhs = lhs..(i % 10) + for i = 1, MAXMAPLEN do + lhs = lhs .. (i % 10) end -- exactly 50 chars should be fine - meths.set_keymap('', lhs, 'rhs', {}) + api.nvim_set_keymap('', lhs, 'rhs', {}) -- del_keymap should unmap successfully - meths.del_keymap('', lhs) + api.nvim_del_keymap('', lhs) eq({}, get_mapargs('', lhs)) -- 51 chars should produce an error - lhs = lhs..'1' - eq('LHS exceeds maximum map length: '..lhs, - pcall_err(meths.set_keymap, '', lhs, 'rhs', {})) - eq('LHS exceeds maximum map length: '..lhs, - pcall_err(meths.del_keymap, '', lhs)) + lhs = lhs .. '1' + eq( + 'LHS exceeds maximum map length: ' .. lhs, + pcall_err(api.nvim_set_keymap, '', lhs, 'rhs', {}) + ) + eq('LHS exceeds maximum map length: ' .. lhs, pcall_err(api.nvim_del_keymap, '', lhs)) end) it('does not throw errors when rhs is longer than MAXMAPLEN', function() local MAXMAPLEN = 50 local rhs = '' - for i=1,MAXMAPLEN do - rhs = rhs..(i % 10) + for i = 1, MAXMAPLEN do + rhs = rhs .. (i % 10) end - rhs = rhs..'1' - meths.set_keymap('', 'lhs', rhs, {}) - eq(generate_mapargs('', 'lhs', rhs), - get_mapargs('', 'lhs')) + rhs = rhs .. '1' + api.nvim_set_keymap('', 'lhs', rhs, {}) + eq(generate_mapargs('', 'lhs', rhs), get_mapargs('', 'lhs')) end) it('error on invalid mode shortname', function() - eq('Invalid mode shortname: " "', pcall_err(meths.set_keymap, ' ', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "m"', pcall_err(meths.set_keymap, 'm', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "?"', pcall_err(meths.set_keymap, '?', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "y"', pcall_err(meths.set_keymap, 'y', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "p"', pcall_err(meths.set_keymap, 'p', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "a"', pcall_err(meths.set_keymap, 'a', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "oa"', pcall_err(meths.set_keymap, 'oa', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "!o"', pcall_err(meths.set_keymap, '!o', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "!i"', pcall_err(meths.set_keymap, '!i', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "!!"', pcall_err(meths.set_keymap, '!!', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "map"', pcall_err(meths.set_keymap, 'map', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "vmap"', pcall_err(meths.set_keymap, 'vmap', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {})) - eq('Invalid mode shortname: " "', pcall_err(meths.del_keymap, ' ', 'lhs')) - eq('Invalid mode shortname: "m"', pcall_err(meths.del_keymap, 'm', 'lhs')) - eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs')) - eq('Invalid mode shortname: "y"', pcall_err(meths.del_keymap, 'y', 'lhs')) - eq('Invalid mode shortname: "p"', pcall_err(meths.del_keymap, 'p', 'lhs')) - eq('Invalid mode shortname: "a"', pcall_err(meths.del_keymap, 'a', 'lhs')) - eq('Invalid mode shortname: "oa"', pcall_err(meths.del_keymap, 'oa', 'lhs')) - eq('Invalid mode shortname: "!o"', pcall_err(meths.del_keymap, '!o', 'lhs')) - eq('Invalid mode shortname: "!i"', pcall_err(meths.del_keymap, '!i', 'lhs')) - eq('Invalid mode shortname: "!!"', pcall_err(meths.del_keymap, '!!', 'lhs')) - eq('Invalid mode shortname: "map"', pcall_err(meths.del_keymap, 'map', 'lhs')) - eq('Invalid mode shortname: "vmap"', pcall_err(meths.del_keymap, 'vmap', 'lhs')) - eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.del_keymap, 'xnoremap', 'lhs')) + eq('Invalid mode shortname: " "', pcall_err(api.nvim_set_keymap, ' ', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "m"', pcall_err(api.nvim_set_keymap, 'm', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "?"', pcall_err(api.nvim_set_keymap, '?', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "y"', pcall_err(api.nvim_set_keymap, 'y', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "p"', pcall_err(api.nvim_set_keymap, 'p', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "a"', pcall_err(api.nvim_set_keymap, 'a', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "oa"', pcall_err(api.nvim_set_keymap, 'oa', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "!o"', pcall_err(api.nvim_set_keymap, '!o', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "!i"', pcall_err(api.nvim_set_keymap, '!i', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "!!"', pcall_err(api.nvim_set_keymap, '!!', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "map"', pcall_err(api.nvim_set_keymap, 'map', 'lhs', 'rhs', {})) + eq('Invalid mode shortname: "vmap"', pcall_err(api.nvim_set_keymap, 'vmap', 'lhs', 'rhs', {})) + eq( + 'Invalid mode shortname: "xnoremap"', + pcall_err(api.nvim_set_keymap, 'xnoremap', 'lhs', 'rhs', {}) + ) + eq('Invalid mode shortname: " "', pcall_err(api.nvim_del_keymap, ' ', 'lhs')) + eq('Invalid mode shortname: "m"', pcall_err(api.nvim_del_keymap, 'm', 'lhs')) + eq('Invalid mode shortname: "?"', pcall_err(api.nvim_del_keymap, '?', 'lhs')) + eq('Invalid mode shortname: "y"', pcall_err(api.nvim_del_keymap, 'y', 'lhs')) + eq('Invalid mode shortname: "p"', pcall_err(api.nvim_del_keymap, 'p', 'lhs')) + eq('Invalid mode shortname: "a"', pcall_err(api.nvim_del_keymap, 'a', 'lhs')) + eq('Invalid mode shortname: "oa"', pcall_err(api.nvim_del_keymap, 'oa', 'lhs')) + eq('Invalid mode shortname: "!o"', pcall_err(api.nvim_del_keymap, '!o', 'lhs')) + eq('Invalid mode shortname: "!i"', pcall_err(api.nvim_del_keymap, '!i', 'lhs')) + eq('Invalid mode shortname: "!!"', pcall_err(api.nvim_del_keymap, '!!', 'lhs')) + eq('Invalid mode shortname: "map"', pcall_err(api.nvim_del_keymap, 'map', 'lhs')) + eq('Invalid mode shortname: "vmap"', pcall_err(api.nvim_del_keymap, 'vmap', 'lhs')) + eq('Invalid mode shortname: "xnoremap"', pcall_err(api.nvim_del_keymap, 'xnoremap', 'lhs')) end) it('error on invalid optnames', function() - eq("Invalid key: 'silentt'", - pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true})) - eq("Invalid key: 'sidd'", - pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {sidd = false})) - eq("Invalid key: 'nowaiT'", - pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {nowaiT = false})) + eq( + "Invalid key: 'silentt'", + pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { silentt = true }) + ) + eq("Invalid key: 'sidd'", pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { sidd = false })) + eq( + "Invalid key: 'nowaiT'", + pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { nowaiT = false }) + ) end) it('error on <buffer> option key', function() - eq("Invalid key: 'buffer'", - pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true})) + eq( + "Invalid key: 'buffer'", + pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { buffer = true }) + ) end) it('error when "replace_keycodes" is used without "expr"', function() - eq('"replace_keycodes" requires "expr"', - pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {replace_keycodes = true})) + eq( + '"replace_keycodes" requires "expr"', + pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { replace_keycodes = true }) + ) end) - local optnames = {'nowait', 'silent', 'script', 'expr', 'unique'} + local optnames = { 'nowait', 'silent', 'script', 'expr', 'unique' } for _, opt in ipairs(optnames) do -- note: need '%' to escape hyphens, which have special meaning in lua - it('throws an error when given non-boolean value for '..opt, function() + it('throws an error when given non-boolean value for ' .. opt, function() local opts = {} opts[opt] = 'fooo' - eq(opt..' is not a boolean', - pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts)) + eq(opt .. ' is not a boolean', pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', opts)) end) end -- Perform tests of basic functionality it('sets ordinary mappings', function() - meths.set_keymap('n', 'lhs', 'rhs', {}) + api.nvim_set_keymap('n', 'lhs', 'rhs', {}) eq(generate_mapargs('n', 'lhs', 'rhs'), get_mapargs('n', 'lhs')) - meths.set_keymap('v', 'lhs', 'rhs', {}) + api.nvim_set_keymap('v', 'lhs', 'rhs', {}) eq(generate_mapargs('v', 'lhs', 'rhs'), get_mapargs('v', 'lhs')) end) it('does not throw when LHS or RHS have leading/trailing whitespace', function() - meths.set_keymap('n', ' lhs', 'rhs', {}) - eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'), - get_mapargs('n', ' lhs')) + api.nvim_set_keymap('n', ' lhs', 'rhs', {}) + eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'), get_mapargs('n', ' lhs')) - meths.set_keymap('n', 'lhs ', 'rhs', {}) - eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'), - get_mapargs('n', 'lhs ')) + api.nvim_set_keymap('n', 'lhs ', 'rhs', {}) + eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'), get_mapargs('n', 'lhs ')) - meths.set_keymap('v', ' lhs ', '\trhs\t\f', {}) - eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'), - get_mapargs('v', ' lhs ')) + api.nvim_set_keymap('v', ' lhs ', '\trhs\t\f', {}) + eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'), get_mapargs('v', ' lhs ')) end) it('can set noremap mappings', function() - meths.set_keymap('x', 'lhs', 'rhs', {noremap = true}) - eq(generate_mapargs('x', 'lhs', 'rhs', {noremap = true}), - get_mapargs('x', 'lhs')) + api.nvim_set_keymap('x', 'lhs', 'rhs', { noremap = true }) + eq(generate_mapargs('x', 'lhs', 'rhs', { noremap = true }), get_mapargs('x', 'lhs')) - meths.set_keymap('t', 'lhs', 'rhs', {noremap = true}) - eq(generate_mapargs('t', 'lhs', 'rhs', {noremap = true}), - get_mapargs('t', 'lhs')) + api.nvim_set_keymap('t', 'lhs', 'rhs', { noremap = true }) + eq(generate_mapargs('t', 'lhs', 'rhs', { noremap = true }), get_mapargs('t', 'lhs')) end) it('can unmap mappings', function() - meths.set_keymap('v', 'lhs', 'rhs', {}) - meths.del_keymap('v', 'lhs') + api.nvim_set_keymap('v', 'lhs', 'rhs', {}) + api.nvim_del_keymap('v', 'lhs') eq({}, get_mapargs('v', 'lhs')) - meths.set_keymap('t', 'lhs', 'rhs', {noremap = true}) - meths.del_keymap('t', 'lhs') + api.nvim_set_keymap('t', 'lhs', 'rhs', { noremap = true }) + api.nvim_del_keymap('t', 'lhs') eq({}, get_mapargs('t', 'lhs')) end) -- Test some edge cases it('"!" and empty string are synonyms for mapmode-nvo', function() - local nvo_shortnames = {'', '!'} + local nvo_shortnames = { '', '!' } for _, name in ipairs(nvo_shortnames) do - meths.set_keymap(name, 'lhs', 'rhs', {}) - meths.del_keymap(name, 'lhs') + api.nvim_set_keymap(name, 'lhs', 'rhs', {}) + api.nvim_del_keymap(name, 'lhs') eq({}, get_mapargs(name, 'lhs')) end end) - local special_chars = {'<C-U>', '<S-Left>', '<F12><F2><Tab>', '<Space><Tab>'} + local special_chars = { '<C-U>', '<S-Left>', '<F12><F2><Tab>', '<Space><Tab>' } for _, lhs in ipairs(special_chars) do for _, rhs in ipairs(special_chars) do local mapmode = '!' - it('can set mappings with special characters, lhs: '..lhs..', rhs: '..rhs, - function() - meths.set_keymap(mapmode, lhs, rhs, {}) + it('can set mappings with special characters, lhs: ' .. lhs .. ', rhs: ' .. rhs, function() + api.nvim_set_keymap(mapmode, lhs, rhs, {}) eq(generate_mapargs(mapmode, lhs, rhs), get_mapargs(mapmode, lhs)) end) end end it('can set mappings containing literal keycodes', function() - meths.set_keymap('n', '\n\r\n', 'rhs', {}) + api.nvim_set_keymap('n', '\n\r\n', 'rhs', {}) local expected = generate_mapargs('n', '<NL><CR><NL>', 'rhs') eq(expected, get_mapargs('n', '<NL><CR><NL>')) end) it('can set mappings whose RHS is a <Nop>', function() - meths.set_keymap('i', 'lhs', '<Nop>', {}) + api.nvim_set_keymap('i', 'lhs', '<Nop>', {}) command('normal ilhs') - eq({''}, curbufmeths.get_lines(0, -1, 0)) -- imap to <Nop> does nothing - eq(generate_mapargs('i', 'lhs', '<Nop>', {}), - get_mapargs('i', 'lhs')) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0)) -- imap to <Nop> does nothing + eq(generate_mapargs('i', 'lhs', '<Nop>', {}), get_mapargs('i', 'lhs')) -- also test for case insensitivity - meths.set_keymap('i', 'lhs', '<nOp>', {}) + api.nvim_set_keymap('i', 'lhs', '<nOp>', {}) command('normal ilhs') - eq({''}, curbufmeths.get_lines(0, -1, 0)) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0)) -- note: RHS in returned mapargs() dict reflects the original RHS -- provided by the user - eq(generate_mapargs('i', 'lhs', '<nOp>', {}), - get_mapargs('i', 'lhs')) + eq(generate_mapargs('i', 'lhs', '<nOp>', {}), get_mapargs('i', 'lhs')) - meths.set_keymap('i', 'lhs', '<NOP>', {}) + api.nvim_set_keymap('i', 'lhs', '<NOP>', {}) command('normal ilhs') - eq({''}, curbufmeths.get_lines(0, -1, 0)) - eq(generate_mapargs('i', 'lhs', '<NOP>', {}), - get_mapargs('i', 'lhs')) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0)) + eq(generate_mapargs('i', 'lhs', '<NOP>', {}), get_mapargs('i', 'lhs')) -- a single ^V in RHS is also <Nop> (see :h map-empty-rhs) - meths.set_keymap('i', 'lhs', '\022', {}) + api.nvim_set_keymap('i', 'lhs', '\022', {}) command('normal ilhs') - eq({''}, curbufmeths.get_lines(0, -1, 0)) - eq(generate_mapargs('i', 'lhs', '\022', {}), - get_mapargs('i', 'lhs')) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0)) + eq(generate_mapargs('i', 'lhs', '\022', {}), get_mapargs('i', 'lhs')) end) it('treats an empty RHS in a mapping like a <Nop>', function() - meths.set_keymap('i', 'lhs', '', {}) + api.nvim_set_keymap('i', 'lhs', '', {}) command('normal ilhs') - eq({''}, curbufmeths.get_lines(0, -1, 0)) - eq(generate_mapargs('i', 'lhs', '', {}), - get_mapargs('i', 'lhs')) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0)) + eq(generate_mapargs('i', 'lhs', '', {}), get_mapargs('i', 'lhs')) end) it('can set and unset <M-">', function() -- Taken from the legacy test: test_mapping.vim. Exposes a bug in which -- replace_termcodes changes the length of the mapping's LHS, but -- do_map continues to use the *old* length of LHS. - meths.set_keymap('i', '<M-">', 'foo', {}) - meths.del_keymap('i', '<M-">') + api.nvim_set_keymap('i', '<M-">', 'foo', {}) + api.nvim_del_keymap('i', '<M-">') eq({}, get_mapargs('i', '<M-">')) end) - it('interprets control sequences in expr-quotes correctly when called ' - ..'inside vim', function() - command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]]) - eq(generate_mapargs('i', '<Space>', '\t', {sid=0}), - get_mapargs('i', '<Space>')) - feed('i ') - eq({'\t'}, curbufmeths.get_lines(0, -1, 0)) - end) + it( + 'interprets control sequences in expr-quotes correctly when called ' .. 'inside vim', + function() + command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]]) + eq(generate_mapargs('i', '<Space>', '\t', { sid = 0 }), get_mapargs('i', '<Space>')) + feed('i ') + eq({ '\t' }, api.nvim_buf_get_lines(0, 0, -1, 0)) + end + ) it('throws appropriate error messages when setting <unique> maps', function() - meths.set_keymap('l', 'lhs', 'rhs', {}) - eq('E227: mapping already exists for lhs', - pcall_err(meths.set_keymap, 'l', 'lhs', 'rhs', {unique = true})) + api.nvim_set_keymap('l', 'lhs', 'rhs', {}) + eq( + 'E227: mapping already exists for lhs', + pcall_err(api.nvim_set_keymap, 'l', 'lhs', 'rhs', { unique = true }) + ) -- different mapmode, no error should be thrown - meths.set_keymap('t', 'lhs', 'rhs', {unique = true}) + api.nvim_set_keymap('t', 'lhs', 'rhs', { unique = true }) end) it('can set <expr> mappings whose RHS change dynamically', function() @@ -723,50 +814,50 @@ describe('nvim_set_keymap, nvim_del_keymap', function() return g:flip endfunction ]]) - eq(1, meths.call_function('FlipFlop', {})) - eq(0, meths.call_function('FlipFlop', {})) - eq(1, meths.call_function('FlipFlop', {})) - eq(0, meths.call_function('FlipFlop', {})) + eq(1, api.nvim_call_function('FlipFlop', {})) + eq(0, api.nvim_call_function('FlipFlop', {})) + eq(1, api.nvim_call_function('FlipFlop', {})) + eq(0, api.nvim_call_function('FlipFlop', {})) - meths.set_keymap('i', 'lhs', 'FlipFlop()', {expr = true}) + api.nvim_set_keymap('i', 'lhs', 'FlipFlop()', { expr = true }) command('normal ilhs') - eq({'1'}, curbufmeths.get_lines(0, -1, 0)) + eq({ '1' }, api.nvim_buf_get_lines(0, 0, -1, 0)) command('normal! ggVGd') command('normal ilhs') - eq({'0'}, curbufmeths.get_lines(0, -1, 0)) + eq({ '0' }, api.nvim_buf_get_lines(0, 0, -1, 0)) end) it('can set mappings that do trigger other mappings', function() - meths.set_keymap('i', 'mhs', 'rhs', {}) - meths.set_keymap('i', 'lhs', 'mhs', {}) + api.nvim_set_keymap('i', 'mhs', 'rhs', {}) + api.nvim_set_keymap('i', 'lhs', 'mhs', {}) command('normal imhs') - eq({'rhs'}, curbufmeths.get_lines(0, -1, 0)) + eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, -1, 0)) command('normal! ggVGd') command('normal ilhs') - eq({'rhs'}, curbufmeths.get_lines(0, -1, 0)) + eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, -1, 0)) end) it("can set noremap mappings that don't trigger other mappings", function() - meths.set_keymap('i', 'mhs', 'rhs', {}) - meths.set_keymap('i', 'lhs', 'mhs', {noremap = true}) + api.nvim_set_keymap('i', 'mhs', 'rhs', {}) + api.nvim_set_keymap('i', 'lhs', 'mhs', { noremap = true }) command('normal imhs') - eq({'rhs'}, curbufmeths.get_lines(0, -1, 0)) + eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, -1, 0)) command('normal! ggVGd') - command('normal ilhs') -- shouldn't trigger mhs-to-rhs mapping - eq({'mhs'}, curbufmeths.get_lines(0, -1, 0)) + command('normal ilhs') -- shouldn't trigger mhs-to-rhs mapping + eq({ 'mhs' }, api.nvim_buf_get_lines(0, 0, -1, 0)) end) - it("can set nowait mappings that fire without waiting", function() - meths.set_keymap('i', '123456', 'longer', {}) - meths.set_keymap('i', '123', 'shorter', {nowait = true}) + it('can set nowait mappings that fire without waiting', function() + api.nvim_set_keymap('i', '123456', 'longer', {}) + api.nvim_set_keymap('i', '123', 'shorter', { nowait = true }) -- feed keys one at a time; if all keys arrive atomically, the longer -- mapping will trigger @@ -775,84 +866,99 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed(c) sleep(5) end - eq({'shorter456'}, curbufmeths.get_lines(0, -1, 0)) + eq({ 'shorter456' }, api.nvim_buf_get_lines(0, 0, -1, 0)) end) -- Perform exhaustive tests of basic functionality - local mapmodes = {'n', 'v', 'x', 's', 'o', '!', 'i', 'l', 'c', 't', '', 'ia', 'ca', '!a'} + local mapmodes = { 'n', 'v', 'x', 's', 'o', '!', 'i', 'l', 'c', 't', '', 'ia', 'ca', '!a' } for _, mapmode in ipairs(mapmodes) do - it('can set/unset normal mappings in mapmode '..mapmode, function() - meths.set_keymap(mapmode, 'lhs', 'rhs', {}) - eq(generate_mapargs(mapmode, 'lhs', 'rhs'), - get_mapargs(mapmode, 'lhs')) + it('can set/unset normal mappings in mapmode ' .. mapmode, function() + api.nvim_set_keymap(mapmode, 'lhs', 'rhs', {}) + eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs')) -- some mapmodes (like 'o') will prevent other mapmodes (like '!') from -- taking effect, so unmap after each mapping - meths.del_keymap(mapmode, 'lhs') + api.nvim_del_keymap(mapmode, 'lhs') eq({}, get_mapargs(mapmode, 'lhs')) end) end for _, mapmode in ipairs(mapmodes) do - it('can set/unset noremap mappings using mapmode '..mapmode, function() - meths.set_keymap(mapmode, 'lhs', 'rhs', {noremap = true}) - eq(generate_mapargs(mapmode, 'lhs', 'rhs', {noremap = true}), - get_mapargs(mapmode, 'lhs')) + it('can set/unset noremap mappings using mapmode ' .. mapmode, function() + api.nvim_set_keymap(mapmode, 'lhs', 'rhs', { noremap = true }) + eq(generate_mapargs(mapmode, 'lhs', 'rhs', { noremap = true }), get_mapargs(mapmode, 'lhs')) - meths.del_keymap(mapmode, 'lhs') + api.nvim_del_keymap(mapmode, 'lhs') eq({}, get_mapargs(mapmode, 'lhs')) end) end -- Test map-arguments, using optnames from above -- remove some map arguments that are harder to test, or were already tested - optnames = {'nowait', 'silent', 'expr', 'noremap'} + optnames = { 'nowait', 'silent', 'expr', 'noremap' } for _, mapmode in ipairs(mapmodes) do -- Test with single mappings for _, maparg in ipairs(optnames) do - it('can set/unset '..mapmode..'-mappings with maparg: '..maparg, - function() - meths.set_keymap(mapmode, 'lhs', 'rhs', {[maparg] = true}) - eq(generate_mapargs(mapmode, 'lhs', 'rhs', {[maparg] = true}), - get_mapargs(mapmode, 'lhs')) - meths.del_keymap(mapmode, 'lhs') - eq({}, get_mapargs(mapmode, 'lhs')) - end) - it ('can set/unset '..mapmode..'-mode mappings with maparg '.. - maparg..', whose value is false', function() - meths.set_keymap(mapmode, 'lhs', 'rhs', {[maparg] = false}) - eq(generate_mapargs(mapmode, 'lhs', 'rhs'), - get_mapargs(mapmode, 'lhs')) - meths.del_keymap(mapmode, 'lhs') + it('can set/unset ' .. mapmode .. '-mappings with maparg: ' .. maparg, function() + api.nvim_set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = true }) + eq( + generate_mapargs(mapmode, 'lhs', 'rhs', { [maparg] = true }), + get_mapargs(mapmode, 'lhs') + ) + api.nvim_del_keymap(mapmode, 'lhs') eq({}, get_mapargs(mapmode, 'lhs')) end) + it( + 'can set/unset ' + .. mapmode + .. '-mode mappings with maparg ' + .. maparg + .. ', whose value is false', + function() + api.nvim_set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = false }) + eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs')) + api.nvim_del_keymap(mapmode, 'lhs') + eq({}, get_mapargs(mapmode, 'lhs')) + end + ) end -- Test with triplets of mappings, one of which is false for i = 1, (#optnames - 2) do local opt1, opt2, opt3 = optnames[i], optnames[i + 1], optnames[i + 2] - it('can set/unset '..mapmode..'-mode mappings with mapargs '.. - opt1..', '..opt2..', '..opt3, function() - local opts = {[opt1] = true, [opt2] = false, [opt3] = true} - meths.set_keymap(mapmode, 'lhs', 'rhs', opts) - eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts), - get_mapargs(mapmode, 'lhs')) - meths.del_keymap(mapmode, 'lhs') - eq({}, get_mapargs(mapmode, 'lhs')) - end) + it( + 'can set/unset ' + .. mapmode + .. '-mode mappings with mapargs ' + .. opt1 + .. ', ' + .. opt2 + .. ', ' + .. opt3, + function() + local opts = { [opt1] = true, [opt2] = false, [opt3] = true } + api.nvim_set_keymap(mapmode, 'lhs', 'rhs', opts) + eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts), get_mapargs(mapmode, 'lhs')) + api.nvim_del_keymap(mapmode, 'lhs') + eq({}, get_mapargs(mapmode, 'lhs')) + end + ) end end it('can make lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) end) it(':map command shows lua mapping correctly', function() @@ -861,8 +967,8 @@ describe('nvim_set_keymap, nvim_del_keymap', function() ]] assert.truthy( string.match( - exec_lua[[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]], - "^\nn asdf <Lua %d+>" + exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]], + '^\nn asdf <Lua %d+>' ) ) end) @@ -871,29 +977,34 @@ describe('nvim_set_keymap, nvim_del_keymap', function() exec_lua [[ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end }) ]] - assert.truthy(string.match(funcs.mapcheck('asdf', 'n'), - "^<Lua %d+>")) + assert.truthy(string.match(fn.mapcheck('asdf', 'n'), '^<Lua %d+>')) end) it('maparg() returns lua mapping correctly', function() - eq(0, exec_lua([[ + eq( + 0, + exec_lua([[ GlobalCount = 0 vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]])) + ]]) + ) - assert.truthy(string.match(funcs.maparg('asdf', 'n'), "^<Lua %d+>")) + assert.truthy(string.match(fn.maparg('asdf', 'n'), '^<Lua %d+>')) - local mapargs = funcs.maparg('asdf', 'n', false, true) + local mapargs = fn.maparg('asdf', 'n', false, true) mapargs.callback = nil mapargs.lhsraw = nil mapargs.lhsrawalt = nil - eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs) + eq(generate_mapargs('n', 'asdf', nil, { sid = sid_lua }), mapargs) - eq(1, exec_lua([[ + eq( + 1, + exec_lua([[ vim.fn.maparg('asdf', 'n', false, true).callback() return GlobalCount - ]])) + ]]) + ) exec([[ call maparg('asdf', 'n', v:false, v:true).callback() @@ -908,7 +1019,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed('aa') - eq({'π<M-π>foo<'}, meths.buf_get_lines(0, 0, -1, false)) + eq({ 'π<M-π>foo<' }, api.nvim_buf_get_lines(0, 0, -1, false)) end) it('can make lua expr mappings without replacing keycodes', function() @@ -918,7 +1029,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed('iaa<esc>') - eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false)) + eq({ '<space>' }, api.nvim_buf_get_lines(0, 0, -1, false)) end) it('lua expr mapping returning nil is equivalent to returning an empty string', function() @@ -928,41 +1039,50 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed('iaa<esc>') - eq({''}, meths.buf_get_lines(0, 0, -1, false)) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false)) end) it('does not reset pum in lua mapping', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ VisibleCount = 0 vim.api.nvim_set_keymap('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end}) return VisibleCount - ]]) + ]] + ) feed('i<C-X><C-V><F2><F2><esc>') - eq(2, exec_lua[[return VisibleCount]]) + eq(2, exec_lua [[return VisibleCount]]) end) it('redo of lua mappings in op-pending mode work', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ OpCount = 0 vim.api.nvim_set_keymap('o', '<F2>', '', {callback = function() OpCount = OpCount + 1 end}) return OpCount - ]]) + ]] + ) feed('d<F2>') - eq(1, exec_lua[[return OpCount]]) + eq(1, exec_lua [[return OpCount]]) feed('.') - eq(2, exec_lua[[return OpCount]]) + eq(2, exec_lua [[return OpCount]]) end) it('can overwrite lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end }) @@ -970,19 +1090,22 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed('asdf\n') - eq(0, exec_lua[[return GlobalCount]]) + eq(0, exec_lua [[return GlobalCount]]) end) it('can unmap lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ vim.api.nvim_del_keymap('n', 'asdf' ) @@ -990,20 +1113,23 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) eq('\nNo mapping found', helpers.exec_capture('nmap asdf')) end) it('no double-free when unmapping simplifiable lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_set_keymap('n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('<C-I>\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ vim.api.nvim_del_keymap('n', '<C-I>') @@ -1011,15 +1137,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function() feed('<C-I>\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) eq('\nNo mapping found', helpers.exec_capture('nmap <C-I>')) end) it('can set descriptions on mappings', function() - meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"}) - eq(generate_mapargs('n', 'lhs', 'rhs', {desc="map description"}), get_mapargs('n', 'lhs')) - eq("\nn lhs rhs\n map description", - helpers.exec_capture("nmap lhs")) + api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' }) + eq(generate_mapargs('n', 'lhs', 'rhs', { desc = 'map description' }), get_mapargs('n', 'lhs')) + eq('\nn lhs rhs\n map description', helpers.exec_capture('nmap lhs')) end) it('can define !-mode abbreviations with lua callbacks', function() @@ -1032,10 +1157,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function() ]] feed 'iThe foo and the bar and the foo again<esc>' - eq('The 1 and the bar and the 2 again', meths.get_current_line()) + eq('The 1 and the bar and the 2 again', api.nvim_get_current_line()) feed ':let x = "The foo is the one"<cr>' - eq('The 3 is the one', meths.eval'x') + eq('The 3 is the one', api.nvim_eval 'x') end) it('can define insert mode abbreviations with lua callbacks', function() @@ -1048,10 +1173,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function() ]] feed 'iThe foo and the bar and the foo again<esc>' - eq('The 1 and the bar and the 2 again', meths.get_current_line()) + eq('The 1 and the bar and the 2 again', api.nvim_get_current_line()) feed ':let x = "The foo is the one"<cr>' - eq('The foo is the one', meths.eval'x') + eq('The foo is the one', api.nvim_eval 'x') end) it('can define cmdline mode abbreviations with lua callbacks', function() @@ -1064,10 +1189,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function() ]] feed 'iThe foo and the bar and the foo again<esc>' - eq('The foo and the bar and the foo again', meths.get_current_line()) + eq('The foo and the bar and the foo again', api.nvim_get_current_line()) feed ':let x = "The foo is the one"<cr>' - eq('The 1 is the one', meths.eval'x') + eq('The 1 is the one', api.nvim_eval 'x') end) end) @@ -1081,7 +1206,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() -- switch to the given buffer, abandoning any changes in the current buffer local function switch_to_buf(bufnr) - command(bufnr..'buffer!') + command(bufnr .. 'buffer!') end -- `set hidden`, then create two buffers and return their bufnr's @@ -1090,10 +1215,10 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() local function make_two_buffers(start_from_first) command('set hidden') - local first_buf = meths.call_function('bufnr', {'%'}) + local first_buf = api.nvim_call_function('bufnr', { '%' }) command('new') - local second_buf = meths.call_function('bufnr', {'%'}) - neq(second_buf, first_buf) -- sanity check + local second_buf = api.nvim_call_function('bufnr', { '%' }) + neq(second_buf, first_buf) -- sanity check if start_from_first then switch_to_buf(first_buf) @@ -1103,80 +1228,84 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() end it('rejects negative bufnr values', function() - eq('Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer', - pcall_err(bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {})) + eq( + 'Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer', + pcall_err(api.nvim_buf_set_keymap, -1, '', 'lhs', 'rhs', {}) + ) end) it('can set mappings active in the current buffer but not others', function() local first, second = make_two_buffers(true) - bufmeths.set_keymap(0, '', 'lhs', 'irhs<Esc>', {}) + api.nvim_buf_set_keymap(0, '', 'lhs', 'irhs<Esc>', {}) command('normal lhs') - eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, 1, 1)) -- mapping should have no effect in new buffer switch_to_buf(second) command('normal lhs') - eq({''}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ '' }, api.nvim_buf_get_lines(0, 0, 1, 1)) -- mapping should remain active in old buffer switch_to_buf(first) command('normal ^lhs') - eq({'rhsrhs'}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ 'rhsrhs' }, api.nvim_buf_get_lines(0, 0, 1, 1)) end) it('can set local mappings in buffer other than current', function() local first = make_two_buffers(false) - bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) + api.nvim_buf_set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) -- shouldn't do anything command('normal lhs') - eq({''}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ '' }, api.nvim_buf_get_lines(0, 0, 1, 1)) -- should take effect switch_to_buf(first) command('normal lhs') - eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, 1, 1)) end) it('can disable mappings made in another buffer, inside that buffer', function() local first = make_two_buffers(false) - bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) - bufmeths.del_keymap(first, '', 'lhs') + api.nvim_buf_set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) + api.nvim_buf_del_keymap(first, '', 'lhs') switch_to_buf(first) -- shouldn't do anything command('normal lhs') - eq({''}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ '' }, api.nvim_buf_get_lines(0, 0, 1, 1)) end) it("can't disable mappings given wrong buffer handle", function() local first, second = make_two_buffers(false) - bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) - eq('E31: No such mapping', - pcall_err(bufmeths.del_keymap, second, '', 'lhs')) + api.nvim_buf_set_keymap(first, '', 'lhs', 'irhs<Esc>', {}) + eq('E31: No such mapping', pcall_err(api.nvim_buf_del_keymap, second, '', 'lhs')) -- should still work switch_to_buf(first) command('normal lhs') - eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1)) + eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, 1, 1)) end) - it("does not crash when setting mapping in a non-existing buffer #13541", function() - pcall_err(bufmeths.set_keymap, 100, '', 'lsh', 'irhs<Esc>', {}) + it('does not crash when setting mapping in a non-existing buffer #13541', function() + pcall_err(api.nvim_buf_set_keymap, 100, '', 'lsh', 'irhs<Esc>', {}) helpers.assert_alive() end) it('can make lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) end) it('can make lua expr mappings replacing keycodes', function() @@ -1186,7 +1315,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() feed('aa') - eq({'π<M-π>foo<'}, meths.buf_get_lines(0, 0, -1, false)) + eq({ 'π<M-π>foo<' }, api.nvim_buf_get_lines(0, 0, -1, false)) end) it('can make lua expr mappings without replacing keycodes', function() @@ -1196,20 +1325,22 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() feed('iaa<esc>') - eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false)) + eq({ '<space>' }, api.nvim_buf_get_lines(0, 0, -1, false)) end) - it('can overwrite lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end }) @@ -1217,19 +1348,22 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() feed('asdf\n') - eq(0, exec_lua[[return GlobalCount]]) + eq(0, exec_lua [[return GlobalCount]]) end) it('can unmap lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ vim.api.nvim_buf_del_keymap(0, 'n', 'asdf' ) @@ -1237,20 +1371,23 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() feed('asdf\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) eq('\nNo mapping found', helpers.exec_capture('nmap asdf')) end) it('no double-free when unmapping simplifiable lua mappings', function() - eq(0, exec_lua [[ + eq( + 0, + exec_lua [[ GlobalCount = 0 vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end }) return GlobalCount - ]]) + ]] + ) feed('<C-I>\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) exec_lua [[ vim.api.nvim_buf_del_keymap(0, 'n', '<C-I>') @@ -1258,7 +1395,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function() feed('<C-I>\n') - eq(1, exec_lua[[return GlobalCount]]) + eq(1, exec_lua [[return GlobalCount]]) eq('\nNo mapping found', helpers.exec_capture('nmap <C-I>')) end) end) diff --git a/test/functional/api/menu_spec.lua b/test/functional/api/menu_spec.lua index 34a92477f3..44b9039393 100644 --- a/test/functional/api/menu_spec.lua +++ b/test/functional/api/menu_spec.lua @@ -5,8 +5,7 @@ local clear = helpers.clear local command = helpers.command local feed = helpers.feed -describe("update_menu notification", function() - +describe('update_menu notification', function() local screen before_each(function() @@ -16,23 +15,26 @@ describe("update_menu notification", function() end) local function expect_sent(expected) - screen:expect{condition=function() - if screen.update_menu ~= expected then - if expected then - error('update_menu was expected but not sent') - else - error('update_menu was sent unexpectedly') + screen:expect { + condition = function() + if screen.update_menu ~= expected then + if expected then + error('update_menu was expected but not sent') + else + error('update_menu was sent unexpectedly') + end end - end - end, unchanged=(not expected)} + end, + unchanged = not expected, + } end - it("should be sent when adding a menu", function() + it('should be sent when adding a menu', function() command('menu Test.Test :') expect_sent(true) end) - it("should be sent when deleting a menu", function() + it('should be sent when deleting a menu', function() command('menu Test.Test :') screen.update_menu = false @@ -40,9 +42,8 @@ describe("update_menu notification", function() expect_sent(true) end) - it("should not be sent unnecessarily", function() + it('should not be sent unnecessarily', function() feed('i12345<ESC>:redraw<CR>') expect_sent(false) end) - end) diff --git a/test/functional/api/proc_spec.lua b/test/functional/api/proc_spec.lua index 20edea3feb..50c441792c 100644 --- a/test/functional/api/proc_spec.lua +++ b/test/functional/api/proc_spec.lua @@ -2,12 +2,12 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq -local funcs = helpers.funcs +local fn = helpers.fn local neq = helpers.neq local nvim_argv = helpers.nvim_argv local request = helpers.request local retry = helpers.retry -local NIL = helpers.NIL +local NIL = vim.NIL local is_os = helpers.is_os describe('API', function() @@ -15,44 +15,44 @@ describe('API', function() describe('nvim_get_proc_children', function() it('returns child process ids', function() - local this_pid = funcs.getpid() + local this_pid = fn.getpid() -- Might be non-zero already (left-over from some other test?), -- but this is not what is tested here. local initial_children = request('nvim_get_proc_children', this_pid) - local job1 = funcs.jobstart(nvim_argv) + local job1 = fn.jobstart(nvim_argv) retry(nil, nil, function() eq(#initial_children + 1, #request('nvim_get_proc_children', this_pid)) end) - local job2 = funcs.jobstart(nvim_argv) + local job2 = fn.jobstart(nvim_argv) retry(nil, nil, function() eq(#initial_children + 2, #request('nvim_get_proc_children', this_pid)) end) - funcs.jobstop(job1) + fn.jobstop(job1) retry(nil, nil, function() eq(#initial_children + 1, #request('nvim_get_proc_children', this_pid)) end) - funcs.jobstop(job2) + fn.jobstop(job2) retry(nil, nil, function() eq(#initial_children, #request('nvim_get_proc_children', this_pid)) end) end) it('validation', function() - local status, rv = pcall(request, "nvim_get_proc_children", -1) + local status, rv = pcall(request, 'nvim_get_proc_children', -1) eq(false, status) - eq("Invalid 'pid': -1", string.match(rv, "Invalid.*")) + eq("Invalid 'pid': -1", string.match(rv, 'Invalid.*')) - status, rv = pcall(request, "nvim_get_proc_children", 0) + status, rv = pcall(request, 'nvim_get_proc_children', 0) eq(false, status) - eq("Invalid 'pid': 0", string.match(rv, "Invalid.*")) + eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*')) -- Assume PID 99999 does not exist. - status, rv = pcall(request, "nvim_get_proc_children", 99999) + status, rv = pcall(request, 'nvim_get_proc_children', 99999) eq(true, status) eq({}, rv) end) @@ -60,7 +60,7 @@ describe('API', function() describe('nvim_get_proc', function() it('returns process info', function() - local pid = funcs.getpid() + local pid = fn.getpid() local pinfo = request('nvim_get_proc', pid) eq((is_os('win') and 'nvim.exe' or 'nvim'), pinfo.name) eq(pid, pinfo.pid) @@ -69,16 +69,16 @@ describe('API', function() end) it('validation', function() - local status, rv = pcall(request, "nvim_get_proc", -1) + local status, rv = pcall(request, 'nvim_get_proc', -1) eq(false, status) - eq("Invalid 'pid': -1", string.match(rv, "Invalid.*")) + eq("Invalid 'pid': -1", string.match(rv, 'Invalid.*')) - status, rv = pcall(request, "nvim_get_proc", 0) + status, rv = pcall(request, 'nvim_get_proc', 0) eq(false, status) - eq("Invalid 'pid': 0", string.match(rv, "Invalid.*")) + eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*')) -- Assume PID 99999 does not exist. - status, rv = pcall(request, "nvim_get_proc", 99999) + status, rv = pcall(request, 'nvim_get_proc', 99999) eq(true, status) eq(NIL, rv) end) diff --git a/test/functional/api/rpc_fixture.lua b/test/functional/api/rpc_fixture.lua index c860a6da59..050d439a1b 100644 --- a/test/functional/api/rpc_fixture.lua +++ b/test/functional/api/rpc_fixture.lua @@ -4,8 +4,8 @@ package.path = arg[1] package.cpath = arg[2] -local StdioStream = require'test.client.uv_stream'.StdioStream -local Session = require'test.client.session' +local StdioStream = require 'test.client.uv_stream'.StdioStream +local Session = require 'test.client.session' local stdio_stream = StdioStream.open() local session = Session.new(stdio_stream) @@ -15,8 +15,8 @@ local function on_request(method, args) return 'ok' elseif method == 'write_stderr' then io.stderr:write(args[1]) - return "done!" - elseif method == "exit" then + return 'done!' + elseif method == 'exit' then session:stop() return vim.NIL end @@ -24,7 +24,7 @@ end local function on_notification(event, args) if event == 'ping' and #args == 0 then - session:notify("nvim_eval", "rpcnotify(g:channel, 'pong')") + session:notify('nvim_eval', "rpcnotify(g:channel, 'pong')") end end diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua index bc43f6564d..d1608a951c 100644 --- a/test/functional/api/server_notifications_spec.lua +++ b/test/functional/api/server_notifications_spec.lua @@ -1,9 +1,8 @@ local helpers = require('test.functional.helpers')(after_each) local assert_log = helpers.assert_log -local eq, clear, eval, command, nvim, next_msg = - helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim, - helpers.next_msg -local meths = helpers.meths +local eq, clear, eval, command, next_msg = + helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.next_msg +local api = helpers.api local exec_lua = helpers.exec_lua local retry = helpers.retry local assert_alive = helpers.assert_alive @@ -15,7 +14,7 @@ describe('notify', function() before_each(function() clear() - channel = nvim('get_api_info')[1] + channel = api.nvim_get_chan_info(0).id end) after_each(function() @@ -24,34 +23,34 @@ describe('notify', function() describe('passing a valid channel id', function() it('sends the notification/args to the corresponding channel', function() - eval('rpcnotify('..channel..', "test-event", 1, 2, 3)') - eq({'notification', 'test-event', {1, 2, 3}}, next_msg()) - command('au FileType lua call rpcnotify('..channel..', "lua!")') + eval('rpcnotify(' .. channel .. ', "test-event", 1, 2, 3)') + eq({ 'notification', 'test-event', { 1, 2, 3 } }, next_msg()) + command('au FileType lua call rpcnotify(' .. channel .. ', "lua!")') command('set filetype=lua') - eq({'notification', 'lua!', {}}, next_msg()) + eq({ 'notification', 'lua!', {} }, next_msg()) end) end) describe('passing 0 as the channel id', function() it('sends the notification/args to all subscribed channels', function() - nvim('subscribe', 'event2') + api.nvim_subscribe('event2') eval('rpcnotify(0, "event1", 1, 2, 3)') eval('rpcnotify(0, "event2", 4, 5, 6)') eval('rpcnotify(0, "event2", 7, 8, 9)') - eq({'notification', 'event2', {4, 5, 6}}, next_msg()) - eq({'notification', 'event2', {7, 8, 9}}, next_msg()) - nvim('unsubscribe', 'event2') - nvim('subscribe', 'event1') + eq({ 'notification', 'event2', { 4, 5, 6 } }, next_msg()) + eq({ 'notification', 'event2', { 7, 8, 9 } }, next_msg()) + api.nvim_unsubscribe('event2') + api.nvim_subscribe('event1') eval('rpcnotify(0, "event2", 10, 11, 12)') eval('rpcnotify(0, "event1", 13, 14, 15)') - eq({'notification', 'event1', {13, 14, 15}}, next_msg()) + eq({ 'notification', 'event1', { 13, 14, 15 } }, next_msg()) end) it('does not crash for deeply nested variable', function() - meths.set_var('l', {}) + api.nvim_set_var('l', {}) local nest_level = 1000 - meths.command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1)) - eval('rpcnotify('..channel..', "event", g:l)') + command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1)) + eval('rpcnotify(' .. channel .. ', "event", g:l)') local msg = next_msg() eq('notification', msg[1]) eq('event', msg[2]) @@ -77,27 +76,37 @@ describe('notify', function() end) it('unsubscribe non-existing event #8745', function() - clear{env={ - NVIM_LOG_FILE=testlog, - }} - nvim('subscribe', 'event1') - nvim('unsubscribe', 'doesnotexist') + clear { env = { + NVIM_LOG_FILE = testlog, + } } + api.nvim_subscribe('event1') + api.nvim_unsubscribe('doesnotexist') assert_log("tried to unsubscribe unknown event 'doesnotexist'", testlog, 10) - nvim('unsubscribe', 'event1') + api.nvim_unsubscribe('event1') assert_alive() end) it('cancels stale events on channel close', function() local catchan = eval("jobstart(['cat'], {'rpc': v:true})") local catpath = eval('exepath("cat")') - eq({id=catchan, argv={catpath}, stream='job', mode='rpc', client = {}}, exec_lua ([[ + eq( + { id = catchan, argv = { catpath }, stream = 'job', mode = 'rpc', client = {} }, + exec_lua( + [[ vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'}) vim.rpcnotify(..., "nvim_subscribe", "daily_rant") return vim.api.nvim_get_chan_info(...) - ]], catchan)) + ]], + catchan + ) + ) assert_alive() - eq({false, 'Invalid channel: '..catchan}, - exec_lua ([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan)) - retry(nil, 3000, function() eq({}, meths.get_chan_info(catchan)) end) -- cat be dead :( + eq( + { false, 'Invalid channel: ' .. catchan }, + exec_lua([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan) + ) + retry(nil, 3000, function() + eq({}, api.nvim_get_chan_info(catchan)) + end) -- cat be dead :( end) end) diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 1ad4ad3a02..298dbac217 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -2,12 +2,12 @@ -- `rpcrequest` calls we need the client event loop to be running. local helpers = require('test.functional.helpers')(after_each) -local clear, nvim, eval = helpers.clear, helpers.nvim, helpers.eval +local clear, eval = helpers.clear, helpers.eval local eq, neq, run, stop = helpers.eq, helpers.neq, helpers.run, helpers.stop -local nvim_prog, command, funcs = helpers.nvim_prog, helpers.command, helpers.funcs +local nvim_prog, command, fn = helpers.nvim_prog, helpers.command, helpers.fn local source, next_msg = helpers.source, helpers.next_msg local ok = helpers.ok -local meths = helpers.meths +local api = helpers.api local spawn, merge_args = helpers.spawn, helpers.merge_args local set_session = helpers.set_session local pcall_err = helpers.pcall_err @@ -18,18 +18,18 @@ describe('server -> client', function() before_each(function() clear() - cid = nvim('get_api_info')[1] + cid = api.nvim_get_chan_info(0).id end) it('handles unexpected closed stream while preparing RPC response', function() source([[ let g:_nvim_args = [v:progpath, '--embed', '--headless', '-n', '-u', 'NONE', '-i', 'NONE', ] let ch1 = jobstart(g:_nvim_args, {'rpc': v:true}) - let child1_ch = rpcrequest(ch1, "nvim_get_api_info")[0] + let child1_ch = rpcrequest(ch1, "nvim_get_chan_info", 0).id call rpcnotify(ch1, 'nvim_eval', 'rpcrequest('.child1_ch.', "nvim_get_api_info")') let ch2 = jobstart(g:_nvim_args, {'rpc': v:true}) - let child2_ch = rpcrequest(ch2, "nvim_get_api_info")[0] + let child2_ch = rpcrequest(ch2, "nvim_get_chan_info", 0).id call rpcnotify(ch2, 'nvim_eval', 'rpcrequest('.child2_ch.', "nvim_get_api_info")') call jobstop(ch1) @@ -40,14 +40,14 @@ describe('server -> client', function() describe('simple call', function() it('works', function() local function on_setup() - eq({4, 5, 6}, eval('rpcrequest('..cid..', "scall", 1, 2, 3)')) + eq({ 4, 5, 6 }, eval('rpcrequest(' .. cid .. ', "scall", 1, 2, 3)')) stop() end local function on_request(method, args) eq('scall', method) - eq({1, 2, 3}, args) - nvim('command', 'let g:result = [4, 5, 6]') + eq({ 1, 2, 3 }, args) + command('let g:result = [4, 5, 6]') return eval('g:result') end run(on_request, nil, on_setup) @@ -61,14 +61,14 @@ describe('server -> client', function() -- elements following the empty string. it('works', function() local function on_setup() - eq({1, 2, '', 3, 'asdf'}, eval('rpcrequest('..cid..', "nstring")')) + eq({ 1, 2, '', 3, 'asdf' }, eval('rpcrequest(' .. cid .. ', "nstring")')) stop() end local function on_request() -- No need to evaluate the args, we are only interested in -- a response that contains an array with an empty string. - return {1, 2, '', 3, 'asdf'} + return { 1, 2, '', 3, 'asdf' } end run(on_request, nil, on_setup) end) @@ -77,15 +77,15 @@ describe('server -> client', function() describe('recursive call', function() it('works', function() local function on_setup() - nvim('set_var', 'result1', 0) - nvim('set_var', 'result2', 0) - nvim('set_var', 'result3', 0) - nvim('set_var', 'result4', 0) - nvim('command', 'let g:result1 = rpcrequest('..cid..', "rcall", 2)') - eq(4, nvim('get_var', 'result1')) - eq(8, nvim('get_var', 'result2')) - eq(16, nvim('get_var', 'result3')) - eq(32, nvim('get_var', 'result4')) + api.nvim_set_var('result1', 0) + api.nvim_set_var('result2', 0) + api.nvim_set_var('result3', 0) + api.nvim_set_var('result4', 0) + command('let g:result1 = rpcrequest(' .. cid .. ', "rcall", 2)') + eq(4, api.nvim_get_var('result1')) + eq(8, api.nvim_get_var('result2')) + eq(16, api.nvim_get_var('result3')) + eq(32, api.nvim_get_var('result4')) stop() end @@ -95,13 +95,13 @@ describe('server -> client', function() if n <= 16 then local cmd if n == 4 then - cmd = 'let g:result2 = rpcrequest('..cid..', "rcall", '..n..')' + cmd = 'let g:result2 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' elseif n == 8 then - cmd = 'let g:result3 = rpcrequest('..cid..', "rcall", '..n..')' + cmd = 'let g:result3 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' elseif n == 16 then - cmd = 'let g:result4 = rpcrequest('..cid..', "rcall", '..n..')' + cmd = 'let g:result4 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')' end - nvim('command', cmd) + command(cmd) end return n end @@ -113,18 +113,18 @@ describe('server -> client', function() it('does not delay notifications during pending request', function() local received = false local function on_setup() - eq("retval", funcs.rpcrequest(cid, "doit")) + eq('retval', fn.rpcrequest(cid, 'doit')) stop() end local function on_request(method) - if method == "doit" then - funcs.rpcnotify(cid, "headsup") - eq(true,received) - return "retval" + if method == 'doit' then + fn.rpcnotify(cid, 'headsup') + eq(true, received) + return 'retval' end end local function on_notification(method) - if method == "headsup" then + if method == 'headsup' then received = true end end @@ -148,28 +148,28 @@ describe('server -> client', function() -- of nvim's request stack). pending('will close connection if not properly synchronized', function() local function on_setup() - eq('notified!', eval('rpcrequest('..cid..', "notify")')) + eq('notified!', eval('rpcrequest(' .. cid .. ', "notify")')) end local function on_request(method) - if method == "notify" then - eq(1, eval('rpcnotify('..cid..', "notification")')) + if method == 'notify' then + eq(1, eval('rpcnotify(' .. cid .. ', "notification")')) return 'notified!' - elseif method == "nested" then + elseif method == 'nested' then -- do some busywork, so the first request will return -- before this one for _ = 1, 5 do assert_alive() end - eq(1, eval('rpcnotify('..cid..', "nested_done")')) + eq(1, eval('rpcnotify(' .. cid .. ', "nested_done")')) return 'done!' end end local function on_notification(method) - if method == "notification" then - eq('done!', eval('rpcrequest('..cid..', "nested")')) - elseif method == "nested_done" then + if method == 'notification' then + eq('done!', eval('rpcrequest(' .. cid .. ', "nested")')) + elseif method == 'nested_done' then ok(false, 'never sent', 'sent') end end @@ -182,49 +182,57 @@ describe('server -> client', function() describe('recursive (child) nvim client', function() before_each(function() - command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])") + command( + "let vim = rpcstart('" + .. nvim_prog + .. "', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])" + ) neq(0, eval('vim')) end) - after_each(function() command('call rpcstop(vim)') end) + after_each(function() + command('call rpcstop(vim)') + end) it('can send/receive notifications and make requests', function() - nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')") + command("call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')") -- Wait for the notification to complete. - nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") + command("call rpcrequest(vim, 'vim_eval', '0')") eq('SOME TEXT', eval("rpcrequest(vim, 'vim_get_current_line')")) end) it('can communicate buffers, tabpages, and windows', function() - eq({1}, eval("rpcrequest(vim, 'nvim_list_tabpages')")) + eq({ 1 }, eval("rpcrequest(vim, 'nvim_list_tabpages')")) -- Window IDs start at 1000 (LOWEST_WIN_ID in window.h) - eq({1000}, eval("rpcrequest(vim, 'nvim_list_wins')")) + eq({ 1000 }, eval("rpcrequest(vim, 'nvim_list_wins')")) local buf = eval("rpcrequest(vim, 'nvim_list_bufs')")[1] eq(1, buf) - eval("rpcnotify(vim, 'buffer_set_line', "..buf..", 0, 'SOME TEXT')") - nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") -- wait + eval("rpcnotify(vim, 'buffer_set_line', " .. buf .. ", 0, 'SOME TEXT')") + command("call rpcrequest(vim, 'vim_eval', '0')") -- wait - eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', "..buf..", 0)")) + eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', " .. buf .. ', 0)')) -- Call get_lines(buf, range [0,0], strict_indexing) - eq({'SOME TEXT'}, eval("rpcrequest(vim, 'buffer_get_lines', "..buf..", 0, 1, 1)")) + eq({ 'SOME TEXT' }, eval("rpcrequest(vim, 'buffer_get_lines', " .. buf .. ', 0, 1, 1)')) end) it('returns an error if the request failed', function() - eq("Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist", - pcall_err(eval, "rpcrequest(vim, 'does-not-exist')")) + eq( + "Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist", + pcall_err(eval, "rpcrequest(vim, 'does-not-exist')") + ) end) end) describe('jobstart()', function() local jobid before_each(function() - local channel = nvim('get_api_info')[1] - nvim('set_var', 'channel', channel) + local channel = api.nvim_get_chan_info(0).id + api.nvim_set_var('channel', channel) source([[ function! s:OnEvent(id, data, event) call rpcnotify(g:channel, a:event, 0, a:data) @@ -236,64 +244,67 @@ describe('server -> client', function() \ 'rpc': v:true \ } ]]) - meths.set_var("args", { - nvim_prog, '-ll', + api.nvim_set_var('args', { + nvim_prog, + '-ll', 'test/functional/api/rpc_fixture.lua', package.path, package.cpath, }) - jobid = eval("jobstart(g:args, g:job_opts)") + jobid = eval('jobstart(g:args, g:job_opts)') neq(0, jobid) end) after_each(function() - pcall(funcs.jobstop, jobid) + pcall(fn.jobstop, jobid) end) - if helpers.skip(helpers.is_os('win')) then return end + if helpers.skip(helpers.is_os('win')) then + return + end it('rpc and text stderr can be combined', function() - local status, rv = pcall(funcs.rpcrequest, jobid, 'poll') + local status, rv = pcall(fn.rpcrequest, jobid, 'poll') if not status then error(string.format('missing nvim Lua module? (%s)', rv)) end eq('ok', rv) - funcs.rpcnotify(jobid, "ping") - eq({'notification', 'pong', {}}, next_msg()) - eq("done!",funcs.rpcrequest(jobid, "write_stderr", "fluff\n")) - eq({'notification', 'stderr', {0, {'fluff', ''}}}, next_msg()) - pcall(funcs.rpcrequest, jobid, "exit") - eq({'notification', 'stderr', {0, {''}}}, next_msg()) - eq({'notification', 'exit', {0, 0}}, next_msg()) + fn.rpcnotify(jobid, 'ping') + eq({ 'notification', 'pong', {} }, next_msg()) + eq('done!', fn.rpcrequest(jobid, 'write_stderr', 'fluff\n')) + eq({ 'notification', 'stderr', { 0, { 'fluff', '' } } }, next_msg()) + pcall(fn.rpcrequest, jobid, 'exit') + eq({ 'notification', 'stderr', { 0, { '' } } }, next_msg()) + eq({ 'notification', 'exit', { 0, 0 } }, next_msg()) end) end) describe('connecting to another (peer) nvim', function() - local nvim_argv = merge_args(helpers.nvim_argv, {'--headless'}) + local nvim_argv = merge_args(helpers.nvim_argv, { '--headless' }) local function connect_test(server, mode, address) - local serverpid = funcs.getpid() + local serverpid = fn.getpid() local client = spawn(nvim_argv, false, nil, true) set_session(client) - local clientpid = funcs.getpid() + local clientpid = fn.getpid() neq(serverpid, clientpid) - local id = funcs.sockconnect(mode, address, {rpc=true}) + local id = fn.sockconnect(mode, address, { rpc = true }) ok(id > 0) - funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') - local client_id = funcs.rpcrequest(id, 'nvim_get_api_info')[1] + fn.rpcrequest(id, 'nvim_set_current_line', 'hello') + local client_id = fn.rpcrequest(id, 'nvim_get_chan_info', 0).id set_session(server) - eq(serverpid, funcs.getpid()) - eq('hello', meths.get_current_line()) + eq(serverpid, fn.getpid()) + eq('hello', api.nvim_get_current_line()) -- method calls work both ways - funcs.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!') - eq(id, funcs.rpcrequest(client_id, 'nvim_get_api_info')[1]) + fn.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!') + eq(id, fn.rpcrequest(client_id, 'nvim_get_chan_info', 0).id) set_session(client) - eq(clientpid, funcs.getpid()) - eq('howdy!', meths.get_current_line()) + eq(clientpid, fn.getpid()) + eq('howdy!', api.nvim_get_current_line()) server:close() client:close() @@ -302,8 +313,8 @@ describe('server -> client', function() it('via named pipe', function() local server = spawn(nvim_argv) set_session(server) - local address = funcs.serverlist()[1] - local first = string.sub(address,1,1) + local address = fn.serverlist()[1] + local first = string.sub(address, 1, 1) ok(first == '/' or first == '\\') connect_test(server, 'pipe', address) end) @@ -311,42 +322,42 @@ describe('server -> client', function() it('via ipv4 address', function() local server = spawn(nvim_argv) set_session(server) - local status, address = pcall(funcs.serverstart, "127.0.0.1:") + local status, address = pcall(fn.serverstart, '127.0.0.1:') if not status then pending('no ipv4 stack') end - eq('127.0.0.1:', string.sub(address,1,10)) + eq('127.0.0.1:', string.sub(address, 1, 10)) connect_test(server, 'tcp', address) end) it('via ipv6 address', function() local server = spawn(nvim_argv) set_session(server) - local status, address = pcall(funcs.serverstart, '::1:') + local status, address = pcall(fn.serverstart, '::1:') if not status then pending('no ipv6 stack') end - eq('::1:', string.sub(address,1,4)) + eq('::1:', string.sub(address, 1, 4)) connect_test(server, 'tcp', address) end) it('via hostname', function() local server = spawn(nvim_argv) set_session(server) - local address = funcs.serverstart("localhost:") - eq('localhost:', string.sub(address,1,10)) + local address = fn.serverstart('localhost:') + eq('localhost:', string.sub(address, 1, 10)) connect_test(server, 'tcp', address) end) it('does not crash on receiving UI events', function() local server = spawn(nvim_argv) set_session(server) - local address = funcs.serverlist()[1] + local address = fn.serverlist()[1] local client = spawn(nvim_argv, false, nil, true) set_session(client) - local id = funcs.sockconnect('pipe', address, {rpc=true}) - funcs.rpcrequest(id, 'nvim_ui_attach', 80, 24, {}) + local id = fn.sockconnect('pipe', address, { rpc = true }) + fn.rpcrequest(id, 'nvim_ui_attach', 80, 24, {}) assert_alive() server:close() @@ -356,18 +367,18 @@ describe('server -> client', function() describe('connecting to its own pipe address', function() it('does not deadlock', function() - local address = funcs.serverlist()[1] - local first = string.sub(address,1,1) + local address = fn.serverlist()[1] + local first = string.sub(address, 1, 1) ok(first == '/' or first == '\\') - local serverpid = funcs.getpid() + local serverpid = fn.getpid() - local id = funcs.sockconnect('pipe', address, {rpc=true}) + local id = fn.sockconnect('pipe', address, { rpc = true }) - funcs.rpcrequest(id, 'nvim_set_current_line', 'hello') - eq('hello', meths.get_current_line()) - eq(serverpid, funcs.rpcrequest(id, "nvim_eval", "getpid()")) + fn.rpcrequest(id, 'nvim_set_current_line', 'hello') + eq('hello', api.nvim_get_current_line()) + eq(serverpid, fn.rpcrequest(id, 'nvim_eval', 'getpid()')) - eq(id, funcs.rpcrequest(id, 'nvim_get_api_info')[1]) + eq(id, fn.rpcrequest(id, 'nvim_get_chan_info', 0).id) end) end) end) diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua index 20b3163d95..36955c4ace 100644 --- a/test/functional/api/tabpage_spec.lua +++ b/test/functional/api/tabpage_spec.lua @@ -1,11 +1,9 @@ local helpers = require('test.functional.helpers')(after_each) -local clear, nvim, tabpage, curtab, eq, ok = - helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, - helpers.ok -local curtabmeths = helpers.curtabmeths -local funcs = helpers.funcs +local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok +local api = helpers.api +local fn = helpers.fn local request = helpers.request -local NIL = helpers.NIL +local NIL = vim.NIL local pcall_err = helpers.pcall_err local command = helpers.command @@ -14,48 +12,108 @@ describe('api/tabpage', function() describe('list_wins and get_win', function() it('works', function() - nvim('command', 'tabnew') - nvim('command', 'vsplit') - local tab1, tab2 = unpack(nvim('list_tabpages')) - local win1, win2, win3 = unpack(nvim('list_wins')) - eq({win1}, tabpage('list_wins', tab1)) - eq({win2, win3}, tabpage('list_wins', tab2)) - eq(win2, tabpage('get_win', tab2)) - nvim('set_current_win', win3) - eq(win3, tabpage('get_win', tab2)) + command('tabnew') + command('vsplit') + local tab1, tab2 = unpack(api.nvim_list_tabpages()) + local win1, win2, win3 = unpack(api.nvim_list_wins()) + eq({ win1 }, api.nvim_tabpage_list_wins(tab1)) + eq(win1, api.nvim_tabpage_get_win(tab1)) + eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2)) + eq(win2, api.nvim_tabpage_get_win(tab2)) + api.nvim_set_current_win(win3) + eq(win3, api.nvim_tabpage_get_win(tab2)) + command('tabprev') + eq(win1, api.nvim_tabpage_get_win(tab1)) + eq(win3, api.nvim_tabpage_get_win(tab2)) end) it('validates args', function() - eq('Invalid tabpage id: 23', pcall_err(tabpage, 'list_wins', 23)) + eq('Invalid tabpage id: 23', pcall_err(api.nvim_tabpage_list_wins, 23)) + end) + end) + + describe('set_win', function() + it('works', function() + command('tabnew') + command('vsplit') + local tab1, tab2 = unpack(api.nvim_list_tabpages()) + local win1, win2, win3 = unpack(api.nvim_list_wins()) + eq({ win1 }, api.nvim_tabpage_list_wins(tab1)) + eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2)) + eq(win2, api.nvim_tabpage_get_win(tab2)) + api.nvim_tabpage_set_win(tab2, win3) + eq(win3, api.nvim_tabpage_get_win(tab2)) + end) + + it('works in non-current tabpages', function() + command('tabnew') + command('vsplit') + local tab1, tab2 = unpack(api.nvim_list_tabpages()) + local win1, win2, win3 = unpack(api.nvim_list_wins()) + eq({ win1 }, api.nvim_tabpage_list_wins(tab1)) + eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2)) + eq(win2, api.nvim_tabpage_get_win(tab2)) + eq(win2, api.nvim_get_current_win()) + + command('tabprev') + + eq(tab1, api.nvim_get_current_tabpage()) + + eq(win2, api.nvim_tabpage_get_win(tab2)) + api.nvim_tabpage_set_win(tab2, win3) + eq(win3, api.nvim_tabpage_get_win(tab2)) + + command('tabnext') + eq(win3, api.nvim_get_current_win()) + end) + + it('throws an error when the window does not belong to the tabpage', function() + command('tabnew') + command('vsplit') + local tab1, tab2 = unpack(api.nvim_list_tabpages()) + local win1, win2, win3 = unpack(api.nvim_list_wins()) + eq({ win1 }, api.nvim_tabpage_list_wins(tab1)) + eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2)) + eq(win2, api.nvim_get_current_win()) + + eq( + string.format('Window does not belong to tabpage %d', tab2), + pcall_err(api.nvim_tabpage_set_win, tab2, win1) + ) + + eq( + string.format('Window does not belong to tabpage %d', tab1), + pcall_err(api.nvim_tabpage_set_win, tab1, win3) + ) end) end) describe('{get,set,del}_var', function() it('works', function() - curtab('set_var', 'lua', {1, 2, {['3'] = 1}}) - eq({1, 2, {['3'] = 1}}, curtab('get_var', 'lua')) - eq({1, 2, {['3'] = 1}}, nvim('eval', 't:lua')) - eq(1, funcs.exists('t:lua')) - curtabmeths.del_var('lua') - eq(0, funcs.exists('t:lua')) - eq('Key not found: lua', pcall_err(curtabmeths.del_var, 'lua')) - curtabmeths.set_var('lua', 1) + api.nvim_tabpage_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } }) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_tabpage_get_var(0, 'lua')) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('t:lua')) + eq(1, fn.exists('t:lua')) + api.nvim_tabpage_del_var(0, 'lua') + eq(0, fn.exists('t:lua')) + eq('Key not found: lua', pcall_err(api.nvim_tabpage_del_var, 0, 'lua')) + api.nvim_tabpage_set_var(0, 'lua', 1) command('lockvar t:lua') - eq('Key is locked: lua', pcall_err(curtabmeths.del_var, 'lua')) - eq('Key is locked: lua', pcall_err(curtabmeths.set_var, 'lua', 1)) + eq('Key is locked: lua', pcall_err(api.nvim_tabpage_del_var, 0, 'lua')) + eq('Key is locked: lua', pcall_err(api.nvim_tabpage_set_var, 0, 'lua', 1)) end) it('tabpage_set_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } eq(NIL, request('tabpage_set_var', 0, 'lua', val1)) eq(val1, request('tabpage_set_var', 0, 'lua', val2)) end) it('tabpage_del_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} - eq(NIL, request('tabpage_set_var', 0, 'lua', val1)) + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } + eq(NIL, request('tabpage_set_var', 0, 'lua', val1)) eq(val1, request('tabpage_set_var', 0, 'lua', val2)) eq(val2, request('tabpage_del_var', 0, 'lua')) end) @@ -63,28 +121,28 @@ describe('api/tabpage', function() describe('get_number', function() it('works', function() - local tabs = nvim('list_tabpages') - eq(1, tabpage('get_number', tabs[1])) + local tabs = api.nvim_list_tabpages() + eq(1, api.nvim_tabpage_get_number(tabs[1])) - nvim('command', 'tabnew') - local tab1, tab2 = unpack(nvim('list_tabpages')) - eq(1, tabpage('get_number', tab1)) - eq(2, tabpage('get_number', tab2)) + command('tabnew') + local tab1, tab2 = unpack(api.nvim_list_tabpages()) + eq(1, api.nvim_tabpage_get_number(tab1)) + eq(2, api.nvim_tabpage_get_number(tab2)) - nvim('command', '-tabmove') - eq(2, tabpage('get_number', tab1)) - eq(1, tabpage('get_number', tab2)) + command('-tabmove') + eq(2, api.nvim_tabpage_get_number(tab1)) + eq(1, api.nvim_tabpage_get_number(tab2)) end) end) describe('is_valid', function() it('works', function() - nvim('command', 'tabnew') - local tab = nvim('list_tabpages')[2] - nvim('set_current_tabpage', tab) - ok(tabpage('is_valid', tab)) - nvim('command', 'tabclose') - ok(not tabpage('is_valid', tab)) + command('tabnew') + local tab = api.nvim_list_tabpages()[2] + api.nvim_set_current_tabpage(tab) + ok(api.nvim_tabpage_is_valid(tab)) + command('tabclose') + ok(not api.nvim_tabpage_is_valid(tab)) end) end) end) diff --git a/test/functional/api/ui_spec.lua b/test/functional/api/ui_spec.lua index 6efb6726fe..3e1f1ec965 100644 --- a/test/functional/api/ui_spec.lua +++ b/test/functional/api/ui_spec.lua @@ -6,7 +6,7 @@ local eq = helpers.eq local eval = helpers.eval local exec = helpers.exec local feed = helpers.feed -local meths = helpers.meths +local api = helpers.api local request = helpers.request local pcall_err = helpers.pcall_err @@ -23,42 +23,56 @@ describe('nvim_ui_attach()', function() end) it('validation', function() - eq('No such UI option: foo', - pcall_err(meths.ui_attach, 80, 24, { foo={'foo'} })) + eq('No such UI option: foo', pcall_err(api.nvim_ui_attach, 80, 24, { foo = { 'foo' } })) - eq("Invalid 'ext_linegrid': expected Boolean, got Array", - pcall_err(meths.ui_attach, 80, 24, { ext_linegrid={} })) - eq("Invalid 'override': expected Boolean, got Array", - pcall_err(meths.ui_attach, 80, 24, { override={} })) - eq("Invalid 'rgb': expected Boolean, got Array", - pcall_err(meths.ui_attach, 80, 24, { rgb={} })) - eq("Invalid 'term_name': expected String, got Boolean", - pcall_err(meths.ui_attach, 80, 24, { term_name=true })) - eq("Invalid 'term_colors': expected Integer, got Boolean", - pcall_err(meths.ui_attach, 80, 24, { term_colors=true })) - eq("Invalid 'stdin_fd': expected Integer, got String", - pcall_err(meths.ui_attach, 80, 24, { stdin_fd='foo' })) - eq("Invalid 'stdin_tty': expected Boolean, got String", - pcall_err(meths.ui_attach, 80, 24, { stdin_tty='foo' })) - eq("Invalid 'stdout_tty': expected Boolean, got String", - pcall_err(meths.ui_attach, 80, 24, { stdout_tty='foo' })) + eq( + "Invalid 'ext_linegrid': expected Boolean, got Array", + pcall_err(api.nvim_ui_attach, 80, 24, { ext_linegrid = {} }) + ) + eq( + "Invalid 'override': expected Boolean, got Array", + pcall_err(api.nvim_ui_attach, 80, 24, { override = {} }) + ) + eq( + "Invalid 'rgb': expected Boolean, got Array", + pcall_err(api.nvim_ui_attach, 80, 24, { rgb = {} }) + ) + eq( + "Invalid 'term_name': expected String, got Boolean", + pcall_err(api.nvim_ui_attach, 80, 24, { term_name = true }) + ) + eq( + "Invalid 'term_colors': expected Integer, got Boolean", + pcall_err(api.nvim_ui_attach, 80, 24, { term_colors = true }) + ) + eq( + "Invalid 'stdin_fd': expected Integer, got String", + pcall_err(api.nvim_ui_attach, 80, 24, { stdin_fd = 'foo' }) + ) + eq( + "Invalid 'stdin_tty': expected Boolean, got String", + pcall_err(api.nvim_ui_attach, 80, 24, { stdin_tty = 'foo' }) + ) + eq( + "Invalid 'stdout_tty': expected Boolean, got String", + pcall_err(api.nvim_ui_attach, 80, 24, { stdout_tty = 'foo' }) + ) - eq('UI not attached to channel: 1', - pcall_err(request, 'nvim_ui_try_resize', 40, 10)) - eq('UI not attached to channel: 1', - pcall_err(request, 'nvim_ui_set_option', 'rgb', true)) - eq('UI not attached to channel: 1', - pcall_err(request, 'nvim_ui_detach')) + eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_try_resize', 40, 10)) + eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_set_option', 'rgb', true)) + eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_detach')) local screen = Screen.new() - screen:attach({rgb=false}) - eq('UI already attached to channel: 1', - pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb=false })) + screen:attach({ rgb = false }) + eq( + 'UI already attached to channel: 1', + pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb = false }) + ) end) end) it('autocmds UIEnter/UILeave', function() - clear{args_rm={'--headless'}} + clear { args_rm = { '--headless' } } exec([[ let g:evs = [] autocmd UIEnter * call add(g:evs, "UIEnter") | let g:uienter_ev = deepcopy(v:event) @@ -67,9 +81,9 @@ it('autocmds UIEnter/UILeave', function() ]]) local screen = Screen.new() screen:attach() - eq({chan=1}, eval('g:uienter_ev')) + eq({ chan = 1 }, eval('g:uienter_ev')) screen:detach() - eq({chan=1}, eval('g:uileave_ev')) + eq({ chan = 1 }, eval('g:uileave_ev')) eq({ 'VimEnter', 'UIEnter', @@ -89,29 +103,37 @@ it('autocmds VimSuspend/VimResume #22041', function() eq(false, screen.suspended) feed('<C-Z>') - screen:expect(function() eq(true, screen.suspended) end) + screen:expect(function() + eq(true, screen.suspended) + end) eq({ 's' }, eval('g:ev')) screen.suspended = false feed('<Ignore>') eq({ 's', 'r' }, eval('g:ev')) command('suspend') - screen:expect(function() eq(true, screen.suspended) end) + screen:expect(function() + eq(true, screen.suspended) + end) eq({ 's', 'r', 's' }, eval('g:ev')) screen.suspended = false - meths.input_mouse('move', '', '', 0, 0, 0) + api.nvim_input_mouse('move', '', '', 0, 0, 0) eq({ 's', 'r', 's', 'r' }, eval('g:ev')) feed('<C-Z><C-Z><C-Z>') - screen:expect(function() eq(true, screen.suspended) end) - meths.ui_set_focus(false) + screen:expect(function() + eq(true, screen.suspended) + end) + api.nvim_ui_set_focus(false) eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev')) screen.suspended = false - meths.ui_set_focus(true) + api.nvim_ui_set_focus(true) eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev')) command('suspend | suspend | suspend') - screen:expect(function() eq(true, screen.suspended) end) + screen:expect(function() + eq(true, screen.suspended) + end) screen:detach() eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev')) screen.suspended = false diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua index 6d466b0cc1..c304f1aa88 100644 --- a/test/functional/api/version_spec.lua +++ b/test/functional/api/version_spec.lua @@ -1,8 +1,6 @@ local helpers = require('test.functional.helpers')(after_each) -local mpack = require('mpack') -local clear, funcs, eq = helpers.clear, helpers.funcs, helpers.eq -local call = helpers.call -local meths = helpers.meths +local clear, fn, eq = helpers.clear, helpers.fn, helpers.eq +local api = helpers.api local function read_mpack_file(fname) local fd = io.open(fname, 'rb') @@ -12,48 +10,47 @@ local function read_mpack_file(fname) local data = fd:read('*a') fd:close() - local unpack = mpack.Unpacker() + local unpack = vim.mpack.Unpacker() return unpack(data) end describe("api_info()['version']", function() before_each(clear) - it("returns API level", function() - local version = call('api_info')['version'] + it('returns API level', function() + local version = fn.api_info()['version'] local current = version['api_level'] - local compat = version['api_compatible'] - eq("number", type(current)) - eq("number", type(compat)) + local compat = version['api_compatible'] + eq('number', type(current)) + eq('number', type(compat)) assert(current >= compat) end) - it("returns Nvim version", function() - local version = call('api_info')['version'] - local major = version['major'] - local minor = version['minor'] - local patch = version['patch'] + it('returns Nvim version', function() + local version = fn.api_info()['version'] + local major = version['major'] + local minor = version['minor'] + local patch = version['patch'] local prerelease = version['prerelease'] - local build = version['build'] - eq("number", type(major)) - eq("number", type(minor)) - eq("number", type(patch)) - eq("boolean", type(prerelease)) - eq(1, funcs.has("nvim-"..major.."."..minor.."."..patch)) - eq(0, funcs.has("nvim-"..major.."."..minor.."."..(patch + 1))) - eq(0, funcs.has("nvim-"..major.."."..(minor + 1).."."..patch)) - eq(0, funcs.has("nvim-"..(major + 1).."."..minor.."."..patch)) + local build = version['build'] + eq('number', type(major)) + eq('number', type(minor)) + eq('number', type(patch)) + eq('boolean', type(prerelease)) + eq(1, fn.has('nvim-' .. major .. '.' .. minor .. '.' .. patch)) + eq(0, fn.has('nvim-' .. major .. '.' .. minor .. '.' .. (patch + 1))) + eq(0, fn.has('nvim-' .. major .. '.' .. (minor + 1) .. '.' .. patch)) + eq(0, fn.has('nvim-' .. (major + 1) .. '.' .. minor .. '.' .. patch)) assert(build == nil or type(build) == 'string') end) end) - -describe("api metadata", function() +describe('api metadata', function() before_each(clear) local function name_table(entries) local by_name = {} - for _,e in ipairs(entries) do + for _, e in ipairs(entries) do by_name[e.name] = e end return by_name @@ -63,10 +60,10 @@ describe("api metadata", function() local function filter_function_metadata(f) f.deprecated_since = nil for idx, _ in ipairs(f.parameters) do - f.parameters[idx][2] = '' -- Remove parameter name. + f.parameters[idx][2] = '' -- Remove parameter name. end - if string.sub(f.name, 1, 4) ~= "nvim" then + if string.sub(f.name, 1, 4) ~= 'nvim' then f.method = nil end return f @@ -76,7 +73,7 @@ describe("api metadata", function() -- check types of existing params are the same -- adding parameters is ok, but removing params is not (gives nil error) eq(old_e.since, new_e.since, old_e.name) - for i,p in ipairs(old_e.parameters) do + for i, p in ipairs(old_e.parameters) do eq(new_e.parameters[i][1], p[1], old_e.name) end end @@ -92,28 +89,30 @@ describe("api metadata", function() end end - local api, compat, stable, api_level + local api_info, compat, stable, api_level local old_api = {} setup(function() - clear() -- Ensure a session before requesting api_info. - api = meths.get_api_info()[2] - compat = api.version.api_compatible - api_level = api.version.api_level - if api.version.api_prerelease then - stable = api_level-1 + clear() -- Ensure a session before requesting api_info. + api_info = api.nvim_get_api_info()[2] + compat = api_info.version.api_compatible + api_level = api_info.version.api_level + if api_info.version.api_prerelease then + stable = api_level - 1 else stable = api_level end for level = compat, stable do - local path = ('test/functional/fixtures/api_level_'.. - tostring(level)..'.mpack') + local path = ('test/functional/fixtures/api_level_' .. tostring(level) .. '.mpack') old_api[level] = read_mpack_file(path) if old_api[level] == nil then - local errstr = "missing metadata fixture for stable level "..level..". " - if level == api_level and not api.version.api_prerelease then - errstr = (errstr.."If NVIM_API_CURRENT was bumped, ".. - "don't forget to set NVIM_API_PRERELEASE to true.") + local errstr = 'missing metadata fixture for stable level ' .. level .. '. ' + if level == api_level and not api_info.version.api_prerelease then + errstr = ( + errstr + .. 'If NVIM_API_CURRENT was bumped, ' + .. "don't forget to set NVIM_API_PRERELEASE to true." + ) end error(errstr) end @@ -124,60 +123,76 @@ describe("api metadata", function() end end) - it("functions are compatible with old metadata or have new level", function() - local funcs_new = name_table(api.functions) + it('functions are compatible with old metadata or have new level', function() + local funcs_new = name_table(api_info.functions) local funcs_compat = {} for level = compat, stable do - for _,f in ipairs(old_api[level].functions) do + for _, f in ipairs(old_api[level].functions) do if funcs_new[f.name] == nil then if f.since >= compat then - error('function '..f.name..' was removed but exists in level '.. - f.since..' which nvim should be compatible with') + error( + 'function ' + .. f.name + .. ' was removed but exists in level ' + .. f.since + .. ' which nvim should be compatible with' + ) end else - eq(filter_function_metadata(f), - filter_function_metadata(funcs_new[f.name])) + eq(filter_function_metadata(f), filter_function_metadata(funcs_new[f.name])) end end funcs_compat[level] = name_table(old_api[level].functions) end - for _,f in ipairs(api.functions) do + for _, f in ipairs(api_info.functions) do if f.since <= stable then local f_old = funcs_compat[f.since][f.name] if f_old == nil then - if string.sub(f.name, 1, 4) == "nvim" then - local errstr = ("function "..f.name.." has too low since value. ".. - "For new functions set it to "..(stable+1)..".") - if not api.version.api_prerelease then - errstr = (errstr.." Also bump NVIM_API_CURRENT and set ".. - "NVIM_API_PRERELEASE to true in CMakeLists.txt.") + if string.sub(f.name, 1, 4) == 'nvim' then + local errstr = ( + 'function ' + .. f.name + .. ' has too low since value. ' + .. 'For new functions set it to ' + .. (stable + 1) + .. '.' + ) + if not api_info.version.api_prerelease then + errstr = ( + errstr + .. ' Also bump NVIM_API_CURRENT and set ' + .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' + ) end error(errstr) else - error("function name '"..f.name.."' doesn't begin with 'nvim_'") + error("function name '" .. f.name .. "' doesn't begin with 'nvim_'") end end elseif f.since > api_level then - if api.version.api_prerelease then - error("New function "..f.name.." should use since value ".. - api_level) + if api_info.version.api_prerelease then + error('New function ' .. f.name .. ' should use since value ' .. api_level) else - error("function "..f.name.." has since value > api_level. ".. - "Bump NVIM_API_CURRENT and set ".. - "NVIM_API_PRERELEASE to true in CMakeLists.txt.") + error( + 'function ' + .. f.name + .. ' has since value > api_level. ' + .. 'Bump NVIM_API_CURRENT and set ' + .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' + ) end end end end) - it("UI events are compatible with old metadata or have new level", function() - local ui_events_new = name_table(api.ui_events) + it('UI events are compatible with old metadata or have new level', function() + local ui_events_new = name_table(api_info.ui_events) local ui_events_compat = {} -- UI events were formalized in level 3 for level = 3, stable do - for _,e in ipairs(old_api[level].ui_events) do + for _, e in ipairs(old_api[level].ui_events) do local new_e = ui_events_new[e.name] if new_e ~= nil then check_ui_event_compatible(e, new_e) @@ -186,41 +201,53 @@ describe("api metadata", function() ui_events_compat[level] = name_table(old_api[level].ui_events) end - for _,e in ipairs(api.ui_events) do + for _, e in ipairs(api_info.ui_events) do if e.since <= stable then local e_old = ui_events_compat[e.since][e.name] if e_old == nil then - local errstr = ("UI event "..e.name.." has too low since value. ".. - "For new events set it to "..(stable+1)..".") - if not api.version.api_prerelease then - errstr = (errstr.." Also bump NVIM_API_CURRENT and set ".. - "NVIM_API_PRERELEASE to true in CMakeLists.txt.") + local errstr = ( + 'UI event ' + .. e.name + .. ' has too low since value. ' + .. 'For new events set it to ' + .. (stable + 1) + .. '.' + ) + if not api_info.version.api_prerelease then + errstr = ( + errstr + .. ' Also bump NVIM_API_CURRENT and set ' + .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' + ) end error(errstr) end elseif e.since > api_level then - if api.version.api_prerelease then - error("New UI event "..e.name.." should use since value ".. - api_level) + if api_info.version.api_prerelease then + error('New UI event ' .. e.name .. ' should use since value ' .. api_level) else - error("UI event "..e.name.." has since value > api_level. ".. - "Bump NVIM_API_CURRENT and set ".. - "NVIM_API_PRERELEASE to true in CMakeLists.txt.") + error( + 'UI event ' + .. e.name + .. ' has since value > api_level. ' + .. 'Bump NVIM_API_CURRENT and set ' + .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.' + ) end end end end) - it("ui_options are preserved from older levels", function() + it('ui_options are preserved from older levels', function() local available_options = {} - for _, option in ipairs(api.ui_options) do + for _, option in ipairs(api_info.ui_options) do available_options[option] = true end -- UI options were versioned from level 4 for level = 4, stable do for _, option in ipairs(old_api[level].ui_options) do if not available_options[option] then - error("UI option "..option.." from stable metadata is missing") + error('UI option ' .. option .. ' from stable metadata is missing') end end end diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 8bbadda9b0..9a4a457637 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,22 +1,25 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local luv = require('luv') +local uv = vim.uv local fmt = string.format +local dedent = helpers.dedent local assert_alive = helpers.assert_alive -local NIL = helpers.NIL -local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq +local NIL = vim.NIL +local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq local command = helpers.command +local command_output = helpers.api.nvim_command_output local exec = helpers.exec local exec_capture = helpers.exec_capture local eval = helpers.eval local expect = helpers.expect -local funcs = helpers.funcs -local meths = helpers.meths +local fn = helpers.fn +local api = helpers.api local matches = helpers.matches -local pesc = helpers.pesc +local pesc = vim.pesc local mkdir_p = helpers.mkdir_p local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed +local async_meths = helpers.async_meths local is_os = helpers.is_os local parse_context = helpers.parse_context local request = helpers.request @@ -31,203 +34,273 @@ local insert = helpers.insert local skip = helpers.skip local pcall_err = helpers.pcall_err -local format_string = helpers.format_string +local format_string = require('test.format_string').format_string local intchar2lua = helpers.intchar2lua local mergedicts_copy = helpers.mergedicts_copy -local endswith = helpers.endswith +local endswith = vim.endswith describe('API', function() before_each(clear) it('validates requests', function() -- RPC - matches('Invalid method: bogus$', - pcall_err(request, 'bogus')) - matches('Invalid method: … の り 。…$', - pcall_err(request, '… の り 。…')) - matches('Invalid method: <empty>$', - pcall_err(request, '')) + matches('Invalid method: bogus$', pcall_err(request, 'bogus')) + matches('Invalid method: … の り 。…$', pcall_err(request, '… の り 。…')) + matches('Invalid method: <empty>$', pcall_err(request, '')) -- Non-RPC: rpcrequest(v:servername) uses internal channel. - matches('Invalid method: … の り 。…$', - pcall_err(request, 'nvim_eval', - [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), '… の り 。…')]=])) - matches('Invalid method: bogus$', - pcall_err(request, 'nvim_eval', - [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), 'bogus')]=])) + matches( + 'Invalid method: … の り 。…$', + pcall_err( + request, + 'nvim_eval', + [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), '… の り 。…')]=] + ) + ) + matches( + 'Invalid method: bogus$', + pcall_err( + request, + 'nvim_eval', + [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), 'bogus')]=] + ) + ) -- XXX: This must be the last one, else next one will fail: -- "Packer instance already working. Use another Packer ..." - matches("can't serialize object of type .$", - pcall_err(request, nil)) + matches("can't serialize object of type .$", pcall_err(request, nil)) end) it('handles errors in async requests', function() - local error_types = meths.get_api_info()[2].error_types + local error_types = api.nvim_get_api_info()[2].error_types nvim_async('bogus') - eq({'notification', 'nvim_error_event', - {error_types.Exception.id, 'Invalid method: nvim_bogus'}}, next_msg()) + eq({ + 'notification', + 'nvim_error_event', + { error_types.Exception.id, 'Invalid method: bogus' }, + }, next_msg()) -- error didn't close channel. assert_alive() end) it('failed async request emits nvim_error_event', function() - local error_types = meths.get_api_info()[2].error_types - nvim_async('command', 'bogus') - eq({'notification', 'nvim_error_event', - {error_types.Exception.id, 'Vim:E492: Not an editor command: bogus'}}, - next_msg()) + local error_types = api.nvim_get_api_info()[2].error_types + async_meths.nvim_command('bogus') + eq({ + 'notification', + 'nvim_error_event', + { error_types.Exception.id, 'Vim:E492: Not an editor command: bogus' }, + }, next_msg()) -- error didn't close channel. assert_alive() end) + it('input is processed first when followed immediately by non-fast events', function() + api.nvim_set_current_line('ab') + async_meths.nvim_input('x') + async_meths.nvim_exec_lua('_G.res1 = vim.api.nvim_get_current_line()', {}) + async_meths.nvim_exec_lua('_G.res2 = vim.api.nvim_get_current_line()', {}) + eq({ 'b', 'b' }, exec_lua('return { _G.res1, _G.res2 }')) + end) + it('does not set CA_COMMAND_BUSY #7254', function() - nvim('command', 'split') - nvim('command', 'autocmd WinEnter * startinsert') - nvim('command', 'wincmd w') - eq({mode='i', blocking=false}, nvim("get_mode")) + command('split') + command('autocmd WinEnter * startinsert') + command('wincmd w') + eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) end) describe('nvim_exec2', function() it('always returns table', function() -- In built version this results into `vim.empty_dict()` - eq({}, nvim('exec2', 'echo "Hello"', {})) - eq({}, nvim('exec2', 'echo "Hello"', { output = false })) - eq({ output = 'Hello' }, nvim('exec2', 'echo "Hello"', { output = true })) + eq({}, api.nvim_exec2('echo "Hello"', {})) + eq({}, api.nvim_exec2('echo "Hello"', { output = false })) + eq({ output = 'Hello' }, api.nvim_exec2('echo "Hello"', { output = true })) end) it('default options', function() -- Should be equivalent to { output = false } - nvim('exec2', "let x0 = 'a'", {}) - eq('a', nvim('get_var', 'x0')) + api.nvim_exec2("let x0 = 'a'", {}) + eq('a', api.nvim_get_var('x0')) end) it('one-line input', function() - nvim('exec2', "let x1 = 'a'", { output = false }) - eq('a', nvim('get_var', 'x1')) + api.nvim_exec2("let x1 = 'a'", { output = false }) + eq('a', api.nvim_get_var('x1')) end) it(':verbose set {option}?', function() - nvim('exec2', 'set nowrap', { output = false }) - eq({ output = 'nowrap\n\tLast set from anonymous :source' }, - nvim('exec2', 'verbose set wrap?', { output = true })) + api.nvim_exec2('set nowrap', { output = false }) + eq( + { output = 'nowrap\n\tLast set from anonymous :source' }, + api.nvim_exec2('verbose set wrap?', { output = true }) + ) -- Using script var to force creation of a script item - nvim('exec2', [[ + api.nvim_exec2( + [[ let s:a = 1 set nowrap - ]], { output = false }) - eq({ output = 'nowrap\n\tLast set from anonymous :source (script id 1)' }, - nvim('exec2', 'verbose set wrap?', { output = true })) + ]], + { output = false } + ) + eq( + { output = 'nowrap\n\tLast set from anonymous :source (script id 1)' }, + api.nvim_exec2('verbose set wrap?', { output = true }) + ) end) it('multiline input', function() -- Heredoc + empty lines. - nvim('exec2', "let x2 = 'a'\n", { output = false }) - eq('a', nvim('get_var', 'x2')) - nvim('exec2','lua <<EOF\n\n\n\ny=3\n\n\nEOF', { output = false }) - eq(3, nvim('eval', "luaeval('y')")) + api.nvim_exec2("let x2 = 'a'\n", { output = false }) + eq('a', api.nvim_get_var('x2')) + api.nvim_exec2('lua <<EOF\n\n\n\ny=3\n\n\nEOF', { output = false }) + eq(3, api.nvim_eval("luaeval('y')")) - eq({}, nvim('exec2', 'lua <<EOF\ny=3\nEOF', { output = false })) - eq(3, nvim('eval', "luaeval('y')")) + eq({}, api.nvim_exec2('lua <<EOF\ny=3\nEOF', { output = false })) + eq(3, api.nvim_eval("luaeval('y')")) -- Multiple statements - nvim('exec2', 'let x1=1\nlet x2=2\nlet x3=3\n', { output = false }) - eq(1, nvim('eval', 'x1')) - eq(2, nvim('eval', 'x2')) - eq(3, nvim('eval', 'x3')) + api.nvim_exec2('let x1=1\nlet x2=2\nlet x3=3\n', { output = false }) + eq(1, api.nvim_eval('x1')) + eq(2, api.nvim_eval('x2')) + eq(3, api.nvim_eval('x3')) -- Functions - nvim('exec2', 'function Foo()\ncall setline(1,["xxx"])\nendfunction', { output = false }) - eq('', nvim('get_current_line')) - nvim('exec2', 'call Foo()', { output = false }) - eq('xxx', nvim('get_current_line')) + api.nvim_exec2('function Foo()\ncall setline(1,["xxx"])\nendfunction', { output = false }) + eq('', api.nvim_get_current_line()) + api.nvim_exec2('call Foo()', { output = false }) + eq('xxx', api.nvim_get_current_line()) -- Autocmds - nvim('exec2','autocmd BufAdd * :let x1 = "Hello"', { output = false }) - nvim('command', 'new foo') + api.nvim_exec2('autocmd BufAdd * :let x1 = "Hello"', { output = false }) + command('new foo') eq('Hello', request('nvim_eval', 'g:x1')) -- Line continuations - nvim('exec2', [[ + api.nvim_exec2( + [[ let abc = #{ \ a: 1, "\ b: 2, \ c: 3 - \ }]], { output = false }) - eq({a = 1, c = 3}, request('nvim_eval', 'g:abc')) + \ }]], + { output = false } + ) + eq({ a = 1, c = 3 }, request('nvim_eval', 'g:abc')) -- try no spaces before continuations to catch off-by-one error - nvim('exec2', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', { output = false }) - eq({a = 98}, request('nvim_eval', 'g:ab')) + api.nvim_exec2('let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', { output = false }) + eq({ a = 98 }, request('nvim_eval', 'g:ab')) -- Script scope (s:) - eq({ output = 'ahoy! script-scoped varrrrr' }, nvim('exec2', [[ + eq( + { output = 'ahoy! script-scoped varrrrr' }, + api.nvim_exec2( + [[ let s:pirate = 'script-scoped varrrrr' function! s:avast_ye_hades(s) abort return a:s .. ' ' .. s:pirate endfunction echo <sid>avast_ye_hades('ahoy!') - ]], { output = true })) - - eq({ output = "{'output': 'ahoy! script-scoped varrrrr'}" }, nvim('exec2', [[ + ]], + { output = true } + ) + ) + + eq( + { output = "{'output': 'ahoy! script-scoped varrrrr'}" }, + api.nvim_exec2( + [[ let s:pirate = 'script-scoped varrrrr' function! Avast_ye_hades(s) abort return a:s .. ' ' .. s:pirate endfunction echo nvim_exec2('echo Avast_ye_hades(''ahoy!'')', {'output': v:true}) - ]], { output = true })) - - matches('Vim%(echo%):E121: Undefined variable: s:pirate$', - pcall_err(request, 'nvim_exec2', [[ + ]], + { output = true } + ) + ) + + matches( + 'Vim%(echo%):E121: Undefined variable: s:pirate$', + pcall_err( + request, + 'nvim_exec2', + [[ let s:pirate = 'script-scoped varrrrr' call nvim_exec2('echo s:pirate', {'output': v:true}) - ]], { output = false })) + ]], + { output = false } + ) + ) -- Script items are created only on script var access - eq({ output = '1\n0' }, nvim('exec2', [[ + eq( + { output = '1\n0' }, + api.nvim_exec2( + [[ echo expand("<SID>")->empty() let s:a = 123 echo expand("<SID>")->empty() - ]], { output = true })) - - eq({ output = '1\n0' }, nvim('exec2', [[ + ]], + { output = true } + ) + ) + + eq( + { output = '1\n0' }, + api.nvim_exec2( + [[ echo expand("<SID>")->empty() function s:a() abort endfunction echo expand("<SID>")->empty() - ]], { output = true })) + ]], + { output = true } + ) + ) end) it('non-ASCII input', function() - nvim('exec2', [=[ + api.nvim_exec2( + [=[ new exe "normal! i ax \n Ax " :%s/ax/--a1234--/g | :%s/Ax/--A1234--/g - ]=], { output = false }) - nvim('command', '1') - eq(' --a1234-- ', nvim('get_current_line')) - nvim('command', '2') - eq(' --A1234-- ', nvim('get_current_line')) - - nvim('exec2', [[ + ]=], + { output = false } + ) + command('1') + eq(' --a1234-- ', api.nvim_get_current_line()) + command('2') + eq(' --A1234-- ', api.nvim_get_current_line()) + + api.nvim_exec2( + [[ new call setline(1,['xxx']) call feedkeys('r') call feedkeys('ñ', 'xt') - ]], { output = false }) - eq('ñxx', nvim('get_current_line')) + ]], + { output = false } + ) + eq('ñxx', api.nvim_get_current_line()) end) it('execution error', function() - eq('nvim_exec2(): Vim:E492: Not an editor command: bogus_command', - pcall_err(request, 'nvim_exec2', 'bogus_command', {})) - eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated. + eq( + 'nvim_exec2(): Vim:E492: Not an editor command: bogus_command', + pcall_err(request, 'nvim_exec2', 'bogus_command', {}) + ) + eq('', api.nvim_eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) - eq('nvim_exec2(): Vim(buffer):E86: Buffer 23487 does not exist', - pcall_err(request, 'nvim_exec2', 'buffer 23487', {})) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + eq( + 'nvim_exec2(): Vim(buffer):E86: Buffer 23487 does not exist', + pcall_err(request, 'nvim_exec2', 'buffer 23487', {}) + ) + eq('', eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) @@ -240,7 +313,7 @@ describe('API', function() request('nvim_exec2', [[ let x2 = substitute('foo','o','X','g') let x4 = 'should be overwritten' - call nvim_exec2("source ]]..fname..[[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec2','g')\nlet x5='overwritten'\nlet x4=x5\n", {'output': v:false}) + call nvim_exec2("source ]] .. fname .. [[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec2','g')\nlet x5='overwritten'\nlet x4=x5\n", {'output': v:false}) ]], { output = false }) eq('set from :source file', request('nvim_get_var', 'x1')) eq('fXX', request('nvim_get_var', 'x2')) @@ -254,86 +327,108 @@ describe('API', function() local fname = tmpname() write_file(fname, 'echo "hello"\n') local sourcing_fname = tmpname() - write_file(sourcing_fname, 'call nvim_exec2("source '..fname..'", {"output": v:false})\n') - meths.exec2('set verbose=2', { output = false }) - local traceback_output = 'line 0: sourcing "'..sourcing_fname..'"\n'.. - 'line 0: sourcing "'..fname..'"\n'.. - 'hello\n'.. - 'finished sourcing '..fname..'\n'.. - 'continuing in nvim_exec2() called at '..sourcing_fname..':1\n'.. - 'finished sourcing '..sourcing_fname..'\n'.. - 'continuing in nvim_exec2() called at nvim_exec2():0' - eq({ output = traceback_output }, - meths.exec2('call nvim_exec2("source '..sourcing_fname..'", {"output": v:false})', { output = true })) + write_file(sourcing_fname, 'call nvim_exec2("source ' .. fname .. '", {"output": v:false})\n') + api.nvim_exec2('set verbose=2', { output = false }) + local traceback_output = dedent([[ + line 0: sourcing "%s" + line 0: sourcing "%s" + hello + finished sourcing %s + continuing in nvim_exec2() called at %s:1 + finished sourcing %s + continuing in nvim_exec2() called at nvim_exec2():0]]):format( + sourcing_fname, + fname, + fname, + sourcing_fname, + sourcing_fname + ) + eq( + { output = traceback_output }, + api.nvim_exec2( + 'call nvim_exec2("source ' .. sourcing_fname .. '", {"output": v:false})', + { output = true } + ) + ) os.remove(fname) os.remove(sourcing_fname) end) it('returns output', function() - eq({ output = 'this is spinal tap' }, - nvim('exec2', 'lua <<EOF\n\n\nprint("this is spinal tap")\n\n\nEOF', { output = true })) - eq({ output = '' }, nvim('exec2', 'echo', { output = true })) - eq({ output = 'foo 42' }, nvim('exec2', 'echo "foo" 42', { output = true })) + eq( + { output = 'this is spinal tap' }, + api.nvim_exec2('lua <<EOF\n\n\nprint("this is spinal tap")\n\n\nEOF', { output = true }) + ) + eq({ output = '' }, api.nvim_exec2('echo', { output = true })) + eq({ output = 'foo 42' }, api.nvim_exec2('echo "foo" 42', { output = true })) end) it('displays messages when opts.output=false', function() local screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, + [0] = { bold = true, foreground = Screen.colors.Blue }, }) - meths.exec2("echo 'hello'", { output = false }) - screen:expect{grid=[[ + api.nvim_exec2("echo 'hello'", { output = false }) + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 hello | - ]]} + ]], + } end) - it('doesn\'t display messages when output=true', function() + it("doesn't display messages when output=true", function() local screen = Screen.new(40, 6) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, + [0] = { bold = true, foreground = Screen.colors.Blue }, }) - meths.exec2("echo 'hello'", { output = true }) - screen:expect{grid=[[ + api.nvim_exec2("echo 'hello'", { output = true }) + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 | - ]]} + ]], + } exec([[ func Print() call nvim_exec2('echo "hello"', { 'output': v:true }) endfunc ]]) feed([[:echon 1 | call Print() | echon 5<CR>]]) - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 15 | - ]]} + ]], + } + end) + + it('errors properly when command too recursive', function() + exec_lua([[ + _G.success = false + vim.api.nvim_create_user_command('Test', function() + vim.api.nvim_exec2('Test', {}) + _G.success = true + end, {}) + ]]) + pcall_err(command, 'Test') + assert_alive() + eq(false, exec_lua('return _G.success')) end) end) describe('nvim_command', function() it('works', function() local fname = tmpname() - nvim('command', 'new') - nvim('command', 'edit '..fname) - nvim('command', 'normal itesting\napi') - nvim('command', 'w') + command('new') + command('edit ' .. fname) + command('normal itesting\napi') + command('w') local f = assert(io.open(fname)) if is_os('win') then eq('testing\r\napi\r\n', f:read('*a')) @@ -345,158 +440,166 @@ describe('API', function() end) it('Vimscript validation error: fails with specific error', function() - local status, rv = pcall(nvim, "command", "bogus_command") - eq(false, status) -- nvim_command() failed. - eq("E492:", string.match(rv, "E%d*:")) -- Vimscript error was returned. - eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated. + local status, rv = pcall(command, 'bogus_command') + eq(false, status) -- nvim_command() failed. + eq('E492:', string.match(rv, 'E%d*:')) -- Vimscript error was returned. + eq('', api.nvim_eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) it('Vimscript execution error: fails with specific error', function() - local status, rv = pcall(nvim, "command", "buffer 23487") - eq(false, status) -- nvim_command() failed. - eq("E86: Buffer 23487 does not exist", string.match(rv, "E%d*:.*")) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + local status, rv = pcall(command, 'buffer 23487') + eq(false, status) -- nvim_command() failed. + eq('E86: Buffer 23487 does not exist', string.match(rv, 'E%d*:.*')) + eq('', eval('v:errmsg')) -- v:errmsg was not updated. eq('', eval('v:exception')) end) it('gives E493 instead of prompting on backwards range', function() command('split') - eq('Vim(windo):E493: Backwards range given: 2,1windo echo', - pcall_err(command, '2,1windo echo')) + eq( + 'Vim(windo):E493: Backwards range given: 2,1windo echo', + pcall_err(command, '2,1windo echo') + ) end) end) describe('nvim_command_output', function() it('does not induce hit-enter prompt', function() - nvim("ui_attach", 80, 20, {}) + api.nvim_ui_attach(80, 20, {}) -- Induce a hit-enter prompt use nvim_input (non-blocking). - nvim('command', 'set cmdheight=1') - nvim('input', [[:echo "hi\nhi2"<CR>]]) + command('set cmdheight=1') + api.nvim_input([[:echo "hi\nhi2"<CR>]]) -- Verify hit-enter prompt. - eq({mode='r', blocking=true}, nvim("get_mode")) - nvim('input', [[<C-c>]]) + eq({ mode = 'r', blocking = true }, api.nvim_get_mode()) + api.nvim_input([[<C-c>]]) -- Verify NO hit-enter prompt. - nvim('command_output', [[echo "hi\nhi2"]]) - eq({mode='n', blocking=false}, nvim("get_mode")) + command_output([[echo "hi\nhi2"]]) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) it('captures command output', function() - eq('this is\nspinal tap', - nvim('command_output', [[echo "this is\nspinal tap"]])) - eq('no line ending!', - nvim('command_output', [[echon "no line ending!"]])) + eq('this is\nspinal tap', command_output([[echo "this is\nspinal tap"]])) + eq('no line ending!', command_output([[echon "no line ending!"]])) end) it('captures empty command output', function() - eq('', nvim('command_output', 'echo')) + eq('', command_output('echo')) end) it('captures single-char command output', function() - eq('x', nvim('command_output', 'echo "x"')) + eq('x', command_output('echo "x"')) end) it('captures multiple commands', function() - eq('foo\n 1 %a "[No Name]" line 1', - nvim('command_output', 'echo "foo" | ls')) + eq('foo\n 1 %a "[No Name]" line 1', command_output('echo "foo" | ls')) end) it('captures nested execute()', function() - eq('\nnested1\nnested2\n 1 %a "[No Name]" line 1', - nvim('command_output', - [[echo execute('echo "nested1\nnested2"') | ls]])) + eq( + '\nnested1\nnested2\n 1 %a "[No Name]" line 1', + command_output([[echo execute('echo "nested1\nnested2"') | ls]]) + ) end) it('captures nested nvim_command_output()', function() - eq('nested1\nnested2\n 1 %a "[No Name]" line 1', - nvim('command_output', - [[echo nvim_command_output('echo "nested1\nnested2"') | ls]])) + eq( + 'nested1\nnested2\n 1 %a "[No Name]" line 1', + command_output([[echo nvim_command_output('echo "nested1\nnested2"') | ls]]) + ) end) it('returns shell |:!| output', function() local win_lf = is_os('win') and '\r' or '' - eq(':!echo foo\r\n\nfoo'..win_lf..'\n', nvim('command_output', [[!echo foo]])) + eq(':!echo foo\r\n\nfoo' .. win_lf .. '\n', command_output([[!echo foo]])) end) it('Vimscript validation error: fails with specific error', function() - local status, rv = pcall(nvim, "command_output", "bogus commannnd") - eq(false, status) -- nvim_command_output() failed. - eq("E492: Not an editor command: bogus commannnd", - string.match(rv, "E%d*:.*")) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + local status, rv = pcall(command_output, 'bogus commannnd') + eq(false, status) -- nvim_command_output() failed. + eq('E492: Not an editor command: bogus commannnd', string.match(rv, 'E%d*:.*')) + eq('', eval('v:errmsg')) -- v:errmsg was not updated. -- Verify NO hit-enter prompt. - eq({mode='n', blocking=false}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) it('Vimscript execution error: fails with specific error', function() - local status, rv = pcall(nvim, "command_output", "buffer 42") - eq(false, status) -- nvim_command_output() failed. - eq("E86: Buffer 42 does not exist", string.match(rv, "E%d*:.*")) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + local status, rv = pcall(command_output, 'buffer 42') + eq(false, status) -- nvim_command_output() failed. + eq('E86: Buffer 42 does not exist', string.match(rv, 'E%d*:.*')) + eq('', eval('v:errmsg')) -- v:errmsg was not updated. -- Verify NO hit-enter prompt. - eq({mode='n', blocking=false}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) it('does not cause heap buffer overflow with large output', function() - eq(eval('string(range(1000000))'), - nvim('command_output', 'echo range(1000000)')) + eq(eval('string(range(1000000))'), command_output('echo range(1000000)')) end) end) describe('nvim_eval', function() it('works', function() - nvim('command', 'let g:v1 = "a"') - nvim('command', 'let g:v2 = [1, 2, {"v3": 3}]') - eq({v1 = 'a', v2 = { 1, 2, { v3 = 3 } } }, nvim('eval', 'g:')) + command('let g:v1 = "a"') + command('let g:v2 = [1, 2, {"v3": 3}]') + eq({ v1 = 'a', v2 = { 1, 2, { v3 = 3 } } }, api.nvim_eval('g:')) end) it('handles NULL-initialized strings correctly', function() - eq(1, nvim('eval',"matcharg(1) == ['', '']")) - eq({'', ''}, nvim('eval','matcharg(1)')) + eq(1, api.nvim_eval("matcharg(1) == ['', '']")) + eq({ '', '' }, api.nvim_eval('matcharg(1)')) end) it('works under deprecated name', function() - eq(2, request("vim_eval", "1+1")) + eq(2, request('vim_eval', '1+1')) end) - it("Vimscript error: returns error details, does NOT update v:errmsg", function() - eq('Vim:E121: Undefined variable: bogus', - pcall_err(request, 'nvim_eval', 'bogus expression')) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + it('Vimscript error: returns error details, does NOT update v:errmsg', function() + eq('Vim:E121: Undefined variable: bogus', pcall_err(request, 'nvim_eval', 'bogus expression')) + eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) end) describe('nvim_call_function', function() it('works', function() - nvim('call_function', 'setqflist', { { { filename = 'something', lnum = 17 } }, 'r' }) - eq(17, nvim('call_function', 'getqflist', {})[1].lnum) - eq(17, nvim('call_function', 'eval', {17})) - eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'})) - end) - - it("Vimscript validation error: returns specific error, does NOT update v:errmsg", function() - eq('Vim:E117: Unknown function: bogus function', - pcall_err(request, 'nvim_call_function', 'bogus function', {'arg1'})) - eq('Vim:E119: Not enough arguments for function: atan', - pcall_err(request, 'nvim_call_function', 'atan', {})) + api.nvim_call_function('setqflist', { { { filename = 'something', lnum = 17 } }, 'r' }) + eq(17, api.nvim_call_function('getqflist', {})[1].lnum) + eq(17, api.nvim_call_function('eval', { 17 })) + eq('foo', api.nvim_call_function('simplify', { 'this/./is//redundant/../../../foo' })) + end) + + it('Vimscript validation error: returns specific error, does NOT update v:errmsg', function() + eq( + 'Vim:E117: Unknown function: bogus function', + pcall_err(request, 'nvim_call_function', 'bogus function', { 'arg1' }) + ) + eq( + 'Vim:E119: Not enough arguments for function: atan', + pcall_err(request, 'nvim_call_function', 'atan', {}) + ) eq('', eval('v:exception')) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. - end) - - it("Vimscript error: returns error details, does NOT update v:errmsg", function() - eq('Vim:E808: Number or Float required', - pcall_err(request, 'nvim_call_function', 'atan', {'foo'})) - eq('Vim:Invalid channel stream "xxx"', - pcall_err(request, 'nvim_call_function', 'chanclose', {999, 'xxx'})) - eq('Vim:E900: Invalid channel id', - pcall_err(request, 'nvim_call_function', 'chansend', {999, 'foo'})) + eq('', eval('v:errmsg')) -- v:errmsg was not updated. + end) + + it('Vimscript error: returns error details, does NOT update v:errmsg', function() + eq( + 'Vim:E808: Number or Float required', + pcall_err(request, 'nvim_call_function', 'atan', { 'foo' }) + ) + eq( + 'Vim:Invalid channel stream "xxx"', + pcall_err(request, 'nvim_call_function', 'chanclose', { 999, 'xxx' }) + ) + eq( + 'Vim:E900: Invalid channel id', + pcall_err(request, 'nvim_call_function', 'chansend', { 999, 'foo' }) + ) eq('', eval('v:exception')) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) - it("Vimscript exception: returns exception details, does NOT update v:errmsg", function() + it('Vimscript exception: returns exception details, does NOT update v:errmsg', function() source([[ function! Foo() abort throw 'wtf' @@ -504,10 +607,11 @@ describe('API', function() ]]) eq('function Foo, line 1: wtf', pcall_err(request, 'nvim_call_function', 'Foo', {})) eq('', eval('v:exception')) - eq('', eval('v:errmsg')) -- v:errmsg was not updated. + eq('', eval('v:errmsg')) -- v:errmsg was not updated. end) it('validation', function() + -- stylua: ignore local too_many_args = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' } source([[ function! Foo(...) abort @@ -515,8 +619,10 @@ describe('API', function() endfunction ]]) -- E740 - eq('Function called with too many arguments', - pcall_err(request, 'nvim_call_function', 'Foo', too_many_args)) + eq( + 'Function called with too many arguments', + pcall_err(request, 'nvim_call_function', 'Foo', too_many_args) + ) end) end) @@ -535,40 +641,55 @@ describe('API', function() ]]) -- :help Dictionary-function - eq('Hello, World!', nvim('call_dict_function', 'g:test_dict_fn', 'F', {'World'})) + eq('Hello, World!', api.nvim_call_dict_function('g:test_dict_fn', 'F', { 'World' })) -- Funcref is sent as NIL over RPC. - eq({ greeting = 'Hello', F = NIL }, nvim('get_var', 'test_dict_fn')) + eq({ greeting = 'Hello', F = NIL }, api.nvim_get_var('test_dict_fn')) -- :help numbered-function - eq('Hi, Moon ...', nvim('call_dict_function', 'g:test_dict_fn2', 'F2', {'Moon'})) + eq('Hi, Moon ...', api.nvim_call_dict_function('g:test_dict_fn2', 'F2', { 'Moon' })) -- Funcref is sent as NIL over RPC. - eq({ greeting = 'Hi', F2 = NIL }, nvim('get_var', 'test_dict_fn2')) + eq({ greeting = 'Hi', F2 = NIL }, api.nvim_get_var('test_dict_fn2')) -- Function specified via RPC dict. source('function! G() dict\n return "@".(self.result)."@"\nendfunction') - eq('@it works@', nvim('call_dict_function', { result = 'it works', G = 'G'}, 'G', {})) + eq('@it works@', api.nvim_call_dict_function({ result = 'it works', G = 'G' }, 'G', {})) end) it('validation', function() command('let g:d={"baz":"zub","meep":[]}') - eq('Not found: bogus', - pcall_err(request, 'nvim_call_dict_function', 'g:d', 'bogus', {1,2})) - eq('Not a function: baz', - pcall_err(request, 'nvim_call_dict_function', 'g:d', 'baz', {1,2})) - eq('Not a function: meep', - pcall_err(request, 'nvim_call_dict_function', 'g:d', 'meep', {1,2})) - eq('Vim:E117: Unknown function: f', - pcall_err(request, 'nvim_call_dict_function', { f = '' }, 'f', {1,2})) - eq('Not a function: f', - pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", 'f', {1,2})) - eq('dict argument type must be String or Dictionary', - pcall_err(request, 'nvim_call_dict_function', 42, 'f', {1,2})) - eq('Failed to evaluate dict expression', - pcall_err(request, 'nvim_call_dict_function', 'foo', 'f', {1,2})) - eq('dict not found', - pcall_err(request, 'nvim_call_dict_function', '42', 'f', {1,2})) - eq('Invalid (empty) function name', - pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", '', {1,2})) + eq( + 'Not found: bogus', + pcall_err(request, 'nvim_call_dict_function', 'g:d', 'bogus', { 1, 2 }) + ) + eq( + 'Not a function: baz', + pcall_err(request, 'nvim_call_dict_function', 'g:d', 'baz', { 1, 2 }) + ) + eq( + 'Not a function: meep', + pcall_err(request, 'nvim_call_dict_function', 'g:d', 'meep', { 1, 2 }) + ) + eq( + 'Vim:E117: Unknown function: f', + pcall_err(request, 'nvim_call_dict_function', { f = '' }, 'f', { 1, 2 }) + ) + eq( + 'Not a function: f', + pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", 'f', { 1, 2 }) + ) + eq( + 'dict argument type must be String or Dictionary', + pcall_err(request, 'nvim_call_dict_function', 42, 'f', { 1, 2 }) + ) + eq( + 'Failed to evaluate dict expression', + pcall_err(request, 'nvim_call_dict_function', 'foo', 'f', { 1, 2 }) + ) + eq('dict not found', pcall_err(request, 'nvim_call_dict_function', '42', 'f', { 1, 2 })) + eq( + 'Invalid (empty) function name', + pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", '', { 1, 2 }) + ) end) end) @@ -576,85 +697,95 @@ describe('API', function() local start_dir before_each(function() - funcs.mkdir("Xtestdir") - start_dir = funcs.getcwd() + fn.mkdir('Xtestdir') + start_dir = fn.getcwd() end) after_each(function() - helpers.rmdir("Xtestdir") + helpers.rmdir('Xtestdir') end) it('works', function() - meths.set_current_dir("Xtestdir") - eq(funcs.getcwd(), start_dir .. helpers.get_pathsep() .. "Xtestdir") + api.nvim_set_current_dir('Xtestdir') + eq(fn.getcwd(), start_dir .. helpers.get_pathsep() .. 'Xtestdir') end) it('sets previous directory', function() - meths.set_current_dir("Xtestdir") + api.nvim_set_current_dir('Xtestdir') command('cd -') - eq(funcs.getcwd(), start_dir) + eq(fn.getcwd(), start_dir) end) end) describe('nvim_exec_lua', function() it('works', function() - meths.exec_lua('vim.api.nvim_set_var("test", 3)', {}) - eq(3, meths.get_var('test')) + api.nvim_exec_lua('vim.api.nvim_set_var("test", 3)', {}) + eq(3, api.nvim_get_var('test')) - eq(17, meths.exec_lua('a, b = ...\nreturn a + b', {10,7})) + eq(17, api.nvim_exec_lua('a, b = ...\nreturn a + b', { 10, 7 })) - eq(NIL, meths.exec_lua('function xx(a,b)\nreturn a..b\nend',{})) - eq("xy", meths.exec_lua('return xx(...)', {'x','y'})) + eq(NIL, api.nvim_exec_lua('function xx(a,b)\nreturn a..b\nend', {})) + eq('xy', api.nvim_exec_lua('return xx(...)', { 'x', 'y' })) -- Deprecated name: nvim_execute_lua. - eq("xy", meths.execute_lua('return xx(...)', {'x','y'})) + eq('xy', api.nvim_execute_lua('return xx(...)', { 'x', 'y' })) end) it('reports errors', function() - eq([[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']], - pcall_err(meths.exec_lua, 'a+*b', {})) + eq( + [[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']], + pcall_err(api.nvim_exec_lua, 'a+*b', {}) + ) - eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']], - pcall_err(meths.exec_lua, '1+2', {})) + eq( + [[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']], + pcall_err(api.nvim_exec_lua, '1+2', {}) + ) - eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol]], - pcall_err(meths.exec_lua, 'aa=bb\0', {})) + eq( + [[Error loading lua: [string "<nvim>"]:0: unexpected symbol]], + pcall_err(api.nvim_exec_lua, 'aa=bb\0', {}) + ) - eq([[attempt to call global 'bork' (a nil value)]], - pcall_err(meths.exec_lua, 'bork()', {})) + eq( + [[attempt to call global 'bork' (a nil value)]], + pcall_err(api.nvim_exec_lua, 'bork()', {}) + ) - eq('did\nthe\nfail', - pcall_err(meths.exec_lua, 'error("did\\nthe\\nfail")', {})) + eq('did\nthe\nfail', pcall_err(api.nvim_exec_lua, 'error("did\\nthe\\nfail")', {})) end) it('uses native float values', function() - eq(2.5, meths.exec_lua("return select(1, ...)", {2.5})) - eq("2.5", meths.exec_lua("return vim.inspect(...)", {2.5})) + eq(2.5, api.nvim_exec_lua('return select(1, ...)', { 2.5 })) + eq('2.5', api.nvim_exec_lua('return vim.inspect(...)', { 2.5 })) -- "special" float values are still accepted as return values. - eq(2.5, meths.exec_lua("return vim.api.nvim_eval('2.5')", {})) - eq("{\n [false] = 2.5,\n [true] = 3\n}", meths.exec_lua("return vim.inspect(vim.api.nvim_eval('2.5'))", {})) + eq(2.5, api.nvim_exec_lua("return vim.api.nvim_eval('2.5')", {})) + eq( + '{\n [false] = 2.5,\n [true] = 3\n}', + api.nvim_exec_lua("return vim.inspect(vim.api.nvim_eval('2.5'))", {}) + ) end) end) describe('nvim_notify', function() it('can notify a info message', function() - nvim("notify", "hello world", 2, {}) + api.nvim_notify('hello world', 2, {}) end) it('can be overridden', function() - command("lua vim.notify = function(...) return 42 end") - eq(42, meths.exec_lua("return vim.notify('Hello world')", {})) - nvim("notify", "hello world", 4, {}) + command('lua vim.notify = function(...) return 42 end') + eq(42, api.nvim_exec_lua("return vim.notify('Hello world')", {})) + api.nvim_notify('hello world', 4, {}) end) end) describe('nvim_input', function() - it("Vimscript error: does NOT fail, updates v:errmsg", function() - local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>") - local v_errnum = string.match(nvim("eval", "v:errmsg"), "E%d*:") - eq(true, status) -- nvim_input() did not fail. - eq("E117:", v_errnum) -- v:errmsg was updated. + it('Vimscript error: does NOT fail, updates v:errmsg', function() + local status, _ = pcall(api.nvim_input, ':call bogus_fn()<CR>') + local v_errnum = string.match(api.nvim_eval('v:errmsg'), 'E%d*:') + eq(true, status) -- nvim_input() did not fail. + eq('E117:', v_errnum) -- v:errmsg was updated. end) it('does not crash even if trans_special result is largest #11788, #12287', function() @@ -665,30 +796,28 @@ describe('API', function() describe('nvim_paste', function() it('validation', function() - eq("Invalid 'phase': -2", - pcall_err(request, 'nvim_paste', 'foo', true, -2)) - eq("Invalid 'phase': 4", - pcall_err(request, 'nvim_paste', 'foo', true, 4)) + eq("Invalid 'phase': -2", pcall_err(request, 'nvim_paste', 'foo', true, -2)) + eq("Invalid 'phase': 4", pcall_err(request, 'nvim_paste', 'foo', true, 4)) end) local function run_streamed_paste_tests() it('stream: multiple chunks form one undo-block', function() - nvim('paste', '1/chunk 1 (start)\n', true, 1) - nvim('paste', '1/chunk 2 (end)\n', true, 3) + api.nvim_paste('1/chunk 1 (start)\n', true, 1) + api.nvim_paste('1/chunk 2 (end)\n', true, 3) local expected1 = [[ 1/chunk 1 (start) 1/chunk 2 (end) ]] expect(expected1) - nvim('paste', '2/chunk 1 (start)\n', true, 1) - nvim('paste', '2/chunk 2\n', true, 2) + api.nvim_paste('2/chunk 1 (start)\n', true, 1) + api.nvim_paste('2/chunk 2\n', true, 2) expect([[ 1/chunk 1 (start) 1/chunk 2 (end) 2/chunk 1 (start) 2/chunk 2 ]]) - nvim('paste', '2/chunk 3\n', true, 2) - nvim('paste', '2/chunk 4 (end)\n', true, 3) + api.nvim_paste('2/chunk 3\n', true, 2) + api.nvim_paste('2/chunk 4 (end)\n', true, 3) expect([[ 1/chunk 1 (start) 1/chunk 2 (end) @@ -697,17 +826,17 @@ describe('API', function() 2/chunk 3 2/chunk 4 (end) ]]) - feed('u') -- Undo. + feed('u') -- Undo. expect(expected1) end) it('stream: Insert mode', function() -- If nvim_paste() calls :undojoin without making any changes, this makes it an error. feed('afoo<Esc>u') feed('i') - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('aaaaaabbbbbbccccccdddddd') feed('<Esc>u') expect('') @@ -723,17 +852,17 @@ describe('API', function() expect('') end) it('pasting one line', function() - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('aaaaaabbbbbbccccccdddddd') end) it('pasting multiple lines', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ aaaaaa bbbbbb @@ -753,17 +882,17 @@ describe('API', function() expect('||') end) it('pasting one line', function() - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('|aaaaaabbbbbbccccccdddddd|') end) it('pasting multiple lines', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ |aaaaaa bbbbbb @@ -783,17 +912,17 @@ describe('API', function() expect('||') end) it('pasting one line', function() - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('||aaaaaabbbbbbccccccdddddd') end) it('pasting multiple lines', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ ||aaaaaa bbbbbb @@ -817,24 +946,24 @@ describe('API', function() xxx|]]) end) it('with non-empty chunks', function() - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('|aaaaaabbbbbbccccccdddddd|') end) it('with empty first chunk', function() - nvim('paste', '', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('|bbbbbbccccccdddddd|') end) it('with all chunks empty', function() - nvim('paste', '', false, 1) - nvim('paste', '', false, 2) - nvim('paste', '', false, 2) - nvim('paste', '', false, 3) + api.nvim_paste('', false, 1) + api.nvim_paste('', false, 2) + api.nvim_paste('', false, 2) + api.nvim_paste('', false, 3) expect('||') end) end) @@ -852,17 +981,17 @@ describe('API', function() xxx]]) end) it('with non-empty chunks', function() - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('||aaaaaabbbbbbccccccdddddd') end) it('with empty first chunk', function() - nvim('paste', '', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('||bbbbbbccccccdddddd') end) end) @@ -880,17 +1009,17 @@ describe('API', function() xxx]]) end) it('with non-empty chunks', function() - nvim('paste', 'aaaaaa', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('||aaaaaabbbbbbccccccdddddd') end) it('with empty first chunk', function() - nvim('paste', '', false, 1) - nvim('paste', 'bbbbbb', false, 2) - nvim('paste', 'cccccc', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('', false, 1) + api.nvim_paste('bbbbbb', false, 2) + api.nvim_paste('cccccc', false, 2) + api.nvim_paste('dddddd', false, 3) expect('||bbbbbbccccccdddddd') end) end) @@ -913,10 +1042,10 @@ describe('API', function() feed('ggV') end) it('pasting text without final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ aaaaaa bbbbbb @@ -925,10 +1054,10 @@ describe('API', function() 123456789]]) end) it('pasting text with final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd\n', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd\n', false, 3) expect([[ aaaaaa bbbbbb @@ -943,10 +1072,10 @@ describe('API', function() feed('2ggV') end) it('pasting text without final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ 123456789 aaaaaa @@ -955,10 +1084,10 @@ describe('API', function() dddddd123456789]]) end) it('pasting text with final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd\n', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd\n', false, 3) expect([[ 123456789 aaaaaa @@ -973,10 +1102,10 @@ describe('API', function() feed('3ggV') end) it('pasting text without final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ 123456789 987654321 @@ -986,10 +1115,10 @@ describe('API', function() dddddd]]) end) it('pasting text with final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd\n', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd\n', false, 3) expect([[ 123456789 987654321 @@ -1005,10 +1134,10 @@ describe('API', function() feed('ggVG') end) it('pasting text without final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd', false, 3) expect([[ aaaaaa bbbbbb @@ -1016,10 +1145,10 @@ describe('API', function() dddddd]]) end) it('pasting text with final new line', function() - nvim('paste', 'aaaaaa\n', false, 1) - nvim('paste', 'bbbbbb\n', false, 2) - nvim('paste', 'cccccc\n', false, 2) - nvim('paste', 'dddddd\n', false, 3) + api.nvim_paste('aaaaaa\n', false, 1) + api.nvim_paste('bbbbbb\n', false, 2) + api.nvim_paste('cccccc\n', false, 2) + api.nvim_paste('dddddd\n', false, 3) expect([[ aaaaaa bbbbbb @@ -1041,71 +1170,71 @@ describe('API', function() end) it('non-streaming', function() -- With final "\n". - nvim('paste', 'line 1\nline 2\nline 3\n', true, -1) + api.nvim_paste('line 1\nline 2\nline 3\n', true, -1) expect([[ line 1 line 2 line 3 ]]) - eq({0,4,1,0}, funcs.getpos('.')) -- Cursor follows the paste. - eq(false, nvim('get_option_value', 'paste', {})) + eq({ 0, 4, 1, 0 }, fn.getpos('.')) -- Cursor follows the paste. + eq(false, api.nvim_get_option_value('paste', {})) command('%delete _') -- Without final "\n". - nvim('paste', 'line 1\nline 2\nline 3', true, -1) + api.nvim_paste('line 1\nline 2\nline 3', true, -1) expect([[ line 1 line 2 line 3]]) - eq({0,3,6,0}, funcs.getpos('.')) + eq({ 0, 3, 6, 0 }, fn.getpos('.')) command('%delete _') -- CRLF #10872 - nvim('paste', 'line 1\r\nline 2\r\nline 3\r\n', true, -1) + api.nvim_paste('line 1\r\nline 2\r\nline 3\r\n', true, -1) expect([[ line 1 line 2 line 3 ]]) - eq({0,4,1,0}, funcs.getpos('.')) + eq({ 0, 4, 1, 0 }, fn.getpos('.')) command('%delete _') -- CRLF without final "\n". - nvim('paste', 'line 1\r\nline 2\r\nline 3\r', true, -1) + api.nvim_paste('line 1\r\nline 2\r\nline 3\r', true, -1) expect([[ line 1 line 2 line 3 ]]) - eq({0,4,1,0}, funcs.getpos('.')) + eq({ 0, 4, 1, 0 }, fn.getpos('.')) command('%delete _') -- CRLF without final "\r\n". - nvim('paste', 'line 1\r\nline 2\r\nline 3', true, -1) + api.nvim_paste('line 1\r\nline 2\r\nline 3', true, -1) expect([[ line 1 line 2 line 3]]) - eq({0,3,6,0}, funcs.getpos('.')) + eq({ 0, 3, 6, 0 }, fn.getpos('.')) command('%delete _') -- Various other junk. - nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', true, -1) + api.nvim_paste('line 1\r\n\r\rline 2\nline 3\rline 4\r', true, -1) expect('line 1\n\n\nline 2\nline 3\nline 4\n') - eq({0,7,1,0}, funcs.getpos('.')) - eq(false, nvim('get_option_value', 'paste', {})) + eq({ 0, 7, 1, 0 }, fn.getpos('.')) + eq(false, api.nvim_get_option_value('paste', {})) end) it('Replace-mode', function() -- Within single line - nvim('put', {'aabbccdd', 'eeffgghh', 'iijjkkll'}, "c", true, false) + api.nvim_put({ 'aabbccdd', 'eeffgghh', 'iijjkkll' }, 'c', true, false) command('normal l') command('startreplace') - nvim('paste', '123456', true, -1) + api.nvim_paste('123456', true, -1) expect([[ a123456d eeffgghh iijjkkll]]) command('%delete _') -- Across lines - nvim('put', {'aabbccdd', 'eeffgghh', 'iijjkkll'}, "c", true, false) + api.nvim_put({ 'aabbccdd', 'eeffgghh', 'iijjkkll' }, 'c', true, false) command('normal l') command('startreplace') - nvim('paste', '123\n456', true, -1) + api.nvim_paste('123\n456', true, -1) expect([[ a123 456d @@ -1114,34 +1243,33 @@ describe('API', function() end) it('when searching in Visual mode', function() feed('v/') - nvim('paste', 'aabbccdd', true, -1) - eq('aabbccdd', funcs.getcmdline()) + api.nvim_paste('aabbccdd', true, -1) + eq('aabbccdd', fn.getcmdline()) expect('') end) it('mappings are disabled in Cmdline mode', function() command('cnoremap a b') feed(':') - nvim('paste', 'a', true, -1) - eq('a', funcs.getcmdline()) + api.nvim_paste('a', true, -1) + eq('a', fn.getcmdline()) end) it('pasted text is saved in cmdline history when <CR> comes from mapping #20957', function() command('cnoremap <CR> <CR>') feed(':') - nvim('paste', 'echo', true, -1) - eq('', funcs.histget(':')) + api.nvim_paste('echo', true, -1) + eq('', fn.histget(':')) feed('<CR>') - eq('echo', funcs.histget(':')) + eq('echo', fn.histget(':')) end) it('pasting with empty last chunk in Cmdline mode', function() local screen = Screen.new(20, 4) screen:attach() feed(':') - nvim('paste', 'Foo', true, 1) - nvim('paste', '', true, 3) + api.nvim_paste('Foo', true, 1) + api.nvim_paste('', true, 3) screen:expect([[ | - ~ | - ~ | + ~ |*2 :Foo^ | ]]) end) @@ -1149,112 +1277,113 @@ describe('API', function() local screen = Screen.new(20, 4) screen:attach() feed(':') - nvim('paste', 'normal! \023\022\006\027', true, -1) + api.nvim_paste('normal! \023\022\006\027', true, -1) screen:expect([[ | - ~ | - ~ | + ~ |*2 :normal! ^W^V^F^[^ | ]]) end) it('crlf=false does not break lines at CR, CRLF', function() - nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', false, -1) + api.nvim_paste('line 1\r\n\r\rline 2\nline 3\rline 4\r', false, -1) expect('line 1\r\n\r\rline 2\nline 3\rline 4\r') - eq({0,3,14,0}, funcs.getpos('.')) + eq({ 0, 3, 14, 0 }, fn.getpos('.')) end) it('vim.paste() failure', function() - nvim('exec_lua', 'vim.paste = (function(lines, phase) error("fake fail") end)', {}) - eq('fake fail', - pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1)) + api.nvim_exec_lua('vim.paste = (function(lines, phase) error("fake fail") end)', {}) + eq('fake fail', pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1)) end) end) describe('nvim_put', function() it('validation', function() - eq("Invalid 'line': expected String, got Integer", - pcall_err(request, 'nvim_put', {42}, 'l', false, false)) - eq("Invalid 'type': 'x'", - pcall_err(request, 'nvim_put', {'foo'}, 'x', false, false)) + eq( + "Invalid 'line': expected String, got Integer", + pcall_err(request, 'nvim_put', { 42 }, 'l', false, false) + ) + eq("Invalid 'type': 'x'", pcall_err(request, 'nvim_put', { 'foo' }, 'x', false, false)) end) it("fails if 'nomodifiable'", function() command('set nomodifiable') - eq([[Vim:E21: Cannot make changes, 'modifiable' is off]], - pcall_err(request, 'nvim_put', {'a','b'}, 'l', true, true)) + eq( + [[Vim:E21: Cannot make changes, 'modifiable' is off]], + pcall_err(request, 'nvim_put', { 'a', 'b' }, 'l', true, true) + ) end) it('inserts text', function() -- linewise - nvim('put', {'line 1','line 2','line 3'}, 'l', true, true) + api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'l', true, true) expect([[ line 1 line 2 line 3]]) - eq({0,4,1,0}, funcs.getpos('.')) + eq({ 0, 4, 1, 0 }, fn.getpos('.')) command('%delete _') -- charwise - nvim('put', {'line 1','line 2','line 3'}, 'c', true, false) + api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'c', true, false) expect([[ line 1 line 2 line 3]]) - eq({0,1,1,0}, funcs.getpos('.')) -- follow=false + eq({ 0, 1, 1, 0 }, fn.getpos('.')) -- follow=false -- blockwise - nvim('put', {'AA','BB'}, 'b', true, true) + api.nvim_put({ 'AA', 'BB' }, 'b', true, true) expect([[ lAAine 1 lBBine 2 line 3]]) - eq({0,2,4,0}, funcs.getpos('.')) + eq({ 0, 2, 4, 0 }, fn.getpos('.')) command('%delete _') -- Empty lines list. - nvim('put', {}, 'c', true, true) - eq({0,1,1,0}, funcs.getpos('.')) + api.nvim_put({}, 'c', true, true) + eq({ 0, 1, 1, 0 }, fn.getpos('.')) expect([[]]) -- Single empty line. - nvim('put', {''}, 'c', true, true) - eq({0,1,1,0}, funcs.getpos('.')) + api.nvim_put({ '' }, 'c', true, true) + eq({ 0, 1, 1, 0 }, fn.getpos('.')) expect([[ ]]) - nvim('put', {'AB'}, 'c', true, true) + api.nvim_put({ 'AB' }, 'c', true, true) -- after=false, follow=true - nvim('put', {'line 1','line 2'}, 'c', false, true) + api.nvim_put({ 'line 1', 'line 2' }, 'c', false, true) expect([[ Aline 1 line 2B]]) - eq({0,2,7,0}, funcs.getpos('.')) + eq({ 0, 2, 7, 0 }, fn.getpos('.')) command('%delete _') - nvim('put', {'AB'}, 'c', true, true) + api.nvim_put({ 'AB' }, 'c', true, true) -- after=false, follow=false - nvim('put', {'line 1','line 2'}, 'c', false, false) + api.nvim_put({ 'line 1', 'line 2' }, 'c', false, false) expect([[ Aline 1 line 2B]]) - eq({0,1,2,0}, funcs.getpos('.')) - eq('', nvim('eval', 'v:errmsg')) + eq({ 0, 1, 2, 0 }, fn.getpos('.')) + eq('', api.nvim_eval('v:errmsg')) end) it('detects charwise/linewise text (empty {type})', function() -- linewise (final item is empty string) - nvim('put', {'line 1','line 2','line 3',''}, '', true, true) + api.nvim_put({ 'line 1', 'line 2', 'line 3', '' }, '', true, true) expect([[ line 1 line 2 line 3]]) - eq({0,4,1,0}, funcs.getpos('.')) + eq({ 0, 4, 1, 0 }, fn.getpos('.')) command('%delete _') -- charwise (final item is non-empty) - nvim('put', {'line 1','line 2','line 3'}, '', true, true) + api.nvim_put({ 'line 1', 'line 2', 'line 3' }, '', true, true) expect([[ line 1 line 2 line 3]]) - eq({0,3,6,0}, funcs.getpos('.')) + eq({ 0, 3, 6, 0 }, fn.getpos('.')) end) it('allows block width', function() -- behave consistently with setreg(); support "\022{NUM}" return by getregtype() - meths.put({'line 1','line 2','line 3'}, 'l', false, false) + api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'l', false, false) expect([[ line 1 line 2 @@ -1262,67 +1391,69 @@ describe('API', function() ]]) -- larger width create spaces - meths.put({'a', 'bc'}, 'b3', false, false) + api.nvim_put({ 'a', 'bc' }, 'b3', false, false) expect([[ a line 1 bc line 2 line 3 ]]) -- smaller width is ignored - meths.put({'xxx', 'yyy'}, '\0221', false, true) + api.nvim_put({ 'xxx', 'yyy' }, '\0221', false, true) expect([[ xxxa line 1 yyybc line 2 line 3 ]]) - eq("Invalid 'type': 'bx'", - pcall_err(meths.put, {'xxx', 'yyy'}, 'bx', false, true)) - eq("Invalid 'type': 'b3x'", - pcall_err(meths.put, {'xxx', 'yyy'}, 'b3x', false, true)) + eq("Invalid 'type': 'bx'", pcall_err(api.nvim_put, { 'xxx', 'yyy' }, 'bx', false, true)) + eq("Invalid 'type': 'b3x'", pcall_err(api.nvim_put, { 'xxx', 'yyy' }, 'b3x', false, true)) end) end) describe('nvim_strwidth', function() it('works', function() - eq(3, nvim('strwidth', 'abc')) + eq(3, api.nvim_strwidth('abc')) -- 6 + (neovim) -- 19 * 2 (each japanese character occupies two cells) - eq(44, nvim('strwidth', 'neovimのデザインかなりまともなのになってる。')) + eq(44, api.nvim_strwidth('neovimのデザインかなりまともなのになってる。')) end) it('cannot handle NULs', function() - eq(0, nvim('strwidth', '\0abc')) + eq(0, api.nvim_strwidth('\0abc')) end) end) describe('nvim_get_current_line, nvim_set_current_line', function() it('works', function() - eq('', nvim('get_current_line')) - nvim('set_current_line', 'abc') - eq('abc', nvim('get_current_line')) + eq('', api.nvim_get_current_line()) + api.nvim_set_current_line('abc') + eq('abc', api.nvim_get_current_line()) end) end) describe('set/get/del variables', function() it('validation', function() - eq('Key not found: bogus', pcall_err(meths.get_var, 'bogus')) - eq('Key not found: bogus', pcall_err(meths.del_var, 'bogus')) + eq('Key not found: bogus', pcall_err(api.nvim_get_var, 'bogus')) + eq('Key not found: bogus', pcall_err(api.nvim_del_var, 'bogus')) end) it('nvim_get_var, nvim_set_var, nvim_del_var', function() - nvim('set_var', 'lua', {1, 2, {['3'] = 1}}) - eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua')) - eq({1, 2, {['3'] = 1}}, nvim('eval', 'g:lua')) - eq(1, funcs.exists('g:lua')) - meths.del_var('lua') - eq(0, funcs.exists('g:lua')) - eq("Key not found: lua", pcall_err(meths.del_var, 'lua')) - meths.set_var('lua', 1) + api.nvim_set_var('lua', { 1, 2, { ['3'] = 1 } }) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_get_var('lua')) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('g:lua')) + eq(1, fn.exists('g:lua')) + api.nvim_del_var('lua') + eq(0, fn.exists('g:lua')) + eq('Key not found: lua', pcall_err(api.nvim_del_var, 'lua')) + api.nvim_set_var('lua', 1) + + -- Empty keys are allowed in Vim dicts (and msgpack). + api.nvim_set_var('dict_empty_key', { [''] = 'empty key' }) + eq({ [''] = 'empty key' }, api.nvim_get_var('dict_empty_key')) -- Set locked g: var. command('lockvar lua') - eq('Key is locked: lua', pcall_err(meths.del_var, 'lua')) - eq('Key is locked: lua', pcall_err(meths.set_var, 'lua', 1)) + eq('Key is locked: lua', pcall_err(api.nvim_del_var, 'lua')) + eq('Key is locked: lua', pcall_err(api.nvim_set_var, 'lua', 1)) exec([[ function Test() @@ -1332,260 +1463,281 @@ describe('API', function() let g:Unknown_func = function('Test') let g:Unknown_script_func = function('s:Test') ]]) - eq(NIL, meths.get_var('Unknown_func')) - eq(NIL, meths.get_var('Unknown_script_func')) + eq(NIL, api.nvim_get_var('Unknown_func')) + eq(NIL, api.nvim_get_var('Unknown_script_func')) -- Check if autoload works properly local pathsep = helpers.get_pathsep() local xconfig = 'Xhome' .. pathsep .. 'Xconfig' local xdata = 'Xhome' .. pathsep .. 'Xdata' - local autoload_folder = table.concat({xconfig, 'nvim', 'autoload'}, pathsep) - local autoload_file = table.concat({autoload_folder , 'testload.vim'}, pathsep) + local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep) + local autoload_file = table.concat({ autoload_folder, 'testload.vim' }, pathsep) mkdir_p(autoload_folder) - write_file(autoload_file , [[let testload#value = 2]]) + write_file(autoload_file, [[let testload#value = 2]]) - clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata } } - eq(2, meths.get_var('testload#value')) + clear { args_rm = { '-u' }, env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata } } + eq(2, api.nvim_get_var('testload#value')) rmdir('Xhome') end) it('nvim_get_vvar, nvim_set_vvar', function() eq('Key is read-only: count', pcall_err(request, 'nvim_set_vvar', 'count', 42)) eq('Dictionary is locked', pcall_err(request, 'nvim_set_vvar', 'nosuchvar', 42)) - meths.set_vvar('errmsg', 'set by API') - eq('set by API', meths.get_vvar('errmsg')) - meths.set_vvar('errmsg', 42) + api.nvim_set_vvar('errmsg', 'set by API') + eq('set by API', api.nvim_get_vvar('errmsg')) + api.nvim_set_vvar('errmsg', 42) eq('42', eval('v:errmsg')) - meths.set_vvar('oldfiles', { 'one', 'two' }) + api.nvim_set_vvar('oldfiles', { 'one', 'two' }) eq({ 'one', 'two' }, eval('v:oldfiles')) - meths.set_vvar('oldfiles', {}) + api.nvim_set_vvar('oldfiles', {}) eq({}, eval('v:oldfiles')) - eq('Setting v:oldfiles to value with wrong type', pcall_err(meths.set_vvar, 'oldfiles', 'a')) + eq( + 'Setting v:oldfiles to value with wrong type', + pcall_err(api.nvim_set_vvar, 'oldfiles', 'a') + ) eq({}, eval('v:oldfiles')) feed('i foo foo foo<Esc>0/foo<CR>') - eq({1, 1}, meths.win_get_cursor(0)) + eq({ 1, 1 }, api.nvim_win_get_cursor(0)) eq(1, eval('v:searchforward')) feed('n') - eq({1, 5}, meths.win_get_cursor(0)) - meths.set_vvar('searchforward', 0) + eq({ 1, 5 }, api.nvim_win_get_cursor(0)) + api.nvim_set_vvar('searchforward', 0) eq(0, eval('v:searchforward')) feed('n') - eq({1, 1}, meths.win_get_cursor(0)) - meths.set_vvar('searchforward', 1) + eq({ 1, 1 }, api.nvim_win_get_cursor(0)) + api.nvim_set_vvar('searchforward', 1) eq(1, eval('v:searchforward')) feed('n') - eq({1, 5}, meths.win_get_cursor(0)) + eq({ 1, 5 }, api.nvim_win_get_cursor(0)) local screen = Screen.new(60, 3) screen:set_default_attr_ids({ - [0] = {bold = true, foreground = Screen.colors.Blue}, - [1] = {background = Screen.colors.Yellow}, + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { background = Screen.colors.Yellow }, }) screen:attach() eq(1, eval('v:hlsearch')) - screen:expect{grid=[[ + screen:expect { + grid = [[ {1:foo} {1:^foo} {1:foo} | {0:~ }| | - ]]} - meths.set_vvar('hlsearch', 0) + ]], + } + api.nvim_set_vvar('hlsearch', 0) eq(0, eval('v:hlsearch')) - screen:expect{grid=[[ + screen:expect { + grid = [[ foo ^foo foo | {0:~ }| | - ]]} - meths.set_vvar('hlsearch', 1) + ]], + } + api.nvim_set_vvar('hlsearch', 1) eq(1, eval('v:hlsearch')) - screen:expect{grid=[[ + screen:expect { + grid = [[ {1:foo} {1:^foo} {1:foo} | {0:~ }| | - ]]} + ]], + } end) it('vim_set_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } eq(NIL, request('vim_set_var', 'lua', val1)) eq(val1, request('vim_set_var', 'lua', val2)) end) it('vim_del_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} - eq(NIL, request('vim_set_var', 'lua', val1)) + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } + eq(NIL, request('vim_set_var', 'lua', val1)) eq(val1, request('vim_set_var', 'lua', val2)) eq(val2, request('vim_del_var', 'lua')) end) it('truncates values with NULs in them', function() - nvim('set_var', 'xxx', 'ab\0cd') - eq('ab', nvim('get_var', 'xxx')) + api.nvim_set_var('xxx', 'ab\0cd') + eq('ab', api.nvim_get_var('xxx')) end) end) describe('nvim_get_option_value, nvim_set_option_value', function() it('works', function() - ok(nvim('get_option_value', 'equalalways', {})) - nvim('set_option_value', 'equalalways', false, {}) - ok(not nvim('get_option_value', 'equalalways', {})) + ok(api.nvim_get_option_value('equalalways', {})) + api.nvim_set_option_value('equalalways', false, {}) + ok(not api.nvim_get_option_value('equalalways', {})) end) it('works to get global value of local options', function() - eq(false, nvim('get_option_value', 'lisp', {})) - eq(8, nvim('get_option_value', 'shiftwidth', {})) + eq(false, api.nvim_get_option_value('lisp', {})) + eq(8, api.nvim_get_option_value('shiftwidth', {})) end) it('works to set global value of local options', function() - nvim('set_option_value', 'lisp', true, {scope='global'}) - eq(true, nvim('get_option_value', 'lisp', {scope='global'})) - eq(false, nvim('get_option_value', 'lisp', {})) - eq(nil, nvim('command_output', 'setglobal lisp?'):match('nolisp')) - eq('nolisp', nvim('command_output', 'setlocal lisp?'):match('nolisp')) - nvim('set_option_value', 'shiftwidth', 20, {scope='global'}) - eq('20', nvim('command_output', 'setglobal shiftwidth?'):match('%d+')) - eq('8', nvim('command_output', 'setlocal shiftwidth?'):match('%d+')) + api.nvim_set_option_value('lisp', true, { scope = 'global' }) + eq(true, api.nvim_get_option_value('lisp', { scope = 'global' })) + eq(false, api.nvim_get_option_value('lisp', {})) + eq(nil, command_output('setglobal lisp?'):match('nolisp')) + eq('nolisp', command_output('setlocal lisp?'):match('nolisp')) + api.nvim_set_option_value('shiftwidth', 20, { scope = 'global' }) + eq('20', command_output('setglobal shiftwidth?'):match('%d+')) + eq('8', command_output('setlocal shiftwidth?'):match('%d+')) end) it('updates where the option was last set from', function() - nvim('set_option_value', 'equalalways', false, {}) - local status, rv = pcall(nvim, 'command_output', - 'verbose set equalalways?') + api.nvim_set_option_value('equalalways', false, {}) + local status, rv = pcall(command_output, 'verbose set equalalways?') eq(true, status) - ok(nil ~= string.find(rv, 'noequalalways\n'.. - '\tLast set from API client %(channel id %d+%)')) + ok( + nil ~= string.find(rv, 'noequalalways\n' .. '\tLast set from API client %(channel id %d+%)') + ) - nvim('exec_lua', 'vim.api.nvim_set_option_value("equalalways", true, {})', {}) - status, rv = pcall(nvim, 'command_output', - 'verbose set equalalways?') + api.nvim_exec_lua('vim.api.nvim_set_option_value("equalalways", true, {})', {}) + status, rv = pcall(command_output, 'verbose set equalalways?') eq(true, status) eq(' equalalways\n\tLast set from Lua', rv) end) it('updates whether the option has ever been set #25025', function() - eq(false, nvim('get_option_info2', 'autochdir', {}).was_set) - nvim('set_option_value', 'autochdir', true, {}) - eq(true, nvim('get_option_info2', 'autochdir', {}).was_set) + eq(false, api.nvim_get_option_info2('autochdir', {}).was_set) + api.nvim_set_option_value('autochdir', true, {}) + eq(true, api.nvim_get_option_info2('autochdir', {}).was_set) - eq(false, nvim('get_option_info2', 'cmdwinheight', {}).was_set) - nvim('set_option_value', 'cmdwinheight', 10, {}) - eq(true, nvim('get_option_info2', 'cmdwinheight', {}).was_set) + eq(false, api.nvim_get_option_info2('cmdwinheight', {}).was_set) + api.nvim_set_option_value('cmdwinheight', 10, {}) + eq(true, api.nvim_get_option_info2('cmdwinheight', {}).was_set) - eq(false, nvim('get_option_info2', 'debug', {}).was_set) - nvim('set_option_value', 'debug', 'beep', {}) - eq(true, nvim('get_option_info2', 'debug', {}).was_set) + eq(false, api.nvim_get_option_info2('debug', {}).was_set) + api.nvim_set_option_value('debug', 'beep', {}) + eq(true, api.nvim_get_option_info2('debug', {}).was_set) end) it('validation', function() - eq("Invalid 'scope': expected 'local' or 'global'", - pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 'bogus'})) - eq("Invalid 'scope': expected 'local' or 'global'", - pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'})) - eq("Invalid 'scope': expected String, got Integer", - pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42})) - eq("Invalid 'value': expected valid option type, got Array", - pcall_err(nvim, 'set_option_value', 'scrolloff', {}, {})) - eq("Invalid value for option 'scrolloff': expected Number, got Boolean true", - pcall_err(nvim, 'set_option_value', 'scrolloff', true, {})) - eq("Invalid value for option 'scrolloff': expected Number, got String \"wrong\"", - pcall_err(nvim, 'set_option_value', 'scrolloff', 'wrong', {})) + eq( + "Invalid 'scope': expected 'local' or 'global'", + pcall_err(api.nvim_get_option_value, 'scrolloff', { scope = 'bogus' }) + ) + eq( + "Invalid 'scope': expected 'local' or 'global'", + pcall_err(api.nvim_set_option_value, 'scrolloff', 1, { scope = 'bogus' }) + ) + eq( + "Invalid 'scope': expected String, got Integer", + pcall_err(api.nvim_get_option_value, 'scrolloff', { scope = 42 }) + ) + eq( + "Invalid 'value': expected valid option type, got Array", + pcall_err(api.nvim_set_option_value, 'scrolloff', {}, {}) + ) + eq( + "Invalid value for option 'scrolloff': expected number, got boolean true", + pcall_err(api.nvim_set_option_value, 'scrolloff', true, {}) + ) + eq( + 'Invalid value for option \'scrolloff\': expected number, got string "wrong"', + pcall_err(api.nvim_set_option_value, 'scrolloff', 'wrong', {}) + ) end) it('can get local values when global value is set', function() - eq(0, nvim('get_option_value', 'scrolloff', {})) - eq(-1, nvim('get_option_value', 'scrolloff', {scope = 'local'})) + eq(0, api.nvim_get_option_value('scrolloff', {})) + eq(-1, api.nvim_get_option_value('scrolloff', { scope = 'local' })) end) it('can set global and local values', function() - nvim('set_option_value', 'makeprg', 'hello', {}) - eq('hello', nvim('get_option_value', 'makeprg', {})) - eq('', nvim('get_option_value', 'makeprg', {scope = 'local'})) - nvim('set_option_value', 'makeprg', 'world', {scope = 'local'}) - eq('world', nvim('get_option_value', 'makeprg', {scope = 'local'})) - nvim('set_option_value', 'makeprg', 'goodbye', {scope = 'global'}) - eq('goodbye', nvim('get_option_value', 'makeprg', {scope = 'global'})) - nvim('set_option_value', 'makeprg', 'hello', {}) - eq('hello', nvim('get_option_value', 'makeprg', {scope = 'global'})) - eq('hello', nvim('get_option_value', 'makeprg', {})) - eq('', nvim('get_option_value', 'makeprg', {scope = 'local'})) + api.nvim_set_option_value('makeprg', 'hello', {}) + eq('hello', api.nvim_get_option_value('makeprg', {})) + eq('', api.nvim_get_option_value('makeprg', { scope = 'local' })) + api.nvim_set_option_value('makeprg', 'world', { scope = 'local' }) + eq('world', api.nvim_get_option_value('makeprg', { scope = 'local' })) + api.nvim_set_option_value('makeprg', 'goodbye', { scope = 'global' }) + eq('goodbye', api.nvim_get_option_value('makeprg', { scope = 'global' })) + api.nvim_set_option_value('makeprg', 'hello', {}) + eq('hello', api.nvim_get_option_value('makeprg', { scope = 'global' })) + eq('hello', api.nvim_get_option_value('makeprg', {})) + eq('', api.nvim_get_option_value('makeprg', { scope = 'local' })) end) it('clears the local value of an option with nil', function() -- Set global value - nvim('set_option_value', 'shiftwidth', 42, {}) - eq(42, nvim('get_option_value', 'shiftwidth', {})) + api.nvim_set_option_value('shiftwidth', 42, {}) + eq(42, api.nvim_get_option_value('shiftwidth', {})) -- Set local value - nvim('set_option_value', 'shiftwidth', 8, {scope = 'local'}) - eq(8, nvim('get_option_value', 'shiftwidth', {})) - eq(8, nvim('get_option_value', 'shiftwidth', {scope = 'local'})) - eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'global'})) + api.nvim_set_option_value('shiftwidth', 8, { scope = 'local' }) + eq(8, api.nvim_get_option_value('shiftwidth', {})) + eq(8, api.nvim_get_option_value('shiftwidth', { scope = 'local' })) + eq(42, api.nvim_get_option_value('shiftwidth', { scope = 'global' })) -- Clear value without scope - nvim('set_option_value', 'shiftwidth', NIL, {}) - eq(42, nvim('get_option_value', 'shiftwidth', {})) - eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'local'})) + api.nvim_set_option_value('shiftwidth', NIL, {}) + eq(42, api.nvim_get_option_value('shiftwidth', {})) + eq(42, api.nvim_get_option_value('shiftwidth', { scope = 'local' })) -- Clear value with explicit scope - nvim('set_option_value', 'shiftwidth', 8, {scope = 'local'}) - nvim('set_option_value', 'shiftwidth', NIL, {scope = 'local'}) - eq(42, nvim('get_option_value', 'shiftwidth', {})) - eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'local'})) + api.nvim_set_option_value('shiftwidth', 8, { scope = 'local' }) + api.nvim_set_option_value('shiftwidth', NIL, { scope = 'local' }) + eq(42, api.nvim_get_option_value('shiftwidth', {})) + eq(42, api.nvim_get_option_value('shiftwidth', { scope = 'local' })) -- Now try with options with a special "local is unset" value (e.g. 'undolevels') - nvim('set_option_value', 'undolevels', 1000, {}) - nvim('set_option_value', 'undolevels', 1200, {scope = 'local'}) - eq(1200, nvim('get_option_value', 'undolevels', {scope = 'local'})) - nvim('set_option_value', 'undolevels', NIL, {scope = 'local'}) - eq(-123456, nvim('get_option_value', 'undolevels', {scope = 'local'})) - eq(1000, nvim('get_option_value', 'undolevels', {})) + api.nvim_set_option_value('undolevels', 1000, {}) + api.nvim_set_option_value('undolevels', 1200, { scope = 'local' }) + eq(1200, api.nvim_get_option_value('undolevels', { scope = 'local' })) + api.nvim_set_option_value('undolevels', NIL, { scope = 'local' }) + eq(-123456, api.nvim_get_option_value('undolevels', { scope = 'local' })) + eq(1000, api.nvim_get_option_value('undolevels', {})) - nvim('set_option_value', 'autoread', true, {}) - nvim('set_option_value', 'autoread', false, {scope = 'local'}) - eq(false, nvim('get_option_value', 'autoread', {scope = 'local'})) - nvim('set_option_value', 'autoread', NIL, {scope = 'local'}) - eq(NIL, nvim('get_option_value', 'autoread', {scope = 'local'})) - eq(true, nvim('get_option_value', 'autoread', {})) + api.nvim_set_option_value('autoread', true, {}) + api.nvim_set_option_value('autoread', false, { scope = 'local' }) + eq(false, api.nvim_get_option_value('autoread', { scope = 'local' })) + api.nvim_set_option_value('autoread', NIL, { scope = 'local' }) + eq(NIL, api.nvim_get_option_value('autoread', { scope = 'local' })) + eq(true, api.nvim_get_option_value('autoread', {})) end) it('set window options', function() - nvim('set_option_value', 'colorcolumn', '4,3', {}) - eq('4,3', nvim('get_option_value', 'colorcolumn', {scope = 'local'})) - command("set modified hidden") - command("enew") -- edit new buffer, window option is preserved - eq('4,3', nvim('get_option_value', 'colorcolumn', {scope = 'local'})) + api.nvim_set_option_value('colorcolumn', '4,3', {}) + eq('4,3', api.nvim_get_option_value('colorcolumn', { scope = 'local' })) + command('set modified hidden') + command('enew') -- edit new buffer, window option is preserved + eq('4,3', api.nvim_get_option_value('colorcolumn', { scope = 'local' })) end) it('set local window options', function() - nvim('set_option_value', 'colorcolumn', '4,3', {win=0, scope='local'}) - eq('4,3', nvim('get_option_value', 'colorcolumn', {win = 0, scope = 'local'})) - command("set modified hidden") - command("enew") -- edit new buffer, window option is reset - eq('', nvim('get_option_value', 'colorcolumn', {win = 0, scope = 'local'})) + api.nvim_set_option_value('colorcolumn', '4,3', { win = 0, scope = 'local' }) + eq('4,3', api.nvim_get_option_value('colorcolumn', { win = 0, scope = 'local' })) + command('set modified hidden') + command('enew') -- edit new buffer, window option is reset + eq('', api.nvim_get_option_value('colorcolumn', { win = 0, scope = 'local' })) end) it('get buffer or window-local options', function() - nvim('command', 'new') - local buf = nvim('get_current_buf').id - nvim('set_option_value', 'tagfunc', 'foobar', {buf=buf}) - eq('foobar', nvim('get_option_value', 'tagfunc', {buf = buf})) + command('new') + local buf = api.nvim_get_current_buf() + api.nvim_set_option_value('tagfunc', 'foobar', { buf = buf }) + eq('foobar', api.nvim_get_option_value('tagfunc', { buf = buf })) - local win = nvim('get_current_win').id - nvim('set_option_value', 'number', true, {win=win}) - eq(true, nvim('get_option_value', 'number', {win = win})) + local win = api.nvim_get_current_win() + api.nvim_set_option_value('number', true, { win = win }) + eq(true, api.nvim_get_option_value('number', { win = win })) end) it('getting current buffer option does not adjust cursor #19381', function() - nvim('command', 'new') - local buf = nvim('get_current_buf').id - local win = nvim('get_current_win').id + command('new') + local buf = api.nvim_get_current_buf() + print(vim.inspect(api.nvim_get_current_buf())) + local win = api.nvim_get_current_win() insert('some text') feed('0v$') - eq({1, 9}, nvim('win_get_cursor', win)) - nvim('get_option_value', 'filetype', {buf = buf}) - eq({1, 9}, nvim('win_get_cursor', win)) + eq({ 1, 9 }, api.nvim_win_get_cursor(win)) + api.nvim_get_option_value('filetype', { buf = buf }) + eq({ 1, 9 }, api.nvim_win_get_cursor(win)) end) it('can get default option values for filetypes', function() @@ -1593,158 +1745,160 @@ describe('API', function() for ft, opts in pairs { lua = { commentstring = '-- %s' }, vim = { commentstring = '"%s' }, - man = { tagfunc = 'v:lua.require\'man\'.goto_tag' }, - xml = { formatexpr = 'xmlformat#Format()' } + man = { tagfunc = "v:lua.require'man'.goto_tag" }, + xml = { formatexpr = 'xmlformat#Format()' }, } do for option, value in pairs(opts) do - eq(value, nvim('get_option_value', option, { filetype = ft })) + eq(value, api.nvim_get_option_value(option, { filetype = ft })) end end - command'au FileType lua setlocal commentstring=NEW\\ %s' + command 'au FileType lua setlocal commentstring=NEW\\ %s' - eq('NEW %s', nvim('get_option_value', 'commentstring', { filetype = 'lua' })) + eq('NEW %s', api.nvim_get_option_value('commentstring', { filetype = 'lua' })) end) it('errors for bad FileType autocmds', function() - command'au FileType lua setlocal commentstring=BAD' - eq([[FileType Autocommands for "lua": Vim(setlocal):E537: 'commentstring' must be empty or contain %s: commentstring=BAD]], - pcall_err(nvim, 'get_option_value', 'commentstring', { filetype = 'lua' })) + command 'au FileType lua setlocal commentstring=BAD' + eq( + [[FileType Autocommands for "lua": Vim(setlocal):E537: 'commentstring' must be empty or contain %s: commentstring=BAD]], + pcall_err(api.nvim_get_option_value, 'commentstring', { filetype = 'lua' }) + ) end) it("value of 'modified' is always false for scratch buffers", function() - nvim('set_current_buf', nvim('create_buf', true, true)) + api.nvim_set_current_buf(api.nvim_create_buf(true, true)) insert([[ foo bar baz ]]) - eq(false, nvim('get_option_value', 'modified', {})) + eq(false, api.nvim_get_option_value('modified', {})) end) end) describe('nvim_{get,set}_current_buf, nvim_list_bufs', function() it('works', function() - eq(1, #nvim('list_bufs')) - eq(nvim('list_bufs')[1], nvim('get_current_buf')) - nvim('command', 'new') - eq(2, #nvim('list_bufs')) - eq(nvim('list_bufs')[2], nvim('get_current_buf')) - nvim('set_current_buf', nvim('list_bufs')[1]) - eq(nvim('list_bufs')[1], nvim('get_current_buf')) + eq(1, #api.nvim_list_bufs()) + eq(api.nvim_list_bufs()[1], api.nvim_get_current_buf()) + command('new') + eq(2, #api.nvim_list_bufs()) + eq(api.nvim_list_bufs()[2], api.nvim_get_current_buf()) + api.nvim_set_current_buf(api.nvim_list_bufs()[1]) + eq(api.nvim_list_bufs()[1], api.nvim_get_current_buf()) end) end) describe('nvim_{get,set}_current_win, nvim_list_wins', function() it('works', function() - eq(1, #nvim('list_wins')) - eq(nvim('list_wins')[1], nvim('get_current_win')) - nvim('command', 'vsplit') - nvim('command', 'split') - eq(3, #nvim('list_wins')) - eq(nvim('list_wins')[1], nvim('get_current_win')) - nvim('set_current_win', nvim('list_wins')[2]) - eq(nvim('list_wins')[2], nvim('get_current_win')) + eq(1, #api.nvim_list_wins()) + eq(api.nvim_list_wins()[1], api.nvim_get_current_win()) + command('vsplit') + command('split') + eq(3, #api.nvim_list_wins()) + eq(api.nvim_list_wins()[1], api.nvim_get_current_win()) + api.nvim_set_current_win(api.nvim_list_wins()[2]) + eq(api.nvim_list_wins()[2], api.nvim_get_current_win()) end) end) describe('nvim_{get,set}_current_tabpage, nvim_list_tabpages', function() it('works', function() - eq(1, #nvim('list_tabpages')) - eq(nvim('list_tabpages')[1], nvim('get_current_tabpage')) - nvim('command', 'tabnew') - eq(2, #nvim('list_tabpages')) - eq(2, #nvim('list_wins')) - eq(nvim('list_wins')[2], nvim('get_current_win')) - eq(nvim('list_tabpages')[2], nvim('get_current_tabpage')) - nvim('set_current_win', nvim('list_wins')[1]) + eq(1, #api.nvim_list_tabpages()) + eq(api.nvim_list_tabpages()[1], api.nvim_get_current_tabpage()) + command('tabnew') + eq(2, #api.nvim_list_tabpages()) + eq(2, #api.nvim_list_wins()) + eq(api.nvim_list_wins()[2], api.nvim_get_current_win()) + eq(api.nvim_list_tabpages()[2], api.nvim_get_current_tabpage()) + api.nvim_set_current_win(api.nvim_list_wins()[1]) -- Switching window also switches tabpages if necessary - eq(nvim('list_tabpages')[1], nvim('get_current_tabpage')) - eq(nvim('list_wins')[1], nvim('get_current_win')) - nvim('set_current_tabpage', nvim('list_tabpages')[2]) - eq(nvim('list_tabpages')[2], nvim('get_current_tabpage')) - eq(nvim('list_wins')[2], nvim('get_current_win')) + eq(api.nvim_list_tabpages()[1], api.nvim_get_current_tabpage()) + eq(api.nvim_list_wins()[1], api.nvim_get_current_win()) + api.nvim_set_current_tabpage(api.nvim_list_tabpages()[2]) + eq(api.nvim_list_tabpages()[2], api.nvim_get_current_tabpage()) + eq(api.nvim_list_wins()[2], api.nvim_get_current_win()) end) end) describe('nvim_get_mode', function() - it("during normal-mode `g` returns blocking=true", function() - nvim("input", "o") -- add a line - eq({mode='i', blocking=false}, nvim("get_mode")) - nvim("input", [[<C-\><C-N>]]) - eq(2, nvim("eval", "line('.')")) - eq({mode='n', blocking=false}, nvim("get_mode")) + it('during normal-mode `g` returns blocking=true', function() + api.nvim_input('o') -- add a line + eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) + api.nvim_input([[<C-\><C-N>]]) + eq(2, api.nvim_eval("line('.')")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) - nvim("input", "g") - eq({mode='n', blocking=true}, nvim("get_mode")) + api.nvim_input('g') + eq({ mode = 'n', blocking = true }, api.nvim_get_mode()) - nvim("input", "k") -- complete the operator - eq(1, nvim("eval", "line('.')")) -- verify the completed operator - eq({mode='n', blocking=false}, nvim("get_mode")) + api.nvim_input('k') -- complete the operator + eq(1, api.nvim_eval("line('.')")) -- verify the completed operator + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) - it("returns the correct result multiple consecutive times", function() - for _ = 1,5 do - eq({mode='n', blocking=false}, nvim("get_mode")) + it('returns the correct result multiple consecutive times', function() + for _ = 1, 5 do + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end - nvim("input", "g") - for _ = 1,4 do - eq({mode='n', blocking=true}, nvim("get_mode")) + api.nvim_input('g') + for _ = 1, 4 do + eq({ mode = 'n', blocking = true }, api.nvim_get_mode()) end - nvim("input", "g") - for _ = 1,7 do - eq({mode='n', blocking=false}, nvim("get_mode")) + api.nvim_input('g') + for _ = 1, 7 do + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end end) - it("during normal-mode CTRL-W, returns blocking=true", function() - nvim("input", "<C-W>") - eq({mode='n', blocking=true}, nvim("get_mode")) + it('during normal-mode CTRL-W, returns blocking=true', function() + api.nvim_input('<C-W>') + eq({ mode = 'n', blocking = true }, api.nvim_get_mode()) - nvim("input", "s") -- complete the operator - eq(2, nvim("eval", "winnr('$')")) -- verify the completed operator - eq({mode='n', blocking=false}, nvim("get_mode")) + api.nvim_input('s') -- complete the operator + eq(2, api.nvim_eval("winnr('$')")) -- verify the completed operator + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) - it("during press-enter prompt without UI returns blocking=false", function() - eq({mode='n', blocking=false}, nvim("get_mode")) + it('during press-enter prompt without UI returns blocking=false', function() + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) command("echom 'msg1'") command("echom 'msg2'") command("echom 'msg3'") command("echom 'msg4'") command("echom 'msg5'") - eq({mode='n', blocking=false}, nvim("get_mode")) - nvim("input", ":messages<CR>") - eq({mode='n', blocking=false}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + api.nvim_input(':messages<CR>') + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) - it("during press-enter prompt returns blocking=true", function() - nvim("ui_attach", 80, 20, {}) - eq({mode='n', blocking=false}, nvim("get_mode")) + it('during press-enter prompt returns blocking=true', function() + api.nvim_ui_attach(80, 20, {}) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) command("echom 'msg1'") command("echom 'msg2'") command("echom 'msg3'") command("echom 'msg4'") command("echom 'msg5'") - eq({mode='n', blocking=false}, nvim("get_mode")) - nvim("input", ":messages<CR>") - eq({mode='r', blocking=true}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + api.nvim_input(':messages<CR>') + eq({ mode = 'r', blocking = true }, api.nvim_get_mode()) end) - it("during getchar() returns blocking=false", function() - nvim("input", ":let g:test_input = nr2char(getchar())<CR>") + it('during getchar() returns blocking=false', function() + api.nvim_input(':let g:test_input = nr2char(getchar())<CR>') -- Events are enabled during getchar(), RPC calls are *not* blocked. #5384 - eq({mode='n', blocking=false}, nvim("get_mode")) - eq(0, nvim("eval", "exists('g:test_input')")) - nvim("input", "J") - eq("J", nvim("eval", "g:test_input")) - eq({mode='n', blocking=false}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) + eq(0, api.nvim_eval("exists('g:test_input')")) + api.nvim_input('J') + eq('J', api.nvim_eval('g:test_input')) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) -- TODO: bug #6247#issuecomment-286403810 - it("batched with input", function() - nvim("ui_attach", 80, 20, {}) - eq({mode='n', blocking=false}, nvim("get_mode")) + it('batched with input', function() + api.nvim_ui_attach(80, 20, {}) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) command("echom 'msg1'") command("echom 'msg2'") command("echom 'msg3'") @@ -1752,44 +1906,48 @@ describe('API', function() command("echom 'msg5'") local req = { - {'nvim_get_mode', {}}, - {'nvim_input', {':messages<CR>'}}, - {'nvim_get_mode', {}}, - {'nvim_eval', {'1'}}, + { 'nvim_get_mode', {} }, + { 'nvim_input', { ':messages<CR>' } }, + { 'nvim_get_mode', {} }, + { 'nvim_eval', { '1' } }, } - eq({ { {mode='n', blocking=false}, - 13, - {mode='n', blocking=false}, -- TODO: should be blocked=true ? - 1 }, - NIL}, meths.call_atomic(req)) - eq({mode='r', blocking=true}, nvim("get_mode")) + eq({ + { + { mode = 'n', blocking = false }, + 13, + { mode = 'n', blocking = false }, -- TODO: should be blocked=true ? + 1, + }, + NIL, + }, api.nvim_call_atomic(req)) + eq({ mode = 'r', blocking = true }, api.nvim_get_mode()) end) - it("during insert-mode map-pending, returns blocking=true #6166", function() - command("inoremap xx foo") - nvim("input", "ix") - eq({mode='i', blocking=true}, nvim("get_mode")) + it('during insert-mode map-pending, returns blocking=true #6166', function() + command('inoremap xx foo') + api.nvim_input('ix') + eq({ mode = 'i', blocking = true }, api.nvim_get_mode()) end) - it("during normal-mode gU, returns blocking=false #6166", function() - nvim("input", "gu") - eq({mode='no', blocking=false}, nvim("get_mode")) + it('during normal-mode gU, returns blocking=false #6166', function() + api.nvim_input('gu') + eq({ mode = 'no', blocking = false }, api.nvim_get_mode()) end) it("at '-- More --' prompt returns blocking=true #11899", function() command('set more') feed(':digraphs<cr>') - eq({mode='rm', blocking=true}, nvim("get_mode")) + eq({ mode = 'rm', blocking = true }, api.nvim_get_mode()) end) it('after <Nop> mapping returns blocking=false #17257', function() command('nnoremap <F2> <Nop>') feed('<F2>') - eq({mode='n', blocking=false}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) it('after empty string <expr> mapping returns blocking=false #17257', function() command('nnoremap <expr> <F2> ""') feed('<F2>') - eq({mode='n', blocking=false}, nvim("get_mode")) + eq({ mode = 'n', blocking = false }, api.nvim_get_mode()) end) end) @@ -1798,16 +1956,16 @@ describe('API', function() helpers.insert([[ FIRST LINE SECOND LINE]]) - nvim('input', 'gg') - nvim('input', 'gu') + api.nvim_input('gg') + api.nvim_input('gu') -- Make any RPC request (can be non-async: op-pending does not block). - nvim('get_current_buf') + api.nvim_get_current_buf() -- Buffer should not change. expect([[ FIRST LINE SECOND LINE]]) -- Now send input to complete the operator. - nvim('input', 'j') + api.nvim_input('j') expect([[ first line second line]]) @@ -1821,7 +1979,7 @@ describe('API', function() feed('ia<cr>b<cr>c<cr><Esc>kkk') feed('d') -- Make any RPC request (can be non-async: op-pending does not block). - nvim('get_current_buf') + api.nvim_get_current_buf() screen:expect([[ ^a$ | b$ | @@ -1835,12 +1993,12 @@ describe('API', function() helpers.insert([[ FIRST LINE SECOND LINE]]) - nvim('input', 'gg') - nvim('input', 'd') + api.nvim_input('gg') + api.nvim_input('d') -- Make any RPC request (must be async, because map-pending blocks). - nvim('get_api_info') + api.nvim_get_api_info() -- Send input to complete the mapping. - nvim('input', 'd') + api.nvim_input('d') expect([[ FIRST LINE SECOND LINE]]) @@ -1853,11 +2011,11 @@ describe('API', function() helpers.insert([[ FIRST LINE SECOND LINE]]) - nvim('input', 'ix') + api.nvim_input('ix') -- Make any RPC request (must be async, because map-pending blocks). - nvim('get_api_info') + api.nvim_get_api_info() -- Send input to complete the mapping. - nvim('input', 'x') + api.nvim_input('x') expect([[ FIRST LINE SECOND LINfooE]]) @@ -1865,158 +2023,168 @@ describe('API', function() it('does not interrupt Insert mode i_CTRL-O #10035', function() feed('iHello World<c-o>') - eq({mode='niI', blocking=false}, meths.get_mode()) -- fast event - eq(2, eval('1+1')) -- causes K_EVENT key - eq({mode='niI', blocking=false}, meths.get_mode()) -- still in ctrl-o mode + eq({ mode = 'niI', blocking = false }, api.nvim_get_mode()) -- fast event + eq(2, eval('1+1')) -- causes K_EVENT key + eq({ mode = 'niI', blocking = false }, api.nvim_get_mode()) -- still in ctrl-o mode feed('dd') - eq({mode='i', blocking=false}, meths.get_mode()) -- left ctrl-o mode + eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) -- left ctrl-o mode expect('') -- executed the command end) it('does not interrupt Select mode v_CTRL-O #15688', function() feed('iHello World<esc>gh<c-o>') - eq({mode='vs', blocking=false}, meths.get_mode()) -- fast event - eq({mode='vs', blocking=false}, meths.get_mode()) -- again #15288 - eq(2, eval('1+1')) -- causes K_EVENT key - eq({mode='vs', blocking=false}, meths.get_mode()) -- still in ctrl-o mode + eq({ mode = 'vs', blocking = false }, api.nvim_get_mode()) -- fast event + eq({ mode = 'vs', blocking = false }, api.nvim_get_mode()) -- again #15288 + eq(2, eval('1+1')) -- causes K_EVENT key + eq({ mode = 'vs', blocking = false }, api.nvim_get_mode()) -- still in ctrl-o mode feed('^') - eq({mode='s', blocking=false}, meths.get_mode()) -- left ctrl-o mode + eq({ mode = 's', blocking = false }, api.nvim_get_mode()) -- left ctrl-o mode feed('h') - eq({mode='i', blocking=false}, meths.get_mode()) -- entered insert mode - expect('h') -- selection is the whole line and is replaced + eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) -- entered insert mode + expect('h') -- selection is the whole line and is replaced end) it('does not interrupt Insert mode i_0_CTRL-D #13997', function() command('set timeoutlen=9999') feed('i<Tab><Tab>a0') - eq(2, eval('1+1')) -- causes K_EVENT key + eq(2, eval('1+1')) -- causes K_EVENT key feed('<C-D>') - expect('a') -- recognized i_0_CTRL-D + expect('a') -- recognized i_0_CTRL-D end) it("does not interrupt with 'digraph'", function() command('set digraph') feed('i,') - eq(2, eval('1+1')) -- causes K_EVENT key + eq(2, eval('1+1')) -- causes K_EVENT key feed('<BS>') - eq(2, eval('1+1')) -- causes K_EVENT key + eq(2, eval('1+1')) -- causes K_EVENT key feed('.') - expect('…') -- digraph ",." worked + expect('…') -- digraph ",." worked feed('<Esc>') feed(':,') - eq(2, eval('1+1')) -- causes K_EVENT key + eq(2, eval('1+1')) -- causes K_EVENT key feed('<BS>') - eq(2, eval('1+1')) -- causes K_EVENT key + eq(2, eval('1+1')) -- causes K_EVENT key feed('.') - eq('…', funcs.getcmdline()) -- digraph ",." worked + eq('…', fn.getcmdline()) -- digraph ",." worked end) end) describe('nvim_get_context', function() it('validation', function() - eq("Invalid key: 'blah'", - pcall_err(nvim, 'get_context', {blah={}})) - eq("Invalid 'types': expected Array, got Integer", - pcall_err(nvim, 'get_context', {types=42})) - eq("Invalid 'type': 'zub'", - pcall_err(nvim, 'get_context', {types={'jumps', 'zub', 'zam',}})) + eq("Invalid key: 'blah'", pcall_err(api.nvim_get_context, { blah = {} })) + eq( + "Invalid 'types': expected Array, got Integer", + pcall_err(api.nvim_get_context, { types = 42 }) + ) + eq( + "Invalid 'type': 'zub'", + pcall_err(api.nvim_get_context, { types = { 'jumps', 'zub', 'zam' } }) + ) end) it('returns map of current editor state', function() - local opts = {types={'regs', 'jumps', 'bufs', 'gvars'}} - eq({}, parse_context(nvim('get_context', {}))) + local opts = { types = { 'regs', 'jumps', 'bufs', 'gvars' } } + eq({}, parse_context(api.nvim_get_context({}))) feed('i1<cr>2<cr>3<c-[>ddddddqahjklquuu') feed('gg') feed('G') command('edit! BUF1') command('edit BUF2') - nvim('set_var', 'one', 1) - nvim('set_var', 'Two', 2) - nvim('set_var', 'THREE', 3) + api.nvim_set_var('one', 1) + api.nvim_set_var('Two', 2) + api.nvim_set_var('THREE', 3) local expected_ctx = { ['regs'] = { - {['rt'] = 1, ['rc'] = {'1'}, ['n'] = 49, ['ru'] = true}, - {['rt'] = 1, ['rc'] = {'2'}, ['n'] = 50}, - {['rt'] = 1, ['rc'] = {'3'}, ['n'] = 51}, - {['rc'] = {'hjkl'}, ['n'] = 97}, + { ['rt'] = 1, ['rc'] = { '1' }, ['n'] = 49, ['ru'] = true }, + { ['rt'] = 1, ['rc'] = { '2' }, ['n'] = 50 }, + { ['rt'] = 1, ['rc'] = { '3' }, ['n'] = 51 }, + { ['rc'] = { 'hjkl' }, ['n'] = 97 }, }, - ['jumps'] = eval(([[ + ['jumps'] = eval((([[ filter(map(add( getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }), 'filter( { "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum }, { k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)') - ]]):gsub('\n', '')), + ]]):gsub('\n', ''))), ['bufs'] = eval([[ filter(map(getbufinfo(), '{ "f": v:val.name }'), '!empty(v:val.f)') ]]), - ['gvars'] = {{'one', 1}, {'Two', 2}, {'THREE', 3}}, + ['gvars'] = { { 'one', 1 }, { 'Two', 2 }, { 'THREE', 3 } }, } - eq(expected_ctx, parse_context(nvim('get_context', opts))) - eq(expected_ctx, parse_context(nvim('get_context', {}))) - eq(expected_ctx, parse_context(nvim('get_context', {types={}}))) + eq(expected_ctx, parse_context(api.nvim_get_context(opts))) + eq(expected_ctx, parse_context(api.nvim_get_context({}))) + eq(expected_ctx, parse_context(api.nvim_get_context({ types = {} }))) end) end) describe('nvim_load_context', function() it('sets current editor state to given context dictionary', function() - local opts = {types={'regs', 'jumps', 'bufs', 'gvars'}} - eq({}, parse_context(nvim('get_context', opts))) + local opts = { types = { 'regs', 'jumps', 'bufs', 'gvars' } } + eq({}, parse_context(api.nvim_get_context(opts))) - nvim('set_var', 'one', 1) - nvim('set_var', 'Two', 2) - nvim('set_var', 'THREE', 3) - local ctx = nvim('get_context', opts) - nvim('set_var', 'one', 'a') - nvim('set_var', 'Two', 'b') - nvim('set_var', 'THREE', 'c') - eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]')) - nvim('load_context', ctx) - eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]')) + api.nvim_set_var('one', 1) + api.nvim_set_var('Two', 2) + api.nvim_set_var('THREE', 3) + local ctx = api.nvim_get_context(opts) + api.nvim_set_var('one', 'a') + api.nvim_set_var('Two', 'b') + api.nvim_set_var('THREE', 'c') + eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]')) + api.nvim_load_context(ctx) + eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]')) end) it('errors when context dictionary is invalid', function() - eq('E474: Failed to convert list to msgpack string buffer', - pcall_err(nvim, 'load_context', { regs = { {} }, jumps = { {} } })) - eq("Empty dictionary keys aren't allowed", - pcall_err(nvim, 'load_context', { regs = { { [''] = '' } } })) + eq( + 'E474: Failed to convert list to msgpack string buffer', + pcall_err(api.nvim_load_context, { regs = { {} }, jumps = { {} } }) + ) + eq( + 'E474: Failed to convert list to msgpack string buffer', + pcall_err(api.nvim_load_context, { regs = { { [''] = '' } } }) + ) end) end) describe('nvim_replace_termcodes', function() it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function() - eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true)) + eq('\128\254X', helpers.api.nvim_replace_termcodes('\128', true, true, true)) end) it('leaves non-K_SPECIAL string unchanged', function() - eq('abc', helpers.nvim('replace_termcodes', 'abc', true, true, true)) + eq('abc', helpers.api.nvim_replace_termcodes('abc', true, true, true)) end) it('converts <expressions>', function() - eq('\\', helpers.nvim('replace_termcodes', '<Leader>', true, true, true)) + eq('\\', helpers.api.nvim_replace_termcodes('<Leader>', true, true, true)) end) it('converts <LeftMouse> to K_SPECIAL KS_EXTRA KE_LEFTMOUSE', function() -- K_SPECIAL KS_EXTRA KE_LEFTMOUSE -- 0x80 0xfd 0x2c -- 128 253 44 - eq('\128\253\44', helpers.nvim('replace_termcodes', - '<LeftMouse>', true, true, true)) + eq('\128\253\44', helpers.api.nvim_replace_termcodes('<LeftMouse>', true, true, true)) end) it('converts keycodes', function() - eq('\nx\27x\rx<x', helpers.nvim('replace_termcodes', - '<NL>x<Esc>x<CR>x<lt>x', true, true, true)) + eq( + '\nx\27x\rx<x', + helpers.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, true) + ) end) it('does not convert keycodes if special=false', function() - eq('<NL>x<Esc>x<CR>x<lt>x', helpers.nvim('replace_termcodes', - '<NL>x<Esc>x<CR>x<lt>x', true, true, false)) + eq( + '<NL>x<Esc>x<CR>x<lt>x', + helpers.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, false) + ) end) it('does not crash when transforming an empty string', function() @@ -2027,13 +2195,13 @@ describe('API', function() -- then `return str` in vim_replace_termcodes body will make Neovim free -- `str.data` twice: once when freeing arguments, then when freeing return -- value. - eq('', meths.replace_termcodes('', true, true, true)) + eq('', api.nvim_replace_termcodes('', true, true, true)) end) -- Not exactly the case, as nvim_replace_termcodes() escapes K_SPECIAL in Unicode it('translates the result of keytrans() on string with 0x80 byte back', function() local s = 'ff\128\253\097tt' - eq(s, meths.replace_termcodes(funcs.keytrans(s), true, true, true)) + eq(s, api.nvim_replace_termcodes(fn.keytrans(s), true, true, true)) end) end) @@ -2041,15 +2209,15 @@ describe('API', function() it('K_SPECIAL escaping', function() local function on_setup() -- notice the special char(…) \xe2\80\xa6 - nvim('feedkeys', ':let x1="…"\n', '', true) + api.nvim_feedkeys(':let x1="…"\n', '', true) -- Both nvim_replace_termcodes and nvim_feedkeys escape \x80 - local inp = helpers.nvim('replace_termcodes', ':let x2="…"<CR>', true, true, true) - nvim('feedkeys', inp, '', true) -- escape_ks=true + local inp = helpers.api.nvim_replace_termcodes(':let x2="…"<CR>', true, true, true) + api.nvim_feedkeys(inp, '', true) -- escape_ks=true -- nvim_feedkeys with K_SPECIAL escaping disabled - inp = helpers.nvim('replace_termcodes', ':let x3="…"<CR>', true, true, true) - nvim('feedkeys', inp, '', false) -- escape_ks=false + inp = helpers.api.nvim_replace_termcodes(':let x3="…"<CR>', true, true, true) + api.nvim_feedkeys(inp, '', false) -- escape_ks=false helpers.stop() end @@ -2057,10 +2225,10 @@ describe('API', function() -- spin the loop a bit helpers.run(nil, nil, on_setup) - eq('…', nvim('get_var', 'x1')) + eq('…', api.nvim_get_var('x1')) -- Because of the double escaping this is neq - neq('…', nvim('get_var', 'x2')) - eq('…', nvim('get_var', 'x3')) + neq('…', api.nvim_get_var('x2')) + eq('…', api.nvim_get_var('x3')) end) end) @@ -2071,10 +2239,10 @@ describe('API', function() screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold = true, foreground = Screen.colors.Blue}, - [1] = {bold = true, foreground = Screen.colors.SeaGreen}, - [2] = {bold = true, reverse = true}, - [3] = {foreground = Screen.colors.Blue}, + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { bold = true, foreground = Screen.colors.SeaGreen }, + [2] = { bold = true, reverse = true }, + [3] = { foreground = Screen.colors.Blue }, }) end) @@ -2095,47 +2263,48 @@ describe('API', function() silent! call nvim_out_write("\n") redir END ]]) - eq('\naaa\n' .. ('a'):rep(5002) .. '\naaa', meths.get_var('out')) + eq('\naaa\n' .. ('a'):rep(5002) .. '\naaa', api.nvim_get_var('out')) end) it('blank line in message', function() feed([[:call nvim_out_write("\na\n")<CR>]]) - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {2: }| | a | {1:Press ENTER or type command to continue}^ | - ]]} + ]], + } feed('<CR>') feed([[:call nvim_out_write("b\n\nc\n")<CR>]]) - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| + {0:~ }|*2 {2: }| b | | c | {1:Press ENTER or type command to continue}^ | - ]]} + ]], + } end) it('NUL bytes in message', function() feed([[:lua vim.api.nvim_out_write('aaa\0bbb\0\0ccc\nddd\0\0\0eee\n')<CR>]]) - screen:expect{grid=[[ + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {2: }| aaa{3:^@}bbb{3:^@^@}ccc | ddd{3:^@^@^@}eee | {1:Press ENTER or type command to continue}^ | - ]]} + ]], + } end) end) @@ -2146,34 +2315,27 @@ describe('API', function() screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, - [1] = {foreground = Screen.colors.White, background = Screen.colors.Red}, - [2] = {bold = true, foreground = Screen.colors.SeaGreen}, - [3] = {bold = true, reverse = true}, + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { foreground = Screen.colors.White, background = Screen.colors.Red }, + [2] = { bold = true, foreground = Screen.colors.SeaGreen }, + [3] = { bold = true, reverse = true }, }) end) it('can show one line', function() - nvim_async('err_write', 'has bork\n') + async_meths.nvim_err_write('has bork\n') screen:expect([[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 {1:has bork} | ]]) end) it('shows return prompt when more than &cmdheight lines', function() - nvim_async('err_write', 'something happened\nvery bad\n') + async_meths.nvim_err_write('something happened\nvery bad\n') screen:expect([[ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3: }| {1:something happened} | {1:very bad} | @@ -2182,7 +2344,7 @@ describe('API', function() end) it('shows return prompt after all lines are shown', function() - nvim_async('err_write', 'FAILURE\nERROR\nEXCEPTION\nTRACEBACK\n') + async_meths.nvim_err_write('FAILURE\nERROR\nEXCEPTION\nTRACEBACK\n') screen:expect([[ | {0:~ }| @@ -2197,47 +2359,40 @@ describe('API', function() it('handles multiple calls', function() -- without linebreak text is joined to one line - nvim_async('err_write', 'very ') - nvim_async('err_write', 'fail\n') + async_meths.nvim_err_write('very ') + async_meths.nvim_err_write('fail\n') screen:expect([[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 {1:very fail} | ]]) helpers.poke_eventloop() -- shows up to &cmdheight lines - nvim_async('err_write', 'more fail\ntoo fail\n') + async_meths.nvim_err_write('more fail\ntoo fail\n') screen:expect([[ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3: }| {1:more fail} | {1:too fail} | {2:Press ENTER or type command to continue}^ | ]]) - feed('<cr>') -- exit the press ENTER screen + feed('<cr>') -- exit the press ENTER screen end) it('NUL bytes in message', function() - nvim_async('err_write', 'aaa\0bbb\0\0ccc\nddd\0\0\0eee\n') - screen:expect{grid=[[ + async_meths.nvim_err_write('aaa\0bbb\0\0ccc\nddd\0\0\0eee\n') + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {3: }| {1:aaa^@bbb^@^@ccc} | {1:ddd^@^@^@eee} | {2:Press ENTER or type command to continue}^ | - ]]} + ]], + } end) end) @@ -2248,15 +2403,15 @@ describe('API', function() screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, - [1] = {foreground = Screen.colors.White, background = Screen.colors.Red}, - [2] = {bold = true, foreground = Screen.colors.SeaGreen}, - [3] = {bold = true, reverse = true}, + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { foreground = Screen.colors.White, background = Screen.colors.Red }, + [2] = { bold = true, foreground = Screen.colors.SeaGreen }, + [3] = { bold = true, reverse = true }, }) end) it('shows only one return prompt after all lines are shown', function() - nvim_async('err_writeln', 'FAILURE\nERROR\nEXCEPTION\nTRACEBACK') + async_meths.nvim_err_writeln('FAILURE\nERROR\nEXCEPTION\nTRACEBACK') screen:expect([[ | {0:~ }| @@ -2270,12 +2425,7 @@ describe('API', function() feed('<CR>') screen:expect([[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 | ]]) end) @@ -2299,116 +2449,126 @@ describe('API', function() } it('returns {} for invalid channel', function() - eq({}, meths.get_chan_info(0)) - eq({}, meths.get_chan_info(-1)) + eq({}, api.nvim_get_chan_info(-1)) -- more preallocated numbers might be added, try something high - eq({}, meths.get_chan_info(10)) + eq({}, api.nvim_get_chan_info(10)) end) it('stream=stdio channel', function() - eq({[1]=testinfo,[2]=stderr}, meths.list_chans()) - eq(testinfo, meths.get_chan_info(1)) - eq(stderr, meths.get_chan_info(2)) - - meths.set_client_info("functionaltests", - {major=0, minor=3, patch=17}, - 'ui', - {do_stuff={n_args={2,3}}}, - {license= 'Apache2'}) + eq({ [1] = testinfo, [2] = stderr }, api.nvim_list_chans()) + -- 0 should return current channel + eq(testinfo, api.nvim_get_chan_info(0)) + eq(testinfo, api.nvim_get_chan_info(1)) + eq(stderr, api.nvim_get_chan_info(2)) + + api.nvim_set_client_info( + 'functionaltests', + { major = 0, minor = 3, patch = 17 }, + 'ui', + { do_stuff = { n_args = { 2, 3 } } }, + { license = 'Apache2' } + ) local info = { stream = 'stdio', id = 1, mode = 'rpc', client = { - name='functionaltests', - version={major=0, minor=3, patch=17}, - type='ui', - methods={do_stuff={n_args={2,3}}}, - attributes={license='Apache2'}, + name = 'functionaltests', + version = { major = 0, minor = 3, patch = 17 }, + type = 'ui', + methods = { do_stuff = { n_args = { 2, 3 } } }, + attributes = { license = 'Apache2' }, }, } - eq({info=info}, meths.get_var("info_event")) - eq({[1]=info, [2]=stderr}, meths.list_chans()) - eq(info, meths.get_chan_info(1)) + eq({ info = info }, api.nvim_get_var('info_event')) + eq({ [1] = info, [2] = stderr }, api.nvim_list_chans()) + eq(info, api.nvim_get_chan_info(1)) end) it('stream=job channel', function() eq(3, eval("jobstart(['cat'], {'rpc': v:true})")) local catpath = eval('exepath("cat")') local info = { - stream='job', - id=3, - argv={ catpath }, - mode='rpc', - client={}, + stream = 'job', + id = 3, + argv = { catpath }, + mode = 'rpc', + client = {}, } - eq({info=info}, meths.get_var("opened_event")) - eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans()) - eq(info, meths.get_chan_info(3)) - eval('rpcrequest(3, "nvim_set_client_info", "amazing-cat", {}, "remote",'.. - '{"nvim_command":{"n_args":1}},'.. -- and so on - '{"description":"The Amazing Cat"})') + eq({ info = info }, api.nvim_get_var('opened_event')) + eq({ [1] = testinfo, [2] = stderr, [3] = info }, api.nvim_list_chans()) + eq(info, api.nvim_get_chan_info(3)) + eval( + 'rpcrequest(3, "nvim_set_client_info", "amazing-cat", {}, "remote",' + .. '{"nvim_command":{"n_args":1}},' -- and so on + .. '{"description":"The Amazing Cat"})' + ) info = { - stream='job', - id=3, - argv={ catpath }, - mode='rpc', + stream = 'job', + id = 3, + argv = { catpath }, + mode = 'rpc', client = { - name='amazing-cat', - version={major=0}, - type='remote', - methods={nvim_command={n_args=1}}, - attributes={description="The Amazing Cat"}, + name = 'amazing-cat', + version = { major = 0 }, + type = 'remote', + methods = { nvim_command = { n_args = 1 } }, + attributes = { description = 'The Amazing Cat' }, }, } - eq({info=info}, meths.get_var("info_event")) - eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans()) + eq({ info = info }, api.nvim_get_var('info_event')) + eq({ [1] = testinfo, [2] = stderr, [3] = info }, api.nvim_list_chans()) - eq("Vim:Error invoking 'nvim_set_current_buf' on channel 3 (amazing-cat):\nWrong type for argument 1 when calling nvim_set_current_buf, expecting Buffer", - pcall_err(eval, 'rpcrequest(3, "nvim_set_current_buf", -1)')) + eq( + "Vim:Error invoking 'nvim_set_current_buf' on channel 3 (amazing-cat):\nWrong type for argument 1 when calling nvim_set_current_buf, expecting Buffer", + pcall_err(eval, 'rpcrequest(3, "nvim_set_current_buf", -1)') + ) + eq(info, eval('rpcrequest(3, "nvim_get_chan_info", 0)')) end) it('stream=job :terminal channel', function() command(':terminal') - eq({id=1}, meths.get_current_buf()) - eq(3, meths.get_option_value('channel', {buf=1})) + eq(1, api.nvim_get_current_buf()) + eq(3, api.nvim_get_option_value('channel', { buf = 1 })) local info = { - stream='job', - id=3, - argv={ eval('exepath(&shell)') }, - mode='terminal', + stream = 'job', + id = 3, + argv = { eval('exepath(&shell)') }, + mode = 'terminal', buffer = 1, - pty='?', + pty = '?', } - local event = meths.get_var("opened_event") + local event = api.nvim_get_var('opened_event') if not is_os('win') then info.pty = event.info.pty - neq(nil, string.match(info.pty, "^/dev/")) + neq(nil, string.match(info.pty, '^/dev/')) end - eq({info=info}, event) - info.buffer = {id=1} - eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans()) - eq(info, meths.get_chan_info(3)) + eq({ info = info }, event) + info.buffer = 1 + eq({ [1] = testinfo, [2] = stderr, [3] = info }, api.nvim_list_chans()) + eq(info, api.nvim_get_chan_info(3)) -- :terminal with args + running process. - command(':exe "terminal" shellescape(v:progpath) "-u NONE -i NONE"') - eq(-1, eval('jobwait([&channel], 0)[0]')) -- Running? + command('enew') + local progpath_esc = eval('shellescape(v:progpath)') + fn.termopen(('%s -u NONE -i NONE'):format(progpath_esc), { + env = { VIMRUNTIME = os.getenv('VIMRUNTIME') }, + }) + eq(-1, eval('jobwait([&channel], 0)[0]')) -- Running? local expected2 = { stream = 'job', id = 4, - argv = ( - is_os('win') and { - eval('&shell'), - '/s', - '/c', - fmt('"%s -u NONE -i NONE"', eval('shellescape(v:progpath)')), - } or { - eval('&shell'), - eval('&shellcmdflag'), - fmt('%s -u NONE -i NONE', eval('shellescape(v:progpath)')), - } - ), + argv = (is_os('win') and { + eval('&shell'), + '/s', + '/c', + fmt('"%s -u NONE -i NONE"', progpath_esc), + } or { + eval('&shell'), + eval('&shellcmdflag'), + fmt('%s -u NONE -i NONE', progpath_esc), + }), mode = 'terminal', buffer = 2, pty = '?', @@ -2419,163 +2579,172 @@ describe('API', function() -- :terminal with args + stopped process. eq(1, eval('jobstop(&channel)')) - eval('jobwait([&channel], 1000)') -- Wait. - expected2.pty = (is_os('win') and '?' or '') -- pty stream was closed. + eval('jobwait([&channel], 1000)') -- Wait. + expected2.pty = (is_os('win') and '?' or '') -- pty stream was closed. eq(expected2, eval('nvim_get_chan_info(&channel)')) end) end) describe('nvim_call_atomic', function() it('works', function() - meths.buf_set_lines(0, 0, -1, true, {'first'}) + api.nvim_buf_set_lines(0, 0, -1, true, { 'first' }) local req = { - {'nvim_get_current_line', {}}, - {'nvim_set_current_line', {'second'}}, + { 'nvim_get_current_line', {} }, + { 'nvim_set_current_line', { 'second' } }, } - eq({{'first', NIL}, NIL}, meths.call_atomic(req)) - eq({'second'}, meths.buf_get_lines(0, 0, -1, true)) + eq({ { 'first', NIL }, NIL }, api.nvim_call_atomic(req)) + eq({ 'second' }, api.nvim_buf_get_lines(0, 0, -1, true)) end) it('allows multiple return values', function() local req = { - {'nvim_set_var', {'avar', true}}, - {'nvim_set_var', {'bvar', 'string'}}, - {'nvim_get_var', {'avar'}}, - {'nvim_get_var', {'bvar'}}, + { 'nvim_set_var', { 'avar', true } }, + { 'nvim_set_var', { 'bvar', 'string' } }, + { 'nvim_get_var', { 'avar' } }, + { 'nvim_get_var', { 'bvar' } }, } - eq({{NIL, NIL, true, 'string'}, NIL}, meths.call_atomic(req)) + eq({ { NIL, NIL, true, 'string' }, NIL }, api.nvim_call_atomic(req)) end) it('is aborted by errors in call', function() - local error_types = meths.get_api_info()[2].error_types + local error_types = api.nvim_get_api_info()[2].error_types local req = { - {'nvim_set_var', {'one', 1}}, - {'nvim_buf_set_lines', {}}, - {'nvim_set_var', {'two', 2}}, + { 'nvim_set_var', { 'one', 1 } }, + { 'nvim_buf_set_lines', {} }, + { 'nvim_set_var', { 'two', 2 } }, } - eq({{NIL}, {1, error_types.Exception.id, - 'Wrong number of arguments: expecting 5 but got 0'}}, - meths.call_atomic(req)) - eq(1, meths.get_var('one')) - eq(false, pcall(meths.get_var, 'two')) + eq({ + { NIL }, + { + 1, + error_types.Exception.id, + 'Wrong number of arguments: expecting 5 but got 0', + }, + }, api.nvim_call_atomic(req)) + eq(1, api.nvim_get_var('one')) + eq(false, pcall(api.nvim_get_var, 'two')) -- still returns all previous successful calls req = { - {'nvim_set_var', {'avar', 5}}, - {'nvim_set_var', {'bvar', 'string'}}, - {'nvim_get_var', {'avar'}}, - {'nvim_buf_get_lines', {0, 10, 20, true}}, - {'nvim_get_var', {'bvar'}}, + { 'nvim_set_var', { 'avar', 5 } }, + { 'nvim_set_var', { 'bvar', 'string' } }, + { 'nvim_get_var', { 'avar' } }, + { 'nvim_buf_get_lines', { 0, 10, 20, true } }, + { 'nvim_get_var', { 'bvar' } }, } - eq({{NIL, NIL, 5}, {3, error_types.Validation.id, 'Index out of bounds'}}, - meths.call_atomic(req)) + eq( + { { NIL, NIL, 5 }, { 3, error_types.Validation.id, 'Index out of bounds' } }, + api.nvim_call_atomic(req) + ) req = { - {'i_am_not_a_method', {'xx'}}, - {'nvim_set_var', {'avar', 10}}, + { 'i_am_not_a_method', { 'xx' } }, + { 'nvim_set_var', { 'avar', 10 } }, } - eq({{}, {0, error_types.Exception.id, 'Invalid method: i_am_not_a_method'}}, - meths.call_atomic(req)) - eq(5, meths.get_var('avar')) + eq( + { {}, { 0, error_types.Exception.id, 'Invalid method: i_am_not_a_method' } }, + api.nvim_call_atomic(req) + ) + eq(5, api.nvim_get_var('avar')) end) it('validation', function() local req = { - {'nvim_set_var', {'avar', 1}}, - {'nvim_set_var'}, - {'nvim_set_var', {'avar', 2}}, + { 'nvim_set_var', { 'avar', 1 } }, + { 'nvim_set_var' }, + { 'nvim_set_var', { 'avar', 2 } }, } - eq("Invalid 'calls' item: expected 2-item Array", - pcall_err(meths.call_atomic, req)) + eq("Invalid 'calls' item: expected 2-item Array", pcall_err(api.nvim_call_atomic, req)) -- call before was done, but not after - eq(1, meths.get_var('avar')) + eq(1, api.nvim_get_var('avar')) req = { { 'nvim_set_var', { 'bvar', { 2, 3 } } }, 12, } - eq("Invalid 'calls' item: expected Array, got Integer", - pcall_err(meths.call_atomic, req)) - eq({2,3}, meths.get_var('bvar')) + eq("Invalid 'calls' item: expected Array, got Integer", pcall_err(api.nvim_call_atomic, req)) + eq({ 2, 3 }, api.nvim_get_var('bvar')) req = { - {'nvim_set_current_line', 'little line'}, - {'nvim_set_var', {'avar', 3}}, + { 'nvim_set_current_line', 'little line' }, + { 'nvim_set_var', { 'avar', 3 } }, } - eq("Invalid call args: expected Array, got String", - pcall_err(meths.call_atomic, req)) + eq('Invalid call args: expected Array, got String', pcall_err(api.nvim_call_atomic, req)) -- call before was done, but not after - eq(1, meths.get_var('avar')) - eq({''}, meths.buf_get_lines(0, 0, -1, true)) + eq(1, api.nvim_get_var('avar')) + eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, true)) end) end) describe('nvim_list_runtime_paths', function() setup(function() local pathsep = helpers.get_pathsep() - mkdir_p('Xtest'..pathsep..'a') - mkdir_p('Xtest'..pathsep..'b') + mkdir_p('Xtest' .. pathsep .. 'a') + mkdir_p('Xtest' .. pathsep .. 'b') end) teardown(function() rmdir 'Xtest' end) before_each(function() - meths.set_current_dir 'Xtest' + api.nvim_set_current_dir 'Xtest' end) it('returns nothing with empty &runtimepath', function() - meths.set_option_value('runtimepath', '', {}) - eq({}, meths.list_runtime_paths()) + api.nvim_set_option_value('runtimepath', '', {}) + eq({}, api.nvim_list_runtime_paths()) end) it('returns single runtimepath', function() - meths.set_option_value('runtimepath', 'a', {}) - eq({'a'}, meths.list_runtime_paths()) + api.nvim_set_option_value('runtimepath', 'a', {}) + eq({ 'a' }, api.nvim_list_runtime_paths()) end) it('returns two runtimepaths', function() - meths.set_option_value('runtimepath', 'a,b', {}) - eq({'a', 'b'}, meths.list_runtime_paths()) + api.nvim_set_option_value('runtimepath', 'a,b', {}) + eq({ 'a', 'b' }, api.nvim_list_runtime_paths()) end) it('returns empty strings when appropriate', function() - meths.set_option_value('runtimepath', 'a,,b', {}) - eq({'a', '', 'b'}, meths.list_runtime_paths()) - meths.set_option_value('runtimepath', ',a,b', {}) - eq({'', 'a', 'b'}, meths.list_runtime_paths()) + api.nvim_set_option_value('runtimepath', 'a,,b', {}) + eq({ 'a', '', 'b' }, api.nvim_list_runtime_paths()) + api.nvim_set_option_value('runtimepath', ',a,b', {}) + eq({ '', 'a', 'b' }, api.nvim_list_runtime_paths()) -- Trailing "," is ignored. Use ",," if you really really want CWD. - meths.set_option_value('runtimepath', 'a,b,', {}) - eq({'a', 'b'}, meths.list_runtime_paths()) - meths.set_option_value('runtimepath', 'a,b,,', {}) - eq({'a', 'b', ''}, meths.list_runtime_paths()) + api.nvim_set_option_value('runtimepath', 'a,b,', {}) + eq({ 'a', 'b' }, api.nvim_list_runtime_paths()) + api.nvim_set_option_value('runtimepath', 'a,b,,', {}) + eq({ 'a', 'b', '' }, api.nvim_list_runtime_paths()) end) it('truncates too long paths', function() local long_path = ('/a'):rep(8192) - meths.set_option_value('runtimepath', long_path, {}) - local paths_list = meths.list_runtime_paths() + api.nvim_set_option_value('runtimepath', long_path, {}) + local paths_list = api.nvim_list_runtime_paths() eq({}, paths_list) end) end) it('can throw exceptions', function() - local status, err = pcall(nvim, 'get_option_value', 'invalid-option', {}) + local status, err = pcall(api.nvim_get_option_value, 'invalid-option', {}) eq(false, status) ok(err:match("Unknown option 'invalid%-option'") ~= nil) end) it('does not truncate error message <1 MB #5984', function() - local very_long_name = 'A'..('x'):rep(10000)..'Z' - local status, err = pcall(nvim, 'get_option_value', very_long_name, {}) + local very_long_name = 'A' .. ('x'):rep(10000) .. 'Z' + local status, err = pcall(api.nvim_get_option_value, very_long_name, {}) eq(false, status) eq(very_long_name, err:match('Ax+Z?')) end) - it("does not leak memory on incorrect argument types", function() - local status, err = pcall(nvim, 'set_current_dir',{'not', 'a', 'dir'}) + it('does not leak memory on incorrect argument types', function() + local status, err = pcall(api.nvim_set_current_dir, { 'not', 'a', 'dir' }) eq(false, status) - ok(err:match(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String') ~= nil) + ok( + err:match(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String') + ~= nil + ) end) describe('nvim_parse_expression', function() before_each(function() - meths.set_option_value('isident', '', {}) + api.nvim_set_option_value('isident', '', {}) end) local function simplify_east_api_node(line, east_api_node) @@ -2589,21 +2758,26 @@ describe('API', function() end local typ = east_api_node.type if typ == 'Register' then - typ = typ .. ('(name=%s)'):format( - tostring(intchar2lua(east_api_node.name))) + typ = typ .. ('(name=%s)'):format(tostring(intchar2lua(east_api_node.name))) east_api_node.name = nil elseif typ == 'PlainIdentifier' then - typ = typ .. ('(scope=%s,ident=%s)'):format( - tostring(intchar2lua(east_api_node.scope)), east_api_node.ident) + typ = typ + .. ('(scope=%s,ident=%s)'):format( + tostring(intchar2lua(east_api_node.scope)), + east_api_node.ident + ) east_api_node.scope = nil east_api_node.ident = nil elseif typ == 'PlainKey' then typ = typ .. ('(key=%s)'):format(east_api_node.ident) east_api_node.ident = nil elseif typ == 'Comparison' then - typ = typ .. ('(type=%s,inv=%u,ccs=%s)'):format( - east_api_node.cmp_type, east_api_node.invert and 1 or 0, - east_api_node.ccs_strategy) + typ = typ + .. ('(type=%s,inv=%u,ccs=%s)'):format( + east_api_node.cmp_type, + east_api_node.invert and 1 or 0, + east_api_node.ccs_strategy + ) east_api_node.ccs_strategy = nil east_api_node.cmp_type = nil east_api_node.invert = nil @@ -2620,7 +2794,8 @@ describe('API', function() typ = ('%s(scope=%s,ident=%s)'):format( typ, tostring(intchar2lua(east_api_node.scope)), - east_api_node.ident) + east_api_node.ident + ) east_api_node.ident = nil east_api_node.scope = nil elseif typ == 'Environment' then @@ -2628,24 +2803,30 @@ describe('API', function() east_api_node.ident = nil elseif typ == 'Assignment' then local aug = east_api_node.augmentation - if aug == '' then aug = 'Plain' end + if aug == '' then + aug = 'Plain' + end typ = ('%s(%s)'):format(typ, aug) east_api_node.augmentation = nil end typ = ('%s:%u:%u:%s'):format( - typ, east_api_node.start[1], east_api_node.start[2], - line:sub(east_api_node.start[2] + 1, - east_api_node.start[2] + 1 + east_api_node.len - 1)) + typ, + east_api_node.start[1], + east_api_node.start[2], + line:sub(east_api_node.start[2] + 1, east_api_node.start[2] + 1 + east_api_node.len - 1) + ) assert(east_api_node.start[2] + east_api_node.len - 1 <= #line) for k, _ in pairs(east_api_node.start) do - assert(({true, true})[k]) + assert(({ true, true })[k]) end east_api_node.start = nil east_api_node.type = nil east_api_node.len = nil local can_simplify = true for _, _ in pairs(east_api_node) do - if can_simplify then can_simplify = false end + if can_simplify then + can_simplify = false + end end if can_simplify then return typ @@ -2662,7 +2843,7 @@ describe('API', function() east_api.err.message = nil end if east_api.ast then - east_api.ast = {simplify_east_api_node(line, east_api.ast)} + east_api.ast = { simplify_east_api_node(line, east_api.ast) } if #east_api.ast == 0 then east_api.ast = nil end @@ -2674,26 +2855,21 @@ describe('API', function() end local function simplify_east_hl(line, east_hl) for i, v in ipairs(east_hl) do - east_hl[i] = ('%s:%u:%u:%s'):format( - v[4], - v[1], - v[2], - line:sub(v[2] + 1, v[3])) + east_hl[i] = ('%s:%u:%u:%s'):format(v[4], v[1], v[2], line:sub(v[2] + 1, v[3])) end return east_hl end local FLAGS_TO_STR = { - [0] = "", - [1] = "m", - [2] = "E", - [3] = "mE", - [4] = "l", - [5] = "lm", - [6] = "lE", - [7] = "lmE", + [0] = '', + [1] = 'm', + [2] = 'E', + [3] = 'mE', + [4] = 'l', + [5] = 'lm', + [6] = 'lE', + [7] = 'lmE', } - local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, - nz_flags_exps) + local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, nz_flags_exps) if type(str) ~= 'string' then return end @@ -2701,7 +2877,7 @@ describe('API', function() nz_flags_exps = nz_flags_exps or {} for _, flags in ipairs(opts.flags) do local err, msg = pcall(function() - local east_api = meths.parse_expression(str, FLAGS_TO_STR[flags], true) + local east_api = api.nvim_parse_expression(str, FLAGS_TO_STR[flags], true) local east_hl = east_api.highlight east_api.highlight = nil local ast = simplify_east_api(str, east_api) @@ -2734,37 +2910,39 @@ describe('API', function() end) if not err then if type(msg) == 'table' then - local merr, new_msg = pcall( - format_string, 'table error:\n%s\n\n(%r)', msg.message, msg) + local merr, new_msg = pcall(format_string, 'table error:\n%s\n\n(%r)', msg.message, msg) if merr then msg = new_msg else - msg = format_string('table error without .message:\n(%r)', - msg) + msg = format_string('table error without .message:\n(%r)', msg) end elseif type(msg) ~= 'string' then msg = format_string('non-string non-table error:\n%r', msg) end - error(format_string('Error while processing test (%r, %s):\n%s', - str, FLAGS_TO_STR[flags], msg)) + error( + format_string( + 'Error while processing test (%r, %s):\n%s', + str, + FLAGS_TO_STR[flags], + msg + ) + ) end end end local function hl(group, str, shift) return function(next_col) local col = next_col + (shift or 0) - return (('%s:%u:%u:%s'):format( - 'Nvim' .. group, - 0, - col, - str)), (col + #str) + return (('%s:%u:%u:%s'):format('Nvim' .. group, 0, col, str)), (col + #str) end end local function fmtn(typ, args, rest) - if (typ == 'UnknownFigure' - or typ == 'DictLiteral' - or typ == 'CurlyBracesIdentifier' - or typ == 'Lambda') then + if + typ == 'UnknownFigure' + or typ == 'DictLiteral' + or typ == 'CurlyBracesIdentifier' + or typ == 'Lambda' + then return ('%s%s'):format(typ, rest) elseif typ == 'DoubleQuotedString' or typ == 'SingleQuotedString' then if args:sub(-4) == 'NULL' then @@ -2773,18 +2951,17 @@ describe('API', function() return ('%s(%s)%s'):format(typ, args, rest) end end - require('test.unit.viml.expressions.parser_tests')( - it, _check_parsing, hl, fmtn) + require('test.unit.viml.expressions.parser_tests')(it, _check_parsing, hl, fmtn) end) describe('nvim_list_uis', function() it('returns empty if --headless', function() -- Test runner defaults to --headless. - eq({}, nvim("list_uis")) + eq({}, api.nvim_list_uis()) end) it('returns attached UIs', function() local screen = Screen.new(20, 4) - screen:attach({override=true}) + screen:attach({ override = true }) local expected = { { chan = 1, @@ -2806,10 +2983,10 @@ describe('API', function() term_colors = 0, term_name = '', width = 20, - } + }, } - eq(expected, nvim("list_uis")) + eq(expected, api.nvim_list_uis()) screen:detach() screen = Screen.new(44, 99) @@ -2818,96 +2995,102 @@ describe('API', function() expected[1].override = false expected[1].width = 44 expected[1].height = 99 - eq(expected, nvim("list_uis")) + eq(expected, api.nvim_list_uis()) end) end) describe('nvim_create_namespace', function() it('works', function() - eq({}, meths.get_namespaces()) - eq(1, meths.create_namespace("ns-1")) - eq(2, meths.create_namespace("ns-2")) - eq(1, meths.create_namespace("ns-1")) - eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces()) - eq(3, meths.create_namespace("")) - eq(4, meths.create_namespace("")) - eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces()) + eq({}, api.nvim_get_namespaces()) + eq(1, api.nvim_create_namespace('ns-1')) + eq(2, api.nvim_create_namespace('ns-2')) + eq(1, api.nvim_create_namespace('ns-1')) + eq({ ['ns-1'] = 1, ['ns-2'] = 2 }, api.nvim_get_namespaces()) + eq(3, api.nvim_create_namespace('')) + eq(4, api.nvim_create_namespace('')) + eq({ ['ns-1'] = 1, ['ns-2'] = 2 }, api.nvim_get_namespaces()) end) end) describe('nvim_create_buf', function() it('works', function() - eq({id=2}, meths.create_buf(true, false)) - eq({id=3}, meths.create_buf(false, false)) - eq(' 1 %a "[No Name]" line 1\n'.. - ' 2 h "[No Name]" line 0', - meths.command_output("ls")) + eq(2, api.nvim_create_buf(true, false)) + eq(3, api.nvim_create_buf(false, false)) + eq( + ' 1 %a "[No Name]" line 1\n' + .. ' 2 h "[No Name]" line 0', + command_output('ls') + ) -- current buffer didn't change - eq({id=1}, meths.get_current_buf()) + eq(1, api.nvim_get_current_buf()) local screen = Screen.new(20, 4) screen:attach() - meths.buf_set_lines(2, 0, -1, true, {"some text"}) - meths.set_current_buf(2) - screen:expect([[ + api.nvim_buf_set_lines(2, 0, -1, true, { 'some text' }) + api.nvim_set_current_buf(2) + screen:expect( + [[ ^some text | - {1:~ }| - {1:~ }| + {1:~ }|*2 | - ]], { - [1] = {bold = true, foreground = Screen.colors.Blue1}, - }) + ]], + { + [1] = { bold = true, foreground = Screen.colors.Blue1 }, + } + ) end) it('can change buftype before visiting', function() - meths.set_option_value("hidden", false, {}) - eq({id=2}, meths.create_buf(true, false)) - meths.set_option_value("buftype", "nofile", {buf=2}) - meths.buf_set_lines(2, 0, -1, true, {"test text"}) - command("split | buffer 2") - eq({id=2}, meths.get_current_buf()) + api.nvim_set_option_value('hidden', false, {}) + eq(2, api.nvim_create_buf(true, false)) + api.nvim_set_option_value('buftype', 'nofile', { buf = 2 }) + api.nvim_buf_set_lines(2, 0, -1, true, { 'test text' }) + command('split | buffer 2') + eq(2, api.nvim_get_current_buf()) -- if the buf_set_option("buftype") didn't work, this would error out. - command("close") - eq({id=1}, meths.get_current_buf()) + command('close') + eq(1, api.nvim_get_current_buf()) end) - it("does not trigger BufEnter, BufWinEnter", function() - command("let g:fired = v:false") - command("au BufEnter,BufWinEnter * let g:fired = v:true") + it('does not trigger BufEnter, BufWinEnter', function() + command('let g:fired = v:false') + command('au BufEnter,BufWinEnter * let g:fired = v:true') - eq({id=2}, meths.create_buf(true, false)) - meths.buf_set_lines(2, 0, -1, true, {"test", "text"}) + eq(2, api.nvim_create_buf(true, false)) + api.nvim_buf_set_lines(2, 0, -1, true, { 'test', 'text' }) eq(false, eval('g:fired')) end) it('TextChanged and TextChangedI do not trigger without changes', function() - local buf = meths.create_buf(true, false) + local buf = api.nvim_create_buf(true, false) command([[let g:changed = '']]) - meths.create_autocmd({'TextChanged', 'TextChangedI'}, { + api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, { buffer = buf, command = 'let g:changed ..= mode()', }) - meths.set_current_buf(buf) + api.nvim_set_current_buf(buf) feed('i') - eq('', meths.get_var('changed')) + eq('', api.nvim_get_var('changed')) end) it('scratch-buffer', function() - eq({id=2}, meths.create_buf(false, true)) - eq({id=3}, meths.create_buf(true, true)) - eq({id=4}, meths.create_buf(true, true)) + eq(2, api.nvim_create_buf(false, true)) + eq(3, api.nvim_create_buf(true, true)) + eq(4, api.nvim_create_buf(true, true)) local scratch_bufs = { 2, 3, 4 } - eq(' 1 %a "[No Name]" line 1\n'.. - ' 3 h "[Scratch]" line 0\n'.. - ' 4 h "[Scratch]" line 0', - exec_capture('ls')) + eq( + ' 1 %a "[No Name]" line 1\n' + .. ' 3 h "[Scratch]" line 0\n' + .. ' 4 h "[Scratch]" line 0', + exec_capture('ls') + ) -- current buffer didn't change - eq({id=1}, meths.get_current_buf()) + eq(1, api.nvim_get_current_buf()) local screen = Screen.new(20, 4) screen:set_default_attr_ids({ - [1] = {bold = true, foreground = Screen.colors.Blue1}, + [1] = { bold = true, foreground = Screen.colors.Blue1 }, }) screen:attach() @@ -2915,35 +3098,33 @@ describe('API', function() -- Editing a scratch-buffer does NOT change its properties. -- local edited_buf = 2 - meths.buf_set_lines(edited_buf, 0, -1, true, {"some text"}) - for _,b in ipairs(scratch_bufs) do - eq('nofile', meths.get_option_value('buftype', {buf=b})) - eq('hide', meths.get_option_value('bufhidden', {buf=b})) - eq(false, meths.get_option_value('swapfile', {buf=b})) - eq(false, meths.get_option_value('modeline', {buf=b})) + api.nvim_buf_set_lines(edited_buf, 0, -1, true, { 'some text' }) + for _, b in ipairs(scratch_bufs) do + eq('nofile', api.nvim_get_option_value('buftype', { buf = b })) + eq('hide', api.nvim_get_option_value('bufhidden', { buf = b })) + eq(false, api.nvim_get_option_value('swapfile', { buf = b })) + eq(false, api.nvim_get_option_value('modeline', { buf = b })) end -- -- Visiting a scratch-buffer DOES NOT change its properties. -- - meths.set_current_buf(edited_buf) + api.nvim_set_current_buf(edited_buf) screen:expect([[ ^some text | - {1:~ }| - {1:~ }| + {1:~ }|*2 | ]]) - eq('nofile', meths.get_option_value('buftype', {buf=edited_buf})) - eq('hide', meths.get_option_value('bufhidden', {buf=edited_buf})) - eq(false, meths.get_option_value('swapfile', {buf=edited_buf})) - eq(false, meths.get_option_value('modeline', {buf=edited_buf})) + eq('nofile', api.nvim_get_option_value('buftype', { buf = edited_buf })) + eq('hide', api.nvim_get_option_value('bufhidden', { buf = edited_buf })) + eq(false, api.nvim_get_option_value('swapfile', { buf = edited_buf })) + eq(false, api.nvim_get_option_value('modeline', { buf = edited_buf })) -- Scratch buffer can be wiped without error. command('bwipe') screen:expect([[ ^ | - {1:~ }| - {1:~ }| + {1:~ }|*2 | ]]) end) @@ -2959,117 +3140,121 @@ describe('API', function() describe('nvim_get_runtime_file', function() local p = helpers.alter_slashes it('can find files', function() - eq({}, meths.get_runtime_file("bork.borkbork", false)) - eq({}, meths.get_runtime_file("bork.borkbork", true)) - eq(1, #meths.get_runtime_file("autoload/msgpack.vim", false)) - eq(1, #meths.get_runtime_file("autoload/msgpack.vim", true)) - local val = meths.get_runtime_file("autoload/remote/*.vim", true) + eq({}, api.nvim_get_runtime_file('bork.borkbork', false)) + eq({}, api.nvim_get_runtime_file('bork.borkbork', true)) + eq(1, #api.nvim_get_runtime_file('autoload/msgpack.vim', false)) + eq(1, #api.nvim_get_runtime_file('autoload/msgpack.vim', true)) + local val = api.nvim_get_runtime_file('autoload/remote/*.vim', true) eq(2, #val) - if endswith(val[1], "define.vim") then - ok(endswith(val[1], p"autoload/remote/define.vim")) - ok(endswith(val[2], p"autoload/remote/host.vim")) + if endswith(val[1], 'define.vim') then + ok(endswith(val[1], p 'autoload/remote/define.vim')) + ok(endswith(val[2], p 'autoload/remote/host.vim')) else - ok(endswith(val[1], p"autoload/remote/host.vim")) - ok(endswith(val[2], p"autoload/remote/define.vim")) + ok(endswith(val[1], p 'autoload/remote/host.vim')) + ok(endswith(val[2], p 'autoload/remote/define.vim')) end - val = meths.get_runtime_file("autoload/remote/*.vim", false) + val = api.nvim_get_runtime_file('autoload/remote/*.vim', false) eq(1, #val) - ok(endswith(val[1], p"autoload/remote/define.vim") - or endswith(val[1], p"autoload/remote/host.vim")) + ok( + endswith(val[1], p 'autoload/remote/define.vim') + or endswith(val[1], p 'autoload/remote/host.vim') + ) - val = meths.get_runtime_file("lua", true) + val = api.nvim_get_runtime_file('lua', true) eq(1, #val) - ok(endswith(val[1], p"lua")) + ok(endswith(val[1], p 'lua')) - val = meths.get_runtime_file("lua/vim", true) + val = api.nvim_get_runtime_file('lua/vim', true) eq(1, #val) - ok(endswith(val[1], p"lua/vim")) + ok(endswith(val[1], p 'lua/vim')) end) it('can find directories', function() - local val = meths.get_runtime_file("lua/", true) + local val = api.nvim_get_runtime_file('lua/', true) eq(1, #val) - ok(endswith(val[1], p"lua/")) + ok(endswith(val[1], p 'lua/')) - val = meths.get_runtime_file("lua/vim/", true) + val = api.nvim_get_runtime_file('lua/vim/', true) eq(1, #val) - ok(endswith(val[1], p"lua/vim/")) + ok(endswith(val[1], p 'lua/vim/')) - eq({}, meths.get_runtime_file("foobarlang/", true)) + eq({}, api.nvim_get_runtime_file('foobarlang/', true)) end) it('can handle bad patterns', function() skip(is_os('win')) - eq("Vim:E220: Missing }.", pcall_err(meths.get_runtime_file, "{", false)) + eq('Vim:E220: Missing }.', pcall_err(api.nvim_get_runtime_file, '{', false)) - eq('Vim(echo):E5555: API call: Vim:E220: Missing }.', - exc_exec("echo nvim_get_runtime_file('{', v:false)")) + eq( + 'Vim(echo):E5555: API call: Vim:E220: Missing }.', + exc_exec("echo nvim_get_runtime_file('{', v:false)") + ) end) end) describe('nvim_get_all_options_info', function() it('should have key value pairs of option names', function() - local options_info = meths.get_all_options_info() + local options_info = api.nvim_get_all_options_info() neq(nil, options_info.listchars) neq(nil, options_info.tabstop) - eq(meths.get_option_info'winhighlight', options_info.winhighlight) + eq(api.nvim_get_option_info 'winhighlight', options_info.winhighlight) end) it('should not crash when echoed', function() - meths.exec2("echo nvim_get_all_options_info()", { output = true }) + api.nvim_exec2('echo nvim_get_all_options_info()', { output = true }) end) end) describe('nvim_get_option_info', function() it('should error for unknown options', function() - eq("Invalid option (not found): 'bogus'", pcall_err(meths.get_option_info, 'bogus')) + eq("Invalid option (not found): 'bogus'", pcall_err(api.nvim_get_option_info, 'bogus')) end) it('should return the same options for short and long name', function() - eq(meths.get_option_info'winhl', meths.get_option_info'winhighlight') + eq(api.nvim_get_option_info 'winhl', api.nvim_get_option_info 'winhighlight') end) it('should have information about window options', function() eq({ allows_duplicates = false, - commalist = true; - default = ""; - flaglist = false; - global_local = false; - last_set_chan = 0; - last_set_linenr = 0; - last_set_sid = 0; - name = "winhighlight"; - scope = "win"; - shortname = "winhl"; - type = "string"; - was_set = false; - }, meths.get_option_info'winhl') + commalist = true, + default = '', + flaglist = false, + global_local = false, + last_set_chan = 0, + last_set_linenr = 0, + last_set_sid = 0, + name = 'winhighlight', + scope = 'win', + shortname = 'winhl', + type = 'string', + was_set = false, + }, api.nvim_get_option_info 'winhl') end) it('should have information about buffer options', function() eq({ allows_duplicates = true, commalist = false, - default = "", + default = '', flaglist = false, global_local = false, last_set_chan = 0, last_set_linenr = 0, last_set_sid = 0, - name = "filetype", - scope = "buf", - shortname = "ft", - type = "string", - was_set = false - }, meths.get_option_info'filetype') + name = 'filetype', + scope = 'buf', + shortname = 'ft', + type = 'string', + was_set = false, + }, api.nvim_get_option_info 'filetype') end) it('should have information about global options', function() -- precondition: the option was changed from its default -- in test setup. - eq(false, meths.get_option_value('showcmd', {})) + eq(false, api.nvim_get_option_value('showcmd', {})) eq({ allows_duplicates = true, @@ -3080,14 +3265,14 @@ describe('API', function() last_set_chan = 0, last_set_linenr = 0, last_set_sid = -2, - name = "showcmd", - scope = "global", - shortname = "sc", - type = "boolean", - was_set = true - }, meths.get_option_info'showcmd') + name = 'showcmd', + scope = 'global', + shortname = 'sc', + type = 'boolean', + was_set = true, + }, api.nvim_get_option_info 'showcmd') - meths.set_option_value('showcmd', true, {}) + api.nvim_set_option_value('showcmd', true, {}) eq({ allows_duplicates = true, @@ -3098,12 +3283,12 @@ describe('API', function() last_set_chan = 1, last_set_linenr = 0, last_set_sid = -9, - name = "showcmd", - scope = "global", - shortname = "sc", - type = "boolean", - was_set = true - }, meths.get_option_info'showcmd') + name = 'showcmd', + scope = 'global', + shortname = 'sc', + type = 'boolean', + was_set = true, + }, api.nvim_get_option_info 'showcmd') end) end) @@ -3114,7 +3299,9 @@ describe('API', function() before_each(function() fname = tmpname() - write_file(fname, [[ + write_file( + fname, + [[ setglobal dictionary=mydict " 1, global-local (buffer) setlocal formatprg=myprg " 2, global-local (buffer) setglobal equalprg=prg1 " 3, global-local (buffer) @@ -3124,21 +3311,22 @@ describe('API', function() setglobal showbreak=aaa " 7, global-local (window) setlocal showbreak=bbb " 8, global-local (window) setglobal completeopt=menu " 9, global - ]]) + ]] + ) exec_lua 'vim.cmd.vsplit()' - meths.create_buf(false, false) + api.nvim_create_buf(false, false) - bufs = meths.list_bufs() - wins = meths.list_wins() + bufs = api.nvim_list_bufs() + wins = api.nvim_list_wins() - meths.win_set_buf(wins[1].id, bufs[1].id) - meths.win_set_buf(wins[2].id, bufs[2].id) + api.nvim_win_set_buf(wins[1], bufs[1]) + api.nvim_win_set_buf(wins[2], bufs[2]) - meths.set_current_win(wins[2].id) - meths.exec('source ' .. fname, false) + api.nvim_set_current_win(wins[2]) + api.nvim_exec('source ' .. fname, false) - meths.set_current_win(wins[1].id) + api.nvim_set_current_win(wins[1]) end) after_each(function() @@ -3146,12 +3334,13 @@ describe('API', function() end) it('should return option information', function() - eq(meths.get_option_info('dictionary'), meths.get_option_info2('dictionary', {})) -- buffer - eq(meths.get_option_info('fillchars'), meths.get_option_info2('fillchars', {})) -- window - eq(meths.get_option_info('completeopt'), meths.get_option_info2('completeopt', {})) -- global + eq(api.nvim_get_option_info('dictionary'), api.nvim_get_option_info2('dictionary', {})) -- buffer + eq(api.nvim_get_option_info('fillchars'), api.nvim_get_option_info2('fillchars', {})) -- window + eq(api.nvim_get_option_info('completeopt'), api.nvim_get_option_info2('completeopt', {})) -- global end) describe('last set', function() + -- stylua: ignore local tests = { {desc="(buf option, global requested, global set) points to global", linenr=1, sid=1, args={'dictionary', {scope='global'}}}, {desc="(buf option, global requested, local set) is not set", linenr=0, sid=0, args={'formatprg', {scope='global'}}}, @@ -3179,21 +3368,21 @@ describe('API', function() for _, t in pairs(tests) do it(t.desc, function() -- Switch to the target buffer/window so that curbuf/curwin are used. - meths.set_current_win(wins[2].id) - local info = meths.get_option_info2(unpack(t.args)) + api.nvim_set_current_win(wins[2]) + local info = api.nvim_get_option_info2(unpack(t.args)) eq(t.linenr, info.last_set_linenr) eq(t.sid, info.last_set_sid) end) end it('is provided for cross-buffer requests', function() - local info = meths.get_option_info2('formatprg', {buf=bufs[2].id}) + local info = api.nvim_get_option_info2('formatprg', { buf = bufs[2] }) eq(2, info.last_set_linenr) eq(1, info.last_set_sid) end) it('is provided for cross-window requests', function() - local info = meths.get_option_info2('listchars', {win=wins[2].id}) + local info = api.nvim_get_option_info2('listchars', { win = wins[2] }) eq(6, info.last_set_linenr) eq(1, info.last_set_sid) end) @@ -3207,11 +3396,11 @@ describe('API', function() screen = Screen.new(40, 8) screen:attach() screen:set_default_attr_ids({ - [0] = {bold = true, foreground = Screen.colors.Blue}, - [1] = {bold = true, foreground = Screen.colors.SeaGreen}, - [2] = {bold = true, reverse = true}, - [3] = {foreground = Screen.colors.Brown, bold = true}, -- Statement - [4] = {foreground = Screen.colors.SlateBlue}, -- Special + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { bold = true, foreground = Screen.colors.SeaGreen }, + [2] = { bold = true, reverse = true }, + [3] = { foreground = Screen.colors.Brown, bold = true }, -- Statement + [4] = { foreground = Screen.colors.SlateBlue }, -- Special }) command('highlight Statement gui=bold guifg=Brown') command('highlight Special guifg=SlateBlue') @@ -3219,60 +3408,57 @@ describe('API', function() it('should clear cmdline message before echo', function() feed(':call nvim_echo([["msg"]], v:false, {})<CR>') - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 msg | - ]]} + ]], + } end) it('can show highlighted line', function() - nvim_async("echo", {{"msg_a"}, {"msg_b", "Statement"}, {"msg_c", "Special"}}, true, {}) - screen:expect{grid=[[ + async_meths.nvim_echo( + { { 'msg_a' }, { 'msg_b', 'Statement' }, { 'msg_c', 'Special' } }, + true, + {} + ) + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*6 msg_a{3:msg_b}{4:msg_c} | - ]]} + ]], + } end) it('can show highlighted multiline', function() - nvim_async("echo", {{"msg_a\nmsg_a", "Statement"}, {"msg_b", "Special"}}, true, {}) - screen:expect{grid=[[ + async_meths.nvim_echo({ { 'msg_a\nmsg_a', 'Statement' }, { 'msg_b', 'Special' } }, true, {}) + screen:expect { + grid = [[ | - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*3 {2: }| {3:msg_a} | {3:msg_a}{4:msg_b} | {1:Press ENTER or type command to continue}^ | - ]]} + ]], + } end) it('can save message history', function() - nvim('command', 'set cmdheight=2') -- suppress Press ENTER - nvim("echo", {{"msg\nmsg"}, {"msg"}}, true, {}) - eq("msg\nmsgmsg", exec_capture('messages')) + command('set cmdheight=2') -- suppress Press ENTER + api.nvim_echo({ { 'msg\nmsg' }, { 'msg' } }, true, {}) + eq('msg\nmsgmsg', exec_capture('messages')) end) it('can disable saving message history', function() - nvim('command', 'set cmdheight=2') -- suppress Press ENTER - nvim_async("echo", {{"msg\nmsg"}, {"msg"}}, false, {}) - eq("", exec_capture('messages')) + command('set cmdheight=2') -- suppress Press ENTER + async_meths.nvim_echo({ { 'msg\nmsg' }, { 'msg' } }, false, {}) + eq('', exec_capture('messages')) end) end) - describe('nvim_open_term', function() local screen @@ -3280,24 +3466,37 @@ describe('API', function() screen = Screen.new(100, 35) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, - [1] = {background = Screen.colors.Plum1}; - [2] = {background = tonumber('0xffff40'), bg_indexed = true}; - [3] = {background = Screen.colors.Plum1, fg_indexed = true, foreground = tonumber('0x00e000')}; - [4] = {bold = true, reverse = true, background = Screen.colors.Plum1}; - [5] = {foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta, bold = true}; - [6] = {bold = true}; - [7] = {reverse = true, background = Screen.colors.LightMagenta}; + [0] = { bold = true, foreground = Screen.colors.Blue }, + [1] = { background = Screen.colors.Plum1 }, + [2] = { background = tonumber('0xffff40'), bg_indexed = true }, + [3] = { + background = Screen.colors.Plum1, + fg_indexed = true, + foreground = tonumber('0x00e000'), + }, + [4] = { bold = true, reverse = true, background = Screen.colors.Plum1 }, + [5] = { + foreground = Screen.colors.Blue, + background = Screen.colors.LightMagenta, + bold = true, + }, + [6] = { bold = true }, + [7] = { reverse = true, background = Screen.colors.LightMagenta }, }) end) it('can batch process sequences', function() - local b = meths.create_buf(true,true) - meths.open_win(b, false, {width=79, height=31, row=1, col=1, relative='editor'}) - local t = meths.open_term(b, {}) - - meths.chan_send(t, io.open("test/functional/fixtures/smile2.cat", "r"):read("*a")) - screen:expect{grid=[[ + local b = api.nvim_create_buf(true, true) + api.nvim_open_win( + b, + false, + { width = 79, height = 31, row = 1, col = 1, relative = 'editor' } + ) + local t = api.nvim_open_term(b, {}) + + api.nvim_chan_send(t, io.open('test/functional/fixtures/smile2.cat', 'r'):read('*a')) + screen:expect { + grid = [[ ^ | {0:~}{1::smile }{0: }| {0:~}{1: }{2:oooo$$$$$$$$$$$$oooo}{1: }{0: }| @@ -3330,15 +3529,17 @@ describe('API', function() {0:~}{3:Press ENTER or type command to continue}{1: }{0: }| {0:~}{4:term://~/config2/docs/pres//32693:vim --clean +smile 29,39 All}{0: }| {0:~}{1::call nvim__screenshot("smile2.cat") }{0: }| - {0:~ }| - {0:~ }| + {0:~ }|*2 | - ]]} + ]], + } end) it('can handle input', function() screen:try_resize(50, 10) - eq({3, 2}, exec_lua [[ + eq( + { 3, 2 }, + exec_lua [[ buf = vim.api.nvim_create_buf(1,1) stream = '' @@ -3354,251 +3555,297 @@ describe('API', function() term = vim.api.nvim_open_term(buf, {on_input=input}) vim.api.nvim_open_win(buf, true, {width=40, height=5, row=1, col=1, relative='editor'}) return {term, buf} - ]]) + ]] + ) - screen:expect{grid=[[ + screen:expect { + grid = [[ | {0:~}{1:^ }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~}{1: }{0: }|*4 + {0:~ }|*3 | - ]]} + ]], + } feed 'iba<c-x>bla' - screen:expect{grid=[[ + screen:expect { + grid = [[ | {0:~}{7: }{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~}{1: }{0: }|*4 + {0:~ }|*3 {6:-- TERMINAL --} | - ]]} + ]], + } eq('ba\024bla', exec_lua [[ return stream ]]) - eq({3,2}, exec_lua [[ return vals ]]) + eq({ 3, 2 }, exec_lua [[ return vals ]]) exec_lua [[ do_the_echo = true ]] feed 'herrejösses!' - screen:expect{grid=[[ + screen:expect { + grid = [[ | {0:~}{1:herrejösses!}{7: }{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~}{1: }{0: }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~}{1: }{0: }|*4 + {0:~ }|*3 {6:-- TERMINAL --} | - ]]} + ]], + } eq('ba\024blaherrejösses!', exec_lua [[ return stream ]]) end) end) describe('nvim_del_mark', function() it('works', function() - local buf = meths.create_buf(false,true) - meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'}) - eq(true, meths.buf_set_mark(buf, 'F', 2, 2, {})) - eq(true, meths.del_mark('F')) - eq({0, 0}, meths.buf_get_mark(buf, 'F')) + local buf = api.nvim_create_buf(false, true) + api.nvim_buf_set_lines(buf, -1, -1, true, { 'a', 'bit of', 'text' }) + eq(true, api.nvim_buf_set_mark(buf, 'F', 2, 2, {})) + eq(true, api.nvim_del_mark('F')) + eq({ 0, 0 }, api.nvim_buf_get_mark(buf, 'F')) end) it('validation', function() - eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.del_mark, 'f')) - eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.del_mark, '!')) - eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.del_mark, 'fail')) + eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(api.nvim_del_mark, 'f')) + eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(api.nvim_del_mark, '!')) + eq("Invalid mark name (must be a single char): 'fail'", pcall_err(api.nvim_del_mark, 'fail')) end) end) describe('nvim_get_mark', function() it('works', function() - local buf = meths.create_buf(false,true) - meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'}) - meths.buf_set_mark(buf, 'F', 2, 2, {}) - meths.buf_set_name(buf, "mybuf") - local mark = meths.get_mark('F', {}) + local buf = api.nvim_create_buf(false, true) + api.nvim_buf_set_lines(buf, -1, -1, true, { 'a', 'bit of', 'text' }) + api.nvim_buf_set_mark(buf, 'F', 2, 2, {}) + api.nvim_buf_set_name(buf, 'mybuf') + local mark = api.nvim_get_mark('F', {}) -- Compare the path tail only - assert(string.find(mark[4], "mybuf$")) - eq({2, 2, buf.id, mark[4]}, mark) + assert(string.find(mark[4], 'mybuf$')) + eq({ 2, 2, buf, mark[4] }, mark) end) it('validation', function() - eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.get_mark, 'f', {})) - eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.get_mark, '!', {})) - eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.get_mark, 'fail', {})) + eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(api.nvim_get_mark, 'f', {})) + eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(api.nvim_get_mark, '!', {})) + eq( + "Invalid mark name (must be a single char): 'fail'", + pcall_err(api.nvim_get_mark, 'fail', {}) + ) end) it('returns the expected when mark is not set', function() - eq(true, meths.del_mark('A')) - eq({0, 0, 0, ''}, meths.get_mark('A', {})) + eq(true, api.nvim_del_mark('A')) + eq({ 0, 0, 0, '' }, api.nvim_get_mark('A', {})) end) it('works with deleted buffers', function() local fname = tmpname() write_file(fname, 'a\nbit of\text') - nvim("command", "edit " .. fname) - local buf = meths.get_current_buf() + command('edit ' .. fname) + local buf = api.nvim_get_current_buf() - meths.buf_set_mark(buf, 'F', 2, 2, {}) - nvim("command", "new") -- Create new buf to avoid :bd failing - nvim("command", "bd! " .. buf.id) + api.nvim_buf_set_mark(buf, 'F', 2, 2, {}) + command('new') -- Create new buf to avoid :bd failing + command('bd! ' .. buf) os.remove(fname) - local mark = meths.get_mark('F', {}) + local mark = api.nvim_get_mark('F', {}) -- To avoid comparing relative vs absolute path local mfname = mark[4] local tail_patt = [[[\/][^\/]*$]] -- tail of paths should be equals eq(fname:match(tail_patt), mfname:match(tail_patt)) - eq({2, 2, buf.id, mark[4]}, mark) + eq({ 2, 2, buf, mark[4] }, mark) end) end) + describe('nvim_eval_statusline', function() it('works', function() eq({ - str = '%StatusLineStringWithHighlights', - width = 31 - }, - meths.eval_statusline( - '%%StatusLineString%#WarningMsg#WithHighlights', - {})) + str = '%StatusLineStringWithHighlights', + width = 31, + }, api.nvim_eval_statusline('%%StatusLineString%#WarningMsg#WithHighlights', {})) end) - it('doesn\'t exceed maxwidth', function() + + it("doesn't exceed maxwidth", function() eq({ - str = 'Should be trun>', - width = 15 - }, - meths.eval_statusline( - 'Should be truncated%<', - { maxwidth = 15 })) - end) - it('supports ASCII fillchar', function() - eq({ str = 'a~~~b', width = 5 }, - meths.eval_statusline('a%=b', { fillchar = '~', maxwidth = 5 })) - end) - it('supports single-width multibyte fillchar', function() - eq({ str = 'a━━━b', width = 5 }, - meths.eval_statusline('a%=b', { fillchar = '━', maxwidth = 5 })) - end) - it('treats double-width fillchar as single-width', function() - eq({ str = 'a哦哦哦b', width = 5 }, - meths.eval_statusline('a%=b', { fillchar = '哦', maxwidth = 5 })) - end) - it('treats control character fillchar as single-width', function() - eq({ str = 'a\031\031\031b', width = 5 }, - meths.eval_statusline('a%=b', { fillchar = '\031', maxwidth = 5 })) - end) + str = 'Should be trun>', + width = 15, + }, api.nvim_eval_statusline('Should be truncated%<', { maxwidth = 15 })) + end) + + it('has correct default fillchar', function() + local oldwin = api.nvim_get_current_win() + command('set fillchars=stl:#,stlnc:$,wbr:%') + command('new') + eq({ str = 'a###b', width = 5 }, api.nvim_eval_statusline('a%=b', { maxwidth = 5 })) + eq( + { str = 'a$$$b', width = 5 }, + api.nvim_eval_statusline('a%=b', { winid = oldwin, maxwidth = 5 }) + ) + eq( + { str = 'a%%%b', width = 5 }, + api.nvim_eval_statusline('a%=b', { use_winbar = true, maxwidth = 5 }) + ) + eq( + { str = 'a b', width = 5 }, + api.nvim_eval_statusline('a%=b', { use_tabline = true, maxwidth = 5 }) + ) + eq( + { str = 'a b', width = 5 }, + api.nvim_eval_statusline('a%=b', { use_statuscol_lnum = 1, maxwidth = 5 }) + ) + end) + + for fc, desc in pairs({ + ['~'] = 'supports ASCII fillchar', + ['━'] = 'supports single-width multibyte fillchar', + ['c̳'] = 'supports single-width fillchar with composing', + ['哦'] = 'treats double-width fillchar as single-width', + ['\031'] = 'treats control character fillchar as single-width', + }) do + it(desc, function() + eq( + { str = 'a' .. fc:rep(3) .. 'b', width = 5 }, + api.nvim_eval_statusline('a%=b', { fillchar = fc, maxwidth = 5 }) + ) + eq( + { str = 'a' .. fc:rep(3) .. 'b', width = 5 }, + api.nvim_eval_statusline('a%=b', { fillchar = fc, use_winbar = true, maxwidth = 5 }) + ) + eq( + { str = 'a' .. fc:rep(3) .. 'b', width = 5 }, + api.nvim_eval_statusline('a%=b', { fillchar = fc, use_tabline = true, maxwidth = 5 }) + ) + eq( + { str = 'a' .. fc:rep(3) .. 'b', width = 5 }, + api.nvim_eval_statusline('a%=b', { fillchar = fc, use_statuscol_lnum = 1, maxwidth = 5 }) + ) + end) + end + it('rejects multiple-character fillchar', function() - eq("Invalid 'fillchar': expected single character", - pcall_err(meths.eval_statusline, '', { fillchar = 'aa' })) + eq( + "Invalid 'fillchar': expected single character", + pcall_err(api.nvim_eval_statusline, '', { fillchar = 'aa' }) + ) end) + it('rejects empty string fillchar', function() - eq("Invalid 'fillchar': expected single character", - pcall_err(meths.eval_statusline, '', { fillchar = '' })) + eq( + "Invalid 'fillchar': expected single character", + pcall_err(api.nvim_eval_statusline, '', { fillchar = '' }) + ) end) + it('rejects non-string fillchar', function() - eq("Invalid 'fillchar': expected String, got Integer", - pcall_err(meths.eval_statusline, '', { fillchar = 1 })) + eq( + "Invalid 'fillchar': expected String, got Integer", + pcall_err(api.nvim_eval_statusline, '', { fillchar = 1 }) + ) end) + it('rejects invalid string', function() - eq('E539: Illegal character <}>', - pcall_err(meths.eval_statusline, '%{%}', {})) + eq('E539: Illegal character <}>', pcall_err(api.nvim_eval_statusline, '%{%}', {})) end) + it('supports various items', function() - eq({ str = '0', width = 1 }, - meths.eval_statusline('%l', { maxwidth = 5 })) + eq({ str = '0', width = 1 }, api.nvim_eval_statusline('%l', { maxwidth = 5 })) command('set readonly') - eq({ str = '[RO]', width = 4 }, - meths.eval_statusline('%r', { maxwidth = 5 })) + eq({ str = '[RO]', width = 4 }, api.nvim_eval_statusline('%r', { maxwidth = 5 })) local screen = Screen.new(80, 24) screen:attach() command('set showcmd') feed('1234') - screen:expect({any = '1234'}) - eq({ str = '1234', width = 4 }, - meths.eval_statusline('%S', { maxwidth = 5 })) + screen:expect({ any = '1234' }) + eq({ str = '1234', width = 4 }, api.nvim_eval_statusline('%S', { maxwidth = 5 })) feed('56') - screen:expect({any = '123456'}) - eq({ str = '<3456', width = 5 }, - meths.eval_statusline('%S', { maxwidth = 5 })) + screen:expect({ any = '123456' }) + eq({ str = '<3456', width = 5 }, api.nvim_eval_statusline('%S', { maxwidth = 5 })) end) + describe('highlight parsing', function() it('works', function() - eq({ - str = "TextWithWarningHighlightTextWithUserHighlight", + eq( + { + str = 'TextWithWarningHighlightTextWithUserHighlight', width = 45, highlights = { { start = 0, group = 'WarningMsg' }, - { start = 24, group = 'User1' } + { start = 24, group = 'User1' }, }, }, - meths.eval_statusline( + api.nvim_eval_statusline( '%#WarningMsg#TextWithWarningHighlight%1*TextWithUserHighlight', - { highlights = true })) + { highlights = true } + ) + ) end) + it('works with no highlight', function() eq({ - str = "TextWithNoHighlight", - width = 19, - highlights = { - { start = 0, group = 'StatusLine' }, - }, + str = 'TextWithNoHighlight', + width = 19, + highlights = { + { start = 0, group = 'StatusLine' }, }, - meths.eval_statusline( - 'TextWithNoHighlight', - { highlights = true })) + }, api.nvim_eval_statusline('TextWithNoHighlight', { highlights = true })) end) + it('works with inactive statusline', function() command('split') - - eq({ + eq( + { str = 'TextWithNoHighlightTextWithWarningHighlight', width = 43, highlights = { { start = 0, group = 'StatusLineNC' }, - { start = 19, group = 'WarningMsg' } - } + { start = 19, group = 'WarningMsg' }, + }, }, - meths.eval_statusline( + api.nvim_eval_statusline( 'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight', - { winid = meths.list_wins()[2].id, highlights = true })) + { winid = api.nvim_list_wins()[2], highlights = true } + ) + ) end) + it('works with tabline', function() - eq({ + eq( + { str = 'TextWithNoHighlightTextWithWarningHighlight', width = 43, highlights = { { start = 0, group = 'TabLineFill' }, - { start = 19, group = 'WarningMsg' } - } + { start = 19, group = 'WarningMsg' }, + }, }, - meths.eval_statusline( + api.nvim_eval_statusline( 'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight', - { use_tabline = true, highlights = true })) + { use_tabline = true, highlights = true } + ) + ) end) + it('works with winbar', function() - eq({ + eq( + { str = 'TextWithNoHighlightTextWithWarningHighlight', width = 43, highlights = { { start = 0, group = 'WinBar' }, - { start = 19, group = 'WarningMsg' } - } + { start = 19, group = 'WarningMsg' }, + }, }, - meths.eval_statusline( + api.nvim_eval_statusline( 'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight', - { use_winbar = true, highlights = true })) + { use_winbar = true, highlights = true } + ) + ) end) + it('works with statuscolumn', function() exec([[ let &stc='%C%s%=%l ' - set cul nu nuw=3 scl=yes:2 fdc=2 + " should not use "stl" from 'fillchars' + set cul nu nuw=3 scl=yes:2 fdc=2 fillchars=stl:# call setline(1, repeat(['aaaaa'], 5)) let g:ns = nvim_create_namespace('') call sign_define('a', {'text':'aa', 'texthl':'IncSearch', 'numhl':'Normal'}) @@ -3615,28 +3862,31 @@ describe('API', function() { group = 'Normal', start = 6 }, { group = 'IncSearch', start = 6 }, { group = 'ErrorMsg', start = 8 }, - { group = 'Normal', start = 10 } - } - }, meths.eval_statusline('%C%s%=%l ', { use_statuscol_lnum = 4, highlights = true })) - eq({ - str = '3 ' , - width = 2, - highlights = { - { group = 'LineNr', start = 0 }, - { group = 'ErrorMsg', start = 1 } - } - }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true })) + { group = 'Normal', start = 10 }, + }, + }, api.nvim_eval_statusline( + '%C%s%=%l ', + { use_statuscol_lnum = 4, highlights = true } + )) + eq( + { + str = '3 ', + width = 2, + highlights = { + { group = 'LineNr', start = 0 }, + { group = 'ErrorMsg', start = 1 }, + }, + }, + api.nvim_eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true }) + ) end) + it('no memory leak with click functions', function() - meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}) + api.nvim_eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}) eq({ - str = 'StatusLineStringWithClickFunc', - width = 29 - }, - meths.eval_statusline( - '%@ClickFunc@StatusLineStringWithClickFunc%T', - {}) - ) + str = 'StatusLineStringWithClickFunc', + width = 29, + }, api.nvim_eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {})) end) end) end) @@ -3649,8 +3899,8 @@ describe('API', function() bang = false, addr = 'none', magic = { - file = false, - bar = false + file = false, + bar = false, }, nargs = '*', nextcmd = '', @@ -3659,8 +3909,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3673,13 +3923,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('echo foo', {})) + }, + }, api.nvim_parse_cmd('echo foo', {})) end) it('works with ranges', function() eq({ @@ -3689,8 +3939,8 @@ describe('API', function() range = { 4, 6 }, addr = 'line', magic = { - file = false, - bar = false + file = false, + bar = false, }, nargs = '*', nextcmd = '', @@ -3699,8 +3949,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3713,13 +3963,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('4,6s/math.random/math.max/', {})) + }, + }, api.nvim_parse_cmd('4,6s/math.random/math.max/', {})) end) it('works with count', function() eq({ @@ -3730,8 +3980,8 @@ describe('API', function() count = 1, addr = 'buf', magic = { - file = false, - bar = true + file = false, + bar = true, }, nargs = '*', nextcmd = '', @@ -3740,8 +3990,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3754,13 +4004,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('buffer 1', {})) + }, + }, api.nvim_parse_cmd('buffer 1', {})) end) it('works with register', function() eq({ @@ -3771,8 +4021,8 @@ describe('API', function() reg = '+', addr = 'line', magic = { - file = false, - bar = true + file = false, + bar = true, }, nargs = '0', nextcmd = '', @@ -3781,8 +4031,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3795,13 +4045,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('put +', {})) + }, + }, api.nvim_parse_cmd('put +', {})) eq({ cmd = 'put', args = {}, @@ -3810,8 +4060,8 @@ describe('API', function() reg = '', addr = 'line', magic = { - file = false, - bar = true + file = false, + bar = true, }, nargs = '0', nextcmd = '', @@ -3820,8 +4070,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3834,13 +4084,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('put', {})) + }, + }, api.nvim_parse_cmd('put', {})) end) it('works with range, count and register', function() eq({ @@ -3852,8 +4102,8 @@ describe('API', function() reg = '*', addr = 'line', magic = { - file = false, - bar = true + file = false, + bar = true, }, nargs = '0', nextcmd = '', @@ -3862,8 +4112,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3876,13 +4126,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('1,3delete * 5', {})) + }, + }, api.nvim_parse_cmd('1,3delete * 5', {})) end) it('works with bang', function() eq({ @@ -3892,8 +4142,8 @@ describe('API', function() range = {}, addr = 'line', magic = { - file = true, - bar = true + file = true, + bar = true, }, nargs = '?', nextcmd = '', @@ -3902,8 +4152,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -3916,91 +4166,103 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, }, - }, meths.parse_cmd('w!', {})) + }, api.nvim_parse_cmd('w!', {})) end) it('works with modifiers', function() - eq({ - cmd = 'split', - args = { 'foo.txt' }, - bang = false, - range = {}, - addr = '?', - magic = { + eq( + { + cmd = 'split', + args = { 'foo.txt' }, + bang = false, + range = {}, + addr = '?', + magic = { file = true, - bar = true - }, - nargs = '?', - nextcmd = '', - mods = { - browse = false, - confirm = false, - emsg_silent = true, - filter = { - pattern = "foo", - force = false + bar = true, + }, + nargs = '?', + nextcmd = '', + mods = { + browse = false, + confirm = false, + emsg_silent = true, + filter = { + pattern = 'foo', + force = false, + }, + hide = false, + horizontal = true, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = true, + split = 'topleft', + tab = 1, + unsilent = false, + verbose = 15, + vertical = false, }, - hide = false, - horizontal = true, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = true, - split = "topleft", - tab = 1, - unsilent = false, - verbose = 15, - vertical = false, }, - }, meths.parse_cmd('15verbose silent! horizontal topleft tab filter /foo/ split foo.txt', {})) - eq({ - cmd = 'split', - args = { 'foo.txt' }, - bang = false, - range = {}, - addr = '?', - magic = { + api.nvim_parse_cmd( + '15verbose silent! horizontal topleft tab filter /foo/ split foo.txt', + {} + ) + ) + eq( + { + cmd = 'split', + args = { 'foo.txt' }, + bang = false, + range = {}, + addr = '?', + magic = { file = true, - bar = true - }, - nargs = '?', - nextcmd = '', - mods = { - browse = false, - confirm = true, - emsg_silent = false, - filter = { - pattern = "foo", - force = true + bar = true, + }, + nargs = '?', + nextcmd = '', + mods = { + browse = false, + confirm = true, + emsg_silent = false, + filter = { + pattern = 'foo', + force = true, + }, + hide = false, + horizontal = false, + keepalt = false, + keepjumps = false, + keepmarks = false, + keeppatterns = false, + lockmarks = false, + noautocmd = false, + noswapfile = false, + sandbox = false, + silent = false, + split = 'botright', + tab = 0, + unsilent = true, + verbose = 0, + vertical = false, }, - hide = false, - horizontal = false, - keepalt = false, - keepjumps = false, - keepmarks = false, - keeppatterns = false, - lockmarks = false, - noautocmd = false, - noswapfile = false, - sandbox = false, - silent = false, - split = "botright", - tab = 0, - unsilent = true, - verbose = 0, - vertical = false, }, - }, meths.parse_cmd('0verbose unsilent botright 0tab confirm filter! /foo/ split foo.txt', {})) + api.nvim_parse_cmd( + '0verbose unsilent botright 0tab confirm filter! /foo/ split foo.txt', + {} + ) + ) end) it('works with user commands', function() command('command -bang -nargs=+ -range -addr=lines MyCommand echo foo') @@ -4011,8 +4273,8 @@ describe('API', function() range = { 4, 6 }, addr = 'line', magic = { - file = false, - bar = false + file = false, + bar = false, }, nargs = '+', nextcmd = '', @@ -4021,8 +4283,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -4035,13 +4297,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('4,6MyCommand! test it', {})) + }, + }, api.nvim_parse_cmd('4,6MyCommand! test it', {})) end) it('works for commands separated by bar', function() eq({ @@ -4051,8 +4313,8 @@ describe('API', function() range = {}, addr = 'arg', magic = { - file = true, - bar = true + file = true, + bar = true, }, nargs = '*', nextcmd = 'argadd b.txt', @@ -4061,8 +4323,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -4075,13 +4337,13 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('argadd a.txt | argadd b.txt', {})) + }, + }, api.nvim_parse_cmd('argadd a.txt | argadd b.txt', {})) end) it('works for nargs=1', function() command('command -nargs=1 MyCommand echo <q-args>') @@ -4091,8 +4353,8 @@ describe('API', function() bang = false, addr = 'none', magic = { - file = false, - bar = false + file = false, + bar = false, }, nargs = '1', nextcmd = '', @@ -4101,8 +4363,8 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", - force = false + pattern = '', + force = false, }, hide = false, horizontal = false, @@ -4115,33 +4377,41 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('MyCommand test it', {})) + }, + }, api.nvim_parse_cmd('MyCommand test it', {})) end) it('validates command', function() - eq('Error while parsing command line', pcall_err(meths.parse_cmd, '', {})) - eq('Error while parsing command line', pcall_err(meths.parse_cmd, '" foo', {})) - eq('Error while parsing command line: E492: Not an editor command: Fubar', - pcall_err(meths.parse_cmd, 'Fubar', {})) + eq('Error while parsing command line', pcall_err(api.nvim_parse_cmd, '', {})) + eq('Error while parsing command line', pcall_err(api.nvim_parse_cmd, '" foo', {})) + eq( + 'Error while parsing command line: E492: Not an editor command: Fubar', + pcall_err(api.nvim_parse_cmd, 'Fubar', {}) + ) command('command! Fubar echo foo') - eq('Error while parsing command line: E477: No ! allowed', - pcall_err(meths.parse_cmd, 'Fubar!', {})) - eq('Error while parsing command line: E481: No range allowed', - pcall_err(meths.parse_cmd, '4,6Fubar', {})) + eq( + 'Error while parsing command line: E477: No ! allowed', + pcall_err(api.nvim_parse_cmd, 'Fubar!', {}) + ) + eq( + 'Error while parsing command line: E481: No range allowed', + pcall_err(api.nvim_parse_cmd, '4,6Fubar', {}) + ) command('command! Foobar echo foo') - eq('Error while parsing command line: E464: Ambiguous use of user-defined command', - pcall_err(meths.parse_cmd, 'F', {})) + eq( + 'Error while parsing command line: E464: Ambiguous use of user-defined command', + pcall_err(api.nvim_parse_cmd, 'F', {}) + ) end) it('does not interfere with printing line in Ex mode #19400', function() local screen = Screen.new(60, 7) screen:set_default_attr_ids({ - [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText - [1] = {bold = true, reverse = true}, -- MsgSeparator + [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + [1] = { bold = true, reverse = true }, -- MsgSeparator }) screen:attach() insert([[ @@ -4151,13 +4421,12 @@ describe('API', function() screen:expect([[ foo | bar | - {0:~ }| - {0:~ }| + {0:~ }|*2 {1: }| Entering Ex mode. Type "visual" to go to Normal mode. | :1^ | ]]) - eq('Error while parsing command line', pcall_err(meths.parse_cmd, '', {})) + eq('Error while parsing command line', pcall_err(api.nvim_parse_cmd, '', {})) feed('<CR>') screen:expect([[ foo | @@ -4170,16 +4439,16 @@ describe('API', function() ]]) end) it('does not move cursor or change search history/pattern #19878 #19890', function() - meths.buf_set_lines(0, 0, -1, true, {'foo', 'bar', 'foo', 'bar'}) - eq({1, 0}, meths.win_get_cursor(0)) - eq('', funcs.getreg('/')) - eq('', funcs.histget('search')) - feed(':') -- call the API in cmdline mode to test whether it changes search history + api.nvim_buf_set_lines(0, 0, -1, true, { 'foo', 'bar', 'foo', 'bar' }) + eq({ 1, 0 }, api.nvim_win_get_cursor(0)) + eq('', fn.getreg('/')) + eq('', fn.histget('search')) + feed(':') -- call the API in cmdline mode to test whether it changes search history eq({ cmd = 'normal', - args = {'x'}, + args = { 'x' }, bang = true, - range = {3, 4}, + range = { 3, 4 }, addr = 'line', magic = { file = false, @@ -4192,7 +4461,7 @@ describe('API', function() confirm = false, emsg_silent = false, filter = { - pattern = "", + pattern = '', force = false, }, hide = false, @@ -4206,101 +4475,134 @@ describe('API', function() noswapfile = false, sandbox = false, silent = false, - split = "", + split = '', tab = -1, unsilent = false, verbose = -1, vertical = false, - } - }, meths.parse_cmd('+2;/bar/normal! x', {})) - eq({1, 0}, meths.win_get_cursor(0)) - eq('', funcs.getreg('/')) - eq('', funcs.histget('search')) + }, + }, api.nvim_parse_cmd('+2;/bar/normal! x', {})) + eq({ 1, 0 }, api.nvim_win_get_cursor(0)) + eq('', fn.getreg('/')) + eq('', fn.histget('search')) end) it('result can be used directly by nvim_cmd #20051', function() - eq("foo", meths.cmd(meths.parse_cmd('echo "foo"', {}), { output = true })) - meths.cmd(meths.parse_cmd("set cursorline", {}), {}) - eq(true, meths.get_option_value("cursorline", {})) + eq('foo', api.nvim_cmd(api.nvim_parse_cmd('echo "foo"', {}), { output = true })) + api.nvim_cmd(api.nvim_parse_cmd('set cursorline', {}), {}) + eq(true, api.nvim_get_option_value('cursorline', {})) end) it('no side-effects (error messages) in pcall() #20339', function() - eq({ false, 'Error while parsing command line: E16: Invalid range' }, - exec_lua([=[return {pcall(vim.api.nvim_parse_cmd, "'<,'>n", {})}]=])) + eq( + { false, 'Error while parsing command line: E16: Invalid range' }, + exec_lua([=[return {pcall(vim.api.nvim_parse_cmd, "'<,'>n", {})}]=]) + ) eq('', eval('v:errmsg')) end) end) describe('nvim_cmd', function() - it('works', function () - meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) - eq(true, meths.get_option_value("cursorline", {})) + it('works', function() + api.nvim_cmd({ cmd = 'set', args = { 'cursorline' } }, {}) + eq(true, api.nvim_get_option_value('cursorline', {})) end) it('validation', function() - eq("Invalid 'cmd': expected non-empty String", - pcall_err(meths.cmd, { cmd = ""}, {})) - eq("Invalid 'cmd': expected String, got Array", - pcall_err(meths.cmd, { cmd = {}}, {})) - eq("Invalid 'args': expected Array, got Boolean", - pcall_err(meths.cmd, { cmd = "set", args = true }, {})) - eq("Invalid command arg: expected non-whitespace", - pcall_err(meths.cmd, { cmd = "set", args = {' '}, }, {})) - eq("Invalid command arg: expected valid type, got Array", - pcall_err(meths.cmd, { cmd = "set", args = {{}}, }, {})) - eq("Wrong number of arguments", - pcall_err(meths.cmd, { cmd = "aboveleft", args = {}, }, {})) - eq("Command cannot accept bang: print", - pcall_err(meths.cmd, { cmd = "print", args = {}, bang = true }, {})) - - eq("Command cannot accept range: set", - pcall_err(meths.cmd, { cmd = "set", args = {}, range = {1} }, {})) - eq("Invalid 'range': expected Array, got Boolean", - pcall_err(meths.cmd, { cmd = "print", args = {}, range = true }, {})) - eq("Invalid 'range': expected <=2 elements", - pcall_err(meths.cmd, { cmd = "print", args = {}, range = {1,2,3,4} }, {})) - eq("Invalid range element: expected non-negative Integer", - pcall_err(meths.cmd, { cmd = "print", args = {}, range = {-1} }, {})) - - eq("Command cannot accept count: set", - pcall_err(meths.cmd, { cmd = "set", args = {}, count = 1 }, {})) - eq("Invalid 'count': expected Integer, got Boolean", - pcall_err(meths.cmd, { cmd = "print", args = {}, count = true }, {})) - eq("Invalid 'count': expected non-negative Integer", - pcall_err(meths.cmd, { cmd = "print", args = {}, count = -1 }, {})) - - eq("Command cannot accept register: set", - pcall_err(meths.cmd, { cmd = "set", args = {}, reg = 'x' }, {})) - eq('Cannot use register "=', - pcall_err(meths.cmd, { cmd = "put", args = {}, reg = '=' }, {})) - eq("Invalid 'reg': expected single character, got xx", - pcall_err(meths.cmd, { cmd = "put", args = {}, reg = 'xx' }, {})) + eq("Invalid 'cmd': expected non-empty String", pcall_err(api.nvim_cmd, { cmd = '' }, {})) + eq("Invalid 'cmd': expected String, got Array", pcall_err(api.nvim_cmd, { cmd = {} }, {})) + eq( + "Invalid 'args': expected Array, got Boolean", + pcall_err(api.nvim_cmd, { cmd = 'set', args = true }, {}) + ) + eq( + 'Invalid command arg: expected non-whitespace', + pcall_err(api.nvim_cmd, { cmd = 'set', args = { ' ' } }, {}) + ) + eq( + 'Invalid command arg: expected valid type, got Array', + pcall_err(api.nvim_cmd, { cmd = 'set', args = { {} } }, {}) + ) + eq('Wrong number of arguments', pcall_err(api.nvim_cmd, { cmd = 'aboveleft', args = {} }, {})) + eq( + 'Command cannot accept bang: print', + pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, bang = true }, {}) + ) + + eq( + 'Command cannot accept range: set', + pcall_err(api.nvim_cmd, { cmd = 'set', args = {}, range = { 1 } }, {}) + ) + eq( + "Invalid 'range': expected Array, got Boolean", + pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, range = true }, {}) + ) + eq( + "Invalid 'range': expected <=2 elements", + pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, range = { 1, 2, 3, 4 } }, {}) + ) + eq( + 'Invalid range element: expected non-negative Integer', + pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, range = { -1 } }, {}) + ) + + eq( + 'Command cannot accept count: set', + pcall_err(api.nvim_cmd, { cmd = 'set', args = {}, count = 1 }, {}) + ) + eq( + "Invalid 'count': expected Integer, got Boolean", + pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, count = true }, {}) + ) + eq( + "Invalid 'count': expected non-negative Integer", + pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, count = -1 }, {}) + ) + + eq( + 'Command cannot accept register: set', + pcall_err(api.nvim_cmd, { cmd = 'set', args = {}, reg = 'x' }, {}) + ) + eq( + 'Cannot use register "=', + pcall_err(api.nvim_cmd, { cmd = 'put', args = {}, reg = '=' }, {}) + ) + eq( + "Invalid 'reg': expected single character, got xx", + pcall_err(api.nvim_cmd, { cmd = 'put', args = {}, reg = 'xx' }, {}) + ) -- #20681 - eq('Invalid command: "win_getid"', pcall_err(meths.cmd, { cmd = 'win_getid'}, {})) - eq('Invalid command: "echo "hi""', pcall_err(meths.cmd, { cmd = 'echo "hi"'}, {})) + eq('Invalid command: "win_getid"', pcall_err(api.nvim_cmd, { cmd = 'win_getid' }, {})) + eq('Invalid command: "echo "hi""', pcall_err(api.nvim_cmd, { cmd = 'echo "hi"' }, {})) eq('Invalid command: "win_getid"', pcall_err(exec_lua, [[return vim.cmd.win_getid{}]])) -- Lua call allows empty {} for dict item. eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, magic = {} }]])) eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, mods = {} }]])) - eq('', meths.cmd({ cmd = "set", args = {}, magic = {} }, {})) + eq('', api.nvim_cmd({ cmd = 'set', args = {}, magic = {} }, {})) -- Lua call does not allow non-empty list-like {} for dict item. - eq("Invalid 'magic': Expected Dict-like Lua table", - pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]])) - eq("Invalid key: 'bogus'", - pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]])) - eq("Invalid key: 'bogus'", - pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, mods = { bogus = true } }]])) + eq( + "Invalid 'magic': Expected Dict-like Lua table", + pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]]) + ) + eq( + "Invalid key: 'bogus'", + pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]]) + ) + eq( + "Invalid key: 'bogus'", + pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, mods = { bogus = true } }]]) + ) end) it('captures output', function() - eq("foo", meths.cmd({ cmd = "echo", args = { '"foo"' } }, { output = true })) + eq('foo', api.nvim_cmd({ cmd = 'echo', args = { '"foo"' } }, { output = true })) end) it('sets correct script context', function() - meths.cmd({ cmd = "set", args = { "cursorline" } }, {}) + api.nvim_cmd({ cmd = 'set', args = { 'cursorline' } }, {}) local str = exec_capture([[verbose set cursorline?]]) - neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)")) + neq(nil, str:find('cursorline\n\tLast set from API client %(channel id %d+%)')) end) it('works with range', function() @@ -4313,7 +4615,7 @@ describe('API', function() line5 line6 ]] - meths.cmd({ cmd = "del", range = {2, 4} }, {}) + api.nvim_cmd({ cmd = 'del', range = { 2, 4 } }, {}) expect [[ line1 you didn't expect this @@ -4321,6 +4623,7 @@ describe('API', function() line6 ]] end) + it('works with count', function() insert [[ line1 @@ -4331,13 +4634,14 @@ describe('API', function() line5 line6 ]] - meths.cmd({ cmd = "del", range = { 2 }, count = 4 }, {}) + api.nvim_cmd({ cmd = 'del', range = { 2 }, count = 4 }, {}) expect [[ line1 line5 line6 ]] end) + it('works with register', function() insert [[ line1 @@ -4348,7 +4652,7 @@ describe('API', function() line5 line6 ]] - meths.cmd({ cmd = "del", range = { 2, 4 }, reg = 'a' }, {}) + api.nvim_cmd({ cmd = 'del', range = { 2, 4 }, reg = 'a' }, {}) command('1put a') expect [[ line1 @@ -4360,192 +4664,293 @@ describe('API', function() line6 ]] end) - it('works with bang', function () - meths.create_user_command("Foo", 'echo "<bang>"', { bang = true }) - eq("!", meths.cmd({ cmd = "Foo", bang = true }, { output = true })) - eq("", meths.cmd({ cmd = "Foo", bang = false }, { output = true })) + + it('works with bang', function() + api.nvim_create_user_command('Foo', 'echo "<bang>"', { bang = true }) + eq('!', api.nvim_cmd({ cmd = 'Foo', bang = true }, { output = true })) + eq('', api.nvim_cmd({ cmd = 'Foo', bang = false }, { output = true })) end) + it('works with modifiers', function() -- with silent = true output is still captured - eq('1', - meths.cmd({ cmd = 'echomsg', args = { '1' }, mods = { silent = true } }, - { output = true })) + eq( + '1', + api.nvim_cmd( + { cmd = 'echomsg', args = { '1' }, mods = { silent = true } }, + { output = true } + ) + ) -- but message isn't added to message history - eq('', meths.cmd({ cmd = 'messages' }, { output = true })) - - meths.create_user_command("Foo", 'set verbose', {}) - eq(" verbose=1", meths.cmd({ cmd = "Foo", mods = { verbose = 1 } }, { output = true })) - - meths.create_user_command("Mods", "echo '<mods>'", {}) - eq('keepmarks keeppatterns silent 3verbose aboveleft horizontal', - meths.cmd({ cmd = "Mods", mods = { - horizontal = true, - keepmarks = true, - keeppatterns = true, - silent = true, - split = 'aboveleft', - verbose = 3, - } }, { output = true })) - eq(0, meths.get_option_value("verbose", {})) + eq('', api.nvim_cmd({ cmd = 'messages' }, { output = true })) + + api.nvim_create_user_command('Foo', 'set verbose', {}) + eq(' verbose=1', api.nvim_cmd({ cmd = 'Foo', mods = { verbose = 1 } }, { output = true })) + + api.nvim_create_user_command('Mods', "echo '<mods>'", {}) + eq( + 'keepmarks keeppatterns silent 3verbose aboveleft horizontal', + api.nvim_cmd({ + cmd = 'Mods', + mods = { + horizontal = true, + keepmarks = true, + keeppatterns = true, + silent = true, + split = 'aboveleft', + verbose = 3, + }, + }, { output = true }) + ) + eq(0, api.nvim_get_option_value('verbose', {})) command('edit foo.txt | edit bar.txt') - eq(' 1 #h "foo.txt" line 1', - meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = false } } }, - { output = true })) - eq(' 2 %a "bar.txt" line 1', - meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = true } } }, - { output = true })) + eq( + ' 1 #h "foo.txt" line 1', + api.nvim_cmd( + { cmd = 'buffers', mods = { filter = { pattern = 'foo', force = false } } }, + { output = true } + ) + ) + eq( + ' 2 %a "bar.txt" line 1', + api.nvim_cmd( + { cmd = 'buffers', mods = { filter = { pattern = 'foo', force = true } } }, + { output = true } + ) + ) -- with emsg_silent = true error is suppressed feed([[:lua vim.api.nvim_cmd({ cmd = 'call', mods = { emsg_silent = true } }, {})<CR>]]) - eq('', meths.cmd({ cmd = 'messages' }, { output = true })) + eq('', api.nvim_cmd({ cmd = 'messages' }, { output = true })) -- error from the next command typed is not suppressed #21420 feed(':call<CR><CR>') - eq('E471: Argument required', meths.cmd({ cmd = 'messages' }, { output = true })) + eq('E471: Argument required', api.nvim_cmd({ cmd = 'messages' }, { output = true })) end) + it('works with magic.file', function() exec_lua([[ vim.api.nvim_create_user_command("Foo", function(opts) vim.api.nvim_echo({{ opts.fargs[1] }}, false, {}) end, { nargs = 1 }) ]]) - eq(luv.cwd(), - meths.cmd({ cmd = "Foo", args = { '%:p:h' }, magic = { file = true } }, - { output = true })) + eq( + uv.cwd(), + api.nvim_cmd( + { cmd = 'Foo', args = { '%:p:h' }, magic = { file = true } }, + { output = true } + ) + ) end) + it('splits arguments correctly', function() exec([[ function! FooFunc(...) echo a:000 endfunction ]]) - meths.create_user_command("Foo", "call FooFunc(<f-args>)", { nargs = '+' }) - eq([=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=], - meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}}, - { output = true })) - eq([=[['test \ \\ \"""\', 'more\ tests\" ']]=], - meths.cmd({ cmd = "Foo", args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } }, - { output = true })) + api.nvim_create_user_command('Foo', 'call FooFunc(<f-args>)', { nargs = '+' }) + eq( + [=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=], + api.nvim_cmd( + { cmd = 'Foo', args = { 'a quick', 'brown fox', 'jumps over the', 'lazy dog' } }, + { output = true } + ) + ) + eq( + [=[['test \ \\ \"""\', 'more\ tests\" ']]=], + api.nvim_cmd( + { cmd = 'Foo', args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } }, + { output = true } + ) + ) end) + it('splits arguments correctly for Lua callback', function() - meths.exec_lua([[ + api.nvim_exec_lua( + [[ local function FooFunc(opts) vim.print(opts.fargs) end vim.api.nvim_create_user_command("Foo", FooFunc, { nargs = '+' }) - ]], {}) - eq([[{ "a quick", "brown fox", "jumps over the", "lazy dog" }]], - meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}}, - { output = true })) - eq([[{ 'test \\ \\\\ \\"""\\', 'more\\ tests\\" ' }]], - meths.cmd({ cmd = "Foo", args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } }, - { output = true })) + ]], + {} + ) + eq( + [[{ "a quick", "brown fox", "jumps over the", "lazy dog" }]], + api.nvim_cmd( + { cmd = 'Foo', args = { 'a quick', 'brown fox', 'jumps over the', 'lazy dog' } }, + { output = true } + ) + ) + eq( + [[{ 'test \\ \\\\ \\"""\\', 'more\\ tests\\" ' }]], + api.nvim_cmd( + { cmd = 'Foo', args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } }, + { output = true } + ) + ) end) + it('works with buffer names', function() - command("edit foo.txt | edit bar.txt") - meths.cmd({ cmd = "buffer", args = { "foo.txt" } }, {}) - eq("foo.txt", funcs.fnamemodify(meths.buf_get_name(0), ":t")) - meths.cmd({ cmd = "buffer", args = { "bar.txt" } }, {}) - eq("bar.txt", funcs.fnamemodify(meths.buf_get_name(0), ":t")) + command('edit foo.txt | edit bar.txt') + api.nvim_cmd({ cmd = 'buffer', args = { 'foo.txt' } }, {}) + eq('foo.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t')) + api.nvim_cmd({ cmd = 'buffer', args = { 'bar.txt' } }, {}) + eq('bar.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t')) end) + it('triggers CmdUndefined event if command is not found', function() - meths.exec_lua([[ + api.nvim_exec_lua( + [[ vim.api.nvim_create_autocmd("CmdUndefined", { pattern = "Foo", callback = function() vim.api.nvim_create_user_command("Foo", "echo 'foo'", {}) end }) - ]], {}) - eq("foo", meths.cmd({ cmd = "Foo" }, { output = true })) + ]], + {} + ) + eq('foo', api.nvim_cmd({ cmd = 'Foo' }, { output = true })) end) + it('errors if command is not implemented', function() - eq("Command not implemented: winpos", pcall_err(meths.cmd, { cmd = "winpos" }, {})) + eq('Command not implemented: winpos', pcall_err(api.nvim_cmd, { cmd = 'winpos' }, {})) end) + it('works with empty arguments list', function() - meths.cmd({ cmd = "update" }, {}) - meths.cmd({ cmd = "buffer", count = 0 }, {}) + api.nvim_cmd({ cmd = 'update' }, {}) + api.nvim_cmd({ cmd = 'buffer', count = 0 }, {}) end) - it('doesn\'t suppress errors when used in keymapping', function() - meths.exec_lua([[ + + it("doesn't suppress errors when used in keymapping", function() + api.nvim_exec_lua( + [[ vim.keymap.set("n", "[l", function() vim.api.nvim_cmd({ cmd = "echo", args = {"foo"} }, {}) end) - ]], {}) - feed("[l") - neq(nil, string.find(eval("v:errmsg"), "E5108:")) + ]], + {} + ) + feed('[l') + neq(nil, string.find(eval('v:errmsg'), 'E5108:')) end) + it('handles 0 range #19608', function() - meths.buf_set_lines(0, 0, -1, false, { "aa" }) - meths.cmd({ cmd = 'delete', range = { 0 } }, {}) + api.nvim_buf_set_lines(0, 0, -1, false, { 'aa' }) + api.nvim_cmd({ cmd = 'delete', range = { 0 } }, {}) command('undo') - eq({'aa'}, meths.buf_get_lines(0, 0, 1, false)) + eq({ 'aa' }, api.nvim_buf_get_lines(0, 0, 1, false)) assert_alive() end) + it('supports filename expansion', function() - meths.cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {}) - local arg = funcs.expand('%:p:h:t') - eq({ arg, arg }, funcs.argv()) + api.nvim_cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {}) + local arg = fn.expand('%:p:h:t') + eq({ arg, arg }, fn.argv()) end) - it("'make' command works when argument count isn't 1 #19696", function() + + it(":make command works when argument count isn't 1 #19696", function() command('set makeprg=echo') command('set shellquote=') - matches('^:!echo ', - meths.cmd({ cmd = 'make' }, { output = true })) + matches('^:!echo ', api.nvim_cmd({ cmd = 'make' }, { output = true })) assert_alive() - matches('^:!echo foo bar', - meths.cmd({ cmd = 'make', args = { 'foo', 'bar' } }, { output = true })) + matches( + '^:!echo foo bar', + api.nvim_cmd({ cmd = 'make', args = { 'foo', 'bar' } }, { output = true }) + ) assert_alive() - local arg_pesc = pesc(funcs.expand('%:p:h:t')) - matches(('^:!echo %s %s'):format(arg_pesc, arg_pesc), - meths.cmd({ cmd = 'make', args = { '%:p:h:t', '%:p:h:t' } }, { output = true })) + local arg_pesc = pesc(fn.expand('%:p:h:t')) + matches( + ('^:!echo %s %s'):format(arg_pesc, arg_pesc), + api.nvim_cmd({ cmd = 'make', args = { '%:p:h:t', '%:p:h:t' } }, { output = true }) + ) assert_alive() end) - it('doesn\'t display messages when output=true', function() + + it("doesn't display messages when output=true", function() local screen = Screen.new(40, 6) screen:attach() screen:set_default_attr_ids({ - [0] = {bold=true, foreground=Screen.colors.Blue}, + [0] = { bold = true, foreground = Screen.colors.Blue }, }) - meths.cmd({cmd = 'echo', args = {[['hello']]}}, {output = true}) - screen:expect{grid=[[ + api.nvim_cmd({ cmd = 'echo', args = { [['hello']] } }, { output = true }) + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 | - ]]} + ]], + } exec([[ func Print() call nvim_cmd(#{cmd: 'echo', args: ['"hello"']}, #{output: v:true}) endfunc ]]) feed([[:echon 1 | call Print() | echon 5<CR>]]) - screen:expect{grid=[[ + screen:expect { + grid = [[ ^ | - {0:~ }| - {0:~ }| - {0:~ }| - {0:~ }| + {0:~ }|*4 15 | - ]]} + ]], + } end) + it('works with non-String args', function() - eq('2', meths.cmd({cmd = 'echo', args = {2}}, {output = true})) - eq('1', meths.cmd({cmd = 'echo', args = {true}}, {output = true})) + eq('2', api.nvim_cmd({ cmd = 'echo', args = { 2 } }, { output = true })) + eq('1', api.nvim_cmd({ cmd = 'echo', args = { true } }, { output = true })) end) + describe('first argument as count', function() it('works', function() command('vsplit | enew') - meths.cmd({cmd = 'bdelete', args = {meths.get_current_buf()}}, {}) - eq(1, meths.get_current_buf().id) + api.nvim_cmd({ cmd = 'bdelete', args = { api.nvim_get_current_buf() } }, {}) + eq(1, api.nvim_get_current_buf()) end) + it('works with :sleep using milliseconds', function() - local start = luv.now() - meths.cmd({cmd = 'sleep', args = {'100m'}}, {}) - ok(luv.now() - start <= 300) + local start = uv.now() + api.nvim_cmd({ cmd = 'sleep', args = { '100m' } }, {}) + ok(uv.now() - start <= 300) end) end) + + it(':call with unknown function does not crash #26289', function() + eq( + 'Vim:E117: Unknown function: UnknownFunc', + pcall_err(api.nvim_cmd, { cmd = 'call', args = { 'UnknownFunc()' } }, {}) + ) + end) + + it(':throw does not crash #24556', function() + eq('42', pcall_err(api.nvim_cmd, { cmd = 'throw', args = { '42' } }, {})) + end) + + it('can use :return #24556', function() + exec([[ + func Foo() + let g:pos = 'before' + call nvim_cmd({'cmd': 'return', 'args': ['[1, 2, 3]']}, {}) + let g:pos = 'after' + endfunc + let g:result = Foo() + ]]) + eq('before', api.nvim_get_var('pos')) + eq({ 1, 2, 3 }, api.nvim_get_var('result')) + end) + + it('errors properly when command too recursive #27210', function() + exec_lua([[ + _G.success = false + vim.api.nvim_create_user_command('Test', function() + vim.api.nvim_cmd({ cmd = 'Test' }, {}) + _G.success = true + end, {}) + ]]) + pcall_err(command, 'Test') + assert_alive() + eq(false, exec_lua('return _G.success')) + end) end) end) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 6737c2d15b..097a546ef2 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1,17 +1,24 @@ local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') -local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq, - ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf, - helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq, - helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval, - helpers.tabpage +local clear, curbuf, curbuf_contents, curwin, eq, neq, matches, ok, feed, insert, eval = + helpers.clear, + helpers.api.nvim_get_current_buf, + helpers.curbuf_contents, + helpers.api.nvim_get_current_win, + helpers.eq, + helpers.neq, + helpers.matches, + helpers.ok, + helpers.feed, + helpers.insert, + helpers.eval local poke_eventloop = helpers.poke_eventloop -local curwinmeths = helpers.curwinmeths local exec = helpers.exec -local funcs = helpers.funcs +local exec_lua = helpers.exec_lua +local fn = helpers.fn local request = helpers.request -local NIL = helpers.NIL -local meths = helpers.meths +local NIL = vim.NIL +local api = helpers.api local command = helpers.command local pcall_err = helpers.pcall_err local assert_alive = helpers.assert_alive @@ -21,201 +28,229 @@ describe('API/win', function() describe('get_buf', function() it('works', function() - eq(curbuf(), window('get_buf', nvim('list_wins')[1])) - nvim('command', 'new') - nvim('set_current_win', nvim('list_wins')[2]) - eq(curbuf(), window('get_buf', nvim('list_wins')[2])) - neq(window('get_buf', nvim('list_wins')[1]), - window('get_buf', nvim('list_wins')[2])) + eq(curbuf(), api.nvim_win_get_buf(api.nvim_list_wins()[1])) + command('new') + api.nvim_set_current_win(api.nvim_list_wins()[2]) + eq(curbuf(), api.nvim_win_get_buf(api.nvim_list_wins()[2])) + neq( + api.nvim_win_get_buf(api.nvim_list_wins()[1]), + api.nvim_win_get_buf(api.nvim_list_wins()[2]) + ) end) end) describe('set_buf', function() it('works', function() - nvim('command', 'new') - local windows = nvim('list_wins') - neq(window('get_buf', windows[2]), window('get_buf', windows[1])) - window('set_buf', windows[2], window('get_buf', windows[1])) - eq(window('get_buf', windows[2]), window('get_buf', windows[1])) + command('new') + local windows = api.nvim_list_wins() + neq(api.nvim_win_get_buf(windows[2]), api.nvim_win_get_buf(windows[1])) + api.nvim_win_set_buf(windows[2], api.nvim_win_get_buf(windows[1])) + eq(api.nvim_win_get_buf(windows[2]), api.nvim_win_get_buf(windows[1])) end) it('validates args', function() - eq('Invalid buffer id: 23', pcall_err(window, 'set_buf', nvim('get_current_win'), 23)) - eq('Invalid window id: 23', pcall_err(window, 'set_buf', 23, nvim('get_current_buf'))) + eq('Invalid buffer id: 23', pcall_err(api.nvim_win_set_buf, api.nvim_get_current_win(), 23)) + eq('Invalid window id: 23', pcall_err(api.nvim_win_set_buf, 23, api.nvim_get_current_buf())) end) - it('disallowed in cmdwin if win={old_}curwin or buf=curbuf', function() - local new_buf = meths.create_buf(true, true) - local old_win = meths.get_current_win() - local new_win = meths.open_win(new_buf, false, { - relative='editor', row=10, col=10, width=50, height=10, + it('disallowed in cmdwin if win=cmdwin_{old_cur}win or buf=cmdwin_buf', function() + local new_buf = api.nvim_create_buf(true, true) + local old_win = api.nvim_get_current_win() + local new_win = api.nvim_open_win(new_buf, false, { + relative = 'editor', + row = 10, + col = 10, + width = 50, + height = 10, }) feed('q:') - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.win_set_buf, 0, new_buf)) - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.win_set_buf, old_win, new_buf)) - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.win_set_buf, new_win, 0)) - - local next_buf = meths.create_buf(true, true) - meths.win_set_buf(new_win, next_buf) - eq(next_buf, meths.win_get_buf(new_win)) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_set_buf, 0, new_buf) + ) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_set_buf, old_win, new_buf) + ) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_set_buf, new_win, 0) + ) + matches( + 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$', + pcall_err( + exec_lua, + [[ + local cmdwin_buf = vim.api.nvim_get_current_buf() + local new_win, new_buf = ... + vim.api.nvim_buf_call(new_buf, function() + vim.api.nvim_win_set_buf(new_win, cmdwin_buf) + end) + ]], + new_win, + new_buf + ) + ) + matches( + 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$', + pcall_err( + exec_lua, + [[ + local cmdwin_win = vim.api.nvim_get_current_win() + local new_win, new_buf = ... + vim.api.nvim_win_call(new_win, function() + vim.api.nvim_win_set_buf(cmdwin_win, new_buf) + end) + ]], + new_win, + new_buf + ) + ) + + local next_buf = api.nvim_create_buf(true, true) + api.nvim_win_set_buf(new_win, next_buf) + eq(next_buf, api.nvim_win_get_buf(new_win)) end) end) describe('{get,set}_cursor', function() it('works', function() - eq({1, 0}, curwin('get_cursor')) - nvim('command', 'normal ityping\027o some text') + eq({ 1, 0 }, api.nvim_win_get_cursor(0)) + command('normal ityping\027o some text') eq('typing\n some text', curbuf_contents()) - eq({2, 10}, curwin('get_cursor')) - curwin('set_cursor', {2, 6}) - nvim('command', 'normal i dumb') + eq({ 2, 10 }, api.nvim_win_get_cursor(0)) + api.nvim_win_set_cursor(0, { 2, 6 }) + command('normal i dumb') eq('typing\n some dumb text', curbuf_contents()) end) it('does not leak memory when using invalid window ID with invalid pos', function() - eq('Invalid window id: 1', pcall_err(meths.win_set_cursor, 1, {"b\na"})) + eq('Invalid window id: 1', pcall_err(api.nvim_win_set_cursor, 1, { 'b\na' })) end) it('updates the screen, and also when the window is unfocused', function() local screen = Screen.new(30, 9) screen:set_default_attr_ids({ - [1] = {bold = true, foreground = Screen.colors.Blue}, - [2] = {bold = true, reverse = true}; - [3] = {reverse = true}; + [1] = { bold = true, foreground = Screen.colors.Blue }, + [2] = { bold = true, reverse = true }, + [3] = { reverse = true }, }) screen:attach() - insert("prologue") + insert('prologue') feed('100o<esc>') - insert("epilogue") + insert('epilogue') local win = curwin() feed('gg') - screen:expect{grid=[[ + screen:expect { + grid = [[ ^prologue | - | - | - | - | - | - | - | - | - ]]} + |*8 + ]], + } -- cursor position is at beginning - eq({1, 0}, window('get_cursor', win)) + eq({ 1, 0 }, api.nvim_win_get_cursor(win)) -- move cursor to end - window('set_cursor', win, {101, 0}) - screen:expect{grid=[[ - | - | - | - | - | - | - | + api.nvim_win_set_cursor(win, { 101, 0 }) + screen:expect { + grid = [[ + |*7 ^epilogue | | - ]]} + ]], + } -- move cursor to the beginning again - window('set_cursor', win, {1, 0}) - screen:expect{grid=[[ + api.nvim_win_set_cursor(win, { 1, 0 }) + screen:expect { + grid = [[ ^prologue | - | - | - | - | - | - | - | - | - ]]} + |*8 + ]], + } -- move focus to new window - nvim('command',"new") + command('new') neq(win, curwin()) -- sanity check, cursor position is kept - eq({1, 0}, window('get_cursor', win)) - screen:expect{grid=[[ + eq({ 1, 0 }, api.nvim_win_get_cursor(win)) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| + {1:~ }|*2 {2:[No Name] }| prologue | - | - | + |*2 {3:[No Name] [+] }| | - ]]} + ]], + } -- move cursor to end - window('set_cursor', win, {101, 0}) - screen:expect{grid=[[ + api.nvim_win_set_cursor(win, { 101, 0 }) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| + {1:~ }|*2 {2:[No Name] }| - | - | + |*2 epilogue | {3:[No Name] [+] }| | - ]]} + ]], + } -- move cursor to the beginning again - window('set_cursor', win, {1, 0}) - screen:expect{grid=[[ + api.nvim_win_set_cursor(win, { 1, 0 }) + screen:expect { + grid = [[ ^ | - {1:~ }| - {1:~ }| + {1:~ }|*2 {2:[No Name] }| prologue | - | - | + |*2 {3:[No Name] [+] }| | - ]]} + ]], + } -- curwin didn't change back neq(win, curwin()) end) it('remembers what column it wants to be in', function() - insert("first line") + insert('first line') feed('o<esc>') - insert("second line") + insert('second line') feed('gg') poke_eventloop() -- let nvim process the 'gg' command -- cursor position is at beginning local win = curwin() - eq({1, 0}, window('get_cursor', win)) + eq({ 1, 0 }, api.nvim_win_get_cursor(win)) -- move cursor to column 5 - window('set_cursor', win, {1, 5}) + api.nvim_win_set_cursor(win, { 1, 5 }) -- move down a line feed('j') poke_eventloop() -- let nvim process the 'j' command -- cursor is still in column 5 - eq({2, 5}, window('get_cursor', win)) + eq({ 2, 5 }, api.nvim_win_get_cursor(win)) end) it('updates cursorline and statusline ruler in non-current window', function() local screen = Screen.new(60, 8) screen:set_default_attr_ids({ - [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText - [2] = {background = Screen.colors.Grey90}, -- CursorLine - [3] = {bold = true, reverse = true}, -- StatusLine - [4] = {reverse = true}, -- StatusLineNC + [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + [2] = { background = Screen.colors.Grey90 }, -- CursorLine + [3] = { bold = true, reverse = true }, -- StatusLine + [4] = { reverse = true }, -- StatusLineNC }) screen:attach() command('set ruler') @@ -232,19 +267,17 @@ describe('API/win', function() bbb │bbb | ccc │ccc | {2:dd^d }│{2:ddd }| - {1:~ }│{1:~ }| - {1:~ }│{1:~ }| + {1:~ }│{1:~ }|*2 {3:[No Name] [+] 4,3 All }{4:[No Name] [+] 4,3 All}| | ]]) - window('set_cursor', oldwin, {1, 0}) + api.nvim_win_set_cursor(oldwin, { 1, 0 }) screen:expect([[ aaa │{2:aaa }| bbb │bbb | ccc │ccc | {2:dd^d }│ddd | - {1:~ }│{1:~ }| - {1:~ }│{1:~ }| + {1:~ }│{1:~ }|*2 {3:[No Name] [+] 4,3 All }{4:[No Name] [+] 1,1 All}| | ]]) @@ -253,10 +286,10 @@ describe('API/win', function() it('updates cursorcolumn in non-current window', function() local screen = Screen.new(60, 8) screen:set_default_attr_ids({ - [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText - [2] = {background = Screen.colors.Grey90}, -- CursorColumn - [3] = {bold = true, reverse = true}, -- StatusLine - [4] = {reverse = true}, -- StatusLineNC + [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText + [2] = { background = Screen.colors.Grey90 }, -- CursorColumn + [3] = { bold = true, reverse = true }, -- StatusLine + [4] = { reverse = true }, -- StatusLineNC }) screen:attach() command('set cursorcolumn') @@ -272,19 +305,17 @@ describe('API/win', function() bb{2:b} │bb{2:b} | cc{2:c} │cc{2:c} | dd^d │ddd | - {1:~ }│{1:~ }| - {1:~ }│{1:~ }| + {1:~ }│{1:~ }|*2 {3:[No Name] [+] }{4:[No Name] [+] }| | ]]) - window('set_cursor', oldwin, {2, 0}) + api.nvim_win_set_cursor(oldwin, { 2, 0 }) screen:expect([[ aa{2:a} │{2:a}aa | bb{2:b} │bbb | cc{2:c} │{2:c}cc | dd^d │{2:d}dd | - {1:~ }│{1:~ }| - {1:~ }│{1:~ }| + {1:~ }│{1:~ }|*2 {3:[No Name] [+] }{4:[No Name] [+] }| | ]]) @@ -293,31 +324,35 @@ describe('API/win', function() describe('{get,set}_height', function() it('works', function() - nvim('command', 'vsplit') - eq(window('get_height', nvim('list_wins')[2]), - window('get_height', nvim('list_wins')[1])) - nvim('set_current_win', nvim('list_wins')[2]) - nvim('command', 'split') - eq(window('get_height', nvim('list_wins')[2]), - math.floor(window('get_height', nvim('list_wins')[1]) / 2)) - window('set_height', nvim('list_wins')[2], 2) - eq(2, window('get_height', nvim('list_wins')[2])) + command('vsplit') + eq( + api.nvim_win_get_height(api.nvim_list_wins()[2]), + api.nvim_win_get_height(api.nvim_list_wins()[1]) + ) + api.nvim_set_current_win(api.nvim_list_wins()[2]) + command('split') + eq( + api.nvim_win_get_height(api.nvim_list_wins()[2]), + math.floor(api.nvim_win_get_height(api.nvim_list_wins()[1]) / 2) + ) + api.nvim_win_set_height(api.nvim_list_wins()[2], 2) + eq(2, api.nvim_win_get_height(api.nvim_list_wins()[2])) end) it('correctly handles height=1', function() - nvim('command', 'split') - nvim('set_current_win', nvim('list_wins')[1]) - window('set_height', nvim('list_wins')[2], 1) - eq(1, window('get_height', nvim('list_wins')[2])) + command('split') + api.nvim_set_current_win(api.nvim_list_wins()[1]) + api.nvim_win_set_height(api.nvim_list_wins()[2], 1) + eq(1, api.nvim_win_get_height(api.nvim_list_wins()[2])) end) it('correctly handles height=1 with a winbar', function() - nvim('command', 'set winbar=foobar') - nvim('command', 'set winminheight=0') - nvim('command', 'split') - nvim('set_current_win', nvim('list_wins')[1]) - window('set_height', nvim('list_wins')[2], 1) - eq(1, window('get_height', nvim('list_wins')[2])) + command('set winbar=foobar') + command('set winminheight=0') + command('split') + api.nvim_set_current_win(api.nvim_list_wins()[1]) + api.nvim_win_set_height(api.nvim_list_wins()[2], 1) + eq(1, api.nvim_win_get_height(api.nvim_list_wins()[2])) end) it('do not cause ml_get errors with foldmethod=expr #19989', function() @@ -333,21 +368,25 @@ describe('API/win', function() call nvim_win_set_height(w, 5) ]]) feed('l') - eq('', meths.get_vvar('errmsg')) + eq('', api.nvim_get_vvar('errmsg')) end) end) describe('{get,set}_width', function() it('works', function() - nvim('command', 'split') - eq(window('get_width', nvim('list_wins')[2]), - window('get_width', nvim('list_wins')[1])) - nvim('set_current_win', nvim('list_wins')[2]) - nvim('command', 'vsplit') - eq(window('get_width', nvim('list_wins')[2]), - math.floor(window('get_width', nvim('list_wins')[1]) / 2)) - window('set_width', nvim('list_wins')[2], 2) - eq(2, window('get_width', nvim('list_wins')[2])) + command('split') + eq( + api.nvim_win_get_width(api.nvim_list_wins()[2]), + api.nvim_win_get_width(api.nvim_list_wins()[1]) + ) + api.nvim_set_current_win(api.nvim_list_wins()[2]) + command('vsplit') + eq( + api.nvim_win_get_width(api.nvim_list_wins()[2]), + math.floor(api.nvim_win_get_width(api.nvim_list_wins()[1]) / 2) + ) + api.nvim_win_set_width(api.nvim_list_wins()[2], 2) + eq(2, api.nvim_win_get_width(api.nvim_list_wins()[2])) end) it('do not cause ml_get errors with foldmethod=expr #19989', function() @@ -363,36 +402,36 @@ describe('API/win', function() call nvim_win_set_width(w, 5) ]]) feed('l') - eq('', meths.get_vvar('errmsg')) + eq('', api.nvim_get_vvar('errmsg')) end) end) describe('{get,set,del}_var', function() it('works', function() - curwin('set_var', 'lua', {1, 2, {['3'] = 1}}) - eq({1, 2, {['3'] = 1}}, curwin('get_var', 'lua')) - eq({1, 2, {['3'] = 1}}, nvim('eval', 'w:lua')) - eq(1, funcs.exists('w:lua')) - curwinmeths.del_var('lua') - eq(0, funcs.exists('w:lua')) - eq('Key not found: lua', pcall_err(curwinmeths.del_var, 'lua')) - curwinmeths.set_var('lua', 1) + api.nvim_win_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } }) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_win_get_var(0, 'lua')) + eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('w:lua')) + eq(1, fn.exists('w:lua')) + api.nvim_win_del_var(0, 'lua') + eq(0, fn.exists('w:lua')) + eq('Key not found: lua', pcall_err(api.nvim_win_del_var, 0, 'lua')) + api.nvim_win_set_var(0, 'lua', 1) command('lockvar w:lua') - eq('Key is locked: lua', pcall_err(curwinmeths.del_var, 'lua')) - eq('Key is locked: lua', pcall_err(curwinmeths.set_var, 'lua', 1)) + eq('Key is locked: lua', pcall_err(api.nvim_win_del_var, 0, 'lua')) + eq('Key is locked: lua', pcall_err(api.nvim_win_set_var, 0, 'lua', 1)) end) it('window_set_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } eq(NIL, request('window_set_var', 0, 'lua', val1)) eq(val1, request('window_set_var', 0, 'lua', val2)) end) it('window_del_var returns the old value', function() - local val1 = {1, 2, {['3'] = 1}} - local val2 = {4, 7} - eq(NIL, request('window_set_var', 0, 'lua', val1)) + local val1 = { 1, 2, { ['3'] = 1 } } + local val2 = { 4, 7 } + eq(NIL, request('window_set_var', 0, 'lua', val1)) eq(val1, request('window_set_var', 0, 'lua', val2)) eq(val2, request('window_del_var', 0, 'lua')) end) @@ -400,53 +439,51 @@ describe('API/win', function() describe('nvim_get_option_value, nvim_set_option_value', function() it('works', function() - nvim('set_option_value', 'colorcolumn', '4,3', {}) - eq('4,3', nvim('get_option_value', 'colorcolumn', {})) - command("set modified hidden") - command("enew") -- edit new buffer, window option is preserved - eq('4,3', nvim('get_option_value', 'colorcolumn', {})) + api.nvim_set_option_value('colorcolumn', '4,3', {}) + eq('4,3', api.nvim_get_option_value('colorcolumn', {})) + command('set modified hidden') + command('enew') -- edit new buffer, window option is preserved + eq('4,3', api.nvim_get_option_value('colorcolumn', {})) -- global-local option - nvim('set_option_value', 'statusline', 'window-status', {win=0}) - eq('window-status', nvim('get_option_value', 'statusline', {win=0})) - eq('', nvim('get_option_value', 'statusline', {scope='global'})) - command("set modified") - command("enew") -- global-local: not preserved in new buffer + api.nvim_set_option_value('statusline', 'window-status', { win = 0 }) + eq('window-status', api.nvim_get_option_value('statusline', { win = 0 })) + eq('', api.nvim_get_option_value('statusline', { scope = 'global' })) + command('set modified') + command('enew') -- global-local: not preserved in new buffer -- confirm local value was not copied - eq('', nvim('get_option_value', 'statusline', {win = 0})) + eq('', api.nvim_get_option_value('statusline', { win = 0 })) eq('', eval('&l:statusline')) end) it('after switching windows #15390', function() - nvim('command', 'tabnew') - local tab1 = unpack(nvim('list_tabpages')) - local win1 = unpack(tabpage('list_wins', tab1)) - nvim('set_option_value', 'statusline', 'window-status', {win=win1.id}) - nvim('command', 'split') - nvim('command', 'wincmd J') - nvim('command', 'wincmd j') - eq('window-status', nvim('get_option_value', 'statusline', {win = win1.id})) + command('tabnew') + local tab1 = unpack(api.nvim_list_tabpages()) + local win1 = unpack(api.nvim_tabpage_list_wins(tab1)) + api.nvim_set_option_value('statusline', 'window-status', { win = win1 }) + command('split') + command('wincmd J') + command('wincmd j') + eq('window-status', api.nvim_get_option_value('statusline', { win = win1 })) assert_alive() end) it('returns values for unset local options', function() - eq(-1, nvim('get_option_value', 'scrolloff', {win=0, scope='local'})) + eq(-1, api.nvim_get_option_value('scrolloff', { win = 0, scope = 'local' })) end) end) describe('get_position', function() it('works', function() - local height = window('get_height', nvim('list_wins')[1]) - local width = window('get_width', nvim('list_wins')[1]) - nvim('command', 'split') - nvim('command', 'vsplit') - eq({0, 0}, window('get_position', nvim('list_wins')[1])) + local height = api.nvim_win_get_height(api.nvim_list_wins()[1]) + local width = api.nvim_win_get_width(api.nvim_list_wins()[1]) + command('split') + command('vsplit') + eq({ 0, 0 }, api.nvim_win_get_position(api.nvim_list_wins()[1])) local vsplit_pos = math.floor(width / 2) local split_pos = math.floor(height / 2) - local win2row, win2col = - unpack(window('get_position', nvim('list_wins')[2])) - local win3row, win3col = - unpack(window('get_position', nvim('list_wins')[3])) + local win2row, win2col = unpack(api.nvim_win_get_position(api.nvim_list_wins()[2])) + local win3row, win3col = unpack(api.nvim_win_get_position(api.nvim_list_wins()[3])) eq(0, win2row) eq(0, win3col) ok(vsplit_pos - 1 <= win2col and win2col <= vsplit_pos + 1) @@ -456,239 +493,362 @@ describe('API/win', function() describe('get_position', function() it('works', function() - nvim('command', 'tabnew') - nvim('command', 'vsplit') - eq(window('get_tabpage', - nvim('list_wins')[1]), nvim('list_tabpages')[1]) - eq(window('get_tabpage', - nvim('list_wins')[2]), nvim('list_tabpages')[2]) - eq(window('get_tabpage', - nvim('list_wins')[3]), nvim('list_tabpages')[2]) + command('tabnew') + command('vsplit') + eq(api.nvim_win_get_tabpage(api.nvim_list_wins()[1]), api.nvim_list_tabpages()[1]) + eq(api.nvim_win_get_tabpage(api.nvim_list_wins()[2]), api.nvim_list_tabpages()[2]) + eq(api.nvim_win_get_tabpage(api.nvim_list_wins()[3]), api.nvim_list_tabpages()[2]) end) end) describe('get_number', function() it('works', function() - local wins = nvim('list_wins') - eq(1, window('get_number', wins[1])) + local wins = api.nvim_list_wins() + eq(1, api.nvim_win_get_number(wins[1])) - nvim('command', 'split') - local win1, win2 = unpack(nvim('list_wins')) - eq(1, window('get_number', win1)) - eq(2, window('get_number', win2)) + command('split') + local win1, win2 = unpack(api.nvim_list_wins()) + eq(1, api.nvim_win_get_number(win1)) + eq(2, api.nvim_win_get_number(win2)) - nvim('command', 'wincmd J') - eq(2, window('get_number', win1)) - eq(1, window('get_number', win2)) + command('wincmd J') + eq(2, api.nvim_win_get_number(win1)) + eq(1, api.nvim_win_get_number(win2)) - nvim('command', 'tabnew') - local win3 = nvim('list_wins')[3] + command('tabnew') + local win3 = api.nvim_list_wins()[3] -- First tab page - eq(2, window('get_number', win1)) - eq(1, window('get_number', win2)) + eq(2, api.nvim_win_get_number(win1)) + eq(1, api.nvim_win_get_number(win2)) -- Second tab page - eq(1, window('get_number', win3)) + eq(1, api.nvim_win_get_number(win3)) end) end) describe('is_valid', function() it('works', function() - nvim('command', 'split') - local win = nvim('list_wins')[2] - nvim('set_current_win', win) - ok(window('is_valid', win)) - nvim('command', 'close') - ok(not window('is_valid', win)) + command('split') + local win = api.nvim_list_wins()[2] + api.nvim_set_current_win(win) + ok(api.nvim_win_is_valid(win)) + command('close') + ok(not api.nvim_win_is_valid(win)) end) end) describe('close', function() it('can close current window', function() - local oldwin = meths.get_current_win() + local oldwin = api.nvim_get_current_win() command('split') - local newwin = meths.get_current_win() - meths.win_close(newwin,false) - eq({oldwin}, meths.list_wins()) + local newwin = api.nvim_get_current_win() + api.nvim_win_close(newwin, false) + eq({ oldwin }, api.nvim_list_wins()) end) it('can close noncurrent window', function() - local oldwin = meths.get_current_win() + local oldwin = api.nvim_get_current_win() command('split') - local newwin = meths.get_current_win() - meths.win_close(oldwin,false) - eq({newwin}, meths.list_wins()) + local newwin = api.nvim_get_current_win() + api.nvim_win_close(oldwin, false) + eq({ newwin }, api.nvim_list_wins()) end) it("handles changed buffer when 'hidden' is unset", function() command('set nohidden') - local oldwin = meths.get_current_win() + local oldwin = api.nvim_get_current_win() insert('text') command('new') - local newwin = meths.get_current_win() - eq("Vim:E37: No write since last change (add ! to override)", - pcall_err(meths.win_close, oldwin,false)) - eq({newwin,oldwin}, meths.list_wins()) + local newwin = api.nvim_get_current_win() + eq( + 'Vim:E37: No write since last change (add ! to override)', + pcall_err(api.nvim_win_close, oldwin, false) + ) + eq({ newwin, oldwin }, api.nvim_list_wins()) end) it('handles changed buffer with force', function() - local oldwin = meths.get_current_win() + local oldwin = api.nvim_get_current_win() insert('text') command('new') - local newwin = meths.get_current_win() - meths.win_close(oldwin,true) - eq({newwin}, meths.list_wins()) + local newwin = api.nvim_get_current_win() + api.nvim_win_close(oldwin, true) + eq({ newwin }, api.nvim_list_wins()) end) it('in cmdline-window #9767', function() command('split') - eq(2, #meths.list_wins()) - local oldwin = meths.get_current_win() - local otherwin = meths.open_win(0, false, { - relative='editor', row=10, col=10, width=10, height=10, + eq(2, #api.nvim_list_wins()) + local oldbuf = api.nvim_get_current_buf() + local oldwin = api.nvim_get_current_win() + local otherwin = api.nvim_open_win(0, false, { + relative = 'editor', + row = 10, + col = 10, + width = 10, + height = 10, }) -- Open cmdline-window. feed('q:') - eq(4, #meths.list_wins()) - eq(':', funcs.getcmdwintype()) + eq(4, #api.nvim_list_wins()) + eq(':', fn.getcmdwintype()) -- Not allowed to close previous window from cmdline-window. - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.win_close, oldwin, true)) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_close, oldwin, true) + ) -- Closing other windows is fine. - meths.win_close(otherwin, true) - eq(false, meths.win_is_valid(otherwin)) + api.nvim_win_close(otherwin, true) + eq(false, api.nvim_win_is_valid(otherwin)) -- Close cmdline-window. - meths.win_close(0, true) - eq(2, #meths.list_wins()) - eq('', funcs.getcmdwintype()) + api.nvim_win_close(0, true) + eq(2, #api.nvim_list_wins()) + eq('', fn.getcmdwintype()) + + -- Closing curwin in context of a different window shouldn't close cmdwin. + otherwin = api.nvim_open_win(0, false, { + relative = 'editor', + row = 10, + col = 10, + width = 10, + height = 10, + }) + feed('q:') + exec_lua( + [[ + vim.api.nvim_win_call(..., function() + vim.api.nvim_win_close(0, true) + end) + ]], + otherwin + ) + eq(false, api.nvim_win_is_valid(otherwin)) + eq(':', fn.getcmdwintype()) + -- Closing cmdwin in context of a non-previous window is still OK. + otherwin = api.nvim_open_win(oldbuf, false, { + relative = 'editor', + row = 10, + col = 10, + width = 10, + height = 10, + }) + exec_lua( + [[ + local otherwin, cmdwin = ... + vim.api.nvim_win_call(otherwin, function() + vim.api.nvim_win_close(cmdwin, true) + end) + ]], + otherwin, + api.nvim_get_current_win() + ) + eq('', fn.getcmdwintype()) + eq(true, api.nvim_win_is_valid(otherwin)) end) it('closing current (float) window of another tabpage #15313', function() command('tabedit') command('botright split') - local prevwin = curwin().id + local prevwin = curwin() eq(2, eval('tabpagenr()')) - local win = meths.open_win(0, true, { - relative='editor', row=10, col=10, width=50, height=10 + local win = api.nvim_open_win(0, true, { + relative = 'editor', + row = 10, + col = 10, + width = 50, + height = 10, }) local tab = eval('tabpagenr()') command('tabprevious') eq(1, eval('tabpagenr()')) - meths.win_close(win, false) + api.nvim_win_close(win, false) - eq(prevwin, meths.tabpage_get_win(tab).id) + eq(prevwin, api.nvim_tabpage_get_win(tab)) assert_alive() end) end) describe('hide', function() it('can hide current window', function() - local oldwin = meths.get_current_win() + local oldwin = api.nvim_get_current_win() command('split') - local newwin = meths.get_current_win() - meths.win_hide(newwin) - eq({oldwin}, meths.list_wins()) + local newwin = api.nvim_get_current_win() + api.nvim_win_hide(newwin) + eq({ oldwin }, api.nvim_list_wins()) end) it('can hide noncurrent window', function() - local oldwin = meths.get_current_win() + local oldwin = api.nvim_get_current_win() command('split') - local newwin = meths.get_current_win() - meths.win_hide(oldwin) - eq({newwin}, meths.list_wins()) + local newwin = api.nvim_get_current_win() + api.nvim_win_hide(oldwin) + eq({ newwin }, api.nvim_list_wins()) end) it('does not close the buffer', function() - local oldwin = meths.get_current_win() - local oldbuf = meths.get_current_buf() - local buf = meths.create_buf(true, false) - local newwin = meths.open_win(buf, true, { - relative='win', row=3, col=3, width=12, height=3 + local oldwin = api.nvim_get_current_win() + local oldbuf = api.nvim_get_current_buf() + local buf = api.nvim_create_buf(true, false) + local newwin = api.nvim_open_win(buf, true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, }) - meths.win_hide(newwin) - eq({oldwin}, meths.list_wins()) - eq({oldbuf, buf}, meths.list_bufs()) + api.nvim_win_hide(newwin) + eq({ oldwin }, api.nvim_list_wins()) + eq({ oldbuf, buf }, api.nvim_list_bufs()) end) it('deletes the buffer when bufhidden=wipe', function() - local oldwin = meths.get_current_win() - local oldbuf = meths.get_current_buf() - local buf = meths.create_buf(true, false).id - local newwin = meths.open_win(buf, true, { - relative='win', row=3, col=3, width=12, height=3 + local oldwin = api.nvim_get_current_win() + local oldbuf = api.nvim_get_current_buf() + local buf = api.nvim_create_buf(true, false) + local newwin = api.nvim_open_win(buf, true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, }) - meths.set_option_value('bufhidden', 'wipe', {buf=buf}) - meths.win_hide(newwin) - eq({oldwin}, meths.list_wins()) - eq({oldbuf}, meths.list_bufs()) + api.nvim_set_option_value('bufhidden', 'wipe', { buf = buf }) + api.nvim_win_hide(newwin) + eq({ oldwin }, api.nvim_list_wins()) + eq({ oldbuf }, api.nvim_list_bufs()) end) it('in the cmdwin', function() feed('q:') -- Can close the cmdwin. - meths.win_hide(0) - eq('', funcs.getcmdwintype()) - - local old_win = meths.get_current_win() - local other_win = meths.open_win(0, false, { - relative='win', row=3, col=3, width=12, height=3 + api.nvim_win_hide(0) + eq('', fn.getcmdwintype()) + + local old_buf = api.nvim_get_current_buf() + local old_win = api.nvim_get_current_win() + local other_win = api.nvim_open_win(0, false, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, }) feed('q:') -- Cannot close the previous window. - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.win_hide, old_win)) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_win_hide, old_win) + ) -- Can close other windows. - meths.win_hide(other_win) - eq(false, meths.win_is_valid(other_win)) + api.nvim_win_hide(other_win) + eq(false, api.nvim_win_is_valid(other_win)) + + -- Closing curwin in context of a different window shouldn't close cmdwin. + other_win = api.nvim_open_win(old_buf, false, { + relative = 'editor', + row = 10, + col = 10, + width = 10, + height = 10, + }) + exec_lua( + [[ + vim.api.nvim_win_call(..., function() + vim.api.nvim_win_hide(0) + end) + ]], + other_win + ) + eq(false, api.nvim_win_is_valid(other_win)) + eq(':', fn.getcmdwintype()) + -- Closing cmdwin in context of a non-previous window is still OK. + other_win = api.nvim_open_win(old_buf, false, { + relative = 'editor', + row = 10, + col = 10, + width = 10, + height = 10, + }) + exec_lua( + [[ + local otherwin, cmdwin = ... + vim.api.nvim_win_call(otherwin, function() + vim.api.nvim_win_hide(cmdwin) + end) + ]], + other_win, + api.nvim_get_current_win() + ) + eq('', fn.getcmdwintype()) + eq(true, api.nvim_win_is_valid(other_win)) end) end) describe('text_height', function() it('validation', function() - local X = meths.get_vvar('maxcol') + local X = api.nvim_get_vvar('maxcol') insert([[ aaa bbb ccc ddd eee]]) - eq("Invalid window id: 23", - pcall_err(meths.win_text_height, 23, {})) - eq("Line index out of bounds", - pcall_err(curwinmeths.text_height, { start_row = 5 })) - eq("Line index out of bounds", - pcall_err(curwinmeths.text_height, { start_row = -6 })) - eq("Line index out of bounds", - pcall_err(curwinmeths.text_height, { end_row = 5 })) - eq("Line index out of bounds", - pcall_err(curwinmeths.text_height, { end_row = -6 })) - eq("'start_row' is higher than 'end_row'", - pcall_err(curwinmeths.text_height, { start_row = 3, end_row = 1 })) - eq("'start_vcol' specified without 'start_row'", - pcall_err(curwinmeths.text_height, { end_row = 2, start_vcol = 0 })) - eq("'end_vcol' specified without 'end_row'", - pcall_err(curwinmeths.text_height, { start_row = 2, end_vcol = 0 })) - eq("Invalid 'start_vcol': out of range", - pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = -1 })) - eq("Invalid 'start_vcol': out of range", - pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = X + 1 })) - eq("Invalid 'end_vcol': out of range", - pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = -1 })) - eq("Invalid 'end_vcol': out of range", - pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = X + 1 })) - eq("'start_vcol' is higher than 'end_vcol'", - pcall_err(curwinmeths.text_height, { start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 })) + eq('Invalid window id: 23', pcall_err(api.nvim_win_text_height, 23, {})) + eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { start_row = 5 })) + eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { start_row = -6 })) + eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { end_row = 5 })) + eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { end_row = -6 })) + eq( + "'start_row' is higher than 'end_row'", + pcall_err(api.nvim_win_text_height, 0, { start_row = 3, end_row = 1 }) + ) + eq( + "'start_vcol' specified without 'start_row'", + pcall_err(api.nvim_win_text_height, 0, { end_row = 2, start_vcol = 0 }) + ) + eq( + "'end_vcol' specified without 'end_row'", + pcall_err(api.nvim_win_text_height, 0, { start_row = 2, end_vcol = 0 }) + ) + eq( + "Invalid 'start_vcol': out of range", + pcall_err(api.nvim_win_text_height, 0, { start_row = 2, start_vcol = -1 }) + ) + eq( + "Invalid 'start_vcol': out of range", + pcall_err(api.nvim_win_text_height, 0, { start_row = 2, start_vcol = X + 1 }) + ) + eq( + "Invalid 'end_vcol': out of range", + pcall_err(api.nvim_win_text_height, 0, { end_row = 2, end_vcol = -1 }) + ) + eq( + "Invalid 'end_vcol': out of range", + pcall_err(api.nvim_win_text_height, 0, { end_row = 2, end_vcol = X + 1 }) + ) + eq( + "'start_vcol' is higher than 'end_vcol'", + pcall_err( + api.nvim_win_text_height, + 0, + { start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 } + ) + ) end) it('with two diff windows', function() - local X = meths.get_vvar('maxcol') + local X = api.nvim_get_vvar('maxcol') local screen = Screen.new(45, 22) screen:set_default_attr_ids({ - [0] = {foreground = Screen.colors.Blue1, bold = true}; - [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey}; - [2] = {foreground = Screen.colors.Brown}; - [3] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan1, bold = true}; - [4] = {background = Screen.colors.LightBlue}; - [5] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey}; - [6] = {background = Screen.colors.Plum1}; - [7] = {background = Screen.colors.Red, bold = true}; - [8] = {reverse = true}; - [9] = {bold = true, reverse = true}; + [0] = { foreground = Screen.colors.Blue1, bold = true }, + [1] = { foreground = Screen.colors.Blue4, background = Screen.colors.Grey }, + [2] = { foreground = Screen.colors.Brown }, + [3] = { + foreground = Screen.colors.Blue1, + background = Screen.colors.LightCyan1, + bold = true, + }, + [4] = { background = Screen.colors.LightBlue }, + [5] = { foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey }, + [6] = { background = Screen.colors.Plum1 }, + [7] = { background = Screen.colors.Red, bold = true }, + [8] = { reverse = true }, + [9] = { bold = true, reverse = true }, }) screen:attach() exec([[ @@ -700,7 +860,8 @@ describe('API/win', function() windo diffthis ]]) feed('24gg') - screen:expect{grid=[[ + screen:expect { + grid = [[ {1: }{2: }{3:----------------}│{1: }{2: 1 }{4:00000001! }| {1: }{2: }{3:----------------}│{1: }{2: 2 }{4:00000002!! }| {1: }{2: 1 }00000003!!! │{1: }{2: 3 }00000003!!! | @@ -723,68 +884,117 @@ describe('API/win', function() {1: }{2: 41 }{4:00000050!!!!!!!!}│{1: }{2: }{3:----------------}| {8:[No Name] [+] }{9:[No Name] [+] }| | - ]]} + ]], + } screen:try_resize(45, 3) - screen:expect{grid=[[ + screen:expect { + grid = [[ {1: }{2: 19 }00000028!!!!!!!!│{1: }{2: 24 }^00000028!!!!!!!!| {8:[No Name] [+] }{9:[No Name] [+] }| | - ]]} - eq({ all = 20, fill = 5 }, meths.win_text_height(1000, {})) - eq({ all = 20, fill = 5 }, meths.win_text_height(1001, {})) - eq({ all = 20, fill = 5 }, meths.win_text_height(1000, { start_row = 0 })) - eq({ all = 20, fill = 5 }, meths.win_text_height(1001, { start_row = 0 })) - eq({ all = 15, fill = 0 }, meths.win_text_height(1000, { end_row = -1 })) - eq({ all = 15, fill = 0 }, meths.win_text_height(1000, { end_row = 40 })) - eq({ all = 20, fill = 5 }, meths.win_text_height(1001, { end_row = -1 })) - eq({ all = 20, fill = 5 }, meths.win_text_height(1001, { end_row = 40 })) - eq({ all = 10, fill = 5 }, meths.win_text_height(1000, { start_row = 23 })) - eq({ all = 13, fill = 3 }, meths.win_text_height(1001, { start_row = 18 })) - eq({ all = 11, fill = 0 }, meths.win_text_height(1000, { end_row = 23 })) - eq({ all = 11, fill = 5 }, meths.win_text_height(1001, { end_row = 18 })) - eq({ all = 11, fill = 0 }, meths.win_text_height(1000, { start_row = 3, end_row = 39 })) - eq({ all = 11, fill = 3 }, meths.win_text_height(1001, { start_row = 1, end_row = 34 })) - eq({ all = 9, fill = 0 }, meths.win_text_height(1000, { start_row = 4, end_row = 38 })) - eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 2, end_row = 33 })) - eq({ all = 9, fill = 0 }, meths.win_text_height(1000, { start_row = 5, end_row = 37 })) - eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 3, end_row = 32 })) - eq({ all = 9, fill = 0 }, meths.win_text_height(1000, { start_row = 17, end_row = 25 })) - eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 15, end_row = 20 })) - eq({ all = 7, fill = 0 }, meths.win_text_height(1000, { start_row = 18, end_row = 24 })) - eq({ all = 7, fill = 3 }, meths.win_text_height(1001, { start_row = 16, end_row = 19 })) - eq({ all = 6, fill = 5 }, meths.win_text_height(1000, { start_row = -1 })) - eq({ all = 5, fill = 5 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X })) - eq({ all = 0, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 })) - eq({ all = 0, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X })) - eq({ all = 1, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X })) - eq({ all = 3, fill = 2 }, meths.win_text_height(1001, { end_row = 0 })) - eq({ all = 2, fill = 2 }, meths.win_text_height(1001, { end_row = 0, end_vcol = 0 })) - eq({ all = 2, fill = 2 }, meths.win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 })) - eq({ all = 0, fill = 0 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 })) - eq({ all = 1, fill = 0 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X })) - eq({ all = 11, fill = 5 }, meths.win_text_height(1001, { end_row = 18 })) - eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 })) - eq({ all = 10, fill = 5 }, meths.win_text_height(1001, { end_row = 18, end_vcol = 0 })) - eq({ all = 8, fill = 3 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 })) + ]], + } + eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1000, {})) + eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, {})) + eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1000, { start_row = 0 })) + eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, { start_row = 0 })) + eq({ all = 15, fill = 0 }, api.nvim_win_text_height(1000, { end_row = -1 })) + eq({ all = 15, fill = 0 }, api.nvim_win_text_height(1000, { end_row = 40 })) + eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, { end_row = -1 })) + eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 40 })) + eq({ all = 10, fill = 5 }, api.nvim_win_text_height(1000, { start_row = 23 })) + eq({ all = 13, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 18 })) + eq({ all = 11, fill = 0 }, api.nvim_win_text_height(1000, { end_row = 23 })) + eq({ all = 11, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 18 })) + eq({ all = 11, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 3, end_row = 39 })) + eq({ all = 11, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 1, end_row = 34 })) + eq({ all = 9, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 4, end_row = 38 })) + eq({ all = 9, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 2, end_row = 33 })) + eq({ all = 9, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 5, end_row = 37 })) + eq({ all = 9, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 3, end_row = 32 })) + eq({ all = 9, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 17, end_row = 25 })) + eq({ all = 9, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 15, end_row = 20 })) + eq({ all = 7, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 18, end_row = 24 })) + eq({ all = 7, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 16, end_row = 19 })) + eq({ all = 6, fill = 5 }, api.nvim_win_text_height(1000, { start_row = -1 })) + eq({ all = 5, fill = 5 }, api.nvim_win_text_height(1000, { start_row = -1, start_vcol = X })) + eq( + { all = 0, fill = 0 }, + api.nvim_win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 }) + ) + eq( + { all = 0, fill = 0 }, + api.nvim_win_text_height( + 1000, + { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X } + ) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height( + 1000, + { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X } + ) + ) + eq({ all = 3, fill = 2 }, api.nvim_win_text_height(1001, { end_row = 0 })) + eq({ all = 2, fill = 2 }, api.nvim_win_text_height(1001, { end_row = 0, end_vcol = 0 })) + eq( + { all = 2, fill = 2 }, + api.nvim_win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 }) + ) + eq( + { all = 0, fill = 0 }, + api.nvim_win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 }) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X }) + ) + eq({ all = 11, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 18 })) + eq( + { all = 9, fill = 3 }, + api.nvim_win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 }) + ) + eq({ all = 10, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 18, end_vcol = 0 })) + eq( + { all = 8, fill = 3 }, + api.nvim_win_text_height( + 1001, + { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 } + ) + ) end) it('with wrapped lines', function() - local X = meths.get_vvar('maxcol') + local X = api.nvim_get_vvar('maxcol') local screen = Screen.new(45, 22) screen:set_default_attr_ids({ - [0] = {foreground = Screen.colors.Blue1, bold = true}; - [1] = {foreground = Screen.colors.Brown}; - [2] = {background = Screen.colors.Yellow}; + [0] = { foreground = Screen.colors.Blue1, bold = true }, + [1] = { foreground = Screen.colors.Brown }, + [2] = { background = Screen.colors.Yellow }, }) screen:attach() exec([[ set number cpoptions+=n call setline(1, repeat([repeat('foobar-', 36)], 3)) ]]) - local ns = meths.create_namespace('') - meths.buf_set_extmark(0, ns, 1, 100, { virt_text = {{('?'):rep(15), 'Search'}}, virt_text_pos = 'inline' }) - meths.buf_set_extmark(0, ns, 2, 200, { virt_text = {{('!'):rep(75), 'Search'}}, virt_text_pos = 'inline' }) - screen:expect{grid=[[ + local ns = api.nvim_create_namespace('') + api.nvim_buf_set_extmark( + 0, + ns, + 1, + 100, + { virt_text = { { ('?'):rep(15), 'Search' } }, virt_text_pos = 'inline' } + ) + api.nvim_buf_set_extmark( + 0, + ns, + 2, + 200, + { virt_text = { { ('!'):rep(75), 'Search' } }, virt_text_pos = 'inline' } + ) + screen:expect { + grid = [[ {1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar| -foobar-foobar-foobar-foobar-foobar-foobar-fo| obar-foobar-foobar-foobar-foobar-foobar-fooba| @@ -807,133 +1017,897 @@ describe('API/win', function() {2:!!!!!!!!!}ar-foobar-foobar-foobar-foobar-fooba| r-foobar-foobar- | | - ]]} + ]], + } screen:try_resize(45, 2) - screen:expect{grid=[[ + screen:expect { + grid = [[ {1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar| | - ]]} - eq({ all = 21, fill = 0 }, meths.win_text_height(0, {})) - eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 0, end_row = 0 })) - eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, end_row = 1 })) - eq({ all = 8, fill = 0 }, meths.win_text_height(0, { start_row = 2, end_row = 2 })) - eq({ all = 0, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 0 })) - eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 })) - eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 })) - eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 })) - eq({ all = 3, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 })) - eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 })) - eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 })) - eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 })) - eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 })) - eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X })) - eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X })) - eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X })) - eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X })) - eq({ all = 5, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X })) - eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X })) - eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X })) - eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X })) - eq({ all = 0, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X })) - eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = 131 })) - eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 221, end_row = 1, end_vcol = 266 })) - eq({ all = 18, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 131 })) - eq({ all = 19, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 130 })) - eq({ all = 20, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 311 })) - eq({ all = 21, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 312 })) - eq({ all = 17, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 })) - eq({ all = 19, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 })) - eq({ all = 16, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 221 })) - eq({ all = 17, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 220 })) - eq({ all = 14, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 41 })) - eq({ all = 15, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 42 })) - eq({ all = 9, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 })) - eq({ all = 11, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 })) + ]], + } + eq({ all = 21, fill = 0 }, api.nvim_win_text_height(0, {})) + eq({ all = 6, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 })) + eq({ all = 7, fill = 0 }, api.nvim_win_text_height(0, { start_row = 1, end_row = 1 })) + eq({ all = 8, fill = 0 }, api.nvim_win_text_height(0, { start_row = 2, end_row = 2 })) + eq( + { all = 0, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 0 }) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 }) + ) + eq( + { all = 2, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 }) + ) + eq( + { all = 2, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 }) + ) + eq( + { all = 3, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 }) + ) + eq( + { all = 6, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 }) + ) + eq( + { all = 7, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 }) + ) + eq( + { all = 7, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 }) + ) + eq( + { all = 7, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 }) + ) + eq( + { all = 7, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X }) + ) + eq( + { all = 7, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X }) + ) + eq( + { all = 6, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X }) + ) + eq( + { all = 6, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X }) + ) + eq( + { all = 5, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X }) + ) + eq( + { all = 2, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X }) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X }) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X }) + ) + eq( + { all = 0, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X }) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = 131 }) + ) + eq( + { all = 1, fill = 0 }, + api.nvim_win_text_height( + 0, + { start_row = 1, start_vcol = 221, end_row = 1, end_vcol = 266 } + ) + ) + eq({ all = 18, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 131 })) + eq({ all = 19, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 130 })) + eq({ all = 20, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 311 })) + eq({ all = 21, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 312 })) + eq( + { all = 17, fill = 0 }, + api.nvim_win_text_height( + 0, + { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 } + ) + ) + eq( + { all = 19, fill = 0 }, + api.nvim_win_text_height( + 0, + { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 } + ) + ) + eq({ all = 16, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 221 })) + eq({ all = 17, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 220 })) + eq({ all = 14, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 41 })) + eq({ all = 15, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 42 })) + eq( + { all = 9, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 }) + ) + eq( + { all = 11, fill = 0 }, + api.nvim_win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 }) + ) end) end) describe('open_win', function() it('noautocmd option works', function() command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1') - meths.open_win(meths.create_buf(true, true), true, { - relative='win', row=3, col=3, width=12, height=3, noautocmd=true + api.nvim_open_win(api.nvim_create_buf(true, true), true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, + noautocmd = true, }) - eq(0, funcs.exists('g:fired')) - meths.open_win(meths.create_buf(true, true), true, { - relative='win', row=3, col=3, width=12, height=3 + eq(0, fn.exists('g:fired')) + api.nvim_open_win(api.nvim_create_buf(true, true), true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, }) - eq(1, funcs.exists('g:fired')) + eq(1, fn.exists('g:fired')) end) - it('disallowed in cmdwin if enter=true or buf=curbuf', function() - local new_buf = meths.create_buf(true, true) + it('disallowed in cmdwin if enter=true or buf=cmdwin_buf', function() + local new_buf = api.nvim_create_buf(true, true) feed('q:') - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.open_win, new_buf, true, { - relative='editor', row=5, col=5, width=5, height=5, - })) - eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits', - pcall_err(meths.open_win, 0, false, { - relative='editor', row=5, col=5, width=5, height=5, - })) - - eq(new_buf, meths.win_get_buf(meths.open_win(new_buf, false, { - relative='editor', row=5, col=5, width=5, height=5, - }))) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_open_win, new_buf, true, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + ) + eq( + 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits', + pcall_err(api.nvim_open_win, 0, false, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + ) + matches( + 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$', + pcall_err( + exec_lua, + [[ + local cmdwin_buf = vim.api.nvim_get_current_buf() + vim.api.nvim_buf_call(vim.api.nvim_create_buf(false, true), function() + vim.api.nvim_open_win(cmdwin_buf, false, { + relative='editor', row=5, col=5, width=5, height=5, + }) + end) + ]] + ) + ) + + eq( + new_buf, + api.nvim_win_get_buf(api.nvim_open_win(new_buf, false, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + })) + ) end) it('aborts if buffer is invalid', function() - local wins_before = meths.list_wins() - eq('Invalid buffer id: 1337', pcall_err(meths.open_win, 1337, false, { - relative='editor', row=5, col=5, width=5, height=5, - })) - eq(wins_before, meths.list_wins()) + local wins_before = api.nvim_list_wins() + eq( + 'Invalid buffer id: 1337', + pcall_err(api.nvim_open_win, 1337, false, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + ) + eq(wins_before, api.nvim_list_wins()) + end) + + it('creates a split window', function() + local win = api.nvim_open_win(0, true, { + vertical = false, + }) + eq('', api.nvim_win_get_config(win).relative) + end) + + it('creates split windows in the correct direction', function() + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + vertical = true, + }) + eq('', api.nvim_win_get_config(win).relative) + + local layout = fn.winlayout() + + eq({ + 'row', + { + { 'leaf', win }, + { 'leaf', initial_win }, + }, + }, layout) + end) + + it("respects the 'split' option", function() + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + split = 'below', + }) + eq('', api.nvim_win_get_config(win).relative) + + local layout = fn.winlayout() + + eq({ + 'col', + { + { 'leaf', initial_win }, + { 'leaf', win }, + }, + }, layout) + end) + + it( + "doesn't change tp_curwin when splitting window in non-current tab with enter=false", + function() + local tab1 = api.nvim_get_current_tabpage() + local tab1_win = api.nvim_get_current_win() + + helpers.command('tabnew') + local tab2 = api.nvim_get_current_tabpage() + local tab2_win = api.nvim_get_current_win() + + eq({ tab1_win, tab2_win }, api.nvim_list_wins()) + eq({ tab1, tab2 }, api.nvim_list_tabpages()) + + api.nvim_set_current_tabpage(tab1) + eq(tab1_win, api.nvim_get_current_win()) + + local tab2_prevwin = fn.tabpagewinnr(tab2, '#') + + -- split in tab2 whine in tab2, with enter = false + local tab2_win2 = api.nvim_open_win(api.nvim_create_buf(false, true), false, { + win = tab2_win, + split = 'right', + }) + eq(tab1_win, api.nvim_get_current_win()) -- we should still be in the first tp + eq(tab1_win, api.nvim_tabpage_get_win(tab1)) + + eq(tab2_win, api.nvim_tabpage_get_win(tab2)) -- tab2's tp_curwin should not have changed + eq(tab2_prevwin, fn.tabpagewinnr(tab2, '#')) -- tab2's tp_prevwin should not have changed + eq({ tab1_win, tab2_win, tab2_win2 }, api.nvim_list_wins()) + eq({ tab2_win, tab2_win2 }, api.nvim_tabpage_list_wins(tab2)) + end + ) + + it('creates splits in the correct location', function() + local first_win = api.nvim_get_current_win() + -- specifying window 0 should create a split next to the current window + local win = api.nvim_open_win(0, true, { + vertical = false, + }) + local layout = fn.winlayout() + eq({ + 'col', + { + { 'leaf', win }, + { 'leaf', first_win }, + }, + }, layout) + -- not specifying a window should create a top-level split + local win2 = api.nvim_open_win(0, true, { + split = 'left', + win = -1, + }) + layout = fn.winlayout() + eq({ + 'row', + { + { 'leaf', win2 }, + { + 'col', + { + { 'leaf', win }, + { 'leaf', first_win }, + }, + }, + }, + }, layout) + + -- specifying a window should create a split next to that window + local win3 = api.nvim_open_win(0, true, { + win = win, + vertical = false, + }) + layout = fn.winlayout() + eq({ + 'row', + { + { 'leaf', win2 }, + { + 'col', + { + { 'leaf', win3 }, + { 'leaf', win }, + { 'leaf', first_win }, + }, + }, + }, + }, layout) + end) + end) + + describe('set_config', function() + it('moves a split into a float', function() + local win = api.nvim_open_win(0, true, { + vertical = false, + }) + eq('', api.nvim_win_get_config(win).relative) + api.nvim_win_set_config(win, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + eq('editor', api.nvim_win_get_config(win).relative) + end) + + it('throws error when attempting to move the last window', function() + local err = pcall_err(api.nvim_win_set_config, 0, { + vertical = false, + }) + eq('Cannot move last window', err) + end) + + it('passing retval of get_config results in no-op', function() + -- simple split layout + local win = api.nvim_open_win(0, true, { + split = 'left', + }) + local layout = fn.winlayout() + local config = api.nvim_win_get_config(win) + api.nvim_win_set_config(win, config) + eq(layout, fn.winlayout()) + + -- nested split layout + local win2 = api.nvim_open_win(0, true, { + vertical = true, + }) + local win3 = api.nvim_open_win(0, true, { + win = win2, + vertical = false, + }) + layout = fn.winlayout() + config = api.nvim_win_get_config(win2) + api.nvim_win_set_config(win2, config) + eq(layout, fn.winlayout()) + + config = api.nvim_win_get_config(win3) + api.nvim_win_set_config(win3, config) + eq(layout, fn.winlayout()) + end) + + it('moves a float into a split', function() + local layout = fn.winlayout() + eq('leaf', layout[1]) + local win = api.nvim_open_win(0, true, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + api.nvim_win_set_config(win, { + split = 'below', + win = -1, + }) + eq('', api.nvim_win_get_config(win).relative) + layout = fn.winlayout() + eq('col', layout[1]) + eq(2, #layout[2]) + eq(win, layout[2][2][2]) + end) + + it('respects the "split" option', function() + local layout = fn.winlayout() + eq('leaf', layout[1]) + local first_win = layout[2] + local win = api.nvim_open_win(0, true, { + relative = 'editor', + row = 5, + col = 5, + width = 5, + height = 5, + }) + api.nvim_win_set_config(win, { + split = 'right', + win = first_win, + }) + layout = fn.winlayout() + eq('row', layout[1]) + eq(2, #layout[2]) + eq(win, layout[2][2][2]) + local config = api.nvim_win_get_config(win) + eq('', config.relative) + eq('right', config.split) + api.nvim_win_set_config(win, { + split = 'below', + win = first_win, + }) + layout = fn.winlayout() + eq('col', layout[1]) + eq(2, #layout[2]) + eq(win, layout[2][2][2]) + config = api.nvim_win_get_config(win) + eq('', config.relative) + eq('below', config.split) + end) + + it('creates top-level splits', function() + local win = api.nvim_open_win(0, true, { + vertical = false, + }) + local win2 = api.nvim_open_win(0, true, { + vertical = true, + win = -1, + }) + local layout = fn.winlayout() + eq('row', layout[1]) + eq(2, #layout[2]) + eq(win2, layout[2][1][2]) + api.nvim_win_set_config(win, { + split = 'below', + win = -1, + }) + layout = fn.winlayout() + eq('col', layout[1]) + eq(2, #layout[2]) + eq('row', layout[2][1][1]) + eq(win, layout[2][2][2]) + end) + + it('moves splits to other tabpages', function() + local curtab = api.nvim_get_current_tabpage() + local win = api.nvim_open_win(0, false, { split = 'left' }) + command('tabnew') + local tabnr = api.nvim_get_current_tabpage() + command('tabprev') -- return to the initial tab + + api.nvim_win_set_config(win, { + split = 'right', + win = api.nvim_tabpage_get_win(tabnr), + }) + + eq(tabnr, api.nvim_win_get_tabpage(win)) + -- we are changing the config, the current tabpage should not change + eq(curtab, api.nvim_get_current_tabpage()) + + command('tabnext') -- switch to the new tabpage so we can get the layout + local layout = fn.winlayout() + + eq({ + 'row', + { + { 'leaf', api.nvim_tabpage_get_win(tabnr) }, + { 'leaf', win }, + }, + }, layout) + end) + + it('correctly moves curwin when moving curwin to a different tabpage', function() + local curtab = api.nvim_get_current_tabpage() + command('tabnew') + local tab2 = api.nvim_get_current_tabpage() + local tab2_win = api.nvim_get_current_win() + + command('tabprev') -- return to the initial tab + + local neighbor = api.nvim_get_current_win() + + -- create and enter a new split + local win = api.nvim_open_win(0, true, { + vertical = false, + }) + + eq(curtab, api.nvim_win_get_tabpage(win)) + + eq({ win, neighbor }, api.nvim_tabpage_list_wins(curtab)) + + -- move the current win to a different tabpage + api.nvim_win_set_config(win, { + split = 'right', + win = api.nvim_tabpage_get_win(tab2), + }) + + eq(curtab, api.nvim_get_current_tabpage()) + + -- win should have moved to tab2 + eq(tab2, api.nvim_win_get_tabpage(win)) + -- tp_curwin of tab2 should not have changed + eq(tab2_win, api.nvim_tabpage_get_win(tab2)) + -- win lists should be correct + eq({ tab2_win, win }, api.nvim_tabpage_list_wins(tab2)) + eq({ neighbor }, api.nvim_tabpage_list_wins(curtab)) + + -- current win should have moved to neighboring win + eq(neighbor, api.nvim_tabpage_get_win(curtab)) + end) + + it('splits windows in non-current tabpage', function() + local curtab = api.nvim_get_current_tabpage() + command('tabnew') + local tabnr = api.nvim_get_current_tabpage() + command('tabprev') -- return to the initial tab + + local win = api.nvim_open_win(0, false, { + vertical = false, + win = api.nvim_tabpage_get_win(tabnr), + }) + + eq(tabnr, api.nvim_win_get_tabpage(win)) + -- since enter = false, the current tabpage should not change + eq(curtab, api.nvim_get_current_tabpage()) + end) + + it('moves the current split window', function() + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, true, { + vertical = true, + }) + local win2 = api.nvim_open_win(0, true, { + vertical = true, + }) + api.nvim_set_current_win(win) + eq({ + 'row', + { + { 'leaf', win2 }, + { 'leaf', win }, + { 'leaf', initial_win }, + }, + }, fn.winlayout()) + + api.nvim_win_set_config(0, { + vertical = false, + win = 0, + }) + eq(win, api.nvim_get_current_win()) + eq({ + 'col', + { + { 'leaf', win }, + { + 'row', + { + { 'leaf', win2 }, + { 'leaf', initial_win }, + }, + }, + }, + }, fn.winlayout()) + + api.nvim_set_current_win(win2) + local win3 = api.nvim_open_win(0, true, { + vertical = true, + }) + eq(win3, api.nvim_get_current_win()) + + eq({ + 'col', + { + { 'leaf', win }, + { + 'row', + { + { 'leaf', win3 }, + { 'leaf', win2 }, + { 'leaf', initial_win }, + }, + }, + }, + }, fn.winlayout()) + + api.nvim_win_set_config(0, { + vertical = false, + win = 0, + }) + + eq(win3, api.nvim_get_current_win()) + eq({ + 'col', + { + { 'leaf', win }, + { + 'row', + { + { + 'col', + { + { 'leaf', win3 }, + { 'leaf', win2 }, + }, + }, + { 'leaf', initial_win }, + }, + }, + }, + }, fn.winlayout()) end) end) describe('get_config', function() it('includes border', function() local b = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' } - local win = meths.open_win(0, true, { - relative='win', row=3, col=3, width=12, height=3, + local win = api.nvim_open_win(0, true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, border = b, }) - local cfg = meths.win_get_config(win) + local cfg = api.nvim_win_get_config(win) eq(b, cfg.border) end) it('includes border with highlight group', function() local b = { - {'a', 'Normal'}, - {'b', 'Special'}, - {'c', 'String'}, - {'d', 'Comment'}, - {'e', 'Visual'}, - {'f', 'Error'}, - {'g', 'Constant'}, - {'h', 'PreProc'}, + { 'a', 'Normal' }, + { 'b', 'Special' }, + { 'c', 'String' }, + { 'd', 'Comment' }, + { 'e', 'Visual' }, + { 'f', 'Error' }, + { 'g', 'Constant' }, + { 'h', 'PreProc' }, } - local win = meths.open_win(0, true, { - relative='win', row=3, col=3, width=12, height=3, + local win = api.nvim_open_win(0, true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, border = b, }) - local cfg = meths.win_get_config(win) + local cfg = api.nvim_win_get_config(win) eq(b, cfg.border) end) it('includes title and footer', function() - local title = { {'A', {'StatusLine', 'TabLine'}}, {'B'}, {'C', 'WinBar'} } - local footer = { {'A', 'WinBar'}, {'B'}, {'C', {'StatusLine', 'TabLine'}} } - local win = meths.open_win(0, true, { - relative='win', row=3, col=3, width=12, height=3, - border = 'single', title = title, footer = footer, + local title = { { 'A', { 'StatusLine', 'TabLine' } }, { 'B' }, { 'C', 'WinBar' } } + local footer = { { 'A', 'WinBar' }, { 'B' }, { 'C', { 'StatusLine', 'TabLine' } } } + local win = api.nvim_open_win(0, true, { + relative = 'win', + row = 3, + col = 3, + width = 12, + height = 3, + border = 'single', + title = title, + footer = footer, }) - local cfg = meths.win_get_config(win) + local cfg = api.nvim_win_get_config(win) eq(title, cfg.title) eq(footer, cfg.footer) end) + + it('includes split for normal windows', function() + local win = api.nvim_open_win(0, true, { + vertical = true, + win = -1, + }) + eq('left', api.nvim_win_get_config(win).split) + api.nvim_win_set_config(win, { + vertical = false, + win = -1, + }) + eq('above', api.nvim_win_get_config(win).split) + api.nvim_win_set_config(win, { + split = 'below', + win = -1, + }) + eq('below', api.nvim_win_get_config(win).split) + end) + + it('includes split when splitting with ex commands', function() + local win = api.nvim_get_current_win() + eq('left', api.nvim_win_get_config(win).split) + + command('vsplit') + local win2 = api.nvim_get_current_win() + + -- initial window now be marked as right split + -- since it was split with a vertical split + -- and 'splitright' is false by default + eq('right', api.nvim_win_get_config(win).split) + eq('left', api.nvim_win_get_config(win2).split) + + api.nvim_set_option_value('splitbelow', true, { + scope = 'global', + }) + api.nvim_win_close(win, true) + command('split') + local win3 = api.nvim_get_current_win() + eq('below', api.nvim_win_get_config(win3).split) + end) + + it("includes the correct 'split' option in complex layouts", function() + local initial_win = api.nvim_get_current_win() + local win = api.nvim_open_win(0, false, { + split = 'right', + win = -1, + }) + + local win2 = api.nvim_open_win(0, false, { + split = 'below', + win = win, + }) + + api.nvim_win_set_config(win2, { + width = 50, + }) + + api.nvim_win_set_config(win, { + split = 'left', + win = -1, + }) + + local win3 = api.nvim_open_win(0, false, { + split = 'above', + win = -1, + }) + local float = api.nvim_open_win(0, false, { + relative = 'editor', + width = 40, + height = 20, + col = 20, + row = 10, + }) + api.nvim_win_set_config(float, { + split = 'right', + win = -1, + }) + + local layout = fn.winlayout() + + eq({ + 'row', + { + { + 'col', + { + { 'leaf', win3 }, + { + 'row', + { + { 'leaf', win }, + { 'leaf', initial_win }, + { 'leaf', win2 }, + }, + }, + }, + }, + { + 'leaf', + float, + }, + }, + }, layout) + + eq('above', api.nvim_win_get_config(win3).split) + eq('left', api.nvim_win_get_config(win).split) + eq('left', api.nvim_win_get_config(initial_win).split) + eq('right', api.nvim_win_get_config(win2).split) + eq('right', api.nvim_win_get_config(float).split) + end) + end) + + describe('set_config', function() + it('no crash with invalid title', function() + local win = api.nvim_open_win(0, true, { + width = 10, + height = 10, + relative = 'editor', + row = 10, + col = 10, + title = { { 'test' } }, + border = 'single', + }) + eq( + 'title/footer cannot be an empty array', + pcall_err(api.nvim_win_set_config, win, { title = {} }) + ) + command('redraw!') + assert_alive() + end) + + it('no crash with invalid footer', function() + local win = api.nvim_open_win(0, true, { + width = 10, + height = 10, + relative = 'editor', + row = 10, + col = 10, + footer = { { 'test' } }, + border = 'single', + }) + eq( + 'title/footer cannot be an empty array', + pcall_err(api.nvim_win_set_config, win, { footer = {} }) + ) + command('redraw!') + assert_alive() + end) + end) + + describe('set_config', function() + it('no crash with invalid title', function() + local win = api.nvim_open_win(0, true, { + width = 10, + height = 10, + relative = 'editor', + row = 10, + col = 10, + title = { { 'test' } }, + border = 'single', + }) + eq( + 'title/footer cannot be an empty array', + pcall_err(api.nvim_win_set_config, win, { title = {} }) + ) + command('redraw!') + assert_alive() + end) + + it('no crash with invalid footer', function() + local win = api.nvim_open_win(0, true, { + width = 10, + height = 10, + relative = 'editor', + row = 10, + col = 10, + footer = { { 'test' } }, + border = 'single', + }) + eq( + 'title/footer cannot be an empty array', + pcall_err(api.nvim_win_set_config, win, { footer = {} }) + ) + command('redraw!') + assert_alive() + end) end) end) |