aboutsummaryrefslogtreecommitdiff
path: root/test/functional/api
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/api')
-rw-r--r--test/functional/api/autocmd_spec.lua191
-rw-r--r--test/functional/api/buffer_spec.lua1276
-rw-r--r--test/functional/api/buffer_updates_spec.lua4
-rw-r--r--test/functional/api/command_spec.lua16
-rw-r--r--test/functional/api/extmark_spec.lua234
-rw-r--r--test/functional/api/highlight_spec.lua369
-rw-r--r--test/functional/api/keymap_spec.lua214
-rw-r--r--test/functional/api/proc_spec.lua12
-rw-r--r--test/functional/api/rpc_fixture.lua7
-rw-r--r--test/functional/api/server_notifications_spec.lua3
-rw-r--r--test/functional/api/server_requests_spec.lua19
-rw-r--r--test/functional/api/ui_spec.lua84
-rw-r--r--test/functional/api/version_spec.lua2
-rw-r--r--test/functional/api/vim_spec.lua876
-rw-r--r--test/functional/api/window_spec.lua354
15 files changed, 3196 insertions, 465 deletions
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index 22a1311ee9..fd46a1dcfa 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -14,14 +14,40 @@ before_each(clear)
describe('autocmd api', function()
describe('nvim_create_autocmd', function()
- it('"command" and "callback" are mutually exclusive', function()
- local rv = pcall_err(meths.create_autocmd, "BufReadPost", {
- pattern = "*.py,*.pyi",
+ 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("specify either 'callback' or 'command', not both", rv)
+ 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 = '' }))
end)
it('doesnt leak when you use ++once', function()
@@ -59,18 +85,8 @@ describe('autocmd api', function()
eq(1, meths.get_var('called'))
end)
- it('does not allow passing buffer and patterns', function()
- local rv = pcall_err(meths.create_autocmd, "Filetype", {
- command = "let g:called = g:called + 1",
- buffer = 0,
- pattern = "*.py",
- })
-
- eq("cannot pass both: 'pattern' and 'buffer' for the same autocmd", rv)
- end)
-
it('does not allow passing invalid buffers', function()
- local ok, msg = pcall(meths.create_autocmd, "Filetype", {
+ local ok, msg = pcall(meths.create_autocmd, 'FileType', {
command = "let g:called = g:called + 1",
buffer = -1,
})
@@ -209,7 +225,7 @@ describe('autocmd api', function()
local aus = meths.get_autocmds({ event = 'User', pattern = 'Test' })
local first = aus[1]
- eq(first.id, 1)
+ eq(true, first.id > 0)
meths.set_var("some_condition", true)
meths.exec_autocmds("User", {pattern = "Test"})
@@ -217,23 +233,28 @@ describe('autocmd api', function()
end)
it('receives an args table', function()
- local res = exec_lua [[
- local group_id = vim.api.nvim_create_augroup("TestGroup", {})
- local autocmd_id = vim.api.nvim_create_autocmd("User", {
+ local group_id = meths.create_augroup("TestGroup", {})
+ -- Having an existing autocmd calling expand("<afile>") shouldn't change args #18964
+ meths.create_autocmd('User', {
+ group = 'TestGroup',
+ pattern = 'Te*',
+ command = 'call expand("<afile>")',
+ })
+
+ local autocmd_id = exec_lua [[
+ return vim.api.nvim_create_autocmd("User", {
group = "TestGroup",
pattern = "Te*",
callback = function(args)
vim.g.autocmd_args = args
end,
})
-
- return {group_id, autocmd_id}
]]
meths.exec_autocmds("User", {pattern = "Test pattern"})
eq({
- id = res[2],
- group = res[1],
+ id = autocmd_id,
+ group = group_id,
event = "User",
match = "Test pattern",
file = "Test pattern",
@@ -241,27 +262,24 @@ describe('autocmd api', function()
}, meths.get_var("autocmd_args"))
-- Test without a group
- res = exec_lua [[
- local autocmd_id = vim.api.nvim_create_autocmd("User", {
+ autocmd_id = exec_lua [[
+ return vim.api.nvim_create_autocmd("User", {
pattern = "*",
callback = function(args)
vim.g.autocmd_args = args
end,
})
-
- return {autocmd_id}
]]
meths.exec_autocmds("User", {pattern = "some_pat"})
eq({
- id = res[1],
+ id = autocmd_id,
group = nil,
event = "User",
match = "some_pat",
file = "some_pat",
buf = 1,
}, meths.get_var("autocmd_args"))
-
end)
it('can receive arbitrary data', function()
@@ -294,8 +312,32 @@ describe('autocmd api', function()
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,
+ }))
+ end)
+
describe('events', function()
- it('should return one autocmd when there is only one for an event', function()
+ it('returns one autocmd when there is only one for an event', function()
command [[au! InsertEnter]]
command [[au InsertEnter * :echo "1"]]
@@ -303,7 +345,7 @@ describe('autocmd api', function()
eq(1, #aus)
end)
- it('should return two autocmds when there are two for an event', function()
+ it('returns two autocmds when there are two for an event', function()
command [[au! InsertEnter]]
command [[au InsertEnter * :echo "1"]]
command [[au InsertEnter * :echo "2"]]
@@ -312,7 +354,7 @@ describe('autocmd api', function()
eq(2, #aus)
end)
- it('should return the same thing if you use string or list', function()
+ it('returns the same thing if you use string or list', function()
command [[au! InsertEnter]]
command [[au InsertEnter * :echo "1"]]
command [[au InsertEnter * :echo "2"]]
@@ -322,7 +364,7 @@ describe('autocmd api', function()
eq(string_aus, array_aus)
end)
- it('should return two autocmds when there are two for an event', function()
+ it('returns two autocmds when there are two for an event', function()
command [[au! InsertEnter]]
command [[au! InsertLeave]]
command [[au InsertEnter * :echo "1"]]
@@ -332,7 +374,7 @@ describe('autocmd api', function()
eq(2, #aus)
end)
- it('should return different IDs for different autocmds', function()
+ it('returns different IDs for different autocmds', function()
command [[au! InsertEnter]]
command [[au! InsertLeave]]
command [[au InsertEnter * :echo "1"]]
@@ -356,7 +398,7 @@ describe('autocmd api', function()
eq(first, new_aus[1])
end)
- it('should return event name', function()
+ it('returns event name', function()
command [[au! InsertEnter]]
command [[au InsertEnter * :echo "1"]]
@@ -364,7 +406,7 @@ describe('autocmd api', function()
eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus)
end)
- it('should work with buffer numbers', function()
+ it('works with buffer numbers', function()
command [[new]]
command [[au! InsertEnter]]
command [[au InsertEnter <buffer=1> :echo "1"]]
@@ -407,8 +449,8 @@ describe('autocmd api', function()
pattern = "<buffer=2>",
}}, aus)
- eq("Invalid value for 'buffer': must be an integer or array of integers", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" }))
- eq("Invalid value for 'buffer': must be an integer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } }))
+ 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 bufs = {}
@@ -416,10 +458,10 @@ describe('autocmd api', function()
table.insert(bufs, meths.create_buf(true, false))
end
- eq("Too many buffers. Please limit yourself to 256 or fewer", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs }))
+ eq("Too many buffers (maximum of 256)", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs }))
end)
- it('should return autocmds when group is specified by id', function()
+ 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"' })
@@ -431,7 +473,7 @@ describe('autocmd api', function()
eq(0, #aus2)
end)
- it('should return autocmds when group is specified by name', function()
+ 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"' })
@@ -531,7 +573,7 @@ describe('autocmd api', function()
command [[augroup END]]
end)
- it('should return all groups if no group is specified', function()
+ it('returns all groups if no group is specified', function()
local aus = meths.get_autocmds { event = "InsertEnter" }
if #aus ~= 4 then
eq({}, aus)
@@ -540,7 +582,7 @@ describe('autocmd api', function()
eq(4, #aus)
end)
- it('should return only the group specified', function()
+ it('returns only the group specified', function()
local aus = meths.get_autocmds {
event = "InsertEnter",
group = "GroupOne",
@@ -551,7 +593,7 @@ describe('autocmd api', function()
eq("GroupOne", aus[1].group_name)
end)
- it('should return only the group specified, multiple values', function()
+ it('returns only the group specified, multiple values', function()
local aus = meths.get_autocmds {
event = "InsertEnter",
group = "GroupTwo",
@@ -578,7 +620,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
- matches('invalid augroup: NotDefined', code)
+ matches("Invalid 'group': 'NotDefined'", code)
end)
it('raises error for undefined augroup id', function()
@@ -596,7 +638,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
- matches('invalid augroup: 1', code)
+ matches("Invalid 'group': 1", code)
end)
it('raises error for invalid group type', function()
@@ -611,7 +653,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
- matches("'group' must be a string or an integer", code)
+ matches("Invalid 'group': expected String or Integer, got Boolean", code)
end)
it('raises error for invalid pattern array', function()
@@ -625,7 +667,7 @@ describe('autocmd api', function()
]], {}))
eq(false, success)
- matches("All entries in 'pattern' must be strings", code)
+ matches("Invalid 'pattern' item: expected String, got Array", code)
end)
end)
@@ -640,7 +682,7 @@ describe('autocmd api', function()
command [[au InsertEnter <buffer> :echo "Buffer"]]
end)
- it('should should return for literal match', function()
+ it('returns for literal match', function()
local aus = meths.get_autocmds {
event = "InsertEnter",
pattern = "*"
@@ -650,7 +692,7 @@ describe('autocmd api', function()
eq([[:echo "No Group"]], aus[1].command)
end)
- it('should return for multiple matches', function()
+ it('returns for multiple matches', function()
-- vim.api.nvim_get_autocmds
local aus = meths.get_autocmds {
event = "InsertEnter",
@@ -687,6 +729,26 @@ describe('autocmd api', function()
end)
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', {}}, {}))
+ end)
+
it("can trigger builtin autocmds", function()
meths.set_var("autocmd_executed", false)
@@ -1004,6 +1066,12 @@ describe('autocmd api', function()
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, 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, 12342)]])
+ eq('Vim:E367: No such group: "[NULL]"', pcall_err(meths.del_augroup_by_id, 12312))
end)
it('groups work with once', function()
@@ -1036,7 +1104,7 @@ describe('autocmd api', function()
local augroup = "WillBeDeleted"
meths.create_augroup(augroup, { clear = true })
- meths.create_autocmd({"Filetype"}, {
+ meths.create_autocmd({"FileType"}, {
pattern = "*",
command = "echo 'does not matter'",
})
@@ -1055,7 +1123,7 @@ describe('autocmd api', function()
meths.set_var("value_set", false)
meths.create_augroup(augroup, { clear = true })
- meths.create_autocmd("Filetype", {
+ meths.create_autocmd("FileType", {
pattern = "<buffer>",
command = "let g:value_set = v:true",
})
@@ -1171,6 +1239,17 @@ describe('autocmd api', function()
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}))
+ 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"')
@@ -1254,7 +1333,7 @@ describe('autocmd api', function()
local without_group = meths.get_autocmds(search)
eq(2, #without_group)
- -- Doest clear with passing group.
+ -- Doesn't clear with passing group.
meths.clear_autocmds { buffer = 0, group = search.group }
local with_group = meths.get_autocmds(search)
eq(1, #with_group)
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 6b13729994..6ed9aa574a 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -16,6 +16,7 @@ local command = helpers.command
local bufmeths = helpers.bufmeths
local feed = helpers.feed
local pcall_err = helpers.pcall_err
+local assert_alive = helpers.assert_alive
describe('api/buf', function()
before_each(clear)
@@ -41,6 +42,14 @@ describe('api/buf', function()
eq(1, curbuf_depr('line_count'))
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, { })
+
+ 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"})
@@ -76,6 +85,38 @@ describe('api/buf', function()
eq({4, 2}, curwin('get_cursor'))
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()
+
+ 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))
+ 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()
+
+ command('split')
+ meths.win_set_cursor(0, {4, 2})
+ local win2 = meths.get_current_win()
+
+ -- set current window to third one with another buffer
+ 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))
+ 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')
@@ -105,6 +146,285 @@ describe('api/buf', function()
-- it's impossible to get out-of-bounds errors for an unloaded buffer
eq({}, buffer('get_lines', bufnr, 8888, 9999, 1))
end)
+
+ describe('handles topline', function()
+ local screen
+ 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};
+ }
+ screen:attach()
+ meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"})
+ meths.set_option_value('modified', false, {})
+ end)
+
+ it('of current window', function()
+ local win = meths.get_current_win()
+ local buf = meths.get_current_buf()
+
+ command('new | wincmd w')
+ meths.win_set_cursor(win, {8,0})
+
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ www |
+ xxx |
+ yyy |
+ ^zzz |
+ {2:[No Name] }|
+ |
+ ]]}
+
+ meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ www |
+ xxx |
+ yyy |
+ ^zzz |
+ {2:[No Name] [+] }|
+ |
+ ]]}
+
+ -- replacing topline keeps it the topline
+ meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ wwweeee |
+ xxx |
+ yyy |
+ ^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=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ wwweeee |
+ xxx |
+ yyy |
+ ^zzz |
+ {2:[No Name] [+] }|
+ |
+ ]], unchanged=true}
+
+ meths.win_set_cursor(0, {7, 0})
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ wwweeee |
+ xxx |
+ ^yyy |
+ zzz |
+ {2:[No Name] [+] }|
+ |
+ ]]}
+
+ meths.buf_set_lines(buf, 4, 4, true, {"mmmeeeee"})
+ screen:expect{grid=[[
+ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {3:[No Name] }|
+ mmmeeeee |
+ wwweeee |
+ xxx |
+ ^yyy |
+ {2:[No Name] [+] }|
+ |
+ ]]}
+ end)
+
+ it('of non-current window', function()
+ local win = meths.get_current_win()
+ local buf = meths.get_current_buf()
+
+ command('new')
+ meths.win_set_cursor(win, {8,0})
+
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] }|
+ www |
+ xxx |
+ yyy |
+ zzz |
+ {3:[No Name] }|
+ |
+ ]]}
+
+ meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] }|
+ www |
+ xxx |
+ yyy |
+ zzz |
+ {3:[No Name] [+] }|
+ |
+ ]]}
+
+ -- replacing topline keeps it the topline
+ meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] }|
+ wwweeee |
+ xxx |
+ yyy |
+ zzz |
+ {3:[No Name] [+] }|
+ |
+ ]]}
+
+ -- inserting just before topline scrolls up
+ meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] }|
+ mmm |
+ wwweeee |
+ xxx |
+ 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()
+
+ command('split')
+ meths.win_set_cursor(win, {8,0})
+ meths.win_set_cursor(0, {1,0})
+
+ screen:expect{grid=[[
+ ^aaa |
+ bbb |
+ ccc |
+ ddd |
+ www |
+ {2:[No Name] }|
+ www |
+ xxx |
+ yyy |
+ zzz |
+ {3:[No Name] }|
+ |
+ ]]}
+ meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
+
+ screen:expect{grid=[[
+ ^aaabbb |
+ ccc |
+ ddd |
+ www |
+ xxx |
+ {2:[No Name] [+] }|
+ www |
+ xxx |
+ yyy |
+ zzz |
+ {3:[No Name] [+] }|
+ |
+ ]]}
+
+ -- replacing topline keeps it the topline
+ meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
+ screen:expect{grid=[[
+ ^aaabbb |
+ ccc |
+ ddd |
+ wwweeee |
+ xxx |
+ {2:[No Name] [+] }|
+ wwweeee |
+ xxx |
+ yyy |
+ zzz |
+ {3:[No Name] [+] }|
+ |
+ ]]}
+
+ -- inserting just before topline scrolls up
+ meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
+ screen:expect{grid=[[
+ ^aaabbb |
+ ccc |
+ ddd |
+ mmm |
+ wwweeee |
+ {2:[No Name] [+] }|
+ mmm |
+ wwweeee |
+ xxx |
+ 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")
+
+ meths.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))
+ end)
end)
describe('deprecated: {get,set,del}_line', function()
@@ -193,7 +513,7 @@ describe('api/buf', function()
it('fails correctly when input is not valid', function()
eq(1, api.curbufmeths.get_number())
- eq([[String cannot contain newlines]],
+ eq([['replacement string' item contains newlines]],
pcall_err(bufmeths.set_lines, 1, 1, 2, false, {'b\na'}))
end)
@@ -393,6 +713,21 @@ describe('api/buf', function()
feed('<c-w>p')
eq(3, funcs.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')
+ 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))
+ end)
end)
describe('nvim_buf_set_text', function()
@@ -437,6 +772,10 @@ describe('api/buf', function()
-- can append to a line
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))
end)
it('works with undo', function()
@@ -480,6 +819,754 @@ describe('api/buf', function()
eq({1, 9}, curwin('get_cursor'))
end)
+ it('updates the cursor position in non-current window', function()
+ insert([[
+ 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()
+
+ 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))
+ -- cursor should be moved left by two columns (replacement is shorter by 2 chars)
+ eq({1, 9}, meths.win_get_cursor(win))
+ end)
+
+ it('updates the cursor position in TWO non-current windows', function()
+ insert([[
+ 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()
+
+ command("split")
+ local win2 = meths.get_current_win()
+ -- position the cursor on `w`
+ meths.win_set_cursor(0, {1, 6})
+
+ 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))
+
+ -- 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))
+ end)
+
+ describe('when text is being added right at cursor position #22526', function()
+ it('updates the cursor position in NORMAL mode', function()
+ insert([[
+ abcd]])
+
+ -- position the cursor on 'c'
+ curwin('set_cursor', {1, 2})
+ -- add 'xxx' before 'c'
+ 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'))
+ end)
+
+ it('updates the cursor position only in non-current window when in INSERT mode', function()
+ insert([[
+ abcd]])
+
+ -- position the cursor on 'c'
+ curwin('set_cursor', {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))
+ -- in the current window cursor should stay after 'b'
+ eq({1, 2}, curwin('get_cursor'))
+ -- quit INSERT mode
+ feed('<esc>')
+ -- close current window