mirror of
https://github.com/neovim/neovim.git
synced 2024-12-25 21:55:17 -07:00
f8795365de
Problem: `vim._with()` has many different use cases which are not covered with tests. Solution: cover with tests. Some (many) test cases are intentionally marked as "pending" because they cover cases which don't work as expected at the moment (and fixing them requires specific knowledge of C codebase). Use them as a reference for future fixes. Also some of "can be nested" tests currently might pass only because the tested context doesn't work.
877 lines
26 KiB
Lua
877 lines
26 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
local fn = n.fn
|
|
local api = n.api
|
|
local command = n.command
|
|
local eq = t.eq
|
|
local exec_lua = n.exec_lua
|
|
local exec_capture = n.exec_capture
|
|
local matches = t.matches
|
|
local pcall_err = t.pcall_err
|
|
|
|
describe('vim._with', function()
|
|
before_each(function()
|
|
n.clear()
|
|
exec_lua([[
|
|
_G.fn = vim.fn
|
|
_G.api = vim.api
|
|
|
|
_G.setup_buffers = function()
|
|
return api.nvim_create_buf(false, true), api.nvim_get_current_buf()
|
|
end
|
|
|
|
_G.setup_windows = function()
|
|
local other_win = api.nvim_get_current_win()
|
|
vim.cmd.new()
|
|
return other_win, api.nvim_get_current_win()
|
|
end
|
|
]])
|
|
end)
|
|
|
|
local validate_events_trigger = function()
|
|
local out = exec_lua [[
|
|
-- Needs three global values defined:
|
|
-- - `test_events` - array of events which are tested.
|
|
-- - `test_context` - context to be tested.
|
|
-- - `test_trig_event` - callable triggering at least one tested event.
|
|
_G.n_events = 0
|
|
local opts = { callback = function() _G.n_events = _G.n_events + 1 end }
|
|
api.nvim_create_autocmd(_G.test_events, opts)
|
|
|
|
local context = { bo = { commentstring = '-- %s' } }
|
|
|
|
-- Should not trigger events on its own
|
|
vim._with(_G.test_context, function() end)
|
|
local is_no_events = _G.n_events == 0
|
|
|
|
-- Should trigger events if specifically asked inside callback
|
|
local is_events = vim._with(_G.test_context, function()
|
|
_G.test_trig_event()
|
|
return _G.n_events > 0
|
|
end)
|
|
return { is_no_events, is_events }
|
|
]]
|
|
eq({ true, true }, out)
|
|
end
|
|
|
|
describe('`buf` context', function()
|
|
it('works', function()
|
|
local out = exec_lua [[
|
|
local other_buf, cur_buf = setup_buffers()
|
|
local inner = vim._with({ buf = other_buf }, function()
|
|
return api.nvim_get_current_buf()
|
|
end)
|
|
return { inner == other_buf, api.nvim_get_current_buf() == cur_buf }
|
|
]]
|
|
eq({ true, true }, out)
|
|
end)
|
|
|
|
it('does not trigger events', function()
|
|
exec_lua [[
|
|
_G.test_events = { 'BufEnter', 'BufLeave', 'BufWinEnter', 'BufWinLeave' }
|
|
_G.test_context = { buf = other_buf }
|
|
_G.test_trig_event = function() vim.cmd.new() end
|
|
]]
|
|
validate_events_trigger()
|
|
end)
|
|
|
|
it('can access buffer options', function()
|
|
local out = exec_lua [[
|
|
other_buf, cur_buf = setup_buffers()
|
|
vim.bo[other_buf].commentstring = '## %s'
|
|
vim.bo[cur_buf].commentstring = '// %s'
|
|
|
|
vim._with({ buf = other_buf }, function()
|
|
vim.cmd.set('commentstring=--\\ %s')
|
|
end)
|
|
|
|
return vim.bo[other_buf].commentstring == '-- %s' and
|
|
vim.bo[cur_buf].commentstring == '// %s'
|
|
]]
|
|
eq(true, out)
|
|
end)
|
|
|
|
it('works with different kinds of buffers', function()
|
|
exec_lua [[
|
|
local validate = function(buf)
|
|
vim._with({ buf = buf }, function()
|
|
assert(api.nvim_get_current_buf() == buf)
|
|
end)
|
|
end
|
|
|
|
-- Current
|
|
validate(api.nvim_get_current_buf())
|
|
|
|
-- Hidden listed
|
|
local listed = api.nvim_create_buf(true, true)
|
|
validate(listed)
|
|
|
|
-- Visible
|
|
local other_win, cur_win = setup_windows()
|
|
api.nvim_win_set_buf(other_win, listed)
|
|
validate(listed)
|
|
|
|
-- Shown but not visible
|
|
vim.cmd.tabnew()
|
|
validate(listed)
|
|
|
|
-- Shown in several windows
|
|
api.nvim_win_set_buf(0, listed)
|
|
validate(listed)
|
|
|
|
-- Shown in floating window
|
|
local float_buf = api.nvim_create_buf(false, true)
|
|
local config = { relative = 'editor', row = 1, col = 1, width = 5, height = 5 }
|
|
api.nvim_open_win(float_buf, false, config)
|
|
validate(float_buf)
|
|
]]
|
|
end)
|
|
|
|
it('does not cause ml_get errors with invalid visual selection', function()
|
|
exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, -1, true, { 'a', 'b', 'c' })
|
|
api.nvim_feedkeys(vim.keycode('G<C-V>'), 'txn', false)
|
|
local other_buf, _ = setup_buffers()
|
|
vim._with({ buf = buf }, function() vim.cmd.redraw() end)
|
|
]]
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
exec_lua [[
|
|
local other_buf, cur_buf = setup_buffers()
|
|
vim._with({ buf = other_buf }, function()
|
|
assert(api.nvim_get_current_buf() == other_buf)
|
|
inner = vim._with({ buf = cur_buf }, function()
|
|
assert(api.nvim_get_current_buf() == cur_buf)
|
|
end)
|
|
assert(api.nvim_get_current_buf() == other_buf)
|
|
end)
|
|
assert(api.nvim_get_current_buf() == cur_buf)
|
|
]]
|
|
end)
|
|
|
|
it('can be nested crazily with hidden buffers', function()
|
|
local out = exec_lua([[
|
|
local n = 0
|
|
local function with_recursive_nested_bufs()
|
|
n = n + 1
|
|
if n > 20 then return true end
|
|
|
|
local other_buf, _ = setup_buffers()
|
|
vim.bo[other_buf].commentstring = '## %s'
|
|
local callback = function()
|
|
return api.nvim_get_current_buf() == other_buf
|
|
and vim.bo[other_buf].commentstring == '## %s'
|
|
and with_recursive_nested_bufs()
|
|
end
|
|
return vim._with({ buf = other_buf }, callback) and
|
|
api.nvim_buf_delete(other_buf, {}) == nil
|
|
end
|
|
|
|
return with_recursive_nested_bufs()
|
|
]])
|
|
eq(true, out)
|
|
end)
|
|
end)
|
|
|
|
describe('`emsg_silent` context', function()
|
|
pending('works', function()
|
|
local ok = pcall(
|
|
exec_lua,
|
|
[[
|
|
_G.f = function()
|
|
error('This error should not interfer with execution', 0)
|
|
end
|
|
-- Should not produce error same as `vim.cmd('silent! lua _G.f()')`
|
|
vim._with({ emsg_silent = true }, f)
|
|
]]
|
|
)
|
|
eq(true, ok)
|
|
|
|
-- Should properly report errors afterwards
|
|
ok = pcall(exec_lua, 'lua _G.f()')
|
|
eq(false, ok)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local ok = pcall(
|
|
exec_lua,
|
|
[[
|
|
_G.f = function()
|
|
error('This error should not interfer with execution', 0)
|
|
end
|
|
-- Should produce error same as `_G.f()`
|
|
vim._with({ emsg_silent = true }, function()
|
|
vim._with( { emsg_silent = false }, f)
|
|
end)
|
|
]]
|
|
)
|
|
eq(false, ok)
|
|
end)
|
|
end)
|
|
|
|
describe('`hide` context', function()
|
|
pending('works', function()
|
|
local ok = pcall(
|
|
exec_lua,
|
|
[[
|
|
vim.o.hidden = false
|
|
vim.bo.modified = true
|
|
local init_buf = api.nvim_get_current_buf()
|
|
-- Should not produce error same as `vim.cmd('hide enew')`
|
|
vim._with({ hide = true }, function()
|
|
vim.cmd.enew()
|
|
end)
|
|
assert(api.nvim_get_current_buf() ~= init_buf)
|
|
]]
|
|
)
|
|
eq(true, ok)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local ok = pcall(
|
|
exec_lua,
|
|
[[
|
|
vim.o.hidden = false
|
|
vim.bo.modified = true
|
|
-- Should produce error same as `vim.cmd.enew()`
|
|
vim._with({ hide = true }, function()
|
|
vim._with({ hide = false }, function()
|
|
vim.cmd.enew()
|
|
end)
|
|
end)
|
|
]]
|
|
)
|
|
eq(false, ok)
|
|
end)
|
|
end)
|
|
|
|
describe('`horizontal` context', function()
|
|
local is_approx_eq = function(dim, id_1, id_2)
|
|
local f = dim == 'height' and api.nvim_win_get_height or api.nvim_win_get_width
|
|
return math.abs(f(id_1) - f(id_2)) <= 1
|
|
end
|
|
|
|
local win_id_1, win_id_2, win_id_3
|
|
before_each(function()
|
|
win_id_1 = api.nvim_get_current_win()
|
|
command('wincmd v | wincmd 5>')
|
|
win_id_2 = api.nvim_get_current_win()
|
|
command('wincmd s | wincmd 5+')
|
|
win_id_3 = api.nvim_get_current_win()
|
|
|
|
eq(is_approx_eq('width', win_id_1, win_id_2), false)
|
|
eq(is_approx_eq('height', win_id_3, win_id_2), false)
|
|
end)
|
|
|
|
pending('works', function()
|
|
exec_lua [[
|
|
-- Should be same as `vim.cmd('horizontal wincmd =')`
|
|
vim._with({ horizontal = true }, function()
|
|
vim.cmd.wincmd('=')
|
|
end)
|
|
]]
|
|
eq(is_approx_eq('width', win_id_1, win_id_2), true)
|
|
eq(is_approx_eq('height', win_id_3, win_id_2), false)
|
|
end)
|
|
|
|
pending('can be nested', function()
|
|
exec_lua [[
|
|
-- Should be same as `vim.cmd.wincmd('=')`
|
|
vim._with({ horizontal = true }, function()
|
|
vim._with({ horizontal = false }, function()
|
|
vim.cmd.wincmd('=')
|
|
end)
|
|
end)
|
|
]]
|
|
eq(is_approx_eq('width', win_id_1, win_id_2), true)
|
|
eq(is_approx_eq('height', win_id_3, win_id_2), true)
|
|
end)
|
|
end)
|
|
|
|
describe('`keepalt` context', function()
|
|
pending('works', function()
|
|
local out = exec_lua [[
|
|
vim.cmd('edit alt')
|
|
vim.cmd('edit new')
|
|
assert(fn.bufname('#') == 'alt')
|
|
|
|
-- Should work as `vim.cmd('keepalt edit very-new')`
|
|
vim._with({ keepalt = true }, function()
|
|
vim.cmd.edit('very-new')
|
|
end)
|
|
return fn.bufname('#') == 'alt'
|
|
]]
|
|
eq(true, out)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local out = exec_lua [[
|
|
vim.cmd('edit alt')
|
|
vim.cmd('edit new')
|
|
assert(fn.bufname('#') == 'alt')
|
|
|
|
-- Should work as `vim.cmd.edit('very-new')`
|
|
vim._with({ keepalt = true }, function()
|
|
vim._with({ keepalt = false }, function()
|
|
vim.cmd.edit('very-new')
|
|
end)
|
|
end)
|
|
return fn.bufname('#') == 'alt'
|
|
]]
|
|
eq(false, out)
|
|
end)
|
|
end)
|
|
|
|
describe('`keepjumps` context', function()
|
|
pending('works', function()
|
|
local out = exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, -1, false, { 'aaa', 'bbb', 'ccc' })
|
|
local jumplist_before = fn.getjumplist()
|
|
-- Should work as `vim.cmd('keepjumps normal! Ggg')`
|
|
vim._with({ keepjumps = true }, function()
|
|
vim.cmd('normal! Ggg')
|
|
end)
|
|
return vim.deep_equal(jumplist_before, fn.getjumplist())
|
|
]]
|
|
eq(true, out)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local out = exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, -1, false, { 'aaa', 'bbb', 'ccc' })
|
|
local jumplist_before = fn.getjumplist()
|
|
vim._with({ keepjumps = true }, function()
|
|
vim._with({ keepjumps = false }, function()
|
|
vim.cmd('normal! Ggg')
|
|
end)
|
|
end)
|
|
return vim.deep_equal(jumplist_before, fn.getjumplist())
|
|
]]
|
|
eq(false, out)
|
|
end)
|
|
end)
|
|
|
|
describe('`keepmarks` context', function()
|
|
pending('works', function()
|
|
local out = exec_lua [[
|
|
vim.cmd('set cpoptions+=R')
|
|
api.nvim_buf_set_lines(0, 0, -1, false, { 'bbb', 'ccc', 'aaa' })
|
|
api.nvim_buf_set_mark(0, 'm', 2, 2, {})
|
|
|
|
-- Should be the same as `vim.cmd('keepmarks %!sort')`
|
|
vim._with({ keepmarks = true }, function()
|
|
vim.cmd('%!sort')
|
|
end)
|
|
return api.nvim_buf_get_mark(0, 'm')
|
|
]]
|
|
eq({ 2, 2 }, out)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local out = exec_lua [[
|
|
vim.cmd('set cpoptions+=R')
|
|
api.nvim_buf_set_lines(0, 0, -1, false, { 'bbb', 'ccc', 'aaa' })
|
|
api.nvim_buf_set_mark(0, 'm', 2, 2, {})
|
|
|
|
vim._with({ keepmarks = true }, function()
|
|
vim._with({ keepmarks = false }, function()
|
|
vim.cmd('%!sort')
|
|
end)
|
|
end)
|
|
return api.nvim_buf_get_mark(0, 'm')
|
|
]]
|
|
eq({ 0, 2 }, out)
|
|
end)
|
|
end)
|
|
|
|
describe('`keepatterns` context', function()
|
|
pending('works', function()
|
|
local out = exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, -1, false, { 'aaa', 'bbb' })
|
|
vim.cmd('/aaa')
|
|
-- Should be the same as `vim.cmd('keeppatterns /bbb')`
|
|
vim._with({ keeppatterns = true }, function()
|
|
vim.cmd('/bbb')
|
|
end)
|
|
return fn.getreg('/')
|
|
]]
|
|
eq('aaa', out)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local out = exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, -1, false, { 'aaa', 'bbb' })
|
|
vim.cmd('/aaa')
|
|
vim._with({ keeppatterns = true }, function()
|
|
vim._with({ keeppatterns = false }, function()
|
|
vim.cmd('/bbb')
|
|
end)
|
|
end)
|
|
return fn.getreg('/')
|
|
]]
|
|
eq('bbb', out)
|
|
end)
|
|
end)
|
|
|
|
describe('`lockmarks` context', function()
|
|
it('works', function()
|
|
local mark = exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, 0, false, { 'aaa', 'bbb', 'ccc' })
|
|
api.nvim_buf_set_mark(0, 'm', 2, 2, {})
|
|
-- Should be same as `:lockmarks lua api.nvim_buf_set_lines(...)`
|
|
vim._with({ lockmarks = true }, function()
|
|
api.nvim_buf_set_lines(0, 0, 2, false, { 'uuu', 'vvv', 'www' })
|
|
end)
|
|
return api.nvim_buf_get_mark(0, 'm')
|
|
]]
|
|
eq({ 2, 2 }, mark)
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
local mark = exec_lua [[
|
|
api.nvim_buf_set_lines(0, 0, 0, false, { 'aaa', 'bbb', 'ccc' })
|
|
api.nvim_buf_set_mark(0, 'm', 2, 2, {})
|
|
vim._with({ lockmarks = true }, function()
|
|
vim._with({ lockmarks = false }, function()
|
|
api.nvim_buf_set_lines(0, 0, 2, false, { 'uuu', 'vvv', 'www' })
|
|
end)
|
|
end)
|
|
return api.nvim_buf_get_mark(0, 'm')
|
|
]]
|
|
eq({ 0, 2 }, mark)
|
|
end)
|
|
end)
|
|
|
|
describe('`noautocmd` context', function()
|
|
it('works', function()
|
|
local out = exec_lua [[
|
|
_G.n_events = 0
|
|
vim.cmd('au ModeChanged * lua _G.n_events = _G.n_events + 1')
|
|
-- Should be the same as `vim.cmd('noautocmd normal! vv')`
|
|
vim._with({ noautocmd = true }, function()
|
|
vim.cmd('normal! vv')
|
|
end)
|
|
return _G.n_events
|
|
]]
|
|
eq(0, out)
|
|
end)
|
|
|
|
it('works with User events', function()
|
|
local out = exec_lua [[
|
|
_G.n_events = 0
|
|
vim.cmd('au User MyEvent lua _G.n_events = _G.n_events + 1')
|
|
-- Should be the same as `vim.cmd('noautocmd doautocmd User MyEvent')`
|
|
vim._with({ noautocmd = true }, function()
|
|
api.nvim_exec_autocmds('User', { pattern = 'MyEvent' })
|
|
end)
|
|
return _G.n_events
|
|
]]
|
|
eq(0, out)
|
|
end)
|
|
|
|
pending('can be nested', function()
|
|
local out = exec_lua [[
|
|
_G.n_events = 0
|
|
vim.cmd('au ModeChanged * lua _G.n_events = _G.n_events + 1')
|
|
vim._with({ noautocmd = true }, function()
|
|
vim._with({ noautocmd = false }, function()
|
|
vim.cmd('normal! vv')
|
|
end)
|
|
end)
|
|
return _G.n_events
|
|
]]
|
|
eq(2, out)
|
|
end)
|
|
end)
|
|
|
|
describe('`sandbox` context', function()
|
|
it('works', function()
|
|
local ok, err = pcall(
|
|
exec_lua,
|
|
[[
|
|
-- Should work as `vim.cmd('sandbox call append(0, "aaa")')`
|
|
vim._with({ sandbox = true }, function()
|
|
fn.append(0, 'aaa')
|
|
end)
|
|
]]
|
|
)
|
|
eq(false, ok)
|
|
matches('Not allowed in sandbox', err)
|
|
end)
|
|
|
|
it('can NOT be nested', function()
|
|
-- This behavior is intentionally different from other flags as allowing
|
|
-- disabling `sandbox` from nested function seems to be against the point
|
|
-- of using `sandbox` context in the first place
|
|
local ok, err = pcall(
|
|
exec_lua,
|
|
[[
|
|
vim._with({ sandbox = true }, function()
|
|
vim._with({ sandbox = false }, function()
|
|
fn.append(0, 'aaa')
|
|
end)
|
|
end)
|
|
]]
|
|
)
|
|
eq(false, ok)
|
|
matches('Not allowed in sandbox', err)
|
|
end)
|
|
end)
|
|
|
|
describe('`silent` context', function()
|
|
it('works', function()
|
|
exec_lua [[
|
|
-- Should be same as `vim.cmd('silent lua print("aaa")')`
|
|
vim._with({ silent = true }, function() print('aaa') end)
|
|
]]
|
|
eq('', exec_capture('messages'))
|
|
|
|
exec_lua [[ vim._with({ silent = true }, function() vim.cmd.echomsg('"bbb"') end) ]]
|
|
eq('', exec_capture('messages'))
|
|
|
|
local screen = Screen.new(20, 5)
|
|
screen:set_default_attr_ids {
|
|
[1] = { bold = true, reverse = true },
|
|
[2] = { bold = true, foreground = Screen.colors.Blue },
|
|
}
|
|
screen:attach()
|
|
exec_lua [[ vim._with({ silent = true }, function() vim.cmd.echo('"ccc"') end) ]]
|
|
screen:expect [[
|
|
^ |
|
|
{2:~ }|*3
|
|
|
|
|
]]
|
|
end)
|
|
|
|
pending('can be nested', function()
|
|
exec_lua [[ vim._with({ silent = true }, function()
|
|
vim._with({ silent = false }, function()
|
|
print('aaa')
|
|
end)
|
|
end)]]
|
|
eq('aaa', exec_capture('messages'))
|
|
end)
|
|
end)
|
|
|
|
describe('`unsilent` context', function()
|
|
it('works', function()
|
|
exec_lua [[
|
|
_G.f = function()
|
|
-- Should be same as `vim.cmd('unsilent lua print("aaa")')`
|
|
vim._with({ unsilent = true }, function() print('aaa') end)
|
|
end
|
|
]]
|
|
command('silent lua f()')
|
|
eq('aaa', exec_capture('messages'))
|
|
end)
|
|
|
|
pending('can be nested', function()
|
|
exec_lua [[
|
|
_G.f = function()
|
|
vim._with({ unsilent = true }, function()
|
|
vim._with({ unsilent = false }, function() print('aaa') end)
|
|
end)
|
|
end
|
|
]]
|
|
command('silent lua f()')
|
|
eq('', exec_capture('messages'))
|
|
end)
|
|
end)
|
|
|
|
describe('`win` context', function()
|
|
it('works', function()
|
|
local out = exec_lua [[
|
|
local other_win, cur_win = setup_windows()
|
|
local inner = vim._with({ win = other_win }, function()
|
|
return api.nvim_get_current_win()
|
|
end)
|
|
return { inner == other_win, api.nvim_get_current_win() == cur_win }
|
|
]]
|
|
eq({ true, true }, out)
|
|
end)
|
|
|
|
it('does not trigger events', function()
|
|
exec_lua [[
|
|
_G.test_events = { 'WinEnter', 'WinLeave', 'BufWinEnter', 'BufWinLeave' }
|
|
_G.test_context = { win = other_win }
|
|
_G.test_trig_event = function() vim.cmd.new() end
|
|
]]
|
|
validate_events_trigger()
|
|
end)
|
|
|
|
it('can access window options', function()
|
|
local out = exec_lua [[
|
|
local other_win, cur_win = setup_windows()
|
|
vim.wo[other_win].winblend = 10
|
|
vim.wo[cur_win].winblend = 25
|
|
|
|
vim._with({ win = other_win }, function()
|
|
vim.cmd.setlocal('winblend=0')
|
|
end)
|
|
|
|
return vim.wo[other_win].winblend == 0 and vim.wo[cur_win].winblend == 25
|
|
]]
|
|
eq(true, out)
|
|
end)
|
|
|
|
it('works with different kinds of windows', function()
|
|
exec_lua [[
|
|
local validate = function(win)
|
|
vim._with({ win = win }, function()
|
|
assert(api.nvim_get_current_win() == win)
|
|
end)
|
|
end
|
|
|
|
-- Current
|
|
validate(api.nvim_get_current_win())
|
|
|
|
-- Not visible
|
|
local other_win, cur_win = setup_windows()
|
|
vim.cmd.tabnew()
|
|
validate(other_win)
|
|
|
|
-- Floating
|
|
local float_win = api.nvim_open_win(
|
|
api.nvim_create_buf(false, true),
|
|
false,
|
|
{ relative = 'editor', row = 1, col = 1, height = 5, width = 5}
|
|
)
|
|
validate(float_win)
|
|
]]
|
|
end)
|
|
|
|
it('does not cause ml_get errors with invalid visual selection', function()
|
|
exec_lua [[
|
|
local feedkeys = function(keys) api.nvim_feedkeys(vim.keycode(keys), 'txn', false) end
|
|
|
|
-- Add lines to the current buffer and make another window looking into an empty buffer.
|
|
local win_empty, win_lines = setup_windows()
|
|
api.nvim_buf_set_lines(0, 0, -1, true, { 'a', 'b', 'c' })
|
|
|
|
-- Start Visual in current window, redraw in other window with fewer lines.
|
|
-- Should be fixed by vim-patch:8.2.4018.
|
|
feedkeys('G<C-V>')
|
|
vim._with({ win = win_empty }, function() vim.cmd.redraw() end)
|
|
|
|
-- Start Visual in current window, extend it in other window with more lines.
|
|
-- Fixed for win_execute by vim-patch:8.2.4026, but nvim_win_call should also not be affected.
|
|
feedkeys('<Esc>gg')
|
|
api.nvim_set_current_win(win_empty)
|
|
feedkeys('gg<C-V>')
|
|
vim._with({ win = win_lines }, function() feedkeys('G<C-V>') end)
|
|
vim.cmd.redraw()
|
|
]]
|
|
end)
|
|
|
|
it('can be nested', function()
|
|
exec_lua [[
|
|
local other_win, cur_win = setup_windows()
|
|
vim._with({ win = other_win }, function()
|
|
assert(api.nvim_get_current_win() == other_win)
|
|
inner = vim._with({ win = cur_win }, function()
|
|
assert(api.nvim_get_current_win() == cur_win)
|
|
end)
|
|
assert(api.nvim_get_current_win() == other_win)
|
|
end)
|
|
assert(api.nvim_get_current_win() == cur_win)
|
|
]]
|
|
end)
|
|
|
|
it('updates ruler if cursor moved', function()
|
|
local screen = Screen.new(30, 5)
|
|
screen:set_default_attr_ids {
|
|
[1] = { reverse = true },
|
|
[2] = { bold = true, reverse = true },
|
|
}
|
|
screen:attach()
|
|
exec_lua [[
|
|
vim.opt.ruler = true
|
|
local lines = {}
|
|
for i = 0, 499 do lines[#lines + 1] = tostring(i) end
|
|
api.nvim_buf_set_lines(0, 0, -1, true, lines)
|
|
api.nvim_win_set_cursor(0, { 20, 0 })
|
|
vim.cmd 'split'
|
|
_G.win = api.nvim_get_current_win()
|
|
vim.cmd "wincmd w | redraw"
|
|
]]
|
|
screen:expect [[
|
|
19 |
|
|
{1:[No Name] [+] 20,1 3%}|
|
|
^19 |
|
|
{2:[No Name] [+] 20,1 3%}|
|
|
|
|
|
]]
|
|
exec_lua [[
|
|
vim._with({ win = win }, function() api.nvim_win_set_cursor(0, { 100, 0 }) end)
|
|
vim.cmd "redraw"
|
|
]]
|
|
screen:expect [[
|
|
99 |
|
|
{1:[No Name] [+] 100,1 19%}|
|
|
^19 |
|
|
{2:[No Name] [+] 20,1 3%}|
|
|
|
|
|
]]
|
|
end)
|
|
|
|
it('layout in current tabpage does not affect windows in others', function()
|
|
command('tab split')
|
|
local t2_move_win = api.nvim_get_current_win()
|
|
command('vsplit')
|
|
local t2_other_win = api.nvim_get_current_win()
|
|
command('tabprevious')
|
|
matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)'))
|
|
command('vsplit')
|
|
|
|
exec_lua('vim._with({ win = ... }, function() vim.cmd.wincmd "J" end)', t2_move_win)
|
|
eq({ 'col', { { 'leaf', t2_other_win }, { 'leaf', t2_move_win } } }, fn.winlayout(2))
|
|
end)
|
|
end)
|
|
|
|
it('returns what callback returns', function()
|
|
local out_verify = exec_lua [[
|
|
out = { vim._with({}, function()
|
|
return 'a', 2, nil, { 4 }, function() end
|
|
end) }
|
|
return {
|
|
out[1] == 'a', out[2] == 2, out[3] == nil,
|
|
vim.deep_equal(out[4], { 4 }),
|
|
type(out[5]) == 'function',
|
|
vim.tbl_count(out),
|
|
}
|
|
]]
|
|
eq({ true, true, true, true, true, 4 }, out_verify)
|
|
end)
|
|
|
|
it('can return values by reference', function()
|
|
local out = exec_lua [[
|
|
local val = { 4, 10 }
|
|
local ref = vim._with({}, function() return val end)
|
|
ref[1] = 7
|
|
return val
|
|
]]
|
|
eq({ 7, 10 }, out)
|
|
end)
|
|
|
|
it('can not work with conflicting `buf` and `win`', function()
|
|
local out = exec_lua [[
|
|
local other_buf, cur_buf = setup_buffers()
|
|
local other_win, cur_win = setup_windows()
|
|
assert(api.nvim_win_get_buf(other_win) ~= other_buf)
|
|
local _, err = pcall(vim._with, { buf = other_buf, win = other_win }, function() end)
|
|
return err
|
|
]]
|
|
matches('Can not set both `buf` and `win`', out)
|
|
end)
|
|
|
|
pending('can forward command modifiers to user command', function()
|
|
local out = exec_lua [[
|
|
local test_flags = {
|
|
'emsg_silent',
|
|
'hide',
|
|
'keepalt',
|
|
'keepjumps',
|
|
'keepmarks',
|
|
'keeppatterns',
|
|
'lockmarks',
|
|
'noautocmd',
|
|
'silent',
|
|
'unsilent',
|
|
}
|
|
|
|
local used_smods
|
|
local command = function(data)
|
|
used_smods = data.smods
|
|
end
|
|
api.nvim_create_user_command('DummyLog', command, {})
|
|
|
|
local res = {}
|
|
for _, flag in ipairs(test_flags) do
|
|
used_smods = nil
|
|
vim._with({ [flag] = true }, function() vim.cmd('DummyLog') end)
|
|
res[flag] = used_smods[flag]
|
|
end
|
|
return res
|
|
]]
|
|
for k, v in pairs(out) do
|
|
eq({ k, true }, { k, v })
|
|
end
|
|
end)
|
|
|
|
it('handles error in callback', function()
|
|
-- Should still restore initial context
|
|
local out_buf = exec_lua [[
|
|
local other_buf, cur_buf = setup_buffers()
|
|
|
|
local context = { buf = other_buf }
|
|
local ok, err = pcall(vim._with, context, function() error('Oops buf', 0) end)
|
|
|
|
return {
|
|
ok,
|
|
err,
|
|
api.nvim_get_current_buf() == cur_buf,
|
|
}
|
|
]]
|
|
eq({ false, 'Oops buf', true }, out_buf)
|
|
|
|
local out_win = exec_lua [[
|
|
local other_win, cur_win = setup_windows()
|
|
vim.wo[other_win].winblend = 25
|
|
|
|
local context = { win = other_win, wo = { winblend = 50 } }
|
|
local ok, err = pcall(vim._with, context, function() error('Oops win', 0) end)
|
|
|
|
return {
|
|
ok,
|
|
err,
|
|
api.nvim_get_current_win() == cur_win,
|
|
vim.wo[other_win].winblend,
|
|
}
|
|
]]
|
|
eq({ false, 'Oops win', true, 25 }, out_win)
|
|
end)
|
|
|
|
it('validates arguments', function()
|
|
exec_lua [[
|
|
_G.get_error = function(...)
|
|
local _, err = pcall(vim._with, ...)
|
|
return err or ''
|
|
end
|
|
]]
|
|
local get_error = function(string_args)
|
|
return exec_lua('return get_error(' .. string_args .. ')')
|
|
end
|
|
|
|
matches('context.*table', get_error("'a', function() end"))
|
|
matches('f.*function', get_error('{}, 1'))
|
|
|
|
local validate_context = function(bad_context, expected_type)
|
|
local bad_field = vim.tbl_keys(bad_context)[1]
|
|
matches(
|
|
'context%.' .. bad_field .. '.*' .. expected_type,
|
|
get_error(vim.inspect(bad_context) .. ', function() end')
|
|
)
|
|
end
|
|
|
|
validate_context({ buf = 'a' }, 'number')
|
|
validate_context({ emsg_silent = 1 }, 'boolean')
|
|
validate_context({ hide = 1 }, 'boolean')
|
|
validate_context({ keepalt = 1 }, 'boolean')
|
|
validate_context({ keepjumps = 1 }, 'boolean')
|
|
validate_context({ keepmarks = 1 }, 'boolean')
|
|
validate_context({ keeppatterns = 1 }, 'boolean')
|
|
validate_context({ lockmarks = 1 }, 'boolean')
|
|
validate_context({ noautocmd = 1 }, 'boolean')
|
|
validate_context({ sandbox = 1 }, 'boolean')
|
|
validate_context({ silent = 1 }, 'boolean')
|
|
validate_context({ unsilent = 1 }, 'boolean')
|
|
validate_context({ win = 'a' }, 'number')
|
|
|
|
matches('Invalid buffer', get_error('{ buf = -1 }, function() end'))
|
|
matches('Invalid window', get_error('{ win = -1 }, function() end'))
|
|
end)
|
|
end)
|