mirror of
https://github.com/neovim/neovim.git
synced 2026-09-13 01:21:06 +00:00
feat(api): add ev.win to autocmd callback args #39826
Problem: Autocmd callbacks currently have to rely on curwin, which may already have changed by the time they run. This is especially noticeable for WinNew, WinClosed, WinResized and WinScrolled. Solution: Track the window in the autocmd context and expose it as ev.win. Pass it explicitly for the window events that need it.
This commit is contained in:
@@ -2204,15 +2204,17 @@ nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()*
|
||||
triggered. Lua callback can return |lua-truthy| to delete
|
||||
the autocommand. Callback receives one argument, a table
|
||||
with keys: *event-args*
|
||||
• buf: (`number`) <abuf>
|
||||
• buf: (`integer`) <abuf>
|
||||
• data: (`any`) Arbitrary data passed from
|
||||
|nvim_exec_autocmds()| *event-data*
|
||||
• event: (`vim.api.keyset.events`) Name of the triggered
|
||||
event |autocmd-events|
|
||||
• file: (`string`) <afile> (not expanded to a full path)
|
||||
• group: (`number?`) Group id, if any
|
||||
• id: (`number`) Autocommand id
|
||||
• group: (`integer?`) Group id, if any
|
||||
• id: (`integer`) Autocommand id
|
||||
• match: (`string`) <amatch> (expanded to a full path)
|
||||
• win: (`integer`) id of the window for the event, see
|
||||
|window-ID|
|
||||
• command (string?) Vim command executed on event. Not
|
||||
allowed with {callback}.
|
||||
• desc (`string?`) Description (for documentation and
|
||||
|
||||
@@ -238,6 +238,7 @@ API
|
||||
• |nvim_set_option_value()| returns the new option value.
|
||||
• |nvim_create_autocmd()| is now |api-fast|, so it can be called from a fast
|
||||
event context (e.g. |vim.uv| callbacks).
|
||||
• |nvim_create_autocmd()| callback |event-args| provide `win`.
|
||||
|
||||
BUILD
|
||||
|
||||
|
||||
7
runtime/lua/vim/_meta/api.gen.lua
generated
7
runtime/lua/vim/_meta/api.gen.lua
generated
@@ -969,13 +969,14 @@ function vim.api.nvim_create_augroup(name, opts) end
|
||||
--- - callback (`function|string?`) Lua function (or Vimscript function name, if string)
|
||||
--- called when the event(s) is triggered. Lua callback can return `lua-truthy` to delete
|
||||
--- the autocommand. Callback receives one argument, a table with keys: [event-args]()
|
||||
--- - buf: (`number`) [<abuf>]
|
||||
--- - buf: (`integer`) [<abuf>]
|
||||
--- - data: (`any`) Arbitrary data passed from [nvim_exec_autocmds()] [event-data]()
|
||||
--- - event: (`vim.api.keyset.events`) Name of the triggered event `autocmd-events`
|
||||
--- - file: (`string`) [<afile>] (not expanded to a full path)
|
||||
--- - group: (`number?`) Group id, if any
|
||||
--- - id: (`number`) Autocommand id
|
||||
--- - group: (`integer?`) Group id, if any
|
||||
--- - id: (`integer`) Autocommand id
|
||||
--- - match: (`string`) [<amatch>] (expanded to a full path)
|
||||
--- - win: (`integer`) id of the window for the event, see `window-ID`
|
||||
--- - command (string?) Vim command executed on event. Not allowed with {callback}.
|
||||
--- - desc (`string?`) Description (for documentation and troubleshooting).
|
||||
--- - group (`string|integer?`) Group name or id to match against.
|
||||
|
||||
@@ -76,6 +76,7 @@ error('Cannot require a meta file')
|
||||
--- @field match string expanded value of <amatch>
|
||||
--- @field buf integer expanded value of <abuf>
|
||||
--- @field file string expanded value of <afile>
|
||||
--- @field win integer id of the window for the event, see |window-ID|
|
||||
--- @field data? any arbitrary data passed from |nvim_exec_autocmds()|
|
||||
|
||||
--- @class vim.api.keyset.create_user_command.command_args
|
||||
|
||||
@@ -373,13 +373,14 @@ cleanup:
|
||||
/// - callback (`function|string?`) Lua function (or Vimscript function name, if string)
|
||||
/// called when the event(s) is triggered. Lua callback can return |lua-truthy| to delete
|
||||
/// the autocommand. Callback receives one argument, a table with keys: [event-args]()
|
||||
/// - buf: (`number`) [<abuf>]
|
||||
/// - buf: (`integer`) [<abuf>]
|
||||
/// - data: (`any`) Arbitrary data passed from [nvim_exec_autocmds()] [event-data]()
|
||||
/// - event: (`vim.api.keyset.events`) Name of the triggered event |autocmd-events|
|
||||
/// - file: (`string`) [<afile>] (not expanded to a full path)
|
||||
/// - group: (`number?`) Group id, if any
|
||||
/// - id: (`number`) Autocommand id
|
||||
/// - group: (`integer?`) Group id, if any
|
||||
/// - id: (`integer`) Autocommand id
|
||||
/// - match: (`string`) [<amatch>] (expanded to a full path)
|
||||
/// - win: (`integer`) id of the window for the event, see |window-ID|
|
||||
/// - command (string?) Vim command executed on event. Not allowed with {callback}.
|
||||
/// - desc (`string?`) Description (for documentation and troubleshooting).
|
||||
/// - group (`string|integer?`) Group name or id to match against.
|
||||
@@ -764,8 +765,8 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Arena *arena, E
|
||||
|
||||
FOREACH_ITEM(patterns, pat, {
|
||||
char *fname = !has_buf ? pat.data.string.data : NULL;
|
||||
did_aucmd |= apply_autocmds_group(event_nr, fname, NULL, true, au_group, b, NULL, data,
|
||||
has_buf);
|
||||
did_aucmd |= apply_autocmds_group(event_nr, fname, NULL, true, au_group, b, curwin, NULL,
|
||||
data, has_buf);
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ Window nvim_open_win(Buffer buf, Boolean enter, Dict(win_config) *config, Error
|
||||
const bool result = ctx_switch(&switchwin, wp, tp, NULL, kCtxNoDisplay);
|
||||
assert(result);
|
||||
(void)result;
|
||||
if (apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf)) {
|
||||
if (apply_autocmds_win(EVENT_WINNEW, NULL, NULL, false, curbuf, wp)) {
|
||||
tp = win_find_tabpage(wp);
|
||||
}
|
||||
ctx_restore(&switchwin);
|
||||
|
||||
@@ -88,6 +88,10 @@ static const char e_autocommand_nesting_too_deep[]
|
||||
// Code for automatic commands.
|
||||
static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands
|
||||
|
||||
/// Window handle for `ev.win`. Unlike autocmd_bufnr/_match this needn't be a
|
||||
/// global: only au_callback() reads it.
|
||||
static handle_T autocmd_winid = 0;
|
||||
|
||||
// ID for associating autocmds created via nvim_create_autocmd
|
||||
// Used to delete autocmds from nvim_del_autocmd
|
||||
static int next_augroup_id = 1;
|
||||
@@ -1165,7 +1169,7 @@ int do_doautocmd(char *arg_start, bool do_msg, bool *did_something)
|
||||
// Loop over the events.
|
||||
while (*arg && !ends_excmd(*arg) && !ascii_iswhite(*arg)) {
|
||||
if (apply_autocmds_group(event_name2nr(arg, &arg), fname, NULL, true, group,
|
||||
curbuf, NULL, NULL, false)) {
|
||||
curbuf, curwin, NULL, NULL, false)) {
|
||||
nothing_done = false;
|
||||
}
|
||||
}
|
||||
@@ -1311,9 +1315,11 @@ static void deferred_event(void **argv)
|
||||
}
|
||||
tv_dict_set_keys_readonly(v_event);
|
||||
|
||||
win_T *win = curwin; // before ctx_switch() may make the context window current
|
||||
|
||||
CtxSwitch aco = { 0 };
|
||||
ctx_switch(&aco, NULL, NULL, buf, 0);
|
||||
apply_autocmds_group(event, fname, fname_io, false, group, buf, eap, data, false);
|
||||
apply_autocmds_group(event, fname, fname_io, false, group, buf, win, eap, data, false);
|
||||
ctx_restore(&aco);
|
||||
|
||||
restore_v_event(v_event, &save_v_event);
|
||||
@@ -1359,6 +1365,8 @@ void aucmd_defer_modified(buf_T *buf, bool new_val)
|
||||
|
||||
/// Execute autocommands for "event" and file name "fname".
|
||||
///
|
||||
/// `ev.win` is curwin; use apply_autocmds_win() for window-specific events.
|
||||
///
|
||||
/// @param event event that occurred
|
||||
/// @param fname filename, NULL or empty means use actual file name
|
||||
/// @param fname_io filename to use for <afile> on cmdline
|
||||
@@ -1368,7 +1376,20 @@ void aucmd_defer_modified(buf_T *buf, bool new_val)
|
||||
/// @return true if some commands were executed.
|
||||
bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_T *buf)
|
||||
{
|
||||
return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL, NULL, false);
|
||||
return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, curwin, NULL, NULL,
|
||||
false);
|
||||
}
|
||||
|
||||
/// Like apply_autocmds(), but with an explicit window for `ev.win`.
|
||||
///
|
||||
/// @param win Window for `ev.win`, NULL for the current window.
|
||||
///
|
||||
/// @return true if some commands were executed.
|
||||
bool apply_autocmds_win(event_T event, char *fname, char *fname_io, bool force, buf_T *buf,
|
||||
win_T *win)
|
||||
{
|
||||
return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, win, NULL, NULL,
|
||||
false);
|
||||
}
|
||||
|
||||
/// Like apply_autocmds(), but with extra "eap" argument. This takes care of
|
||||
@@ -1385,7 +1406,8 @@ bool apply_autocmds(event_T event, char *fname, char *fname_io, bool force, buf_
|
||||
bool apply_autocmds_exarg(event_T event, char *fname, char *fname_io, bool force, buf_T *buf,
|
||||
exarg_T *eap)
|
||||
{
|
||||
return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, eap, NULL, false);
|
||||
return apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, curwin, eap, NULL,
|
||||
false);
|
||||
}
|
||||
|
||||
/// Like apply_autocmds(), but handles the caller's retval. If the script
|
||||
@@ -1408,8 +1430,8 @@ bool apply_autocmds_retval(event_T event, char *fname, char *fname_io, bool forc
|
||||
return false;
|
||||
}
|
||||
|
||||
bool did_cmd = apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, NULL, NULL,
|
||||
false);
|
||||
bool did_cmd = apply_autocmds_group(event, fname, fname_io, force, AUGROUP_ALL, buf, curwin, NULL,
|
||||
NULL, false);
|
||||
if (did_cmd && aborting()) {
|
||||
*retval = FAIL;
|
||||
}
|
||||
@@ -1453,12 +1475,13 @@ bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
/// @param force Ignore autocmd_busy (force "++nested" behavior)
|
||||
/// @param group autocmd group ID or AUGROUP_ALL
|
||||
/// @param buf Buffer for <abuf>
|
||||
/// @param win Window for `ev.win`, NULL for the current window.
|
||||
/// @param eap Ex command arguments
|
||||
/// @param with_buf Run callbacks with "buf" as the current buffer
|
||||
///
|
||||
/// @return true if some commands were executed.
|
||||
bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force, int group,
|
||||
buf_T *buf, exarg_T *eap, Object *data, bool with_buf)
|
||||
buf_T *buf, win_T *win, exarg_T *eap, Object *data, bool with_buf)
|
||||
{
|
||||
char *sfname = NULL; // short file name
|
||||
bool retval = false;
|
||||
@@ -1539,6 +1562,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|
||||
char *save_autocmd_fname = autocmd_fname;
|
||||
bool save_autocmd_fname_full = autocmd_fname_full;
|
||||
int save_autocmd_bufnr = autocmd_bufnr;
|
||||
handle_T save_autocmd_winid = autocmd_winid;
|
||||
char *save_autocmd_match = autocmd_match;
|
||||
int save_autocmd_busy = autocmd_busy;
|
||||
int save_autocmd_nested = autocmd_nested;
|
||||
@@ -1640,6 +1664,10 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|
||||
goto BYPASS_AU;
|
||||
}
|
||||
|
||||
// Set the window handle for `ev.win`. After the last "goto BYPASS_AU", which
|
||||
// skips the restore below, and before ctx_switch().
|
||||
autocmd_winid = win != NULL ? win->handle : (curwin != NULL ? curwin->handle : 0);
|
||||
|
||||
if (with_buf && buf != NULL && buf != curbuf) {
|
||||
ctx_switch(&aco, NULL, NULL, buf, 0);
|
||||
}
|
||||
@@ -1770,6 +1798,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
|
||||
autocmd_fname = save_autocmd_fname;
|
||||
autocmd_fname_full = save_autocmd_fname_full;
|
||||
autocmd_bufnr = save_autocmd_bufnr;
|
||||
autocmd_winid = save_autocmd_winid;
|
||||
autocmd_match = save_autocmd_match;
|
||||
current_sctx = save_current_sctx;
|
||||
restore_funccal();
|
||||
@@ -1839,7 +1868,7 @@ void do_termresponse_autocmd(const String sequence, uint64_t channel_id)
|
||||
MAXSIZE_TEMP_DICT(data, 2);
|
||||
PUT_C(data, "sequence", STRING_OBJ(sequence));
|
||||
PUT_C(data, "chan", INTEGER_OBJ((Integer)channel_id));
|
||||
apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, true, AUGROUP_ALL, NULL, NULL,
|
||||
apply_autocmds_group(EVENT_TERMRESPONSE, NULL, NULL, true, AUGROUP_ALL, NULL, curwin, NULL,
|
||||
&DICT_OBJ(data), false);
|
||||
termresponse_changed = true;
|
||||
termresponse_chan_id = channel_id;
|
||||
@@ -1945,12 +1974,13 @@ static bool au_callback(const AutoCmd *ac, const AutoPatCmd *apc)
|
||||
{
|
||||
Callback callback = ac->handler_fn;
|
||||
if (callback.type == kCallbackLua) {
|
||||
MAXSIZE_TEMP_DICT(data, 7);
|
||||
MAXSIZE_TEMP_DICT(data, 8);
|
||||
PUT_C(data, "id", INTEGER_OBJ(ac->id));
|
||||
PUT_C(data, "event", CSTR_AS_OBJ(event_nr2name(apc->event)));
|
||||
PUT_C(data, "file", CSTR_AS_OBJ(apc->afile_orig));
|
||||
PUT_C(data, "match", CSTR_AS_OBJ(autocmd_match));
|
||||
PUT_C(data, "buf", INTEGER_OBJ(autocmd_bufnr));
|
||||
PUT_C(data, "win", INTEGER_OBJ(autocmd_winid));
|
||||
|
||||
if (apc->data) {
|
||||
PUT_C(data, "data", *apc->data);
|
||||
|
||||
@@ -636,8 +636,8 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
|
||||
if (win_valid && win->w_buffer == buf && buf->b_nwindows == 1) {
|
||||
buf->b_locked++;
|
||||
buf->b_locked_split++;
|
||||
if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false,
|
||||
buf) && !bufref_valid(&bufref)) {
|
||||
if (apply_autocmds_win(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false,
|
||||
buf, win) && !bufref_valid(&bufref)) {
|
||||
// Autocommands deleted the buffer.
|
||||
emsg(_(e_auabort));
|
||||
return false;
|
||||
|
||||
@@ -4725,7 +4725,7 @@ bool before_quit_autocmds(win_T *wp, bool quit_all, bool forceit)
|
||||
if (*get_vim_var_str(VV_EXITREASON) == NUL) {
|
||||
set_vim_var_string(VV_EXITREASON, S_LEN("quit"));
|
||||
}
|
||||
apply_autocmds(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer);
|
||||
apply_autocmds_win(EVENT_QUITPRE, NULL, NULL, false, wp->w_buffer, wp);
|
||||
|
||||
// Bail out when autocommands closed the window.
|
||||
// Refuse to quit when the buffer in the last window is being closed (can
|
||||
|
||||
@@ -795,7 +795,7 @@ void getout(int exitval)
|
||||
bufref_T bufref;
|
||||
|
||||
set_bufref(&bufref, buf);
|
||||
apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false, buf);
|
||||
apply_autocmds_win(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false, buf, wp);
|
||||
if (bufref_valid(&bufref)) {
|
||||
buf_set_changedtick(buf, -1); // note that we did it already
|
||||
}
|
||||
|
||||
@@ -1184,7 +1184,7 @@ void do_autocmd_progress(MsgID msg_id, HlMessage msg, MessageData *msg_data)
|
||||
apply_autocmds_group(EVENT_PROGRESS,
|
||||
(msg_data && msg_data->source.size > 0) ? msg_data->source.data : "", NULL,
|
||||
true,
|
||||
AUGROUP_ALL, NULL, NULL, &DICT_OBJ(data), false);
|
||||
AUGROUP_ALL, NULL, curwin, NULL, &DICT_OBJ(data), false);
|
||||
kv_destroy(messages);
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ static void emit_termrequest(void **argv)
|
||||
VTERM_TERMINATOR_BEL ? STATIC_CSTR_AS_OBJ("\x07") : STATIC_CSTR_AS_OBJ("\x1b\\"));
|
||||
|
||||
term->refcount++;
|
||||
apply_autocmds_group(EVENT_TERMREQUEST, NULL, NULL, true, AUGROUP_ALL, buf, NULL,
|
||||
apply_autocmds_group(EVENT_TERMREQUEST, NULL, NULL, true, AUGROUP_ALL, buf, curwin, NULL,
|
||||
&DICT_OBJ(data), false);
|
||||
term->refcount--;
|
||||
xfree(sequence);
|
||||
@@ -744,7 +744,7 @@ void terminal_close(Terminal **termpp, int status)
|
||||
PUT_C(data, "pos", INTEGER_OBJ(pos));
|
||||
|
||||
apply_autocmds_group(EVENT_TERMCLOSE, NULL, NULL, status >= 0, AUGROUP_ALL,
|
||||
buf, NULL, &DICT_OBJ(data), false);
|
||||
buf, curwin, NULL, &DICT_OBJ(data), false);
|
||||
|
||||
restore_v_event(dict, &save_v_event);
|
||||
}
|
||||
|
||||
@@ -3119,7 +3119,7 @@ static void do_autocmd_winclosed(win_T *win)
|
||||
recursive = true;
|
||||
char winid[NUMBUFLEN];
|
||||
vim_snprintf(winid, sizeof(winid), "%d", win->handle);
|
||||
apply_autocmds(EVENT_WINCLOSED, winid, winid, false, win->w_buffer);
|
||||
apply_autocmds_win(EVENT_WINCLOSED, winid, winid, false, win->w_buffer, win);
|
||||
recursive = false;
|
||||
}
|
||||
|
||||
@@ -6084,17 +6084,21 @@ void may_trigger_win_scrolled_resized(void)
|
||||
|
||||
// Save window info before autocmds since they can free windows
|
||||
char resize_winid[NUMBUFLEN];
|
||||
win_T *resize_win = NULL;
|
||||
bufref_T resize_bufref;
|
||||
if (trigger_resize) {
|
||||
vim_snprintf(resize_winid, sizeof(resize_winid), "%d", first_size_win->handle);
|
||||
set_bufref(&resize_bufref, first_size_win->w_buffer);
|
||||
resize_win = first_size_win;
|
||||
vim_snprintf(resize_winid, sizeof(resize_winid), "%d", resize_win->handle);
|
||||
set_bufref(&resize_bufref, resize_win->w_buffer);
|
||||
}
|
||||
|
||||
char scroll_winid[NUMBUFLEN];
|
||||
win_T *scroll_win = NULL;
|
||||
bufref_T scroll_bufref;
|
||||
if (trigger_scroll) {
|
||||
vim_snprintf(scroll_winid, sizeof(scroll_winid), "%d", first_scroll_win->handle);
|
||||
set_bufref(&scroll_bufref, first_scroll_win->w_buffer);
|
||||
scroll_win = first_scroll_win;
|
||||
vim_snprintf(scroll_winid, sizeof(scroll_winid), "%d", scroll_win->handle);
|
||||
set_bufref(&scroll_bufref, scroll_win->w_buffer);
|
||||
}
|
||||
|
||||
// If both are to be triggered do WinResized first.
|
||||
@@ -6105,7 +6109,9 @@ void may_trigger_win_scrolled_resized(void)
|
||||
if (tv_dict_add_list(v_event, S_LEN("windows"), windows_list) == OK) {
|
||||
tv_dict_set_keys_readonly(v_event);
|
||||
buf_T *buf = bufref_valid(&resize_bufref) ? resize_bufref.br_buf : curbuf;
|
||||
apply_autocmds(EVENT_WINRESIZED, resize_winid, resize_winid, false, buf);
|
||||
// May have been freed by an earlier autocmd.
|
||||
win_T *win = win_valid_any_tab(resize_win) ? resize_win : curwin;
|
||||
apply_autocmds_win(EVENT_WINRESIZED, resize_winid, resize_winid, false, buf, win);
|
||||
}
|
||||
restore_v_event(v_event, &save_v_event);
|
||||
}
|
||||
@@ -6120,7 +6126,9 @@ void may_trigger_win_scrolled_resized(void)
|
||||
tv_dict_unref(scroll_dict);
|
||||
|
||||
buf_T *buf = bufref_valid(&scroll_bufref) ? scroll_bufref.br_buf : curbuf;
|
||||
apply_autocmds(EVENT_WINSCROLLED, scroll_winid, scroll_winid, false, buf);
|
||||
// May have been freed by the WinResized autocmds above.
|
||||
win_T *win = win_valid_any_tab(scroll_win) ? scroll_win : curwin;
|
||||
apply_autocmds_win(EVENT_WINSCROLLED, scroll_winid, scroll_winid, false, buf, win);
|
||||
|
||||
restore_v_event(v_event, &save_v_event);
|
||||
}
|
||||
|
||||
@@ -370,6 +370,7 @@ describe('autocmd api', function()
|
||||
event = event,
|
||||
match = amatch,
|
||||
file = exec_pat,
|
||||
win = api.nvim_get_current_win(),
|
||||
buf = 1,
|
||||
}, api.nvim_get_var('autocmd_args'))
|
||||
|
||||
@@ -392,6 +393,7 @@ describe('autocmd api', function()
|
||||
event = event,
|
||||
match = amatch,
|
||||
file = exec_pat,
|
||||
win = api.nvim_get_current_win(),
|
||||
buf = 1,
|
||||
}, api.nvim_get_var('autocmd_args'))
|
||||
end
|
||||
@@ -406,6 +408,134 @@ describe('autocmd api', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('ev.win #25844', function()
|
||||
it('is the current window for events that are not about a window', function()
|
||||
local win = api.nvim_get_current_win()
|
||||
exec_lua(function()
|
||||
vim.api.nvim_create_autocmd('BufAdd', {
|
||||
callback = function(ev)
|
||||
vim.g.ev_win = ev.win
|
||||
end,
|
||||
})
|
||||
end)
|
||||
command('badd some_file')
|
||||
eq(win, api.nvim_get_var('ev_win'))
|
||||
end)
|
||||
|
||||
it('WinClosed reports the closed window', function()
|
||||
command('split')
|
||||
local closed_win = api.nvim_get_current_win()
|
||||
exec_lua(function()
|
||||
vim.api.nvim_create_autocmd('WinClosed', {
|
||||
callback = function(ev)
|
||||
vim.g.ev_win = ev.win
|
||||
vim.g.ev_match = ev.match
|
||||
end,
|
||||
})
|
||||
end)
|
||||
command('quit')
|
||||
eq(closed_win, api.nvim_get_var('ev_win'))
|
||||
eq(tostring(closed_win), api.nvim_get_var('ev_match'))
|
||||
end)
|
||||
|
||||
it('WinNew reports the new window, not the focused one', function()
|
||||
local origin_win = api.nvim_get_current_win()
|
||||
local buf = api.nvim_create_buf(false, true)
|
||||
exec_lua(function()
|
||||
vim.api.nvim_create_autocmd('WinNew', {
|
||||
callback = function(ev)
|
||||
vim.g.ev_win = ev.win
|
||||
end,
|
||||
})
|
||||
end)
|
||||
local new_win = api.nvim_open_win(buf, false, {
|
||||
relative = 'editor',
|
||||
row = 0,
|
||||
col = 0,
|
||||
width = 10,
|
||||
height = 5,
|
||||
})
|
||||
eq(origin_win, api.nvim_get_current_win())
|
||||
eq(new_win, api.nvim_get_var('ev_win'))
|
||||
end)
|
||||
|
||||
it('WinResized reports the resized window, not curwin', function()
|
||||
local top_win = api.nvim_get_current_win()
|
||||
command('botright split')
|
||||
local bot_win = api.nvim_get_current_win()
|
||||
neq(top_win, bot_win)
|
||||
command('redraw') -- flush the WinResized caused by the split itself
|
||||
exec_lua(function()
|
||||
vim.api.nvim_create_autocmd('WinResized', {
|
||||
callback = function(ev)
|
||||
vim.g.ev_win = ev.win
|
||||
vim.g.ev_match = ev.match
|
||||
vim.g.ev_curwin = vim.api.nvim_get_current_win()
|
||||
end,
|
||||
})
|
||||
end)
|
||||
command('resize 3')
|
||||
command('redraw')
|
||||
-- ev.win is the first window whose size changed, matching <amatch>.
|
||||
eq(top_win, api.nvim_get_var('ev_win'))
|
||||
eq(tostring(top_win), api.nvim_get_var('ev_match'))
|
||||
eq(bot_win, api.nvim_get_var('ev_curwin'))
|
||||
end)
|
||||
|
||||
it('WinScrolled reports the scrolled window, not curwin', function()
|
||||
command('split')
|
||||
local scrolled = api.nvim_get_current_win()
|
||||
exec_lua(function()
|
||||
local lines = {}
|
||||
for i = 1, 30 do
|
||||
lines[i] = 'line ' .. i
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
|
||||
end)
|
||||
command('wincmd w')
|
||||
neq(scrolled, api.nvim_get_current_win())
|
||||
command('redraw')
|
||||
exec_lua(function(scroll_win)
|
||||
vim.api.nvim_create_autocmd('WinScrolled', {
|
||||
callback = function(ev)
|
||||
vim.g.ev_win = ev.win
|
||||
vim.g.ev_match = ev.match
|
||||
vim.g.ev_curwin = vim.api.nvim_get_current_win()
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_win_call(scroll_win, function()
|
||||
vim.cmd('normal! G')
|
||||
end)
|
||||
end, scrolled)
|
||||
command('redraw')
|
||||
eq(scrolled, api.nvim_get_var('ev_win'))
|
||||
eq(tostring(scrolled), api.nvim_get_var('ev_match'))
|
||||
neq(scrolled, api.nvim_get_var('ev_curwin'))
|
||||
end)
|
||||
|
||||
it('is restored after a nested autocmd', function()
|
||||
command('edit a')
|
||||
command('rightbelow vsplit b')
|
||||
command('wincmd w')
|
||||
local trigger_win = api.nvim_get_current_win()
|
||||
exec_lua(function()
|
||||
-- Fires BufLeave/WinLeave/WinEnter/BufEnter, each with its own ev.win.
|
||||
vim.api.nvim_create_autocmd('ColorScheme', {
|
||||
callback = function()
|
||||
vim.cmd('wincmd w')
|
||||
end,
|
||||
})
|
||||
vim.api.nvim_create_autocmd('ColorScheme', {
|
||||
callback = function(ev)
|
||||
vim.g.ev_win = ev.win
|
||||
end,
|
||||
})
|
||||
end)
|
||||
command('colorscheme blue')
|
||||
eq(trigger_win, api.nvim_get_var('ev_win'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('can receive arbitrary data', function()
|
||||
local function test(data)
|
||||
eq(
|
||||
|
||||
Reference in New Issue
Block a user