mirror of
https://github.com/neovim/neovim.git
synced 2026-04-24 00:05:36 +00:00
feat(api): add nvim_open_tabpage
Problem: no API function for opening a new tab page and returning its handle, or to open without entering. Solution: add nvim_open_tabpage.
This commit is contained in:
@@ -173,4 +173,306 @@ describe('api/tabpage', function()
|
||||
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, {
|
||||
enter = 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, {
|
||||
enter = 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, {
|
||||
enter = false,
|
||||
after = api.nvim_tabpage_get_number(tab2),
|
||||
})
|
||||
|
||||
local newtabs2 = api.nvim_list_tabpages()
|
||||
eq(4, #newtabs2)
|
||||
eq({
|
||||
tab1,
|
||||
new_tab,
|
||||
tab2,
|
||||
tab3,
|
||||
}, newtabs2)
|
||||
eq(api.nvim_get_current_tabpage(), tab3)
|
||||
end)
|
||||
|
||||
it('respects the `enter` argument', function()
|
||||
eq(1, #api.nvim_list_tabpages())
|
||||
local tab1 = api.nvim_get_current_tabpage()
|
||||
|
||||
local new_tab = api.nvim_open_tabpage(0, {
|
||||
enter = false,
|
||||
})
|
||||
|
||||
local newtabs = api.nvim_list_tabpages()
|
||||
eq(2, #newtabs)
|
||||
eq(newtabs, {
|
||||
tab1,
|
||||
new_tab,
|
||||
})
|
||||
eq(api.nvim_get_current_tabpage(), tab1)
|
||||
|
||||
local new_tab2 = api.nvim_open_tabpage(0, {
|
||||
enter = 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)
|
||||
end)
|
||||
|
||||
it('applies `enter` autocmds in the context of the new tabpage', function()
|
||||
api.nvim_create_autocmd('TabEnter', {
|
||||
command = 'let g:entered_tab = nvim_get_current_tabpage()',
|
||||
})
|
||||
|
||||
local new_tab = api.nvim_open_tabpage(0, {
|
||||
enter = true,
|
||||
})
|
||||
|
||||
local entered_tab = assert(tonumber(api.nvim_get_var('entered_tab')))
|
||||
|
||||
eq(new_tab, entered_tab)
|
||||
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=1: should become first tab
|
||||
local first_tab = api.nvim_open_tabpage(0, {
|
||||
enter = false,
|
||||
after = 1,
|
||||
})
|
||||
local tabs_after_first = api.nvim_list_tabpages()
|
||||
eq(4, #tabs_after_first)
|
||||
eq({ first_tab, tab1, tab2, tab3 }, tabs_after_first)
|
||||
|
||||
-- Test after=0: should insert after current tab (tab3)
|
||||
local explicit_after_current = api.nvim_open_tabpage(0, {
|
||||
enter = false,
|
||||
after = 0,
|
||||
})
|
||||
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 position 3)
|
||||
local before_middle = api.nvim_open_tabpage(0, {
|
||||
enter = false,
|
||||
after = 3,
|
||||
})
|
||||
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, {
|
||||
enter = 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, {
|
||||
enter = 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 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()
|
||||
|
||||
local new_tab = api.nvim_open_tabpage(buf, {
|
||||
enter = 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())
|
||||
end)
|
||||
|
||||
it('validates buffer parameter', function()
|
||||
-- Test invalid buffer
|
||||
eq('Invalid buffer id: 999', pcall_err(api.nvim_open_tabpage, 999, {}))
|
||||
end)
|
||||
|
||||
it('works with current buffer (0)', function()
|
||||
local current_buf = api.nvim_get_current_buf()
|
||||
|
||||
local new_tab = api.nvim_open_tabpage(0, {
|
||||
enter = false,
|
||||
})
|
||||
|
||||
api.nvim_set_current_tabpage(new_tab)
|
||||
eq(current_buf, api.nvim_get_current_buf())
|
||||
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, {
|
||||
enter = false,
|
||||
after = 0,
|
||||
})
|
||||
|
||||
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 at position 2 (before tab2, which becomes new position 2)
|
||||
local new_at_pos2 = api.nvim_open_tabpage(0, {
|
||||
enter = false,
|
||||
after = 2,
|
||||
})
|
||||
|
||||
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, {
|
||||
enter = true,
|
||||
after = 0,
|
||||
})
|
||||
|
||||
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, {
|
||||
enter = true,
|
||||
after = 1, -- 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)
|
||||
|
||||
Reference in New Issue
Block a user