Compare commits

...

5 Commits

Author SHA1 Message Date
Will Hopkins ee829c007b
Merge 62254a5915 into efb44e0cad 2024-05-05 10:05:59 -04:00
Maria José Solano efb44e0cad
docs: fix lua type warnings (#28633) 2024-05-05 06:08:17 +08:00
zeertzjq e948d7feba
vim-patch:ad4881cb3c04 (#28636)
runtime(doc): correct getscriptinfo() example (vim/vim#14718)

When "sid" is specified, it returns a List with a single item.

ad4881cb3c
2024-05-04 15:53:42 +08:00
Will Hopkins 62254a5915 test: add test for 'enter' argument 2024-03-14 08:44:17 -07:00
Will Hopkins e17a679fe0 feat(api): add `nvim_open_tabpage`
Adds support for opening a new tabpage and
retrieving a handle to it, and optionally not
entering the new tabpage.
2024-03-14 08:36:04 -07:00
15 changed files with 200 additions and 29 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

@ -3014,7 +3014,7 @@ getscriptinfo([{opts}]) *getscriptinfo()*
Examples: >vim
echo getscriptinfo({'name': 'myscript'})
echo getscriptinfo({'sid': 15}).variables
echo getscriptinfo({'sid': 15})[0].variables
<
gettabinfo([{tabnr}]) *gettabinfo()*

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

@ -124,7 +124,7 @@ error('Cannot require a meta file')
--- @field commalist boolean
--- @field flaglist boolean
--- @field was_set boolean
--- @field last_set_id integer
--- @field last_set_sid integer
--- @field last_set_linenr integer
--- @field last_set_chan integer
--- @field type 'string'|'boolean'|'number'

View File

@ -127,3 +127,11 @@
--- @field skipcol integer
--- @field topfill integer
--- @field topline integer
--- @class vim.fn.getscriptinfo.ret
--- @field autoload false
--- @field functions? string[]
--- @field name string
--- @field sid string
--- @field variables? table<string, any>
--- @field version 1

View File

@ -3628,11 +3628,11 @@ function vim.fn.getregtype(regname) end
---
--- Examples: >vim
--- echo getscriptinfo({'name': 'myscript'})
--- echo getscriptinfo({'sid': 15}).variables
--- echo getscriptinfo({'sid': 15})[0].variables
--- <
---
--- @param opts? table
--- @return any
--- @return vim.fn.getscriptinfo.ret[]
function vim.fn.getscriptinfo(opts) end
--- If {tabnr} is not specified, then information about all the

View File

@ -310,6 +310,7 @@ local function is_empty_or_default(bufnr, option)
end
local info = api.nvim_get_option_info2(option, { buf = bufnr })
---@param e vim.fn.getscriptinfo.ret
local scriptinfo = vim.tbl_filter(function(e)
return e.sid == info.last_set_sid
end, vim.fn.getscriptinfo())
@ -515,7 +516,7 @@ local function buf_attach(bufnr)
textDocument = {
uri = uri,
},
reason = protocol.TextDocumentSaveReason.Manual,
reason = protocol.TextDocumentSaveReason.Manual, ---@type integer
}
if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'willSave') then
client.notify(ms.textDocument_willSave, params)
@ -899,7 +900,7 @@ end
--- a `client_id:result` map.
---@return function cancel Function that cancels all requests.
function lsp.buf_request_all(bufnr, method, params, handler)
local results = {} --- @type table<integer,{error:string, result:any}>
local results = {} --- @type table<integer,{error:lsp.ResponseError, result:any}>
local result_count = 0
local expected_result_count = 0
@ -940,7 +941,7 @@ end
---@return table<integer, {err: lsp.ResponseError, result: any}>? result Map of client_id:request_result.
---@return string? err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil.
function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
local request_results
local request_results ---@type table
local cancel = lsp.buf_request_all(bufnr, method, params, function(it)
request_results = it

View File

@ -327,7 +327,7 @@ function M.get_captures_at_cursor(winnr)
end
--- Optional keyword arguments:
--- @class vim.treesitter.get_node.Opts
--- @class vim.treesitter.get_node.Opts : vim.treesitter.LanguageTree.tree_for_range.Opts
--- @inlinedoc
---
--- Buffer number (nil or 0 for current buffer)

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

@ -4470,11 +4470,12 @@ M.funcs = {
Examples: >vim
echo getscriptinfo({'name': 'myscript'})
echo getscriptinfo({'sid': 15}).variables
echo getscriptinfo({'sid': 15})[0].variables
<
]=],
name = 'getscriptinfo',
params = { { 'opts', 'table' } },
returns = 'vim.fn.getscriptinfo.ret[]',
signature = 'getscriptinfo([{opts}])',
},
gettabinfo = {

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 } })