This commit is contained in:
Will Hopkins 2024-05-05 10:05:59 -04:00 committed by GitHub
commit ee829c007b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 181 additions and 20 deletions

View File

@ -3322,6 +3322,19 @@ nvim_win_set_config({window}, {config}) *nvim_win_set_config()*
==============================================================================
Tabpage Functions *api-tabpage*
nvim_open_tabpage({buffer}, {enter}, {opts}) *nvim_open_tabpage()*
Opens a new tabpage with a single window
Parameters: ~
• {buffer} Buffer handle, or 0 for current buffer
• {enter} Boolean, whether to enter the new tabpage
• {opts} Optional parameters
• after: Tabpage handle, open new tabpage after this
tabpage. Defaults to opening after the current tabpage.
Return: ~
Handle to newly created tabpage
nvim_tabpage_del_var({tabpage}, {name}) *nvim_tabpage_del_var()*
Removes a tab-scoped (t:) variable

View File

@ -1542,6 +1542,16 @@ function vim.api.nvim_load_context(dict) end
--- @return any
function vim.api.nvim_notify(msg, log_level, opts) end
--- Opens a new tabpage with a single window
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param enter boolean Boolean, whether to enter the new tabpage
--- @param opts vim.api.keyset.open_tabpage_opts Optional parameters
--- • after: Tabpage handle, open new tabpage after this tabpage.
--- Defaults to opening after the current tabpage.
--- @return integer
function vim.api.nvim_open_tabpage(buffer, enter, opts) end
--- Open a terminal instance in a buffer
---
--- By default (and currently the only option) the terminal will not be

View File

@ -197,6 +197,9 @@ error('Cannot require a meta file')
--- @field desc? string
--- @field replace_keycodes? boolean
--- @class vim.api.keyset.open_tabpage_opts
--- @field after? integer
--- @class vim.api.keyset.open_term
--- @field on_input? function
--- @field force_crlf? boolean

View File

@ -132,6 +132,11 @@ typedef struct {
Boolean hide;
} Dict(win_config);
typedef struct {
OptionalKeys is_set__open_tabpage_opts_;
Integer after;
} Dict(open_tabpage_opts);
typedef struct {
Boolean is_lua;
Boolean do_source;

View File

@ -1,10 +1,14 @@
#include <stdbool.h>
#include <stdlib.h>
#include "nvim/api/keysets_defs.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/api/tabpage.h"
#include "nvim/api/vim.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/globals.h"
#include "nvim/memory.h"
@ -14,6 +18,47 @@
# include "api/tabpage.c.generated.h"
#endif
/// Opens a new tabpage with a single window
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param enter Boolean, whether to enter the new tabpage
/// @param opts Optional parameters
/// - after: Tabpage handle, open new tabpage after this tabpage.
/// Defaults to opening after the current tabpage.
/// @param[out] err Error details, if any
/// @return Handle to newly created tabpage
Tabpage nvim_open_tabpage(Buffer buffer, Boolean enter, Dict(open_tabpage_opts) *opts, Error *err)
FUNC_API_SINCE(12)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
return 0;
}
int after = 0;
if (HAS_KEY(opts, open_tabpage_opts, after)) {
tabpage_T *tp = find_tab_by_handle((Tabpage)opts->after, err);
if (!tp) {
return 0;
}
// Add 1 to the tabpage index because of tabpage numbering.
// Neglecting to do this will result in the new tabpage being opened
// *before* the specified tabpage.
after = tabpage_index(tp) + 1;
}
tabpage_T *tp = win_new_tabpage(after, buf->b_ffname, enter);
if (!tp) {
api_set_error(err, kErrorTypeException, "Failed to create tabpage");
return 0;
}
win_set_buf(tp->tp_firstwin, buf, false, err);
return tp->handle;
}
/// Gets the windows in a tabpage
///
/// @param tabpage Tabpage handle, or 0 for current tabpage

View File

@ -5187,7 +5187,7 @@ void ex_splitview(exarg_T *eap)
// Either open new tab page or split the window.
if (use_tab) {
if (win_new_tabpage(cmdmod.cmod_tab != 0 ? cmdmod.cmod_tab : eap->addr_count == 0
? 0 : (int)eap->line2 + 1, eap->arg) != FAIL) {
? 0 : (int)eap->line2 + 1, eap->arg, true) != NULL) {
do_exedit(eap, old_curwin);
apply_autocmds(EVENT_TABNEWENTERED, NULL, NULL, false, curbuf);

View File

@ -419,7 +419,7 @@ newwindow:
// First create a new tab with the window, then go back to
// the old tab and close the window there.
win_T *wp = curwin;
if (win_new_tabpage(Prenum, NULL) == OK
if (win_new_tabpage(Prenum, NULL, true) != NULL
&& valid_tabpage(oldtab)) {
tabpage_T *newtab = curtab;
goto_tabpage_tp(oldtab, true, true);
@ -4154,28 +4154,31 @@ void free_tabpage(tabpage_T *tp)
/// @param after Put new tabpage after tabpage "after", or after the current
/// tabpage in case of 0.
/// @param filename Will be passed to apply_autocmds().
/// @return Was the new tabpage created successfully? FAIL or OK.
int win_new_tabpage(int after, char *filename)
/// @return Pointer to the new tabpage, or NULL if error.
tabpage_T *win_new_tabpage(int after, char *filename, bool enter)
{
tabpage_T *old_curtab = curtab;
win_T *old_curwin = curwin;
if (cmdwin_type != 0) {
emsg(_(e_cmdwin));
return FAIL;
return NULL;
}
tabpage_T *newtp = alloc_tabpage();
// Remember the current windows in this Tab page.
if (leave_tabpage(curbuf, true) == FAIL) {
if (enter && leave_tabpage(curbuf, true) == FAIL) {
xfree(newtp);
return FAIL;
return NULL;
}
newtp->tp_localdir = old_curtab->tp_localdir
? xstrdup(old_curtab->tp_localdir) : NULL;
curtab = newtp;
if (enter) {
curtab = newtp;
}
// Create a new empty window.
if (win_alloc_firstwin(old_curtab->tp_curwin) == OK) {
@ -4207,26 +4210,35 @@ int win_new_tabpage(int after, char *filename)
newtp->tp_topframe = topframe;
last_status(false);
redraw_all_later(UPD_NOT_VALID);
tabpage_check_windows(old_curtab);
if (enter) {
tabpage_check_windows(old_curtab);
lastused_tabpage = old_curtab;
lastused_tabpage = old_curtab;
entering_window(curwin);
entering_window(curwin);
}
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
if (enter) {
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
}
apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
if (enter) {
apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
}
return OK;
if (!enter) {
curwin = old_curwin;
}
return newtp;
}
// Failed, get back the previous Tab page
enter_tabpage(curtab, curbuf, true, true);
return FAIL;
return NULL;
}
// Open a new tab page if ":tab cmd" was used. It will edit the same buffer,
@ -4242,11 +4254,11 @@ int may_open_tabpage(void)
cmdmod.cmod_tab = 0; // reset it to avoid doing it twice
postponed_split_tab = 0;
int status = win_new_tabpage(n, NULL);
if (status == OK) {
tabpage_T *tp = win_new_tabpage(n, NULL, true);
if (tp != NULL) {
apply_autocmds(EVENT_TABNEWENTERED, NULL, NULL, false, curbuf);
}
return status;
return tp == NULL ? FAIL : OK;
}
// Create up to "maxcount" tabpages with empty windows.
@ -4266,7 +4278,7 @@ int make_tabpages(int maxcount)
int todo;
for (todo = count - 1; todo > 0; todo--) {
if (win_new_tabpage(0, NULL) == FAIL) {
if (win_new_tabpage(0, NULL, true) == NULL) {
break;
}
}

View File

@ -116,6 +116,79 @@ describe('api/tabpage', function()
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 newtabs = api.nvim_list_tabpages()
eq(3, #newtabs)
eq({
tabs[1],
tab2, -- new tabs open after the current tab
tab,
}, newtabs)
eq(tab2, newtabs[2])
eq(tab, newtabs[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 new_tab = api.nvim_open_tabpage(0, false, {
after = tab2,
})
local newtabs = api.nvim_list_tabpages()
eq(4, #newtabs)
eq(newtabs, {
tab1,
tab2,
new_tab,
tab3,
})
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, 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, true, {})
local newtabs = api.nvim_list_tabpages()
eq(3, #newtabs)
eq(newtabs, {
tab1,
new_tab2,
new_tab,
})
eq(api.nvim_get_current_tabpage(), new_tab2)
end)
end)
describe('{get,set,del}_var', function()
it('works', function()
api.nvim_tabpage_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } })