aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/functional/api/vim_spec.lua4
-rw-r--r--test/functional/autocmd/textyankpost_spec.lua6
-rw-r--r--test/functional/ex_cmds/cmd_map_spec.lua4
-rw-r--r--test/functional/legacy/matchparen_spec.lua43
-rw-r--r--test/functional/legacy/memory_usage_spec.lua2
-rw-r--r--test/functional/lua/buffer_updates_spec.lua8
-rw-r--r--test/functional/lua/diagnostic_spec.lua2
-rw-r--r--test/functional/lua/thread_spec.lua4
-rw-r--r--test/functional/lua/vim_spec.lua30
-rw-r--r--test/functional/options/defaults_spec.lua6
-rw-r--r--test/functional/options/num_options_spec.lua2
-rw-r--r--test/functional/options/winfixbuf_spec.lua54
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua10
-rw-r--r--test/functional/plugin/lsp/inlay_hint_spec.lua14
-rw-r--r--test/functional/plugin/lsp_spec.lua14
-rw-r--r--test/functional/shada/merging_spec.lua10
-rw-r--r--test/functional/treesitter/highlight_spec.lua89
-rw-r--r--test/functional/treesitter/parser_spec.lua8
-rw-r--r--test/functional/ui/float_spec.lua2
-rw-r--r--test/functional/ui/inccommand_spec.lua4
-rw-r--r--test/functional/ui/messages_spec.lua10
-rw-r--r--test/old/testdir/test_matchparen.vim25
-rw-r--r--test/old/testdir/test_visual.vim52
-rw-r--r--test/old/testdir/test_winfixbuf.vim3286
-rw-r--r--test/unit/msgpack_spec.lua6
-rw-r--r--test/unit/os/env_spec.lua4
-rw-r--r--test/unit/os/shell_spec.lua24
-rw-r--r--test/unit/profile_spec.lua4
-rw-r--r--test/unit/tempfile_spec.lua4
29 files changed, 3620 insertions, 111 deletions
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 9a4a457637..09a45242ec 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -707,13 +707,13 @@ describe('API', function()
it('works', function()
api.nvim_set_current_dir('Xtestdir')
- eq(fn.getcwd(), start_dir .. helpers.get_pathsep() .. 'Xtestdir')
+ eq(start_dir .. helpers.get_pathsep() .. 'Xtestdir', fn.getcwd())
end)
it('sets previous directory', function()
api.nvim_set_current_dir('Xtestdir')
command('cd -')
- eq(fn.getcwd(), start_dir)
+ eq(start_dir, fn.getcwd())
end)
end)
diff --git a/test/functional/autocmd/textyankpost_spec.lua b/test/functional/autocmd/textyankpost_spec.lua
index 29cd62f586..17eb7695f2 100644
--- a/test/functional/autocmd/textyankpost_spec.lua
+++ b/test/functional/autocmd/textyankpost_spec.lua
@@ -72,19 +72,19 @@ describe('TextYankPost', function()
command('set debug=msg')
-- the regcontents should not be changed without copy.
local status, err = pcall(command, 'call extend(g:event.regcontents, ["more text"])')
- eq(status, false)
+ eq(false, status)
neq(nil, string.find(err, ':E742:'))
-- can't mutate keys inside the autocommand
command('autocmd! TextYankPost * let v:event.regcontents = 0')
status, err = pcall(command, 'normal yy')
- eq(status, false)
+ eq(false, status)
neq(nil, string.find(err, ':E46:'))
-- can't add keys inside the autocommand
command('autocmd! TextYankPost * let v:event.mykey = 0')
status, err = pcall(command, 'normal yy')
- eq(status, false)
+ eq(false, status)
neq(nil, string.find(err, ':E742:'))
end)
diff --git a/test/functional/ex_cmds/cmd_map_spec.lua b/test/functional/ex_cmds/cmd_map_spec.lua
index cb7d7340e2..4499b2172d 100644
--- a/test/functional/ex_cmds/cmd_map_spec.lua
+++ b/test/functional/ex_cmds/cmd_map_spec.lua
@@ -505,7 +505,7 @@ describe('mappings with <Cmd>', function()
feed('"bd<F7>')
expect([[
soest text]])
- eq(fn.getreg('b', 1, 1), { 'me short lines', 'of t' })
+ eq({ 'me short lines', 'of t' }, fn.getreg('b', 1, 1))
-- startinsert aborts operator
feed('d<F8>')
@@ -561,7 +561,7 @@ describe('mappings with <Cmd>', function()
of stuff test text]])
feed('<F5>')
- eq(fn.getreg('a', 1, 1), { 'deed some short little lines', 'of stuff t' })
+ eq({ 'deed some short little lines', 'of stuff t' }, fn.getreg('a', 1, 1))
-- still in insert
screen:expect([[
diff --git a/test/functional/legacy/matchparen_spec.lua b/test/functional/legacy/matchparen_spec.lua
index b03107deb0..137448acbd 100644
--- a/test/functional/legacy/matchparen_spec.lua
+++ b/test/functional/legacy/matchparen_spec.lua
@@ -61,13 +61,15 @@ describe('matchparen', function()
set hidden
call setline(1, ['()'])
normal 0
+
+ func OtherBuffer()
+ enew
+ exe "normal iaa\<Esc>0"
+ endfunc
]])
screen:expect(screen1)
- exec([[
- enew
- exe "normal iaa\<Esc>0"
- ]])
+ exec('call OtherBuffer()')
screen:expect(screen2)
feed('<C-^>')
@@ -77,6 +79,39 @@ describe('matchparen', function()
screen:expect(screen2)
end)
+ -- oldtest: Test_matchparen_win_execute()
+ it('matchparen highlight when switching buffer in win_execute()', function()
+ local screen = Screen.new(20, 5)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Cyan },
+ [2] = { reverse = true, bold = true },
+ [3] = { reverse = true },
+ })
+ screen:attach()
+
+ exec([[
+ source $VIMRUNTIME/plugin/matchparen.vim
+ let s:win = win_getid()
+ call setline(1, '{}')
+ split
+
+ func SwitchBuf()
+ call win_execute(s:win, 'enew | buffer #')
+ endfunc
+ ]])
+ screen:expect([[
+ {1:^{}} |
+ {2:[No Name] [+] }|
+ {} |
+ {3:[No Name] [+] }|
+ |
+ ]])
+
+ -- Switching buffer away and back shouldn't change matchparen highlight.
+ exec('call SwitchBuf()')
+ screen:expect_unchanged()
+ end)
+
-- oldtest: Test_matchparen_pum_clear()
it('is cleared when completion popup is shown', function()
local screen = Screen.new(30, 9)
diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua
index a05e9fdf57..3a6eb2c31c 100644
--- a/test/functional/legacy/memory_usage_spec.lua
+++ b/test/functional/legacy/memory_usage_spec.lua
@@ -59,7 +59,7 @@ local monitor_memory_usage = {
end
table.remove(self.hist, 1)
self.last = self.hist[#self.hist]
- eq(#result, 1)
+ eq(1, #result)
end)
end,
dump = function(self)
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 714e1b951f..2479a433e6 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -312,15 +312,15 @@ describe('lua buffer event callbacks: on_lines', function()
feed('G0')
feed('p')
-- Is the last arg old_byte_size correct? Doesn't matter for this PR
- eq(api.nvim_get_var('linesev'), { 'lines', 1, 4, 2, 3, 5, 4 })
+ eq({ 'lines', 1, 4, 2, 3, 5, 4 }, api.nvim_get_var('linesev'))
feed('2G0')
feed('p')
- eq(api.nvim_get_var('linesev'), { 'lines', 1, 5, 1, 4, 4, 8 })
+ eq({ 'lines', 1, 5, 1, 4, 4, 8 }, api.nvim_get_var('linesev'))
feed('1G0')
feed('P')
- eq(api.nvim_get_var('linesev'), { 'lines', 1, 6, 0, 3, 3, 9 })
+ eq({ 'lines', 1, 6, 0, 3, 3, 9 }, api.nvim_get_var('linesev'))
end)
it(
@@ -541,7 +541,7 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed 'cc'
check_events {
- { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 15, 15, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 15, 15, 0, 0, 0 },
}
feed '<ESC>'
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index 5802925339..716c1e0f30 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -205,7 +205,7 @@ describe('vim.diagnostic', function()
diag[1].col = 10000
return vim.diagnostic.get()[1].col == 10000
]]
- eq(result, false)
+ eq(false, result)
end)
it('resolves buffer number 0 to the current buffer', function()
diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua
index c1981e19d4..9bbee73e27 100644
--- a/test/functional/lua/thread_spec.lua
+++ b/test/functional/lua/thread_spec.lua
@@ -166,7 +166,7 @@ describe('thread', function()
]]
local msg = next_msg()
- eq(msg[1], 'notification')
+ eq('notification', msg[1])
assert(tonumber(msg[2]) >= 72961)
end)
@@ -327,7 +327,7 @@ describe('threadpool', function()
]]
local msg = next_msg()
- eq(msg[1], 'notification')
+ eq('notification', msg[1])
assert(tonumber(msg[2]) >= 72961)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index add3df6d8a..7ab009659b 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2016,7 +2016,7 @@ describe('lua stdlib', function()
vim.opt.scrolloff = 10
return vim.o.scrolloff
]]
- eq(scrolloff, 10)
+ eq(10, scrolloff)
end)
pending('should handle STUPID window things', function()
@@ -2037,7 +2037,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = { 'hello', 'world' }
return vim.o.wildignore
]]
- eq(wildignore, 'hello,world')
+ eq('hello,world', wildignore)
end)
it('should allow setting tables with shortnames', function()
@@ -2045,7 +2045,7 @@ describe('lua stdlib', function()
vim.opt.wig = { 'hello', 'world' }
return vim.o.wildignore
]]
- eq(wildignore, 'hello,world')
+ eq('hello,world', wildignore)
end)
it('should error when you attempt to set string values to numeric options', function()
@@ -2451,13 +2451,13 @@ describe('lua stdlib', function()
vim.opt.wildignore = 'foo'
return vim.o.wildignore
]]
- eq(wildignore, 'foo')
+ eq('foo', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
end)
it('should handle adding duplicates', function()
@@ -2465,19 +2465,19 @@ describe('lua stdlib', function()
vim.opt.wildignore = 'foo'
return vim.o.wildignore
]]
- eq(wildignore, 'foo')
+ eq('foo', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
end)
it('should allow adding multiple times', function()
@@ -2486,7 +2486,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = vim.opt.wildignore + 'bar' + 'baz'
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
end)
it('should remove values when you use minus', function()
@@ -2494,19 +2494,19 @@ describe('lua stdlib', function()
vim.opt.wildignore = 'foo'
return vim.o.wildignore
]]
- eq(wildignore, 'foo')
+ eq('foo', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore + { 'bar', 'baz' }
return vim.o.wildignore
]]
- eq(wildignore, 'foo,bar,baz')
+ eq('foo,bar,baz', wildignore)
wildignore = exec_lua [[
vim.opt.wildignore = vim.opt.wildignore - 'bar'
return vim.o.wildignore
]]
- eq(wildignore, 'foo,baz')
+ eq('foo,baz', wildignore)
end)
it('should prepend values when using ^', function()
@@ -2521,7 +2521,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = vim.opt.wildignore ^ 'super_first'
return vim.o.wildignore
]]
- eq(wildignore, 'super_first,first,foo')
+ eq('super_first,first,foo', wildignore)
end)
it('should not remove duplicates from wildmode: #14708', function()
@@ -2530,7 +2530,7 @@ describe('lua stdlib', function()
return vim.o.wildmode
]]
- eq(wildmode, 'full,list,full')
+ eq('full,list,full', wildmode)
end)
describe('option types', function()
@@ -2738,7 +2738,7 @@ describe('lua stdlib', function()
return vim.go.whichwrap
]]
- eq(ww, 'b,s')
+ eq('b,s', ww)
eq(
'b,s,<,>,[,]',
exec_lua [[
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index d27fa375ee..a7cdc5f9fa 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -1243,11 +1243,11 @@ describe('autocommands', function()
command('au BufEnter * let g:n = g:n + 1')
command('terminal')
- eq(eval('get(g:, "n", 0)'), 1)
+ eq(1, eval('get(g:, "n", 0)'))
helpers.retry(nil, 1000, function()
- neq(api.nvim_get_option_value('buftype', { buf = 0 }), 'terminal')
- eq(eval('get(g:, "n", 0)'), 2)
+ neq('terminal', api.nvim_get_option_value('buftype', { buf = 0 }))
+ eq(2, eval('get(g:, "n", 0)'))
end)
end)
end)
diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua
index 0614bcf814..3b411b109c 100644
--- a/test/functional/options/num_options_spec.lua
+++ b/test/functional/options/num_options_spec.lua
@@ -12,7 +12,7 @@ local function should_fail(opt, value, errmsg)
eq(errmsg, eval('v:errmsg'):match('E%d*'))
feed_command('let v:errmsg = ""')
local status, err = pcall(api.nvim_set_option_value, opt, value, {})
- eq(status, false)
+ eq(false, status)
eq(errmsg, err:match('E%d*'))
eq('', eval('v:errmsg'))
end
diff --git a/test/functional/options/winfixbuf_spec.lua b/test/functional/options/winfixbuf_spec.lua
new file mode 100644
index 0000000000..20407b9bb7
--- /dev/null
+++ b/test/functional/options/winfixbuf_spec.lua
@@ -0,0 +1,54 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local exec_lua = helpers.exec_lua
+
+describe("Nvim API calls with 'winfixbuf'", function()
+ before_each(function()
+ clear()
+ end)
+
+ it("Calling vim.api.nvim_win_set_buf with 'winfixbuf'", function()
+ local results = exec_lua([[
+ local function _setup_two_buffers()
+ local buffer = vim.api.nvim_create_buf(true, true)
+
+ vim.api.nvim_create_buf(true, true) -- Make another buffer
+
+ local current_window = 0
+ vim.api.nvim_set_option_value("winfixbuf", true, {win=current_window})
+
+ return buffer
+ end
+
+ local other_buffer = _setup_two_buffers()
+ local current_window = 0
+ local results, _ = pcall(vim.api.nvim_win_set_buf, current_window, other_buffer)
+
+ return results
+ ]])
+
+ assert(results == false)
+ end)
+
+ it("Calling vim.api.nvim_set_current_buf with 'winfixbuf'", function()
+ local results = exec_lua([[
+ local function _setup_two_buffers()
+ local buffer = vim.api.nvim_create_buf(true, true)
+
+ vim.api.nvim_create_buf(true, true) -- Make another buffer
+
+ local current_window = 0
+ vim.api.nvim_set_option_value("winfixbuf", true, {win=current_window})
+
+ return buffer
+ end
+
+ local other_buffer = _setup_two_buffers()
+ local results, _ = pcall(vim.api.nvim_set_current_buf, other_buffer)
+
+ return results
+ ]])
+
+ assert(results == false)
+ end)
+end)
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 705c182df7..72531db021 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -257,7 +257,7 @@ describe('vim.lsp.diagnostic', function()
}, {client_id=client_id})
return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2"))
]]
- eq(bufnr, -1)
+ eq(-1, bufnr)
-- Create buffer on diagnostics
bufnr = exec_lua [[
@@ -269,8 +269,8 @@ describe('vim.lsp.diagnostic', function()
}, {client_id=client_id})
return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2"))
]]
- neq(bufnr, -1)
- eq(exec_lua([[return #vim.diagnostic.get(...)]], bufnr), 1)
+ neq(-1, bufnr)
+ eq(1, exec_lua([[return #vim.diagnostic.get(...)]], bufnr))
-- Clear diagnostics after buffer was created
bufnr = exec_lua [[
@@ -280,8 +280,8 @@ describe('vim.lsp.diagnostic', function()
}, {client_id=client_id})
return vim.fn.bufnr(vim.uri_to_fname("file:///fake/uri2"))
]]
- neq(bufnr, -1)
- eq(exec_lua([[return #vim.diagnostic.get(...)]], bufnr), 0)
+ neq(-1, bufnr)
+ eq(0, exec_lua([[return #vim.diagnostic.get(...)]], bufnr))
end)
end)
diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua
index 192797b312..864394d7e0 100644
--- a/test/functional/plugin/lsp/inlay_hint_spec.lua
+++ b/test/functional/plugin/lsp/inlay_hint_spec.lua
@@ -169,12 +169,12 @@ describe('vim.lsp.inlay_hint', function()
--- @type vim.lsp.inlay_hint.get.ret
local res = exec_lua([[return vim.lsp.inlay_hint.get()]])
- eq(res, {
+ eq({
{ bufnr = 1, client_id = 1, inlay_hint = expected[1] },
{ bufnr = 1, client_id = 1, inlay_hint = expected[2] },
{ bufnr = 1, client_id = 1, inlay_hint = expected[3] },
{ bufnr = 1, client_id = 2, inlay_hint = expected2 },
- })
+ }, res)
--- @type vim.lsp.inlay_hint.get.ret
res = exec_lua([[return vim.lsp.inlay_hint.get({
@@ -183,9 +183,9 @@ describe('vim.lsp.inlay_hint', function()
["end"] = { line = 2, character = 10 },
},
})]])
- eq(res, {
+ eq({
{ bufnr = 1, client_id = 2, inlay_hint = expected2 },
- })
+ }, res)
--- @type vim.lsp.inlay_hint.get.ret
res = exec_lua([[return vim.lsp.inlay_hint.get({
@@ -195,16 +195,16 @@ describe('vim.lsp.inlay_hint', function()
["end"] = { line = 5, character = 17 },
},
})]])
- eq(res, {
+ eq({
{ bufnr = 1, client_id = 1, inlay_hint = expected[2] },
{ bufnr = 1, client_id = 1, inlay_hint = expected[3] },
- })
+ }, res)
--- @type vim.lsp.inlay_hint.get.ret
res = exec_lua([[return vim.lsp.inlay_hint.get({
bufnr = vim.api.nvim_get_current_buf() + 1,
})]])
- eq(res, {})
+ eq({}, res)
end)
end)
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 4826153edb..0cb2b88948 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -641,11 +641,11 @@ describe('LSP', function()
vim.lsp.stop_client(client_id)
return server.messages
]])
- eq(#messages, 4)
- eq(messages[1].method, 'initialize')
- eq(messages[2].method, 'initialized')
- eq(messages[3].method, 'shutdown')
- eq(messages[4].method, 'exit')
+ eq(4, #messages)
+ eq('initialize', messages[1].method)
+ eq('initialized', messages[2].method)
+ eq('shutdown', messages[3].method)
+ eq('exit', messages[4].method)
end)
it('BufWritePre sends willSave / willSaveWaitUntil, applies textEdits', function()
@@ -4221,7 +4221,7 @@ describe('LSP', function()
server:shutdown()
return vim.json.decode(init)
]]
- eq(result.method, 'initialize')
+ eq('initialize', result.method)
end)
it('can connect to lsp server via rpc.domain_socket_connect', function()
local tmpfile
@@ -4257,7 +4257,7 @@ describe('LSP', function()
]],
tmpfile
)
- eq(result.method, 'initialize')
+ eq('initialize', result.method)
end)
end)
diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua
index 1b5c0eab5d..ff81ce4eb9 100644
--- a/test/functional/shada/merging_spec.lua
+++ b/test/functional/shada/merging_spec.lua
@@ -1003,7 +1003,7 @@ describe('ShaDa jumps support code', function()
eq(jumps[found].line, v.value.l)
end
end
- eq(found, #jumps)
+ eq(#jumps, found)
end)
it('merges JUMPLISTSIZE jumps when writing', function()
@@ -1041,7 +1041,7 @@ describe('ShaDa jumps support code', function()
eq(jumps[found].line, v.value.l)
end
end
- eq(found, 100)
+ eq(100, found)
end)
end)
@@ -1132,7 +1132,7 @@ describe('ShaDa changes support code', function()
eq(changes[found].line, v.value.l or 1)
end
end
- eq(found, #changes)
+ eq(#changes, found)
end)
it('merges JUMPLISTSIZE changes when writing', function()
@@ -1170,7 +1170,7 @@ describe('ShaDa changes support code', function()
eq(changes[found].line, v.value.l)
end
end
- eq(found, 100)
+ eq(100, found)
end)
it('merges JUMPLISTSIZE changes when writing, with new items between old', function()
@@ -1213,6 +1213,6 @@ describe('ShaDa changes support code', function()
eq(changes[found].line, v.value.l)
end
end
- eq(found, 100)
+ eq(100, found)
end)
end)
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index 2bf230fe69..7f2b5751ae 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -681,6 +681,12 @@ describe('treesitter highlighting (C)', function()
((identifier) @Identifier
(#set! conceal "")
(#eq? @Identifier "lstate"))
+
+ ((call_expression
+ function: (identifier) @function
+ arguments: (argument_list) @arguments)
+ (#eq? @function "multiqueue_put")
+ (#set! @function conceal "V"))
]]}})
]=]
@@ -697,7 +703,7 @@ describe('treesitter highlighting (C)', function()
|
LuaRef cb = nlua_ref(, 1); |
|
- multiqueue_put(main_loop.events, nlua_schedule_event, |
+ {11:V}(main_loop.events, nlua_schedule_event, |
1, (void *)(ptrdiff_t)cb); |
return 0; |
^} |
@@ -758,6 +764,44 @@ describe('treesitter highlighting (C)', function()
end)
end)
+describe('treesitter highlighting (lua)', function()
+ local screen
+
+ before_each(function()
+ screen = Screen.new(65, 18)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { foreground = Screen.colors.DarkCyan },
+ [3] = { foreground = Screen.colors.Magenta },
+ [4] = { foreground = Screen.colors.SlateBlue },
+ [5] = { bold = true, foreground = Screen.colors.Brown },
+ }
+ end)
+
+ it('supports language injections', function()
+ insert [[
+ local ffi = require('ffi')
+ ffi.cdef("int (*fun)(int, char *);")
+ ]]
+
+ exec_lua [[
+ vim.bo.filetype = 'lua'
+ vim.treesitter.start()
+ ]]
+
+ screen:expect {
+ grid = [[
+ {5:local} {2:ffi} {5:=} {4:require(}{3:'ffi'}{4:)} |
+ {2:ffi}{4:.}{2:cdef}{4:(}{3:"}{4:int}{3: }{4:(}{5:*}{3:fun}{4:)(int,}{3: }{4:char}{3: }{5:*}{4:);}{3:"}{4:)} |
+ ^ |
+ {1:~ }|*14
+ |
+ ]],
+ }
+ end)
+end)
+
describe('treesitter highlighting (help)', function()
local screen
@@ -891,3 +935,46 @@ vim.cmd([[
}
end)
end)
+
+describe('treesitter highlighting (markdown)', function()
+ local screen
+
+ before_each(function()
+ screen = Screen.new(40, 6)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.Brown },
+ [4] = { foreground = Screen.colors.Cyan4 },
+ [5] = { foreground = Screen.colors.Magenta1 },
+ }
+ end)
+
+ it('supports hyperlinks', function()
+ local url = 'https://example.com'
+ insert(string.format('[This link text](%s) is a hyperlink.', url))
+ exec_lua([[
+ vim.bo.filetype = 'markdown'
+ vim.treesitter.start()
+ ]])
+
+ screen:expect {
+ grid = [[
+ {4:[}{6:This link text}{4:](}{7:https://example.com}{4:)} is|
+ a hyperlink^. |
+ {2:~ }|*3
+ |
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.Brown },
+ [4] = { foreground = Screen.colors.Cyan4 },
+ [5] = { foreground = Screen.colors.Magenta },
+ [6] = { foreground = Screen.colors.Cyan4, url = url },
+ [7] = { underline = true, foreground = Screen.colors.SlateBlue },
+ },
+ }
+ end)
+end)
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index 875b772fec..24f395c1ef 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -828,7 +828,7 @@ end]]
return parser:included_regions()
]]
- eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
+ eq({ { { 0, 0, 0, 17, 1, 508 } } }, range_tbl)
end)
it('allows to set complex ranges', function()
@@ -1111,7 +1111,7 @@ int x = INT_MAX;
return sub_tree == parser:children().c
]])
- eq(result, true)
+ eq(true, result)
end)
end)
@@ -1135,7 +1135,7 @@ int x = INT_MAX;
return result
]])
- eq(result, 'value')
+ eq('value', result)
end)
describe('when setting a key on a capture', function()
@@ -1158,7 +1158,7 @@ int x = INT_MAX;
end
]])
- eq(result, 'value')
+ eq('value', result)
end)
it('it should not overwrite the nested table', function()
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 65a7d359af..361ea3e778 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -6257,7 +6257,7 @@ describe('float window', function()
run(on_request, nil, on_setup)
os.remove('Xtest_written')
os.remove('Xtest_written2')
- eq(exited, true)
+ eq(true, exited)
end)
it(':quit two floats in a row', function()
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 29c8c43ca1..d143c594f5 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -204,8 +204,8 @@ describe(":substitute, 'inccommand' preserves", function()
feed(':%s/as/glork/')
poke_eventloop()
feed('<enter>')
- eq(api.nvim_get_option_value('undolevels', { scope = 'global' }), 139)
- eq(api.nvim_get_option_value('undolevels', { buf = 0 }), 34)
+ eq(139, api.nvim_get_option_value('undolevels', { scope = 'global' }))
+ eq(34, api.nvim_get_option_value('undolevels', { buf = 0 }))
end)
end
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 31b1464589..c18a07fef0 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -844,7 +844,7 @@ describe('ui/ext_messages', function()
}
end)
- it('implies ext_cmdline and ignores cmdheight', function()
+ it("implies ext_cmdline but allows changing 'cmdheight'", function()
eq(0, eval('&cmdheight'))
feed(':set cmdheight=1')
screen:expect {
@@ -864,15 +864,17 @@ describe('ui/ext_messages', function()
feed('<cr>')
screen:expect([[
^ |
- {1:~ }|*4
+ {1:~ }|*3
+ |
]])
- eq(0, eval('&cmdheight'))
+ eq(1, eval('&cmdheight'))
feed(':set cmdheight=0')
screen:expect {
grid = [[
^ |
- {1:~ }|*4
+ {1:~ }|*3
+ |
]],
cmdline = {
{
diff --git a/test/old/testdir/test_matchparen.vim b/test/old/testdir/test_matchparen.vim
index 3138180c66..ab425b046a 100644
--- a/test/old/testdir/test_matchparen.vim
+++ b/test/old/testdir/test_matchparen.vim
@@ -61,6 +61,31 @@ func Test_matchparen_clear_highlight()
call StopVimInTerminal(buf)
endfunc
+" Test for matchparen highlight when switching buffer in win_execute()
+func Test_matchparen_win_execute()
+ CheckScreendump
+
+ let lines =<< trim END
+ source $VIMRUNTIME/plugin/matchparen.vim
+ let s:win = win_getid()
+ call setline(1, '{}')
+ split
+
+ func SwitchBuf()
+ call win_execute(s:win, 'enew | buffer #')
+ endfunc
+ END
+ call writefile(lines, 'XMatchparenWinExecute', 'D')
+ let buf = RunVimInTerminal('-S XMatchparenWinExecute', #{rows: 5})
+ call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {})
+
+ " Switching buffer away and back shouldn't change matchparen highlight.
+ call term_sendkeys(buf, ":call SwitchBuf()\<CR>:\<Esc>")
+ call VerifyScreenDump(buf, 'Test_matchparen_win_execute_1', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" Test for scrolling that modifies buffer during visual block
func Test_matchparen_pum_clear()
CheckScreendump
diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim
index 4c5ab9f61f..d952400367 100644
--- a/test/old/testdir/test_visual.vim
+++ b/test/old/testdir/test_visual.vim
@@ -1741,40 +1741,60 @@ func Test_visual_getregion()
\ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
set virtualedit&
- #" Invalid position
+ #" using wrong types for positions
call cursor(1, 1)
call feedkeys("\<ESC>vjj$", 'tx')
call assert_fails("call getregion(1, 2)", 'E1211:')
call assert_fails("call getregion(getpos('.'), {})", 'E1211:')
- call assert_equal([], getregion(getpos('.'), getpos('.'), {'type': '' }))
-
- #" using the wrong type
call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:')
+ #" using invalid value for "type"
+ call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '' })", 'E475:')
+
#" using a mark from another buffer to current buffer
new
- VAR newbuf = bufnr()
+ LET g:buf = bufnr()
call setline(1, range(10))
normal! GmA
wincmd p
- call assert_equal([newbuf, 10, 1, 0], getpos("'A"))
+ call assert_equal([g:buf, 10, 1, 0], getpos("'A"))
call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' }))
call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' }))
- exe $':{newbuf}bwipe!'
- #" using a mark from another buffer to another buffer
- new
- VAR anotherbuf = bufnr()
- call setline(1, range(10))
- normal! GmA
+ #" using two marks from another buffer
+ wincmd p
normal! GmB
wincmd p
- call assert_equal([anotherbuf, 10, 1, 0], getpos("'A"))
+ call assert_equal([g:buf, 10, 1, 0], getpos("'B"))
call assert_equal(['9'], getregion(getpos("'B"), getpos("'A"), {'type': 'v' }))
- exe $':{anotherbuf}bwipe!'
+
+ #" using two positions from another buffer
+ for type in ['v', 'V', "\<C-V>"]
+ for exclusive in [v:false, v:true]
+ call assert_equal(range(10)->mapnew('string(v:val)'),
+ \ getregion([g:buf, 1, 1, 0], [g:buf, 10, 2, 0],
+ \ {'type': type, 'exclusive': exclusive }))
+ call assert_equal(range(10)->mapnew('string(v:val)'),
+ \ getregion([g:buf, 10, 2, 0], [g:buf, 1, 1, 0],
+ \ {'type': type, 'exclusive': exclusive }))
+ endfor
+ endfor
+
+ #" using invalid positions in buffer
+ call assert_fails('call getregion([g:buf, 0, 1, 0], [g:buf, 10, 2, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 10, 2, 0], [g:buf, 0, 1, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 11, 2, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 11, 2, 0], [g:buf, 1, 1, 0])', 'E966:')
+ call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 0, 0])', 'E964:')
+ call assert_fails('call getregion([g:buf, 10, 0, 0], [g:buf, 1, 1, 0])', 'E964:')
+ call assert_fails('call getregion([g:buf, 1, 1, 0], [g:buf, 10, 3, 0])', 'E964:')
+ call assert_fails('call getregion([g:buf, 10, 3, 0], [g:buf, 1, 1, 0])', 'E964:')
#" using invalid buffer
- call assert_equal([], getregion([10000, 10, 1, 0], [10000, 10, 1, 0]))
+ call assert_fails('call getregion([10000, 10, 1, 0], [10000, 10, 1, 0])', 'E681:')
+
+ exe $':{g:buf}bwipe!'
+ unlet g:buf
END
call CheckLegacyAndVim9Success(lines)
@@ -1935,7 +1955,7 @@ func Test_getregion_invalid_buf()
call assert_equal(['Move around:'], getregion(getpos("'A"), getpos("'B")))
" close the help window
q
- call assert_equal([], getregion(getpos("'A"), getpos("'B")))
+ call assert_fails("call getregion(getpos(\"'A\"), getpos(\"'B\"))", 'E681:')
bwipe!
endfunc
diff --git a/test/old/testdir/test_winfixbuf.vim b/test/old/testdir/test_winfixbuf.vim
new file mode 100644
index 0000000000..112eccf3ef
--- /dev/null
+++ b/test/old/testdir/test_winfixbuf.vim
@@ -0,0 +1,3286 @@
+" Test 'winfixbuf'
+
+source check.vim
+
+" Find the number of open windows in the current tab
+func s:get_windows_count()
+ return tabpagewinnr(tabpagenr(), '$')
+endfunc
+
+" Create some unnamed buffers.
+func s:make_buffers_list()
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file middle
+ let l:middle = bufnr()
+
+ enew
+ file last
+ let l:last = bufnr()
+
+ set winfixbuf
+
+ return [l:first, l:last]
+endfunc
+
+" Create some unnamed buffers and add them to an args list
+func s:make_args_list()
+ let [l:first, l:last] = s:make_buffers_list()
+
+ args! first middle last
+
+ return [l:first, l:last]
+endfunc
+
+" Create two buffers and then set the window to 'winfixbuf'
+func s:make_buffer_pairs(...)
+ let l:reversed = get(a:, 1, 0)
+
+ if l:reversed == 1
+ enew
+ file original
+
+ set winfixbuf
+
+ enew!
+ file other
+ let l:other = bufnr()
+
+ return l:other
+ endif
+
+ enew
+ file other
+ let l:other = bufnr()
+
+ enew
+ file current
+
+ set winfixbuf
+
+ return l:other
+endfunc
+
+" Create 3 quick buffers and set the window to 'winfixbuf'
+func s:make_buffer_trio()
+ edit first
+ let l:first = bufnr()
+ edit second
+ let l:second = bufnr()
+
+ set winfixbuf
+
+ edit! third
+ let l:third = bufnr()
+
+ execute ":buffer! " . l:second
+
+ return [l:first, l:second, l:third]
+endfunc
+
+" Create a location list with at least 2 entries + a 'winfixbuf' window.
+func s:make_simple_location_list()
+ enew
+ file middle
+ let l:middle = bufnr()
+ call append(0, ["winfix search-term", "another line"])
+
+ enew!
+ file first
+ let l:first = bufnr()
+ call append(0, "first search-term")
+
+ enew!
+ file last
+ let l:last = bufnr()
+ call append(0, "last search-term")
+
+ call setloclist(
+ \ 0,
+ \ [
+ \ {
+ \ "filename": "first",
+ \ "bufnr": l:first,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "middle",
+ \ "bufnr": l:middle,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "middle",
+ \ "bufnr": l:middle,
+ \ "lnum": 2,
+ \ },
+ \ {
+ \ "filename": "last",
+ \ "bufnr": l:last,
+ \ "lnum": 1,
+ \ },
+ \ ]
+ \)
+
+ set winfixbuf
+
+ return [l:first, l:middle, l:last]
+endfunc
+
+" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window.
+func s:make_simple_quickfix()
+ enew
+ file current
+ let l:current = bufnr()
+ call append(0, ["winfix search-term", "another line"])
+
+ enew!
+ file first
+ let l:first = bufnr()
+ call append(0, "first search-term")
+
+ enew!
+ file last
+ let l:last = bufnr()
+ call append(0, "last search-term")
+
+ call setqflist(
+ \ [
+ \ {
+ \ "filename": "first",
+ \ "bufnr": l:first,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "current",
+ \ "bufnr": l:current,
+ \ "lnum": 1,
+ \ },
+ \ {
+ \ "filename": "current",
+ \ "bufnr": l:current,
+ \ "lnum": 2,
+ \ },
+ \ {
+ \ "filename": "last",
+ \ "bufnr": l:last,
+ \ "lnum": 1,
+ \ },
+ \ ]
+ \)
+
+ set winfixbuf
+
+ return [l:current, l:last]
+endfunc
+
+" Create a quickfix with at least 2 entries that are in the current 'winfixbuf' window.
+func s:make_quickfix_windows()
+ let [l:current, _] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ split
+ let l:first_window = win_getid()
+ execute "normal \<C-w>j"
+ let l:winfix_window = win_getid()
+
+ " Open the quickfix in a separate split and go to it
+ copen
+ let l:quickfix_window = win_getid()
+
+ return [l:first_window, l:winfix_window, l:quickfix_window]
+endfunc
+
+" Revert all changes that occurred in any past test
+func s:reset_all_buffers()
+ %bwipeout!
+ set nowinfixbuf
+
+ call setqflist([])
+
+ for l:window_info in getwininfo()
+ call setloclist(l:window_info["winid"], [])
+ endfor
+
+ delmarks A-Z0-9
+endfunc
+
+" Find and set the first quickfix entry that points to `buffer`
+func s:set_quickfix_by_buffer(buffer)
+ let l:index = 1 " quickfix indices start at 1
+ for l:entry in getqflist()
+ if l:entry["bufnr"] == a:buffer
+ execute l:index . "cc"
+
+ return
+ endif
+
+ let l:index += 1
+ endfor
+
+ echoerr 'No quickfix entry matching "' . a:buffer . '" could be found.'
+endfunc
+
+" Fail to call :Next on a 'winfixbuf' window unless :Next! is used.
+func Test_Next()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("Next", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ Next!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Call :argdo and choose the next available 'nowinfixbuf' window.
+func Test_argdo_choose_available_window()
+ call s:reset_all_buffers()
+
+ let [_, l:last] = s:make_args_list()
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :argdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+ let l:expected_windows = s:get_windows_count()
+
+ argdo echo ''
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :argdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_argdo_make_new_window()
+ call s:reset_all_buffers()
+
+ let [l:first, l:last] = s:make_args_list()
+ let l:current = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ argdo echo ''
+ call assert_notequal(l:current, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :argedit but :argedit! is allowed
+func Test_argedit()
+ call s:reset_all_buffers()
+
+ args! first middle last
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file middle
+ let l:middle = bufnr()
+
+ enew
+ file last
+ let l:last = bufnr()
+
+ set winfixbuf
+
+ let l:current = bufnr()
+ call assert_fails("argedit first middle last", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ argedit! first middle last
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :arglocal but :arglocal! is allowed
+func Test_arglocal()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+ argglobal! other
+ execute "buffer! " . l:current
+
+ call assert_fails("arglocal other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ arglocal! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :argglobal but :argglobal! is allowed
+func Test_argglobal()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("argglobal other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ argglobal! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :args but :args! is allowed
+func Test_args()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_buffers_list()
+ let l:current = bufnr()
+
+ call assert_fails("args first middle last", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ args! first middle last
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :bNext but :bNext! is allowed
+func Test_bNext()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ call assert_fails("bNext", "E1513:")
+ let l:current = bufnr()
+
+ call assert_equal(l:current, bufnr())
+
+ bNext!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Allow :badd because it doesn't actually change the current window's buffer
+func Test_badd()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ badd other
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow :balt because it doesn't actually change the current window's buffer
+func Test_balt()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ balt other
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail :bfirst but :bfirst! is allowed
+func Test_bfirst()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("bfirst", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bfirst!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :blast but :blast! is allowed
+func Test_blast()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs(1)
+ bfirst!
+ let l:current = bufnr()
+
+ call assert_fails("blast", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ blast!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :bmodified but :bmodified! is allowed
+func Test_bmodified()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ execute "buffer! " . l:other
+ set modified
+ execute "buffer! " . l:current
+
+ call assert_fails("bmodified", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bmodified!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :bnext but :bnext! is allowed
+func Test_bnext()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("bnext", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bnext!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :bprevious but :bprevious! is allowed
+func Test_bprevious()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("bprevious", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ bprevious!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :brewind but :brewind! is allowed
+func Test_brewind()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("brewind", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ brewind!
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :browse edit but :browse edit! is allowed
+func Test_browse_edit_fail()
+ " A GUI dialog may stall the test.
+ CheckNotGui
+
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("browse edit other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ try
+ browse edit! other
+ call assert_equal(l:other, bufnr())
+ catch /E338:/
+ " Ignore E338, which occurs if console Vim is built with +browse.
+ " Console Vim without +browse will treat this as a regular :edit.
+ endtry
+endfunc
+
+" Allow :browse w because it doesn't change the buffer in the current file
+func Test_browse_edit_pass()
+ " A GUI dialog may stall the test.
+ CheckNotGui
+
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ try
+ browse write other
+ catch /E338:/
+ " Ignore E338, which occurs if console Vim is built with +browse.
+ " Console Vim without +browse will treat this as a regular :write.
+ endtry
+
+ call delete("other")
+endfunc
+
+" Call :bufdo and choose the next available 'nowinfixbuf' window.
+func Test_bufdo_choose_available_window()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :bufdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+
+ let l:current = bufnr()
+ let l:expected_windows = s:get_windows_count()
+
+ call assert_notequal(l:current, l:other)
+
+ bufdo echo ''
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_notequal(l:other, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :bufdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_bufdo_make_new_window()
+ call s:reset_all_buffers()
+
+ let [l:first, l:last] = s:make_buffers_list()
+ execute "buffer! " . l:first
+ let l:current = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ bufdo echo ''
+ call assert_notequal(l:current, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :buffer but :buffer! is allowed
+func Test_buffer()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("buffer " . l:other, "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ execute "buffer! " . l:other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Allow :buffer on a 'winfixbuf' window if there is no change in buffer
+func Test_buffer_same_buffer()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ execute "buffer " . l:current
+ call assert_equal(l:current, bufnr())
+
+ execute "buffer! " . l:current
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow :cNext but the 'nowinfixbuf' window is selected, instead
+func Test_cNext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cNext` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cNext
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cNfile but the 'nowinfixbuf' window is selected, instead
+func Test_cNfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cNfile` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cNfile
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :caddexpr because it doesn't change the current buffer
+func Test_caddexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ execute 'caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")'
+ call assert_equal(l:current, bufnr())
+
+ call delete(l:file_path)
+endfunc
+
+" Fail :cbuffer but :cbuffer! is allowed
+func Test_cbuffer()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ call assert_fails("cbuffer " . l:file_buffer)
+ call assert_equal(l:current, bufnr())
+
+ execute "cbuffer! " . l:file_buffer
+ call assert_equal("first.unittest", expand("%:t"))
+
+ call delete(l:file_path)
+endfunc
+
+" Allow :cc but the 'nowinfixbuf' window is selected, instead
+func Test_cc()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+ " Go up one line in the quickfix window to an quickfix entry that doesn't
+ " point to a winfixbuf buffer
+ normal k
+ " Attempt to make the previous window, winfixbuf buffer, to go to the
+ " non-winfixbuf quickfix entry
+ .cc
+
+ " Confirm that :.cc did not change the winfixbuf-enabled window
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Call :cdo and choose the next available 'nowinfixbuf' window.
+func Test_cdo_choose_available_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :cdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+ let l:expected_windows = s:get_windows_count()
+
+ cdo echo ''
+
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :cdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_cdo_make_new_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current_buffer, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current_buffer
+
+ let l:current_window = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ cdo echo ''
+ call assert_notequal(l:current_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current_buffer, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :cexpr but :cexpr! is allowed
+func Test_cexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ let l:entry = '["' . l:file . ':1:bar"]'
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("cexpr " . l:entry)
+ call assert_equal(l:current, bufnr())
+
+ execute "cexpr! " . l:entry
+ call assert_equal(fnamemodify(l:file, ":t"), expand("%:t"))
+endfunc
+
+" Call :cfdo and choose the next available 'nowinfixbuf' window.
+func Test_cfdo_choose_available_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :cfdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+ let l:expected_windows = s:get_windows_count()
+
+ cfdo echo ''
+
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :cfdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_cfdo_make_new_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current_buffer, l:last] = s:make_simple_quickfix()
+ execute "buffer! " . l:current_buffer
+
+ let l:current_window = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ cfdo echo ''
+ call assert_notequal(l:current_window, win_getid())
+ call assert_equal(l:last, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:current_buffer, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :cfile but :cfile! is allowed
+func Test_cfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+ write
+ let l:first = bufnr()
+
+ edit! second.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ let l:file = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file)
+
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails(":cfile " . l:file)
+ call assert_equal(l:current, bufnr())
+
+ execute ":cfile! " . l:file
+ call assert_equal(l:first, bufnr())
+
+ call delete(l:file)
+ call delete("first.unittest")
+ call delete("second.unittest")
+endfunc
+
+" Allow :cfirst but the 'nowinfixbuf' window is selected, instead
+func Test_cfirst()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cfirst` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cfirst
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :clast but the 'nowinfixbuf' window is selected, instead
+func Test_clast()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:clast` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ clast
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cnext but the 'nowinfixbuf' window is selected, instead
+" Make sure no new windows are created and previous windows are reused
+func Test_cnext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+ let l:expected = s:get_windows_count()
+
+ " The call to `:cnext` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ cnext!
+ call assert_equal(l:expected, s:get_windows_count())
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cnext
+ call assert_equal(l:first_window, win_getid())
+ call assert_equal(l:expected, s:get_windows_count())
+endfunc
+
+" Make sure :cnext creates a split window if no previous window exists
+func Test_cnext_no_previous_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, _] = s:make_simple_quickfix()
+ execute "buffer! " . l:current
+
+ let l:expected = s:get_windows_count()
+
+ " Open the quickfix in a separate split and go to it
+ copen
+
+ call assert_equal(l:expected + 1, s:get_windows_count())
+endfunc
+
+" Allow :cnext and create a 'nowinfixbuf' window if none exists
+func Test_cnext_make_new_window()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:current, _] = s:make_simple_quickfix()
+ let l:current = win_getid()
+
+ cfirst!
+
+ let l:windows = s:get_windows_count()
+ let l:expected = l:windows + 1 " We're about to create a new split window
+
+ cnext
+ call assert_equal(l:expected, s:get_windows_count())
+
+ cnext!
+ call assert_equal(l:expected, s:get_windows_count())
+endfunc
+
+" Allow :cprevious but the 'nowinfixbuf' window is selected, instead
+func Test_cprevious()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cprevious` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cprevious
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cnfile but the 'nowinfixbuf' window is selected, instead
+func Test_cnfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cnfile` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cnfile
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :cpfile but the 'nowinfixbuf' window is selected, instead
+func Test_cpfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:cpfile` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ cpfile
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow :crewind but the 'nowinfixbuf' window is selected, instead
+func Test_crewind()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first_window, l:winfix_window, l:quickfix_window] = s:make_quickfix_windows()
+
+ " The call to `:crewind` succeeds but it selects the window with 'nowinfixbuf' instead
+ call s:set_quickfix_by_buffer(winbufnr(l:winfix_window))
+ cnext!
+
+ " Make sure the previous window has 'winfixbuf' so we can test that our
+ " "skip 'winfixbuf' window" logic works.
+ call win_gotoid(l:winfix_window)
+ call win_gotoid(l:quickfix_window)
+
+ crewind
+ call assert_equal(l:first_window, win_getid())
+endfunc
+
+" Allow <C-w>f because it opens in a new split
+func Test_ctrl_w_f()
+ call s:reset_all_buffers()
+
+ enew
+ let l:file_name = tempname()
+ call writefile([], l:file_name)
+ let l:file_buffer = bufnr()
+
+ enew
+ file other
+ let l:other_buffer = bufnr()
+
+ set winfixbuf
+
+ call setline(1, l:file_name)
+ let l:current_windows = s:get_windows_count()
+ execute "normal \<C-w>f"
+
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+
+ call delete(l:file_name)
+endfunc
+
+" Fail :djump but :djump! is allowed
+func Test_djump()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("djump 1 /min/", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ djump! 1 /min/
+ call assert_notequal(l:current, bufnr())
+
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail :drop but :drop! is allowed
+func Test_drop()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("drop other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ drop! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :edit but :edit! is allowed
+func Test_edit()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("edit other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ edit! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :enew but :enew! is allowed
+func Test_enew()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("enew", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ enew!
+ call assert_notequal(l:other, bufnr())
+ call assert_notequal(3, bufnr())
+endfunc
+
+" Fail :ex but :ex! is allowed
+func Test_ex()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("ex other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ ex! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :find but :find! is allowed
+func Test_find()
+ call s:reset_all_buffers()
+
+ let l:current = bufnr()
+ let l:file = tempname()
+ call writefile([], l:file)
+ let l:file = fnamemodify(l:file, ':p') " In case it's Windows 8.3-style.
+ let l:directory = fnamemodify(l:file, ":p:h")
+ let l:name = fnamemodify(l:file, ":p:t")
+
+ let l:original_path = &path
+ execute "set path=" . l:directory
+
+ set winfixbuf
+
+ call assert_fails("execute 'find " . l:name . "'", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ execute "find! " . l:name
+ call assert_equal(l:file, expand("%:p"))
+
+ execute "set path=" . l:original_path
+ call delete(l:file)
+endfunc
+
+" Fail :first but :first! is allowed
+func Test_first()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("first", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ first!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :grep but :grep! is allowed
+func Test_grep()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:first = bufnr()
+
+ edit current.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ set winfixbuf
+
+ buffer! current.unittest
+
+ call assert_fails("silent! grep some-search-term *.unittest", "E1513:")
+ call assert_equal(l:current, bufnr())
+ execute "edit! " . l:first
+
+ silent! grep! some-search-term *.unittest
+ call assert_notequal(l:first, bufnr())
+
+ call delete("first.unittest")
+ call delete("current.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :ijump but :ijump! is allowed
+func Test_ijump()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile([
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ set define=^\\s*#\\s*define
+ set include=^\\s*#\\s*include
+ set path=.,/usr/include,,
+
+ call assert_fails("ijump /min/", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ ijump! /min/
+ call assert_notequal(l:current, bufnr())
+
+ set define&
+ set include&
+ set path&
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail :lNext but :lNext! is allowed
+func Test_lNext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, _] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ call assert_fails("lNext", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lnext!
+ call assert_equal(3, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lNext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lNext!
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :lNfile but :lNfile! is allowed
+func Test_lNfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:current, _] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ call assert_fails("lNfile", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ lnext!
+ call assert_equal(3, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ lNfile!
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Allow :laddexpr because it doesn't change the current buffer
+func Test_laddexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ execute 'laddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")'
+ call assert_equal(l:current, bufnr())
+
+ call delete(l:file_path)
+endfunc
+
+" Fail :last but :last! is allowed
+func Test_last()
+ call s:reset_all_buffers()
+
+ let [_, l:last] = s:make_args_list()
+ next!
+
+ call assert_fails("last", "E1513:")
+ call assert_notequal(l:last, bufnr())
+
+ last!
+ call assert_equal(l:last, bufnr())
+endfunc
+
+" Fail :lbuffer but :lbuffer! is allowed
+func Test_lbuffer()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file_path = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path)
+ execute "edit " . l:file_path
+ let l:file_buffer = bufnr()
+ let l:current = bufnr()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+
+ edit! other.unittest
+
+ set winfixbuf
+
+ execute "buffer! " . l:file_buffer
+
+ call assert_fails("lbuffer " . l:file_buffer)
+ call assert_equal(l:current, bufnr())
+
+ execute "lbuffer! " . l:file_buffer
+ call assert_equal("first.unittest", expand("%:t"))
+
+ call delete(l:file_path)
+endfunc
+
+" Fail :ldo but :ldo! is allowed
+func Test_ldo()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails('execute "ldo buffer ' . l:first . '"', "E1513:")
+ call assert_equal(l:middle, bufnr())
+ execute "ldo! buffer " . l:first
+ call assert_notequal(l:last, bufnr())
+endfunc
+
+" Fail :lfdo but :lfdo! is allowed
+func Test_lexpr()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ let l:entry = '["' . l:file . ':1:bar"]'
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("lexpr " . l:entry)
+ call assert_equal(l:current, bufnr())
+
+ execute "lexpr! " . l:entry
+ call assert_equal(fnamemodify(l:file, ":t"), expand("%:t"))
+endfunc
+
+" Fail :lfdo but :lfdo! is allowed
+func Test_lfdo()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails('execute "lfdo buffer ' . l:first . '"', "E1513:")
+ call assert_equal(l:middle, bufnr())
+ execute "lfdo! buffer " . l:first
+ call assert_notequal(l:last, bufnr())
+endfunc
+
+" Fail :lfile but :lfile! is allowed
+func Test_lfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term bad-thing-found"])
+ write
+ let l:first = bufnr()
+
+ edit! second.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ let l:file = tempname()
+ call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file)
+
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails(":lfile " . l:file)
+ call assert_equal(l:current, bufnr())
+
+ execute ":lfile! " . l:file
+ call assert_equal(l:first, bufnr())
+
+ call delete(l:file)
+ call delete("first.unittest")
+ call delete("second.unittest")
+endfunc
+
+" Fail :ll but :ll! is allowed
+func Test_ll()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ lopen
+ lfirst!
+ execute "normal \<C-w>j"
+ normal j
+
+ call assert_fails(".ll", "E1513:")
+ execute "normal \<C-w>k"
+ call assert_equal(l:first, bufnr())
+ execute "normal \<C-w>j"
+ .ll!
+ execute "normal \<C-w>k"
+ call assert_equal(l:middle, bufnr())
+endfunc
+
+" Fail :llast but :llast! is allowed
+func Test_llast()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, _, l:last] = s:make_simple_location_list()
+ lfirst!
+
+ call assert_fails("llast", "E1513:")
+ call assert_equal(l:first, bufnr())
+
+ llast!
+ call assert_equal(l:last, bufnr())
+endfunc
+
+" Fail :lnext but :lnext! is allowed
+func Test_lnext()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, l:last] = s:make_simple_location_list()
+ ll!
+
+ call assert_fails("lnext", "E1513:")
+ call assert_equal(l:first, bufnr())
+
+ lnext!
+ call assert_equal(l:middle, bufnr())
+endfunc
+
+" Fail :lnfile but :lnfile! is allowed
+func Test_lnfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [_, l:current, l:last] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ call assert_fails("lnfile", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:current, bufnr())
+
+ lnfile!
+ call assert_equal(4, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:last, bufnr())
+endfunc
+
+" Fail :lpfile but :lpfile! is allowed
+func Test_lpfile()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:current, _] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails("lpfile", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ lnext! " Reset for the next test call
+
+ lpfile!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :lprevious but :lprevious! is allowed
+func Test_lprevious()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, _] = s:make_simple_location_list()
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+
+ lnext!
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ call assert_fails("lprevious", "E1513:")
+ " Ensure the entry didn't change.
+ call assert_equal(2, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:middle, bufnr())
+
+ lprevious!
+ call assert_equal(1, getloclist(0, #{idx: 0}).idx)
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :lrewind but :lrewind! is allowed
+func Test_lrewind()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ let [l:first, l:middle, _] = s:make_simple_location_list()
+ lnext!
+
+ call assert_fails("lrewind", "E1513:")
+ call assert_equal(l:middle, bufnr())
+
+ lrewind!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail :ltag but :ltag! is allowed
+func Test_ltag()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("ltag one", "E1513:")
+
+ ltag! one
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail vim.cmd if we try to change buffers while 'winfixbuf' is set
+func Test_lua_command()
+ " CheckFeature lua
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let l:previous = bufnr()
+
+ enew
+ file second
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails('lua vim.cmd("buffer " .. ' . l:previous . ')')
+ call assert_equal(l:current, bufnr())
+
+ execute 'lua vim.cmd("buffer! " .. ' . l:previous . ')'
+ call assert_equal(l:previous, bufnr())
+endfunc
+
+" Fail :lvimgrep but :lvimgrep! is allowed
+func Test_lvimgrep()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("lvimgrep /some-search-term/ *.unittest", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ lvimgrep! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :lvimgrepadd but :lvimgrepadd! is allowed
+func Test_lvimgrepadd()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("lvimgrepadd /some-search-term/ *.unittest")
+ call assert_equal(l:current, bufnr())
+
+ lvimgrepadd! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Don't allow global marks to change the current 'winfixbuf' window
+func Test_marks_mappings_fail()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+ execute "buffer! " . l:other
+ normal mA
+ execute "buffer! " . l:current
+ normal mB
+
+ call assert_fails("normal `A", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ call assert_fails("normal 'A", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ normal `A
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Allow global marks in a 'winfixbuf' window if the jump is the same buffer
+func Test_marks_mappings_pass_intra_move()
+ call s:reset_all_buffers()
+
+ let l:current = bufnr()
+ call append(0, ["some line", "another line"])
+ normal mA
+ normal j
+ normal mB
+
+ set winfixbuf
+
+ normal `A
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail :next but :next! is allowed
+func Test_next()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ first!
+
+ call assert_fails("next", "E1513:")
+ call assert_equal(l:first, bufnr())
+
+ next!
+ call assert_notequal(l:first, bufnr())
+endfunc
+
+" Ensure :mksession saves 'winfixbuf' details
+func Test_mksession()
+ CheckFeature mksession
+ call s:reset_all_buffers()
+
+ set sessionoptions+=options
+ set winfixbuf
+
+ mksession test_winfixbuf_Test_mksession.vim
+
+ call s:reset_all_buffers()
+ let l:winfixbuf = &winfixbuf
+ call assert_equal(0, l:winfixbuf)
+
+ source test_winfixbuf_Test_mksession.vim
+
+ let l:winfixbuf = &winfixbuf
+ call assert_equal(1, l:winfixbuf)
+
+ set sessionoptions&
+ call delete("test_winfixbuf_Test_mksession.vim")
+endfunc
+
+" Allow :next if the next index is the same as the current buffer
+func Test_next_same_buffer()
+ call s:reset_all_buffers()
+
+ enew
+ file foo
+ enew
+ file bar
+ enew
+ file fizz
+ enew
+ file buzz
+ args foo foo bar fizz buzz
+
+ edit foo
+ set winfixbuf
+ let l:current = bufnr()
+
+ " Allow :next because the args list is `[foo] foo bar fizz buzz
+ next
+ call assert_equal(l:current, bufnr())
+
+ " Fail :next because the args list is `foo [foo] bar fizz buzz
+ " and the next buffer would be bar, which is a different buffer
+ call assert_fails("next", "E1513:")
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail to jump to a tag with g<C-]> if 'winfixbuf' is enabled
+func Test_normal_g_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal g\<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with g<RightMouse> if 'winfixbuf' is enabled
+func Test_normal_g_rightmouse()
+ call s:reset_all_buffers()
+ set mouse=n
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal g\<RightMouse>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ set mouse&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with g] if 'winfixbuf' is enabled
+func Test_normal_g_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal g]", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with <C-RightMouse> if 'winfixbuf' is enabled
+func Test_normal_ctrl_rightmouse()
+ call s:reset_all_buffers()
+ set mouse=n
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-RightMouse>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ set mouse&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with <C-t> if 'winfixbuf' is enabled
+func Test_normal_ctrl_t()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+ execute "normal \<C-]>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-t>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Disallow <C-^> in 'winfixbuf' windows
+func Test_normal_ctrl_hat()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal \<C-^>", "E1513:")
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow <C-i> in 'winfixbuf' windows if the movement stays within the buffer
+func Test_normal_ctrl_i_pass()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew!
+ file current
+ let l:current = bufnr()
+ " Add some lines so we can populate a jumplist"
+ call append(0, ["some line", "another line"])
+ " Add an entry to the jump list
+ " Go up another line
+ normal m`
+ normal k
+ execute "normal \<C-o>"
+
+ set winfixbuf
+
+ let l:line = getcurpos()[1]
+ execute "normal 1\<C-i>"
+ call assert_notequal(l:line, getcurpos()[1])
+endfunc
+
+" Disallow <C-o> in 'winfixbuf' windows if it would cause the buffer to switch
+func Test_normal_ctrl_o_fail()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal \<C-o>", "E1513:")
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Allow <C-o> in 'winfixbuf' windows if the movement stays within the buffer
+func Test_normal_ctrl_o_pass()
+ call s:reset_all_buffers()
+ clearjumps
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew!
+ file current
+ let l:current = bufnr()
+ " Add some lines so we can populate a jumplist
+ call append(0, ["some line", "another line"])
+ " Add an entry to the jump list
+ " Go up another line
+ normal m`
+ normal k
+
+ set winfixbuf
+
+ execute "normal \<C-o>"
+ call assert_equal(l:current, bufnr())
+endfunc
+
+" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled
+func Test_normal_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Allow <C-w><C-]> with 'winfixbuf' enabled because it runs in a new, split window
+func Test_normal_ctrl_w_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current_windows = s:get_windows_count()
+ execute "normal \<C-w>\<C-]>"
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Allow <C-w>g<C-]> with 'winfixbuf' enabled because it runs in a new, split window
+func Test_normal_ctrl_w_g_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current_windows = s:get_windows_count()
+ execute "normal \<C-w>g\<C-]>"
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled
+func Test_normal_gt()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one", "two", "three"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal \<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Prevent gF from switching a 'winfixbuf' window's buffer
+func Test_normal_gF()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gF, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal gF", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal gF
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Prevent gf from switching a 'winfixbuf' window's buffer
+func Test_normal_gf()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gf, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal gf", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal gf
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Fail "goto file under the cursor" (using [f, which is the same as `:normal gf`)
+func Test_normal_square_bracket_left_f()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gf, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal [f", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal [f
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Fail to go to a C macro with [<C-d> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_left_ctrl_d()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+ normal ]\<C-d>
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal [\<C-d>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ execute "normal [\<C-d>"
+ call assert_notequal(l:current, bufnr())
+
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail to go to a C macro with ]<C-d> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_right_ctrl_d()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal ]\<C-d>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ execute "normal ]\<C-d>"
+ call assert_notequal(l:current, bufnr())
+
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail to go to a C macro with [<C-i> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_left_ctrl_i()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(['#include "' . l:include_file . '"',
+ \ "min(1, 12);",
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+ " Move to the line with `min(1, 12);` on it"
+ normal j
+
+ set define=^\\s*#\\s*define
+ set include=^\\s*#\\s*include
+ set path=.,/usr/include,,
+
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal [\<C-i>", "E1513:")
+
+ set nowinfixbuf
+
+ execute "normal [\<C-i>"
+ call assert_notequal(l:current, bufnr())
+
+ set define&
+ set include&
+ set path&
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail to go to a C macro with ]<C-i> if 'winfixbuf' is enabled
+func Test_normal_square_bracket_right_ctrl_i()
+ call s:reset_all_buffers()
+
+ let l:include_file = tempname() . ".h"
+ call writefile(["min(1, 12);",
+ \ '#include "' . l:include_file . '"'
+ \ ],
+ \ "main.c")
+ call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file)
+ edit main.c
+
+ set winfixbuf
+
+ set define=^\\s*#\\s*define
+ set include=^\\s*#\\s*include
+ set path=.,/usr/include,,
+
+ let l:current = bufnr()
+
+ call assert_fails("normal ]\<C-i>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set nowinfixbuf
+
+ execute "normal ]\<C-i>"
+ call assert_notequal(l:current, bufnr())
+
+ set define&
+ set include&
+ set path&
+ call delete("main.c")
+ call delete(l:include_file)
+endfunc
+
+" Fail "goto file under the cursor" (using ]f, which is the same as `:normal gf`)
+func Test_normal_square_bracket_right_f()
+ call s:reset_all_buffers()
+
+ let l:file = tempname()
+ call append(0, [l:file])
+ call writefile([], l:file)
+ " Place the cursor onto the line that has `l:file`
+ normal gg
+ " Prevent Vim from erroring with "No write since last change @ command
+ " line" when we try to call gf, later.
+ set hidden
+
+ set winfixbuf
+
+ let l:buffer = bufnr()
+
+ call assert_fails("normal ]f", "E1513:")
+ call assert_equal(l:buffer, bufnr())
+
+ set nowinfixbuf
+
+ normal ]f
+ call assert_notequal(l:buffer, bufnr())
+
+ call delete(l:file)
+endfunc
+
+" Fail to jump to a tag with v<C-]> if 'winfixbuf' is enabled
+func Test_normal_v_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal v\<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail to jump to a tag with vg<C-]> if 'winfixbuf' is enabled
+func Test_normal_v_g_ctrl_square_bracket_right()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("normal vg\<C-]>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Allow :pedit because, unlike :edit, it uses a separate window
+func Test_pedit()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+
+ pedit other
+
+ execute "normal \<C-w>w"
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :pop but :pop! is allowed
+func Test_pop()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("pop", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ pop!
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :previous but :previous! is allowed
+func Test_previous()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("previous", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ previous!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Fail pyxdo if it changes a window with 'winfixbuf' is set
+func Test_pythonx_pyxdo()
+ CheckFeature pythonx
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let g:_previous_buffer = bufnr()
+
+ enew
+ file second
+
+ set winfixbuf
+
+ pythonx << EOF
+import vim
+
+def test_winfixbuf_Test_pythonx_pyxdo_set_buffer():
+ buffer = vim.vars['_previous_buffer']
+ vim.current.buffer = vim.buffers[buffer]
+EOF
+
+ try
+ pyxdo test_winfixbuf_Test_pythonx_pyxdo_set_buffer()
+ catch /pynvim\.api\.common\.NvimError: E1513: Cannot edit buffer\. 'winfixbuf' is enabled/
+ let l:caught = 1
+ endtry
+
+ call assert_equal(1, l:caught)
+
+ unlet g:_previous_buffer
+endfunc
+
+" Fail pyxfile if it changes a window with 'winfixbuf' is set
+func Test_pythonx_pyxfile()
+ CheckFeature pythonx
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let g:_previous_buffer = bufnr()
+
+ enew
+ file second
+
+ set winfixbuf
+
+ call writefile(["import vim",
+ \ "buffer = vim.vars['_previous_buffer']",
+ \ "vim.current.buffer = vim.buffers[buffer]",
+ \ ],
+ \ "file.py")
+
+ try
+ pyxfile file.py
+ catch /pynvim\.api\.common\.NvimError: E1513: Cannot edit buffer\. 'winfixbuf' is enabled/
+ let l:caught = 1
+ endtry
+
+ call assert_equal(1, l:caught)
+
+ call delete("file.py")
+ unlet g:_previous_buffer
+endfunc
+
+" Fail vim.current.buffer if 'winfixbuf' is set
+func Test_pythonx_vim_current_buffer()
+ CheckFeature pythonx
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let g:_previous_buffer = bufnr()
+
+ enew
+ file second
+
+ let l:caught = 0
+
+ set winfixbuf
+
+ try
+ pythonx << EOF
+import vim
+
+buffer = vim.vars["_previous_buffer"]
+vim.current.buffer = vim.buffers[buffer]
+EOF
+ catch /pynvim\.api\.common\.NvimError: E1513: Cannot edit buffer\. 'winfixbuf' is enabled/
+ let l:caught = 1
+ endtry
+
+ call assert_equal(1, l:caught)
+ unlet g:_previous_buffer
+endfunc
+
+" Ensure remapping to a disabled action still triggers failures
+func Test_remap_key_fail()
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ nnoremap g <C-^>
+
+ call assert_fails("normal g", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ nunmap g
+endfunc
+
+" Ensure remapping a disabled key to something valid does trigger any failures
+func Test_remap_key_pass()
+ call s:reset_all_buffers()
+
+ enew
+ file first
+ let l:first = bufnr()
+
+ enew
+ file current
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ call assert_fails("normal \<C-^>", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ " Disallow <C-^> by default but allow it if the command does something else
+ nnoremap <C-^> :echo "hello!"
+
+ execute "normal \<C-^>"
+ call assert_equal(l:current, bufnr())
+
+ nunmap <C-^>
+endfunc
+
+" Fail :rewind but :rewind! is allowed
+func Test_rewind()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("rewind", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ rewind!
+ call assert_equal(l:first, bufnr())
+endfunc
+
+" Allow :sblast because it opens the buffer in a new, split window
+func Test_sblast()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs(1)
+ bfirst!
+ let l:current = bufnr()
+
+ sblast
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :sbprevious but :sbprevious! is allowed
+func Test_sbprevious()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ sbprevious
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Make sure 'winfixbuf' can be set using 'winfixbuf' or 'wfb'
+func Test_short_option()
+ call s:reset_all_buffers()
+
+ call s:make_buffer_pairs()
+
+ set winfixbuf
+ call assert_fails("edit something_else", "E1513")
+
+ set nowinfixbuf
+ set wfb
+ call assert_fails("edit another_place", "E1513")
+
+ set nowfb
+ edit last_place
+endfunc
+
+" Allow :snext because it makes a new window
+func Test_snext()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ first!
+
+ let l:current_window = win_getid()
+
+ snext
+ call assert_notequal(l:current_window, win_getid())
+ call assert_notequal(l:first, bufnr())
+endfunc
+
+" Ensure the first has 'winfixbuf' and a new split window is 'nowinfixbuf'
+func Test_split_window()
+ call s:reset_all_buffers()
+
+ split
+ execute "normal \<C-w>j"
+
+ set winfixbuf
+
+ let l:winfix_window_1 = win_getid()
+ vsplit
+ let l:winfix_window_2 = win_getid()
+
+ call assert_equal(1, getwinvar(l:winfix_window_1, "&winfixbuf"))
+ call assert_equal(0, getwinvar(l:winfix_window_2, "&winfixbuf"))
+endfunc
+
+" Fail :tNext but :tNext! is allowed
+func Test_tNext()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+ execute "normal \<C-^>"
+ tnext!
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tNext", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tNext!
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Call :tabdo and choose the next available 'nowinfixbuf' window.
+func Test_tabdo_choose_available_window()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+
+ " Make a split window that is 'nowinfixbuf' but make it the second-to-last
+ " window so that :tabdo will first try the 'winfixbuf' window, pass over it,
+ " and prefer the other 'nowinfixbuf' window, instead.
+ "
+ " +-------------------+
+ " | 'nowinfixbuf' |
+ " +-------------------+
+ " | 'winfixbuf' | <-- Cursor is here
+ " +-------------------+
+ split
+ let l:nowinfixbuf_window = win_getid()
+ " Move to the 'winfixbuf' window now
+ execute "normal \<C-w>j"
+ let l:winfixbuf_window = win_getid()
+
+ let l:expected_windows = s:get_windows_count()
+ tabdo echo ''
+ call assert_equal(l:nowinfixbuf_window, win_getid())
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:expected_windows, s:get_windows_count())
+endfunc
+
+" Call :tabdo and create a new split window if all available windows are 'winfixbuf'.
+func Test_tabdo_make_new_window()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_buffers_list()
+ execute "buffer! " . l:first
+
+ let l:current = win_getid()
+ let l:current_windows = s:get_windows_count()
+
+ tabdo echo ''
+ call assert_notequal(l:current, win_getid())
+ call assert_equal(l:first, bufnr())
+ execute "normal \<C-w>j"
+ call assert_equal(l:first, bufnr())
+ call assert_equal(l:current_windows + 1, s:get_windows_count())
+endfunc
+
+" Fail :tag but :tag! is allowed
+func Test_tag()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tag one", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tag! one
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+
+" Fail :tfirst but :tfirst! is allowed
+func Test_tfirst()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tfirst", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tfirst!
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :tjump but :tjump! is allowed
+func Test_tjump()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ call writefile(["one"], "Xother")
+ edit Xother
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tjump one", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tjump! one
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :tlast but :tlast! is allowed
+func Test_tlast()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "one\tXfile\t1",
+ \ "three\tXfile\t3",
+ \ "two\tXfile\t2"],
+ \ "Xtags")
+ call writefile(["one", "two", "three"], "Xfile")
+ edit Xfile
+ tjump one
+ edit Xfile
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tlast", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tlast!
+ call assert_equal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+endfunc
+
+" Fail :tnext but :tnext! is allowed
+func Test_tnext()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+ execute "normal \<C-^>"
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tnext", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tnext!
+ call assert_notequal(l:current, bufnr())
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :tprevious but :tprevious! is allowed
+func Test_tprevious()
+ call s:reset_all_buffers()
+
+ set tags=Xtags
+ call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
+ \ "thesame\tXfile\t1;\"\td\tfile:",
+ \ "thesame\tXfile\t2;\"\td\tfile:",
+ \ "thesame\tXfile\t3;\"\td\tfile:",
+ \ ],
+ \ "Xtags")
+ call writefile(["thesame one", "thesame two", "thesame three"], "Xfile")
+ call writefile(["thesame one"], "Xother")
+ edit Xother
+
+ tag thesame
+ execute "normal \<C-^>"
+ tnext!
+
+ set winfixbuf
+
+ let l:current = bufnr()
+
+ call assert_fails("tprevious", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ tprevious!
+
+ set tags&
+ call delete("Xtags")
+ call delete("Xfile")
+ call delete("Xother")
+endfunc
+
+" Fail :view but :view! is allowed
+func Test_view()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("view other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ view! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :visual but :visual! is allowed
+func Test_visual()
+ call s:reset_all_buffers()
+
+ let l:other = s:make_buffer_pairs()
+ let l:current = bufnr()
+
+ call assert_fails("visual other", "E1513:")
+ call assert_equal(l:current, bufnr())
+
+ visual! other
+ call assert_equal(l:other, bufnr())
+endfunc
+
+" Fail :vimgrep but :vimgrep! is allowed
+func Test_vimgrep()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("vimgrep /some-search-term/ *.unittest")
+ call assert_equal(l:current, bufnr())
+
+ " Don't error and also do swap to the first match because ! was included
+ vimgrep! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :vimgrepadd but ::vimgrepadd! is allowed
+func Test_vimgrepadd()
+ CheckFeature quickfix
+ call s:reset_all_buffers()
+
+ edit first.unittest
+ call append(0, ["some-search-term"])
+ write
+
+ edit winfix.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:current = bufnr()
+
+ set winfixbuf
+
+ edit! last.unittest
+ call append(0, ["some-search-term"])
+ write
+ let l:last = bufnr()
+
+ buffer! winfix.unittest
+
+ call assert_fails("vimgrepadd /some-search-term/ *.unittest")
+ call assert_equal(l:current, bufnr())
+
+ vimgrepadd! /some-search-term/ *.unittest
+ call assert_notequal(l:current, bufnr())
+ call delete("first.unittest")
+ call delete("winfix.unittest")
+ call delete("last.unittest")
+endfunc
+
+" Fail :wNext but :wNext! is allowed
+func Test_wNext()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("wNext", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ wNext!
+ call assert_equal(l:first, bufnr())
+
+ call delete("first")
+ call delete("middle")
+ call delete("last")
+endfunc
+
+" Allow :windo unless `:windo foo` would change a 'winfixbuf' window's buffer
+func Test_windo()
+ call s:reset_all_buffers()
+
+ let l:current_window = win_getid()
+ let l:current_buffer = bufnr()
+ split
+ enew
+ file some_other_buffer
+
+ set winfixbuf
+
+ let l:current = win_getid()
+
+ windo echo ''
+ call assert_equal(l:current_window, win_getid())
+
+ call assert_fails('execute "windo buffer ' . l:current_buffer . '"', "E1513:")
+ call assert_equal(l:current_window, win_getid())
+
+ execute "windo buffer! " . l:current_buffer
+ call assert_equal(l:current_window, win_getid())
+endfunc
+
+" Fail :wnext but :wnext! is allowed
+func Test_wnext()
+ call s:reset_all_buffers()
+
+ let [_, l:last] = s:make_args_list()
+ next!
+
+ call assert_fails("wnext", "E1513:")
+ call assert_notequal(l:last, bufnr())
+
+ wnext!
+ call assert_equal(l:last, bufnr())
+
+ call delete("first")
+ call delete("middle")
+ call delete("last")
+endfunc
+
+" Fail :wprevious but :wprevious! is allowed
+func Test_wprevious()
+ call s:reset_all_buffers()
+
+ let [l:first, _] = s:make_args_list()
+ next!
+
+ call assert_fails("wprevious", "E1513:")
+ call assert_notequal(l:first, bufnr())
+
+ wprevious!
+ call assert_equal(l:first, bufnr())
+
+ call delete("first")
+ call delete("middle")
+ call delete("last")
+endfunc
+
+func Test_quickfix_switchbuf_invalid_prevwin()
+ call s:reset_all_buffers()
+
+ call s:make_simple_quickfix()
+ call assert_equal(1, getqflist(#{idx: 0}).idx)
+
+ set switchbuf=uselast
+ split
+ copen
+ execute winnr('#') 'quit'
+ call assert_equal(2, winnr('$'))
+
+ cnext " Would've triggered a null pointer member access
+ call assert_equal(2, getqflist(#{idx: 0}).idx)
+
+ set switchbuf&
+endfunc
+
+func Test_listdo_goto_prevwin()
+ call s:reset_all_buffers()
+ call s:make_buffers_list()
+
+ new
+ call assert_equal(0, &winfixbuf)
+ wincmd p
+ call assert_equal(1, &winfixbuf)
+ call assert_notequal(bufnr(), bufnr('#'))
+
+ augroup ListDoGotoPrevwin
+ au!
+ au BufLeave * let s:triggered = 1
+ \| call assert_equal(bufnr(), winbufnr(winnr()))
+ augroup END
+ " Should correctly switch to the window without 'winfixbuf', and curbuf should
+ " be consistent with curwin->w_buffer for autocommands.
+ bufdo "
+ call assert_equal(0, &winfixbuf)
+ call assert_equal(1, s:triggered)
+ unlet! s:triggered
+ au! ListDoGotoPrevwin
+
+ set winfixbuf
+ wincmd p
+ call assert_equal(2, winnr('$'))
+ " Both curwin and prevwin have 'winfixbuf' set, so should split a new window
+ " without it set.
+ bufdo "
+ call assert_equal(0, &winfixbuf)
+ call assert_equal(3, winnr('$'))
+
+ quit
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, &winfixbuf)
+ augroup ListDoGotoPrevwin
+ au!
+ au WinEnter * ++once set winfixbuf
+ augroup END
+ " Same as before, but naughty autocommands set 'winfixbuf' for the new window.
+ " :bufdo should give up in this case.
+ call assert_fails('bufdo "', 'E1513:')
+
+ au! ListDoGotoPrevwin
+ augroup! ListDoGotoPrevwin
+endfunc
+
+func Test_quickfix_changed_split_failed()
+ call s:reset_all_buffers()
+
+ call s:make_simple_quickfix()
+ call assert_equal(1, winnr('$'))
+
+ " Quickfix code will open a split in an attempt to get a 'nowinfixbuf' window
+ " to switch buffers in. Interfere with things by setting 'winfixbuf' in it.
+ augroup QfChanged
+ au!
+ au WinEnter * ++once call assert_equal(2, winnr('$'))
+ \| set winfixbuf | call setqflist([], 'f')
+ augroup END
+ call assert_fails('cnext', ['E1513:', 'E925:'])
+ " Check that the split was automatically closed.
+ call assert_equal(1, winnr('$'))
+
+ au! QfChanged
+ augroup! QfChanged
+endfunc
+
+func Test_bufdo_cnext_splitwin_fails()
+ call s:reset_all_buffers()
+ call s:make_simple_quickfix()
+ call assert_equal(1, getqflist(#{idx: 0}).idx)
+ " Make sure there is not enough room to
+ " split the winfixedbuf window
+ let &winheight=&lines
+ let &winminheight=&lines-2
+ " Still want E1513, or it may not be clear why a split was attempted and why
+ " it failing caused the commands to abort.
+ call assert_fails(':bufdo echo 1', ['E36:', 'E1513:'])
+ call assert_fails(':cnext', ['E36:', 'E1513:'])
+ " Ensure the entry didn't change.
+ call assert_equal(1, getqflist(#{idx: 0}).idx)
+ set winminheight&vim winheight&vim
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/unit/msgpack_spec.lua b/test/unit/msgpack_spec.lua
index bd663a3c75..f9fde00a85 100644
--- a/test/unit/msgpack_spec.lua
+++ b/test/unit/msgpack_spec.lua
@@ -51,11 +51,11 @@ describe('msgpack', function()
unpacker_goto(unpacker, payload, payload:len() - 1)
local finished = unpacker_advance(unpacker)
- eq(finished, false)
+ eq(false, finished)
unpacker[0].read_size = unpacker[0].read_size + 1
finished = unpacker_advance(unpacker)
- eq(finished, true)
+ eq(true, finished)
end
)
@@ -73,7 +73,7 @@ describe('msgpack', function()
'\x93\x02\xa6\x72\x65\x64\x72\x61\x77\x91\x92\xa9\x67\x72\x69\x64\x5f\x6c\x69\x6e\x65\x95\x02\x00\x00\x90\xc2'
)
local finished = unpacker_advance(unpacker)
- eq(finished, true)
+ eq(true, finished)
end)
end)
end)
diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua
index 2c638fcb37..310201b8c3 100644
--- a/test/unit/os/env_spec.lua
+++ b/test/unit/os/env_spec.lua
@@ -306,9 +306,9 @@ describe('env.c', function()
-- expand_env_esc SHOULD NOT expand the variable if there is not enough space to
-- contain the result
for i = 0, 3 do
- eq(output[i], input[i])
+ eq(input[i], output[i])
end
- eq(output[4], 0)
+ eq(0, output[4])
end)
end)
end)
diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua
index ae162f2317..05f965585a 100644
--- a/test/unit/os/shell_spec.lua
+++ b/test/unit/os/shell_spec.lua
@@ -125,9 +125,9 @@ describe('shell functions', function()
cimported.p_sxe = to_cstr('"&|<>()@^')
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
- eq(ffi.string(argv[0]), '/bin/sh')
- eq(ffi.string(argv[1]), '-c')
- eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
+ eq('/bin/sh', ffi.string(argv[0]))
+ eq('-c', ffi.string(argv[1]))
+ eq('(echo ^&^|^<^>^(^)^@^^)', ffi.string(argv[2]))
eq(nil, argv[3])
end)
@@ -136,9 +136,9 @@ describe('shell functions', function()
cimported.p_sxe = to_cstr('"&|<>()@^')
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
- eq(ffi.string(argv[0]), '/bin/sh')
- eq(ffi.string(argv[1]), '-c')
- eq(ffi.string(argv[2]), '"(echo -n some text)"')
+ eq('/bin/sh', ffi.string(argv[0]))
+ eq('-c', ffi.string(argv[1]))
+ eq('"(echo -n some text)"', ffi.string(argv[2]))
eq(nil, argv[3])
end)
@@ -147,17 +147,17 @@ describe('shell functions', function()
cimported.p_sxe = to_cstr('')
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
- eq(ffi.string(argv[0]), '/bin/sh')
- eq(ffi.string(argv[1]), '-c')
- eq(ffi.string(argv[2]), '"echo -n some text"')
+ eq('/bin/sh', ffi.string(argv[0]))
+ eq('-c', ffi.string(argv[1]))
+ eq('"echo -n some text"', ffi.string(argv[2]))
eq(nil, argv[3])
end)
itp('with empty shellxquote/shellxescape', function()
local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
- eq(ffi.string(argv[0]), '/bin/sh')
- eq(ffi.string(argv[1]), '-c')
- eq(ffi.string(argv[2]), 'echo -n some text')
+ eq('/bin/sh', ffi.string(argv[0]))
+ eq('-c', ffi.string(argv[1]))
+ eq('echo -n some text', ffi.string(argv[2]))
eq(nil, argv[3])
end)
end)
diff --git a/test/unit/profile_spec.lua b/test/unit/profile_spec.lua
index 011d3632d5..c7dc7db189 100644
--- a/test/unit/profile_spec.lua
+++ b/test/unit/profile_spec.lua
@@ -229,7 +229,7 @@ describe('profiling related functions', function()
describe('profile_msg', function()
itp('prints the zero time as 0.00000', function()
local str = trim(profile_msg(profile_zero()))
- eq(str, '0.000000')
+ eq('0.000000', str)
end)
itp('prints the time passed, in seconds.microsends', function()
@@ -245,7 +245,7 @@ describe('profiling related functions', function()
-- zero seconds have passed (if this is not true, either LuaJIT is too
-- slow or the profiling functions are too slow and need to be fixed)
- eq(s, '0')
+ eq('0', s)
-- more or less the same goes for the microsecond part, if it doesn't
-- start with 0, it's too slow.
diff --git a/test/unit/tempfile_spec.lua b/test/unit/tempfile_spec.lua
index e35490a561..bb0e56d640 100644
--- a/test/unit/tempfile_spec.lua
+++ b/test/unit/tempfile_spec.lua
@@ -28,7 +28,7 @@ describe('tempfile related functions', function()
assert.True(dir ~= nil and dir:len() > 0)
-- os_file_is_writable returns 2 for a directory which we have rights
-- to write into.
- eq(lib.os_file_is_writable(helpers.to_cstr(dir)), 2)
+ eq(2, lib.os_file_is_writable(helpers.to_cstr(dir)))
for entry in vim.fs.dir(dir) do
assert.True(entry == '.' or entry == '..')
end
@@ -57,7 +57,7 @@ describe('tempfile related functions', function()
itp('generate file name in Nvim own temp directory', function()
local dir = vim_gettempdir()
local file = vim_tempname()
- eq(string.sub(file, 1, string.len(dir)), dir)
+ eq(dir, string.sub(file, 1, string.len(dir)))
end)
end)
end)