diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index b547c02ef9..34df0953f6 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -2409,8 +2409,9 @@ nvim_buf_attach({buf}, {send_buffer}, {opts}) *nvim_buf_attach()* • |nvim_buf_detach()| • |api-buffer-updates-lua| -nvim_buf_call({buf}, {fun}) *nvim_buf_call()* - Call a function with buffer as temporary current buffer. +nvim_buf_call({buf}, {fn}) *nvim_buf_call()* + Calls function `fn` in the context of buffer `buf` and returns its result + (may be multiple values). This temporarily switches current buffer to `buf`. If the current window already shows `buf`, the window is not switched. If a window inside the @@ -2422,19 +2423,16 @@ nvim_buf_call({buf}, {fun}) *nvim_buf_call()* This is useful e.g. to call Vimscript functions that only work with the current buffer/window currently, like `jobstart(…, {'term': v:true})`. - This preserves any Lua return values, including multiple return values. - Attributes: ~ Lua |vim.api| only Since: 0.5.0 Parameters: ~ - • {buf} (`integer`) Buffer id, or 0 for current buffer - • {fun} (`function`) Function to call inside the buffer (currently Lua - callable only) + • {buf} (`integer`) Buffer id, or 0 for current buffer. + • {fn} (`function`) Lua function to call inside the buffer. Return: ~ - (`any`) Return value of function. + (`any`) Value(s) returned by `fn()`. nvim_buf_del_keymap({buf}, {mode}, {lhs}) *nvim_buf_del_keymap()* Unmaps a buffer-local |mapping| for the given mode. @@ -4059,22 +4057,20 @@ nvim_win_set_config({win}, {config}) *nvim_win_set_config()* ============================================================================== Window Functions *api-window* -nvim_win_call({win}, {fun}) *nvim_win_call()* - Calls a function with window as temporary current window. - - This preserves any Lua return values, including multiple return values. +nvim_win_call({win}, {fn}) *nvim_win_call()* + Calls function `fn` in the context of window `win` and returns its result + (may be multiple values). Attributes: ~ Lua |vim.api| only Since: 0.5.0 Parameters: ~ - • {win} (`integer`) |window-ID|, or 0 for current window - • {fun} (`function`) Function to call inside the window (currently Lua - callable only) + • {win} (`integer`) |window-ID|, or 0 for current window. + • {fn} (`function`) Lua function to call inside the window. Return: ~ - (`any`) Return value of function. + (`any`) Value(s) returned by `fn()`. See also: ~ • |win_execute()| diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 8a771637f9..ae432002ca 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -111,6 +111,7 @@ The following new features were added. API +• |nvim_buf_call()| and |nvim_win_call()| now preserve multiple return values. • |nvim_set_hl()| supports "font" key. • |nvim_open_win()| `zindex` controls whether the UI will use a dimmed cursor shape when an unfocused float is on top of the cursor. @@ -274,10 +275,6 @@ These existing features changed their behavior. • |nvim_exec_autocmds()| • |nvim_get_autocmds()| -• API: - • |nvim_buf_call()| and |nvim_win_call()| now preserve multiple return - values - ============================================================================== REMOVED FEATURES *news-removed* diff --git a/runtime/lua/vim/_meta/api.gen.lua b/runtime/lua/vim/_meta/api.gen.lua index b280ec4bd4..50ba118b6f 100644 --- a/runtime/lua/vim/_meta/api.gen.lua +++ b/runtime/lua/vim/_meta/api.gen.lua @@ -265,7 +265,8 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start --- otherwise True. function vim.api.nvim_buf_attach(buf, send_buffer, opts) end ---- Call a function with buffer as temporary current buffer. +--- Calls function `fn` in the context of buffer `buf` and returns its result (may be multiple +--- values). --- --- This temporarily switches current buffer to `buf`. --- If the current window already shows `buf`, the window is not switched. @@ -277,13 +278,10 @@ function vim.api.nvim_buf_attach(buf, send_buffer, opts) end --- This is useful e.g. to call Vimscript functions that only work with the --- current buffer/window currently, like `jobstart(…, {'term': v:true})`. --- ---- This preserves any Lua return values, including multiple return values. ---- ---- @param buf integer Buffer id, or 0 for current buffer ---- @param fun function Function to call inside the buffer (currently Lua callable ---- only) ---- @return any # Return value of function. -function vim.api.nvim_buf_call(buf, fun) end +--- @param buf integer Buffer id, or 0 for current buffer. +--- @param fn function Lua function to call inside the buffer. +--- @return any # Value(s) returned by `fn()`. +function vim.api.nvim_buf_call(buf, fn) end --- @deprecated --- @param buffer integer @@ -2422,18 +2420,16 @@ function vim.api.nvim_tabpage_set_win(tabpage, win) end --- @param content string Content to write to the TTY function vim.api.nvim_ui_send(content) end ---- Calls a function with window as temporary current window. +--- Calls function `fn` in the context of window `win` and returns its result (may be multiple +--- values). --- --- ---- This preserves any Lua return values, including multiple return values. ---- --- @see `:help win_execute()` --- @see vim.api.nvim_buf_call ---- @param win integer `window-ID`, or 0 for current window ---- @param fun function Function to call inside the window (currently Lua callable ---- only) ---- @return any # Return value of function. -function vim.api.nvim_win_call(win, fun) end +--- @param win integer `window-ID`, or 0 for current window. +--- @param fn function Lua function to call inside the window. +--- @return any # Value(s) returned by `fn()`. +function vim.api.nvim_win_call(win, fn) end --- Closes the window (like `:close` with a `window-ID`). --- diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index f1b445142b..78be5390d0 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -1178,7 +1178,8 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buf, String name, Arena *arena, Err return rv; } -/// Call a function with buffer as temporary current buffer. +/// Calls function `fn` in the context of buffer `buf` and returns its result (may be multiple +/// values). /// /// This temporarily switches current buffer to `buf`. /// If the current window already shows `buf`, the window is not switched. @@ -1190,14 +1191,11 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buf, String name, Arena *arena, Err /// This is useful e.g. to call Vimscript functions that only work with the /// current buffer/window currently, like `jobstart(…, {'term': v:true})`. /// -/// This preserves any Lua return values, including multiple return values. -/// -/// @param buf Buffer id, or 0 for current buffer -/// @param fun Function to call inside the buffer (currently Lua callable -/// only) -/// @param[out] err Error details, if any -/// @return Return value of function. -Object nvim_buf_call(Buffer buf, LuaRef fun, lua_State *lstate, Error *err) +/// @param buf Buffer id, or 0 for current buffer. +/// @param fn Lua function to call inside the buffer. +/// @param err Error details, if any. +/// @return Value(s) returned by `fn()`. +Object nvim_buf_call(Buffer buf, LuaRef fn, lua_State *lstate, Error *err) FUNC_API_SINCE(7) FUNC_API_LUA_ONLY { @@ -1211,7 +1209,7 @@ Object nvim_buf_call(Buffer buf, LuaRef fun, lua_State *lstate, Error *err) aucmd_prepbuf(&aco, b); Array args = ARRAY_DICT_INIT; - nlua_call_ref(fun, NULL, args, kRetMultiStack, NULL, err); + nlua_call_ref(fn, NULL, args, kRetMultiStack, NULL, err); aucmd_restbuf(&aco); }); diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 7fa5ebed73..5c95c15745 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -396,19 +396,17 @@ void nvim_win_close(Window win, Boolean force, Error *err) }); } -/// Calls a function with window as temporary current window. +/// Calls function `fn` in the context of window `win` and returns its result (may be multiple +/// values). /// /// @see |win_execute()| /// @see |nvim_buf_call()| /// -/// This preserves any Lua return values, including multiple return values. -/// -/// @param win |window-ID|, or 0 for current window -/// @param fun Function to call inside the window (currently Lua callable -/// only) -/// @param[out] err Error details, if any -/// @return Return value of function. -Object nvim_win_call(Window win, LuaRef fun, lua_State *lstate, Error *err) +/// @param win |window-ID|, or 0 for current window. +/// @param fn Lua function to call inside the window. +/// @param err Error details, if any. +/// @return Value(s) returned by `fn()`. +Object nvim_win_call(Window win, LuaRef fn, lua_State *lstate, Error *err) FUNC_API_SINCE(7) FUNC_API_LUA_ONLY { @@ -422,7 +420,7 @@ Object nvim_win_call(Window win, LuaRef fun, lua_State *lstate, Error *err) win_execute_T win_execute_args; if (win_execute_before(&win_execute_args, w, tabpage)) { Array args = ARRAY_DICT_INIT; - nlua_call_ref(fun, NULL, args, kRetMultiStack, NULL, err); + nlua_call_ref(fn, NULL, args, kRetMultiStack, NULL, err); } win_execute_after(&win_execute_args); }); diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 7b05206bb6..749a9b4267 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -2497,5 +2497,105 @@ describe('api/buf', function() end) ) end) + + it('can access buf options', function() + local buf1 = api.nvim_get_current_buf() + local buf2 = exec_lua [[ + buf2 = vim.api.nvim_create_buf(false, true) + return buf2 + ]] + + eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 })) + eq(false, api.nvim_get_option_value('autoindent', { buf = buf2 })) + + local val = exec_lua [[ + return vim.api.nvim_buf_call(buf2, function() + vim.cmd "set autoindent" + return vim.api.nvim_get_current_buf() + end) + ]] + + eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 })) + eq(true, api.nvim_get_option_value('autoindent', { buf = buf2 })) + eq(buf1, api.nvim_get_current_buf()) + eq(buf2, val) + end) + + it('does not cause ml_get errors with invalid visual selection', function() + -- Should be fixed by vim-patch:8.2.4028. + exec_lua [[ + local api = vim.api + local t = function(s) return api.nvim_replace_termcodes(s, true, true, true) end + api.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"}) + api.nvim_feedkeys(t "G", "txn", false) + api.nvim_buf_call(api.nvim_create_buf(false, true), function() vim.cmd "redraw" end) + ]] + end) + + it('can be nested crazily with hidden buffers', function() + eq( + true, + exec_lua([[ + local function scratch_buf_call(fn) + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_option_value('cindent', true, {buf = buf}) + return vim.api.nvim_buf_call(buf, function() + return vim.api.nvim_get_current_buf() == buf + and vim.api.nvim_get_option_value('cindent', {buf = buf}) + and fn() + end) and vim.api.nvim_buf_delete(buf, {}) == nil + end + + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return scratch_buf_call(function() + return true + end) + end) + end) + end) + end) + end) + end) + end) + end) + end) + end) + end) + ]]) + ) + end) + + it('can return values by reference', function() + eq( + { 4, 7 }, + exec_lua [[ + local val = {4, 10} + local ref = vim.api.nvim_buf_call(0, function() return val end) + ref[2] = 7 + return val + ]] + ) + end) + + it('can get Visual selection in current buffer #34162', function() + insert('foo bar baz') + feed('gg0fbvtb') + local text = exec_lua([[ + return vim.api.nvim_buf_call(0, function() + return vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v')) + end) + ]]) + eq({ 'bar ' }, text) + end) end) end) diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 7b0f9e2d56..c69ce3a791 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -3955,5 +3955,132 @@ describe('API/win', function() end) ) end) + + it('can access window options', function() + command('vsplit') + local win1 = api.nvim_get_current_win() + command('wincmd w') + local win2 = exec_lua [[ + win2 = vim.api.nvim_get_current_win() + return win2 + ]] + command('wincmd p') + + eq('', api.nvim_get_option_value('winhighlight', { win = win1 })) + eq('', api.nvim_get_option_value('winhighlight', { win = win2 })) + + local val = exec_lua [[ + return vim.api.nvim_win_call(win2, function() + vim.cmd "setlocal winhighlight=Normal:Normal" + return vim.api.nvim_get_current_win() + end) + ]] + + eq('', api.nvim_get_option_value('winhighlight', { win = win1 })) + eq('Normal:Normal', api.nvim_get_option_value('winhighlight', { win = win2 })) + eq(win1, api.nvim_get_current_win()) + eq(win2, val) + end) + + it('failure modes', function() + matches( + 'nvim_exec2%(%), line 1: Vim:E492: Not an editor command: fooooo', + pcall_err(exec_lua, [[vim.api.nvim_win_call(0, function() vim.cmd 'fooooo' end)]]) + ) + eq( + 'Lua: [string ""]:0: fooooo', + pcall_err(exec_lua, [[vim.api.nvim_win_call(0, function() error('fooooo') end)]]) + ) + end) + + it('does not cause ml_get errors with invalid visual selection', function() + -- Add lines to the current buffer and make another window looking into an empty buffer. + exec_lua [[ + _G.api = vim.api + _G.t = function(s) return api.nvim_replace_termcodes(s, true, true, true) end + _G.win_lines = api.nvim_get_current_win() + vim.cmd "new" + _G.win_empty = api.nvim_get_current_win() + api.nvim_set_current_win(win_lines) + 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. + exec_lua [[ + api.nvim_feedkeys(t "G", "txn", false) + api.nvim_win_call(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. + exec_lua [[ + api.nvim_feedkeys(t "gg", "txn", false) + api.nvim_set_current_win(win_empty) + api.nvim_feedkeys(t "gg", "txn", false) + api.nvim_win_call(win_lines, function() api.nvim_feedkeys(t "G", "txn", false) end) + vim.cmd "redraw" + ]] + end) + + it('updates ruler if cursor moved', function() + -- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too! + local screen = Screen.new(30, 5) + exec_lua [[ + _G.api = vim.api + 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 | + {2:< Name] [+] 20,1 3%}| + ^19 | + {3:< Name] [+] 20,1 3%}| + | + ]] + exec_lua [[ + api.nvim_win_call(win, function() api.nvim_win_set_cursor(0, {100, 0}) end) + vim.cmd "redraw" + ]] + screen:expect [[ + 99 | + {2:< Name] [+] 100,1 19%}| + ^19 | + {3:< Name] [+] 20,1 3%}| + | + ]] + end) + + it('can return values by reference', function() + eq( + { 7, 10 }, + exec_lua [[ + local val = {4, 10} + local ref = vim.api.nvim_win_call(0, function() return val end) + ref[1] = 7 + return val + ]] + ) + end) + + it('layout in current tabpage does not affect windows in others', function() + command('tab split') + local t2_move_win = api.nvim_get_current_win() + command('vsplit') + local t2_other_win = api.nvim_get_current_win() + command('tabprevious') + matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) + command('vsplit') + + -- Without vim-patch:8.2.3862, this gives E36, despite just the 1st tabpage being full. + exec_lua('vim.api.nvim_win_call(..., function() vim.cmd.wincmd "J" end)', t2_move_win) + eq({ 'col', { { 'leaf', t2_other_win }, { 'leaf', t2_move_win } } }, fn.winlayout(2)) + end) end) end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 2734adba84..d5912ad1ea 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -2628,237 +2628,6 @@ describe('lua stdlib', function() end) end) - describe('vim.api.nvim_buf_call', function() - it('can access buf options', function() - local buf1 = api.nvim_get_current_buf() - local buf2 = exec_lua [[ - buf2 = vim.api.nvim_create_buf(false, true) - return buf2 - ]] - - eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 })) - eq(false, api.nvim_get_option_value('autoindent', { buf = buf2 })) - - local val = exec_lua [[ - return vim.api.nvim_buf_call(buf2, function() - vim.cmd "set autoindent" - return vim.api.nvim_get_current_buf() - end) - ]] - - eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 })) - eq(true, api.nvim_get_option_value('autoindent', { buf = buf2 })) - eq(buf1, api.nvim_get_current_buf()) - eq(buf2, val) - end) - - it('does not cause ml_get errors with invalid visual selection', function() - -- Should be fixed by vim-patch:8.2.4028. - exec_lua [[ - local api = vim.api - local t = function(s) return api.nvim_replace_termcodes(s, true, true, true) end - api.nvim_buf_set_lines(0, 0, -1, true, {"a", "b", "c"}) - api.nvim_feedkeys(t "G", "txn", false) - api.nvim_buf_call(api.nvim_create_buf(false, true), function() vim.cmd "redraw" end) - ]] - end) - - it('can be nested crazily with hidden buffers', function() - eq( - true, - exec_lua([[ - local function scratch_buf_call(fn) - local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_set_option_value('cindent', true, {buf = buf}) - return vim.api.nvim_buf_call(buf, function() - return vim.api.nvim_get_current_buf() == buf - and vim.api.nvim_get_option_value('cindent', {buf = buf}) - and fn() - end) and vim.api.nvim_buf_delete(buf, {}) == nil - end - - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return scratch_buf_call(function() - return true - end) - end) - end) - end) - end) - end) - end) - end) - end) - end) - end) - end) - ]]) - ) - end) - - it('can return values by reference', function() - eq( - { 4, 7 }, - exec_lua [[ - local val = {4, 10} - local ref = vim.api.nvim_buf_call(0, function() return val end) - ref[2] = 7 - return val - ]] - ) - end) - - it('can get Visual selection in current buffer #34162', function() - insert('foo bar baz') - feed('gg0fbvtb') - local text = exec_lua([[ - return vim.api.nvim_buf_call(0, function() - return vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v')) - end) - ]]) - eq({ 'bar ' }, text) - end) - end) - - describe('vim.api.nvim_win_call', function() - it('can access window options', function() - command('vsplit') - local win1 = api.nvim_get_current_win() - command('wincmd w') - local win2 = exec_lua [[ - win2 = vim.api.nvim_get_current_win() - return win2 - ]] - command('wincmd p') - - eq('', api.nvim_get_option_value('winhighlight', { win = win1 })) - eq('', api.nvim_get_option_value('winhighlight', { win = win2 })) - - local val = exec_lua [[ - return vim.api.nvim_win_call(win2, function() - vim.cmd "setlocal winhighlight=Normal:Normal" - return vim.api.nvim_get_current_win() - end) - ]] - - eq('', api.nvim_get_option_value('winhighlight', { win = win1 })) - eq('Normal:Normal', api.nvim_get_option_value('winhighlight', { win = win2 })) - eq(win1, api.nvim_get_current_win()) - eq(win2, val) - end) - - it('failure modes', function() - matches( - 'nvim_exec2%(%), line 1: Vim:E492: Not an editor command: fooooo', - pcall_err(exec_lua, [[vim.api.nvim_win_call(0, function() vim.cmd 'fooooo' end)]]) - ) - eq( - 'Lua: [string ""]:0: fooooo', - pcall_err(exec_lua, [[vim.api.nvim_win_call(0, function() error('fooooo') end)]]) - ) - end) - - it('does not cause ml_get errors with invalid visual selection', function() - -- Add lines to the current buffer and make another window looking into an empty buffer. - exec_lua [[ - _G.api = vim.api - _G.t = function(s) return api.nvim_replace_termcodes(s, true, true, true) end - _G.win_lines = api.nvim_get_current_win() - vim.cmd "new" - _G.win_empty = api.nvim_get_current_win() - api.nvim_set_current_win(win_lines) - 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. - exec_lua [[ - api.nvim_feedkeys(t "G", "txn", false) - api.nvim_win_call(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. - exec_lua [[ - api.nvim_feedkeys(t "gg", "txn", false) - api.nvim_set_current_win(win_empty) - api.nvim_feedkeys(t "gg", "txn", false) - api.nvim_win_call(win_lines, function() api.nvim_feedkeys(t "G", "txn", false) end) - vim.cmd "redraw" - ]] - end) - - it('updates ruler if cursor moved', function() - -- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too! - local screen = Screen.new(30, 5) - exec_lua [[ - _G.api = vim.api - 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 | - {2:< Name] [+] 20,1 3%}| - ^19 | - {3:< Name] [+] 20,1 3%}| - | - ]] - exec_lua [[ - api.nvim_win_call(win, function() api.nvim_win_set_cursor(0, {100, 0}) end) - vim.cmd "redraw" - ]] - screen:expect [[ - 99 | - {2:< Name] [+] 100,1 19%}| - ^19 | - {3:< Name] [+] 20,1 3%}| - | - ]] - end) - - it('can return values by reference', function() - eq( - { 7, 10 }, - exec_lua [[ - local val = {4, 10} - local ref = vim.api.nvim_win_call(0, function() return val end) - ref[1] = 7 - return val - ]] - ) - end) - - it('layout in current tabpage does not affect windows in others', function() - command('tab split') - local t2_move_win = api.nvim_get_current_win() - command('vsplit') - local t2_other_win = api.nvim_get_current_win() - command('tabprevious') - matches('E36: Not enough room$', pcall_err(command, 'execute "split|"->repeat(&lines)')) - command('vsplit') - - -- Without vim-patch:8.2.3862, this gives E36, despite just the 1st tabpage being full. - exec_lua('vim.api.nvim_win_call(..., function() vim.cmd.wincmd "J" end)', t2_move_win) - eq({ 'col', { { 'leaf', t2_other_win }, { 'leaf', t2_move_win } } }, fn.winlayout(2)) - end) - end) - describe('vim.iconv', function() it('can convert strings', function() eq(