mirror of
https://github.com/neovim/neovim.git
synced 2026-07-22 17:02:59 +00:00
Problem:
cmdwin (the `:q` cmdline buffer) has various limitations which require
special-casing all over the codebase.
Besides complicating the code, it also breaks async plugins if they try
to create buffers/windows after some work is done, if the user happens
to open cmdwin at the wrong the moment:
Lua callback: …/guh.nvim/lua/guh/util.lua:531:
E11: Invalid in command-line window; <CR> executes, CTRL-C quits
stack traceback:
[C]: in function 'nvim_buf_delete'
…/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526>
Solution:
Just say no to "inception". Reimplement cmdwin as a normal buffer+window.
All of the cmdwin contortions (in both core, and innocent plugins) exist
literally only to support "inception": recursive
cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute,
`:input()`, etc. So we just won't support that (though I have
a potential plan for that later, which I call "modal parking lot").
The benefit is that plugins, and core, no longer have to care about
cmdwin.
BONUS:
- mouse-drag on vertical separators works (it only worked for
horizontal/statusline before)
- inccommand-in-cmdwin now works correctly, for free (thus don't need
#40077).
POTENTIAL FOLLOWUPS
- Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos.
- Unify `BUFLOCK_OK` / `LOCK_OK` ?
DESIGN:
- Eliminate lots of C globals, `EX_CMDWIN`, etc.
- `text_locked()` no longer reports true for cmdwin.
- cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe',
'buftype=nofile'. Invariants come from those options rather than
special cases throughout the codebase.
- `nv_record` for q:/q//q? calls Lua
`nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN`
/ cmdline-reader detour.
- `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls
`vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so
the in-flight cmdline cancels. Reader state is not serialized; instead
the captured `(type, line, col)` is replayed via
`nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms.
- On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the
window and re-feeds the cmdline.
BREAKING CHANGES:
- Expression-register cmdline (`<C-R>=` from insert-mode) no longer
supports cmdwin. Same applies to `input()` / `inputlist()` (already
covered by `text_locked`).
- Usage of cmdwin in macros/mappings will probably break (assuming they
ever worked).
491 lines
17 KiB
Lua
491 lines
17 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
local Screen = require('test.functional.ui.screen')
|
|
|
|
local clear, eq, ok = n.clear, t.eq, t.ok
|
|
local matches = t.matches
|
|
local exec = n.exec
|
|
local feed = n.feed
|
|
local api = n.api
|
|
local fn = n.fn
|
|
local request = n.request
|
|
local NIL = vim.NIL
|
|
local pcall_err = t.pcall_err
|
|
local command = n.command
|
|
|
|
describe('api/tabpage', function()
|
|
before_each(clear)
|
|
|
|
describe('list_wins and get_win', function()
|
|
it('works', function()
|
|
command('tabnew')
|
|
command('vsplit')
|
|
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
|
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
|
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
|
eq(win1, api.nvim_tabpage_get_win(tab1))
|
|
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
|
eq(win2, api.nvim_tabpage_get_win(tab2))
|
|
api.nvim_set_current_win(win3)
|
|
eq(win3, api.nvim_tabpage_get_win(tab2))
|
|
command('tabprev')
|
|
eq(win1, api.nvim_tabpage_get_win(tab1))
|
|
eq(win3, api.nvim_tabpage_get_win(tab2))
|
|
end)
|
|
|
|
it('validates args', function()
|
|
eq('Invalid tabpage id: 23', pcall_err(api.nvim_tabpage_list_wins, 23))
|
|
end)
|
|
end)
|
|
|
|
describe('set_win', function()
|
|
it('works', function()
|
|
command('tabnew')
|
|
command('vsplit')
|
|
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
|
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
|
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
|
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
|
eq(win2, api.nvim_tabpage_get_win(tab2))
|
|
api.nvim_tabpage_set_win(tab2, win3)
|
|
eq(win3, api.nvim_tabpage_get_win(tab2))
|
|
end)
|
|
|
|
it('works in non-current tabpages', function()
|
|
command('tabnew')
|
|
command('vsplit')
|
|
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
|
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
|
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
|
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
|
eq(win2, api.nvim_tabpage_get_win(tab2))
|
|
eq(win2, api.nvim_get_current_win())
|
|
|
|
command('tabprev')
|
|
|
|
eq(tab1, api.nvim_get_current_tabpage())
|
|
|
|
eq(win2, api.nvim_tabpage_get_win(tab2))
|
|
api.nvim_tabpage_set_win(tab2, win3)
|
|
eq(win3, api.nvim_tabpage_get_win(tab2))
|
|
|
|
command('tabnext')
|
|
eq(win3, api.nvim_get_current_win())
|
|
end)
|
|
|
|
it('throws an error when the window does not belong to the tabpage', function()
|
|
command('tabnew')
|
|
command('vsplit')
|
|
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
|
local win1, win2, win3 = unpack(api.nvim_list_wins())
|
|
eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
|
|
eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
|
|
eq(win2, api.nvim_get_current_win())
|
|
|
|
eq(
|
|
string.format('Window does not belong to tabpage %d', tab2),
|
|
pcall_err(api.nvim_tabpage_set_win, tab2, win1)
|
|
)
|
|
|
|
eq(
|
|
string.format('Window does not belong to tabpage %d', tab1),
|
|
pcall_err(api.nvim_tabpage_set_win, tab1, win3)
|
|
)
|
|
end)
|
|
|
|
it('checks textlock restrictions', function()
|
|
command('autocmd TextYankPost * ++once call nvim_open_tabpage(0, 0, {})')
|
|
matches('E565:', pcall_err(command, 'yank'))
|
|
eq(1, fn.tabpagenr('$'))
|
|
|
|
exec([[
|
|
new
|
|
call setline(1, 'foo')
|
|
setlocal debug=throw indentexpr=nvim_tabpage_set_win(0,win_getid())
|
|
]])
|
|
local cur_win = api.nvim_get_current_win()
|
|
matches('E565: Not allowed to change text or change window', pcall_err(command, 'normal! =='))
|
|
eq(cur_win, api.nvim_get_current_win())
|
|
end)
|
|
end)
|
|
|
|
describe('{get,set,del}_var', function()
|
|
it('works', function()
|
|
api.nvim_tabpage_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } })
|
|
eq({ 1, 2, { ['3'] = 1 } }, api.nvim_tabpage_get_var(0, 'lua'))
|
|
eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('t:lua'))
|
|
eq(1, fn.exists('t:lua'))
|
|
api.nvim_tabpage_del_var(0, 'lua')
|
|
eq(0, fn.exists('t:lua'))
|
|
eq('Key not found: lua', pcall_err(api.nvim_tabpage_del_var, 0, 'lua'))
|
|
api.nvim_tabpage_set_var(0, 'lua', 1)
|
|
command('lockvar t:lua')
|
|
eq('Key is locked: lua', pcall_err(api.nvim_tabpage_del_var, 0, 'lua'))
|
|
eq('Key is locked: lua', pcall_err(api.nvim_tabpage_set_var, 0, 'lua', 1))
|
|
end)
|
|
|
|
it('tabpage_set_var returns the old value', function()
|
|
local val1 = { 1, 2, { ['3'] = 1 } }
|
|
local val2 = { 4, 7 }
|
|
eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
|
|
eq(val1, request('tabpage_set_var', 0, 'lua', val2))
|
|
end)
|
|
|
|
it('tabpage_del_var returns the old value', function()
|
|
local val1 = { 1, 2, { ['3'] = 1 } }
|
|
local val2 = { 4, 7 }
|
|
eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
|
|
eq(val1, request('tabpage_set_var', 0, 'lua', val2))
|
|
eq(val2, request('tabpage_del_var', 0, 'lua'))
|
|
end)
|
|
end)
|
|
|
|
describe('get_number', function()
|
|
it('works', function()
|
|
local tabs = api.nvim_list_tabpages()
|
|
eq(1, api.nvim_tabpage_get_number(tabs[1]))
|
|
|
|
command('tabnew')
|
|
local tab1, tab2 = unpack(api.nvim_list_tabpages())
|
|
eq(1, api.nvim_tabpage_get_number(tab1))
|
|
eq(2, api.nvim_tabpage_get_number(tab2))
|
|
|
|
command('-tabmove')
|
|
eq(2, api.nvim_tabpage_get_number(tab1))
|
|
eq(1, api.nvim_tabpage_get_number(tab2))
|
|
end)
|
|
end)
|
|
|
|
describe('is_valid', function()
|
|
it('works', function()
|
|
command('tabnew')
|
|
local tab = api.nvim_list_tabpages()[2]
|
|
api.nvim_set_current_tabpage(tab)
|
|
ok(api.nvim_tabpage_is_valid(tab))
|
|
command('tabclose')
|
|
ok(not api.nvim_tabpage_is_valid(tab))
|
|
end)
|
|
end)
|
|
|
|
describe('open_tabpage', function()
|
|
it('works', function()
|
|
local tabs = api.nvim_list_tabpages()
|
|
eq(1, #tabs)
|
|
local curtab = api.nvim_get_current_tabpage()
|
|
local tab = api.nvim_open_tabpage(0, false, {})
|
|
local newtabs = api.nvim_list_tabpages()
|
|
eq(2, #newtabs)
|
|
eq(tab, newtabs[2])
|
|
eq(curtab, api.nvim_get_current_tabpage())
|
|
|
|
local tab2 = api.nvim_open_tabpage(0, true, {})
|
|
local newtabs2 = api.nvim_list_tabpages()
|
|
eq(3, #newtabs2)
|
|
eq({
|
|
tabs[1],
|
|
tab2, -- new tabs open after the current tab
|
|
tab,
|
|
}, newtabs2)
|
|
eq(tab2, newtabs2[2])
|
|
eq(tab, newtabs2[3])
|
|
eq(tab2, api.nvim_get_current_tabpage())
|
|
end)
|
|
|
|
it('respects the `after` option', function()
|
|
local tab1 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab2 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab3 = api.nvim_get_current_tabpage()
|
|
|
|
local newtabs = api.nvim_list_tabpages()
|
|
eq(3, #newtabs)
|
|
eq(newtabs, {
|
|
tab1,
|
|
tab2,
|
|
-- new_tab,
|
|
tab3,
|
|
})
|
|
|
|
local new_tab = api.nvim_open_tabpage(0, false, { after = api.nvim_tabpage_get_number(tab2) })
|
|
local newtabs2 = api.nvim_list_tabpages()
|
|
eq(4, #newtabs2)
|
|
eq({
|
|
tab1,
|
|
tab2,
|
|
new_tab,
|
|
tab3,
|
|
}, newtabs2)
|
|
eq(api.nvim_get_current_tabpage(), tab3)
|
|
end)
|
|
|
|
it('respects the `enter` argument', function()
|
|
local screen = Screen.new(50, 8)
|
|
eq(1, #api.nvim_list_tabpages())
|
|
local tab1 = api.nvim_get_current_tabpage()
|
|
|
|
local new_tab = api.nvim_open_tabpage(0, false, {})
|
|
local newtabs = api.nvim_list_tabpages()
|
|
eq(2, #newtabs)
|
|
eq(newtabs, { tab1, new_tab })
|
|
eq(api.nvim_get_current_tabpage(), tab1)
|
|
-- Tabline redrawn when not entering.
|
|
screen:expect([[
|
|
{5: [No Name] }{24: [No Name] }{2: }{24:X}|
|
|
^ |
|
|
{1:~ }|*5
|
|
|
|
|
]])
|
|
|
|
local new_tab2 = api.nvim_open_tabpage(0, true, {})
|
|
local newtabs2 = api.nvim_list_tabpages()
|
|
eq(3, #newtabs2)
|
|
eq(newtabs2, { tab1, new_tab2, new_tab })
|
|
eq(api.nvim_get_current_tabpage(), new_tab2)
|
|
-- Tabline redrawn. (when entering)
|
|
screen:expect([[
|
|
{24: [No Name] }{5: [No Name] }{24: [No Name] }{2: }{24:X}|
|
|
^ |
|
|
{1:~ }|*5
|
|
|
|
|
]])
|
|
|
|
api.nvim_open_tabpage(0, false, {})
|
|
-- Tabline redrawn when not entering, and when there's already one.
|
|
screen:expect([[
|
|
{24: [No Name] }{5: [No Name] }{24: [No Name] [No Name] }{2: }{24:X}|
|
|
^ |
|
|
{1:~ }|*5
|
|
|
|
|
]])
|
|
end)
|
|
|
|
it('applies autocmds in the context of the new tabpage', function()
|
|
exec([=[
|
|
let g:events = []
|
|
autocmd WinNew * let g:events += [['WinNew', nvim_get_current_tabpage(), win_getid()]]
|
|
autocmd WinEnter * let g:events += [['WinEnter', nvim_get_current_tabpage(), win_getid()]]
|
|
autocmd TabNew * let g:events += [['TabNew', nvim_get_current_tabpage(), win_getid()]]
|
|
autocmd TabEnter * let g:events += [['TabEnter', nvim_get_current_tabpage(), win_getid()]]
|
|
autocmd BufEnter * let g:events += [['BufEnter', nvim_get_current_tabpage(), win_getid()]]
|
|
autocmd BufLeave * let g:events += [['BufLeave', nvim_get_current_tabpage(), win_getid()]]
|
|
autocmd BufWinEnter * let g:events += [['BufWinEnter', nvim_get_current_tabpage(), win_getid()]]
|
|
]=])
|
|
|
|
local new_tab = api.nvim_open_tabpage(0, true, {})
|
|
local new_win = api.nvim_tabpage_get_win(new_tab)
|
|
eq({
|
|
{ 'WinNew', new_tab, new_win },
|
|
{ 'WinEnter', new_tab, new_win },
|
|
{ 'TabNew', new_tab, new_win },
|
|
{ 'TabEnter', new_tab, new_win },
|
|
}, api.nvim_get_var('events'))
|
|
eq(new_win, api.nvim_get_current_win())
|
|
|
|
api.nvim_set_var('events', {})
|
|
new_tab = api.nvim_open_tabpage(api.nvim_create_buf(true, true), true, {})
|
|
new_win = api.nvim_tabpage_get_win(new_tab)
|
|
eq({
|
|
{ 'WinNew', new_tab, new_win },
|
|
{ 'WinEnter', new_tab, new_win },
|
|
{ 'TabNew', new_tab, new_win },
|
|
{ 'TabEnter', new_tab, new_win },
|
|
{ 'BufLeave', new_tab, new_win },
|
|
{ 'BufEnter', new_tab, new_win },
|
|
{ 'BufWinEnter', new_tab, new_win },
|
|
}, api.nvim_get_var('events'))
|
|
|
|
local curwin = new_win
|
|
api.nvim_set_var('events', {})
|
|
new_tab = api.nvim_open_tabpage(0, false, {})
|
|
new_win = api.nvim_tabpage_get_win(new_tab)
|
|
eq(
|
|
{ { 'WinNew', new_tab, new_win }, { 'TabNew', new_tab, new_win } },
|
|
api.nvim_get_var('events')
|
|
)
|
|
eq(curwin, api.nvim_get_current_win())
|
|
|
|
api.nvim_set_var('events', {})
|
|
new_tab = api.nvim_open_tabpage(api.nvim_create_buf(true, true), false, {})
|
|
new_win = api.nvim_tabpage_get_win(new_tab)
|
|
eq({
|
|
{ 'WinNew', new_tab, new_win },
|
|
{ 'TabNew', new_tab, new_win },
|
|
{ 'BufWinEnter', new_tab, new_win },
|
|
}, api.nvim_get_var('events'))
|
|
eq(curwin, api.nvim_get_current_win())
|
|
end)
|
|
|
|
it('handles nasty autocmds', function()
|
|
command('autocmd WinNewPre * ++once call nvim_open_tabpage(0, 0, {})')
|
|
matches('E1312:', pcall_err(command, 'split'))
|
|
|
|
command('autocmd TabNew * ++once quit')
|
|
eq('Tabpage was closed immediately', pcall_err(api.nvim_open_tabpage, 0, false, {}))
|
|
command('autocmd BufEnter * ++once quit')
|
|
local buf = api.nvim_create_buf(true, true)
|
|
eq('Tabpage was closed immediately', pcall_err(api.nvim_open_tabpage, buf, true, {}))
|
|
|
|
-- No error if autocmds delete target buffer, if new tabpage is still valid to return.
|
|
command('autocmd BufEnter * ++once buffer # | bwipeout! #')
|
|
local new_tp = api.nvim_open_tabpage(buf, true, {})
|
|
eq(false, api.nvim_buf_is_valid(buf))
|
|
eq(new_tp, api.nvim_get_current_tabpage())
|
|
end)
|
|
|
|
it('handles edge cases for positioning', function()
|
|
-- Start with 3 tabs
|
|
local tab1 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab2 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab3 = api.nvim_get_current_tabpage()
|
|
|
|
local initial_tabs = api.nvim_list_tabpages()
|
|
eq(3, #initial_tabs)
|
|
eq({ tab1, tab2, tab3 }, initial_tabs)
|
|
|
|
-- Test after=0: should become first tab
|
|
local first_tab = api.nvim_open_tabpage(0, false, { after = 0 })
|
|
local tabs_after_first = api.nvim_list_tabpages()
|
|
eq(4, #tabs_after_first)
|
|
eq({ first_tab, tab1, tab2, tab3 }, tabs_after_first)
|
|
|
|
-- Test after=-1: should insert after current tab (tab3)
|
|
local explicit_after_current = api.nvim_open_tabpage(0, false, { after = -1 })
|
|
local tabs_after_current = api.nvim_list_tabpages()
|
|
eq(5, #tabs_after_current)
|
|
eq({ first_tab, tab1, tab2, tab3, explicit_after_current }, tabs_after_current)
|
|
|
|
-- Test inserting before a middle tab (before tab2, which is now number 3)
|
|
local before_middle = api.nvim_open_tabpage(0, false, { after = 2 })
|
|
local tabs_after_middle = api.nvim_list_tabpages()
|
|
eq(6, #tabs_after_middle)
|
|
eq({ first_tab, tab1, before_middle, tab2, tab3, explicit_after_current }, tabs_after_middle)
|
|
|
|
eq(api.nvim_get_current_tabpage(), tab3)
|
|
|
|
-- Test default behavior (after current)
|
|
local default_after_current = api.nvim_open_tabpage(0, false, {})
|
|
local final_tabs = api.nvim_list_tabpages()
|
|
eq(7, #final_tabs)
|
|
eq({
|
|
first_tab,
|
|
tab1,
|
|
before_middle,
|
|
tab2,
|
|
tab3,
|
|
default_after_current,
|
|
explicit_after_current,
|
|
}, final_tabs)
|
|
end)
|
|
|
|
it('handles position beyond last tab', function()
|
|
-- Create a few tabs first
|
|
local tab1 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab2 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab3 = api.nvim_get_current_tabpage()
|
|
|
|
eq(3, #api.nvim_list_tabpages())
|
|
eq({ tab1, tab2, tab3 }, api.nvim_list_tabpages())
|
|
|
|
-- Test that requesting position beyond last tab still works
|
|
-- (should place it at the end)
|
|
local new_tab = api.nvim_open_tabpage(0, false, { after = 10 }) -- Way beyond the last tab
|
|
local final_tabs = api.nvim_list_tabpages()
|
|
eq(4, #final_tabs)
|
|
-- Should append at the end
|
|
eq({ tab1, tab2, tab3, new_tab }, final_tabs)
|
|
end)
|
|
|
|
it('works with specific buffer', function()
|
|
local curbuf = api.nvim_get_current_buf()
|
|
local new_tab = api.nvim_open_tabpage(0, false, {})
|
|
api.nvim_set_current_tabpage(new_tab)
|
|
eq(curbuf, api.nvim_get_current_buf())
|
|
|
|
local buf = api.nvim_create_buf(false, false)
|
|
api.nvim_buf_set_lines(buf, 0, -1, false, { 'test content' })
|
|
|
|
local original_tab = api.nvim_get_current_tabpage()
|
|
local original_buf = api.nvim_get_current_buf()
|
|
new_tab = api.nvim_open_tabpage(buf, true, {}) -- Enter the tab to make testing easier
|
|
|
|
-- Check that new tab has the specified buffer
|
|
eq(new_tab, api.nvim_get_current_tabpage())
|
|
eq(buf, api.nvim_get_current_buf())
|
|
eq({ 'test content' }, api.nvim_buf_get_lines(buf, 0, -1, false))
|
|
|
|
-- Switch back and check original tab still has original buffer
|
|
api.nvim_set_current_tabpage(original_tab)
|
|
eq(original_buf, api.nvim_get_current_buf())
|
|
|
|
-- Test invalid buffer
|
|
eq('Invalid buffer id: 999', pcall_err(api.nvim_open_tabpage, 999, true, {}))
|
|
end)
|
|
|
|
it('handles complex positioning scenarios', function()
|
|
-- Create 5 tabs total
|
|
local tabs = { api.nvim_get_current_tabpage() }
|
|
for i = 2, 5 do
|
|
command('tabnew')
|
|
tabs[i] = api.nvim_get_current_tabpage()
|
|
end
|
|
eq(5, #api.nvim_list_tabpages())
|
|
|
|
-- Go to middle tab (tab 3)
|
|
api.nvim_set_current_tabpage(tabs[3])
|
|
|
|
-- Insert after=0 (after current, which is tab 3)
|
|
local new_after_current = api.nvim_open_tabpage(0, false, {})
|
|
local result_tabs = api.nvim_list_tabpages()
|
|
eq(6, #result_tabs)
|
|
eq({
|
|
tabs[1],
|
|
tabs[2],
|
|
tabs[3],
|
|
new_after_current,
|
|
tabs[4],
|
|
tabs[5],
|
|
}, result_tabs)
|
|
|
|
-- Insert as number 2 (before tab2, which will become number 3)
|
|
local new_at_pos2 = api.nvim_open_tabpage(0, false, { after = 1 })
|
|
local final_result = api.nvim_list_tabpages()
|
|
eq(7, #final_result)
|
|
eq({
|
|
tabs[1],
|
|
new_at_pos2,
|
|
tabs[2],
|
|
tabs[3],
|
|
new_after_current,
|
|
tabs[4],
|
|
tabs[5],
|
|
}, final_result)
|
|
end)
|
|
|
|
it('preserves tab order when entering new tabs', function()
|
|
local tab1 = api.nvim_get_current_tabpage()
|
|
command('tabnew')
|
|
local tab2 = api.nvim_get_current_tabpage()
|
|
|
|
-- Create new tab with enter=true, should insert after current (tab2)
|
|
local tab3 = api.nvim_open_tabpage(0, true, { after = -1 })
|
|
local tabs = api.nvim_list_tabpages()
|
|
eq(3, #tabs)
|
|
eq({ tab1, tab2, tab3 }, tabs)
|
|
eq(tab3, api.nvim_get_current_tabpage())
|
|
|
|
-- Create another with enter=true and specific position
|
|
api.nvim_set_current_tabpage(tab1)
|
|
local tab4 = api.nvim_open_tabpage(0, true, { after = 0 }) -- Should become first tab
|
|
local final_tabs = api.nvim_list_tabpages()
|
|
eq(4, #final_tabs)
|
|
eq({ tab4, tab1, tab2, tab3 }, final_tabs)
|
|
eq(tab4, api.nvim_get_current_tabpage())
|
|
end)
|
|
end)
|
|
end)
|