aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/auevents.lua285
-rw-r--r--src/nvim/autocmd.c77
-rw-r--r--src/nvim/buffer_defs.h2
-rw-r--r--src/nvim/generators/gen_events.lua49
-rw-r--r--src/nvim/generators/gen_vimvim.lua18
-rw-r--r--src/nvim/option.c5
-rw-r--r--src/nvim/options.lua17
-rw-r--r--src/nvim/optionstr.c15
-rw-r--r--src/nvim/window.c56
9 files changed, 266 insertions, 258 deletions
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 84735c293a..9655fef0a4 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -1,156 +1,139 @@
return {
+ --- @type [string, string[], boolean][] List of [eventname, aliases, window-local event] tuples.
events = {
- 'BufAdd', -- after adding a buffer to the buffer list
- 'BufDelete', -- deleting a buffer from the buffer list
- 'BufEnter', -- after entering a buffer
- 'BufFilePost', -- after renaming a buffer
- 'BufFilePre', -- before renaming a buffer
- 'BufHidden', -- just after buffer becomes hidden
- 'BufLeave', -- before leaving a buffer
- 'BufModifiedSet', -- after the 'modified' state of a buffer changes
- 'BufNew', -- after creating any buffer
- 'BufNewFile', -- when creating a buffer for a new file
- 'BufReadCmd', -- read buffer using command
- 'BufReadPost', -- after reading a buffer
- 'BufReadPre', -- before reading a buffer
- 'BufUnload', -- just before unloading a buffer
- 'BufWinEnter', -- after showing a buffer in a window
- 'BufWinLeave', -- just after buffer removed from window
- 'BufWipeout', -- just before really deleting a buffer
- 'BufWriteCmd', -- write buffer using command
- 'BufWritePost', -- after writing a buffer
- 'BufWritePre', -- before writing a buffer
- 'ChanInfo', -- info was received about channel
- 'ChanOpen', -- channel was opened
- 'CmdUndefined', -- command undefined
- 'CmdWinEnter', -- after entering the cmdline window
- 'CmdWinLeave', -- before leaving the cmdline window
- 'CmdlineChanged', -- command line was modified
- 'CmdlineEnter', -- after entering cmdline mode
- 'CmdlineLeave', -- before leaving cmdline mode
- 'ColorScheme', -- after loading a colorscheme
- 'ColorSchemePre', -- before loading a colorscheme
- 'CompleteChanged', -- after popup menu changed
- 'CompleteDone', -- after finishing insert complete
- 'CompleteDonePre', -- idem, before clearing info
- 'CursorHold', -- cursor in same position for a while
- 'CursorHoldI', -- idem, in Insert mode
- 'CursorMoved', -- cursor was moved
- 'CursorMovedC', -- cursor was moved in Cmdline mode
- 'CursorMovedI', -- cursor was moved in Insert mode
- 'DiagnosticChanged', -- diagnostics in a buffer were modified
- 'DiffUpdated', -- diffs have been updated
- 'DirChanged', -- directory changed
- 'DirChangedPre', -- directory is going to change
- 'EncodingChanged', -- after changing the 'encoding' option
- 'ExitPre', -- before exiting
- 'FileAppendCmd', -- append to a file using command
- 'FileAppendPost', -- after appending to a file
- 'FileAppendPre', -- before appending to a file
- 'FileChangedRO', -- before first change to read-only file
- 'FileChangedShell', -- after shell command that changed file
- 'FileChangedShellPost', -- after (not) reloading changed file
- 'FileReadCmd', -- read from a file using command
- 'FileReadPost', -- after reading a file
- 'FileReadPre', -- before reading a file
- 'FileType', -- new file type detected (user defined)
- 'FileWriteCmd', -- write to a file using command
- 'FileWritePost', -- after writing a file
- 'FileWritePre', -- before writing a file
- 'FilterReadPost', -- after reading from a filter
- 'FilterReadPre', -- before reading from a filter
- 'FilterWritePost', -- after writing to a filter
- 'FilterWritePre', -- before writing to a filter
- 'FocusGained', -- got the focus
- 'FocusLost', -- lost the focus to another app
- 'FuncUndefined', -- if calling a function which doesn't exist
- 'GUIEnter', -- after starting the GUI
- 'GUIFailed', -- after starting the GUI failed
- 'InsertChange', -- when changing Insert/Replace mode
- 'InsertCharPre', -- before inserting a char
- 'InsertEnter', -- when entering Insert mode
- 'InsertLeave', -- just after leaving Insert mode
- 'InsertLeavePre', -- just before leaving Insert mode
- 'LspAttach', -- after an LSP client attaches to a buffer
- 'LspDetach', -- after an LSP client detaches from a buffer
- 'LspNotify', -- after an LSP notice has been sent to the server
- 'LspProgress', -- after a LSP progress update
- 'LspRequest', -- after an LSP request is started, canceled, or completed
- 'LspTokenUpdate', -- after a visible LSP token is updated
- 'MenuPopup', -- just before popup menu is displayed
- 'ModeChanged', -- after changing the mode
- 'OptionSet', -- after setting any option
- 'QuickFixCmdPost', -- after :make, :grep etc.
- 'QuickFixCmdPre', -- before :make, :grep etc.
- 'QuitPre', -- before :quit
- 'RecordingEnter', -- when starting to record a macro
- 'RecordingLeave', -- just before a macro stops recording
- 'RemoteReply', -- upon string reception from a remote vim
- 'SafeState', -- going to wait for a character
- 'SearchWrapped', -- after the search wrapped around
- 'SessionLoadPost', -- after loading a session file
- 'SessionWritePost', -- after writing a session file
- 'ShellCmdPost', -- after ":!cmd"
- 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd".
- 'Signal', -- after nvim process received a signal
- 'SourceCmd', -- sourcing a Vim script using command
- 'SourcePost', -- after sourcing a Vim script
- 'SourcePre', -- before sourcing a Vim script
- 'SpellFileMissing', -- spell file missing
- 'StdinReadPost', -- after reading from stdin
- 'StdinReadPre', -- before reading from stdin
- 'SwapExists', -- found existing swap file
- 'Syntax', -- syntax selected
- 'TabClosed', -- a tab has closed
- 'TabEnter', -- after entering a tab page
- 'TabLeave', -- before leaving a tab page
- 'TabNew', -- when creating a new tab
- 'TabNewEntered', -- after entering a new tab
- 'TermChanged', -- after changing 'term'
- 'TermClose', -- after the process exits
- 'TermEnter', -- after entering Terminal mode
- 'TermLeave', -- after leaving Terminal mode
- 'TermOpen', -- after opening a terminal buffer
- 'TermRequest', -- after an unhandled OSC sequence is emitted
- 'TermResponse', -- after setting "v:termresponse"
- 'TextChanged', -- text was modified
- 'TextChangedI', -- text was modified in Insert mode(no popup)
- 'TextChangedP', -- text was modified in Insert mode(popup)
- 'TextChangedT', -- text was modified in Terminal mode
- 'TextYankPost', -- after a yank or delete was done (y, d, c)
- 'UIEnter', -- after UI attaches
- 'UILeave', -- after UI detaches
- 'User', -- user defined autocommand
- 'VimEnter', -- after starting Vim
- 'VimLeave', -- before exiting Vim
- 'VimLeavePre', -- before exiting Vim and writing ShaDa file
- 'VimResized', -- after Vim window was resized
- 'VimResume', -- after Nvim is resumed
- 'VimSuspend', -- before Nvim is suspended
- 'WinClosed', -- after closing a window
- 'WinEnter', -- after entering a window
- 'WinLeave', -- before leaving a window
- 'WinNew', -- when entering a new window
- 'WinResized', -- after a window was resized
- 'WinScrolled', -- after a window was scrolled or resized
- },
- aliases = {
- {
- 'BufCreate',
- 'BufAdd',
- },
- {
- 'BufRead',
- 'BufReadPost',
- },
- {
- 'BufWrite',
- 'BufWritePre',
- },
- {
- 'FileEncoding',
- 'EncodingChanged',
- },
+ { 'BufAdd', { 'BufCreate' }, true }, -- after adding a buffer to the buffer list
+ { 'BufDelete', {}, true }, -- deleting a buffer from the buffer list
+ { 'BufEnter', {}, true }, -- after entering a buffer
+ { 'BufFilePost', {}, true }, -- after renaming a buffer
+ { 'BufFilePre', {}, true }, -- before renaming a buffer
+ { 'BufHidden', {}, true }, -- just after buffer becomes hidden
+ { 'BufLeave', {}, true }, -- before leaving a buffer
+ { 'BufModifiedSet', {}, true }, -- after the 'modified' state of a buffer changes
+ { 'BufNew', {}, true }, -- after creating any buffer
+ { 'BufNewFile', {}, true }, -- when creating a buffer for a new file
+ { 'BufReadCmd', {}, true }, -- read buffer using command
+ { 'BufReadPost', { 'BufRead' }, true }, -- after reading a buffer
+ { 'BufReadPre', {}, true }, -- before reading a buffer
+ { 'BufUnload', {}, true }, -- just before unloading a buffer
+ { 'BufWinEnter', {}, true }, -- after showing a buffer in a window
+ { 'BufWinLeave', {}, true }, -- just after buffer removed from window
+ { 'BufWipeout', {}, true }, -- just before really deleting a buffer
+ { 'BufWriteCmd', {}, true }, -- write buffer using command
+ { 'BufWritePost', {}, true }, -- after writing a buffer
+ { 'BufWritePre', { 'BufWrite' }, true }, -- before writing a buffer
+ { 'ChanInfo', {}, false }, -- info was received about channel
+ { 'ChanOpen', {}, false }, -- channel was opened
+ { 'CmdUndefined', {}, false }, -- command undefined
+ { 'CmdWinEnter', {}, false }, -- after entering the cmdline window
+ { 'CmdWinLeave', {}, false }, -- before leaving the cmdline window
+ { 'CmdlineChanged', {}, false }, -- command line was modified
+ { 'CmdlineEnter', {}, false }, -- after entering cmdline mode
+ { 'CmdlineLeave', {}, false }, -- before leaving cmdline mode
+ { 'ColorScheme', {}, false }, -- after loading a colorscheme
+ { 'ColorSchemePre', {}, false }, -- before loading a colorscheme
+ { 'CompleteChanged', {}, false }, -- after popup menu changed
+ { 'CompleteDone', {}, false }, -- after finishing insert complete
+ { 'CompleteDonePre', {}, false }, -- idem, before clearing info
+ { 'CursorHold', {}, true }, -- cursor in same position for a while
+ { 'CursorHoldI', {}, true }, -- idem, in Insert mode
+ { 'CursorMoved', {}, true }, -- cursor was moved
+ { 'CursorMovedC', {}, true }, -- cursor was moved in Cmdline mode
+ { 'CursorMovedI', {}, true }, -- cursor was moved in Insert mode
+ { 'DiagnosticChanged', {}, false }, -- diagnostics in a buffer were modified
+ { 'DiffUpdated', {}, false }, -- diffs have been updated
+ { 'DirChanged', {}, false }, -- directory changed
+ { 'DirChangedPre', {}, false }, -- directory is going to change
+ { 'EncodingChanged', { 'FileEncoding' }, false }, -- after changing the 'encoding' option
+ { 'ExitPre', {}, false }, -- before exiting
+ { 'FileAppendCmd', {}, true }, -- append to a file using command
+ { 'FileAppendPost', {}, true }, -- after appending to a file
+ { 'FileAppendPre', {}, true }, -- before appending to a file
+ { 'FileChangedRO', {}, true }, -- before first change to read-only file
+ { 'FileChangedShell', {}, true }, -- after shell command that changed file
+ { 'FileChangedShellPost', {}, true }, -- after (not) reloading changed file
+ { 'FileReadCmd', {}, true }, -- read from a file using command
+ { 'FileReadPost', {}, true }, -- after reading a file
+ { 'FileReadPre', {}, true }, -- before reading a file
+ { 'FileType', {}, true }, -- new file type detected (user defined)
+ { 'FileWriteCmd', {}, true }, -- write to a file using command
+ { 'FileWritePost', {}, true }, -- after writing a file
+ { 'FileWritePre', {}, true }, -- before writing a file
+ { 'FilterReadPost', {}, true }, -- after reading from a filter
+ { 'FilterReadPre', {}, true }, -- before reading from a filter
+ { 'FilterWritePost', {}, true }, -- after writing to a filter
+ { 'FilterWritePre', {}, true }, -- before writing to a filter
+ { 'FocusGained', {}, false }, -- got the focus
+ { 'FocusLost', {}, false }, -- lost the focus to another app
+ { 'FuncUndefined', {}, false }, -- if calling a function which doesn't exist
+ { 'GUIEnter', {}, false }, -- after starting the GUI
+ { 'GUIFailed', {}, false }, -- after starting the GUI failed
+ { 'InsertChange', {}, true }, -- when changing Insert/Replace mode
+ { 'InsertCharPre', {}, true }, -- before inserting a char
+ { 'InsertEnter', {}, true }, -- when entering Insert mode
+ { 'InsertLeave', {}, true }, -- just after leaving Insert mode
+ { 'InsertLeavePre', {}, true }, -- just before leaving Insert mode
+ { 'LspAttach', {}, false }, -- after an LSP client attaches to a buffer
+ { 'LspDetach', {}, false }, -- after an LSP client detaches from a buffer
+ { 'LspNotify', {}, false }, -- after an LSP notice has been sent to the server
+ { 'LspProgress', {}, false }, -- after a LSP progress update
+ { 'LspRequest', {}, false }, -- after an LSP request is started, canceled, or completed
+ { 'LspTokenUpdate', {}, false }, -- after a visible LSP token is updated
+ { 'MenuPopup', {}, false }, -- just before popup menu is displayed
+ { 'ModeChanged', {}, false }, -- after changing the mode
+ { 'OptionSet', {}, false }, -- after setting any option
+ { 'QuickFixCmdPost', {}, false }, -- after :make, :grep etc.
+ { 'QuickFixCmdPre', {}, false }, -- before :make, :grep etc.
+ { 'QuitPre', {}, false }, -- before :quit
+ { 'RecordingEnter', {}, true }, -- when starting to record a macro
+ { 'RecordingLeave', {}, true }, -- just before a macro stops recording
+ { 'RemoteReply', {}, false }, -- upon string reception from a remote vim
+ { 'SafeState', {}, false }, -- going to wait for a character
+ { 'SearchWrapped', {}, true }, -- after the search wrapped around
+ { 'SessionLoadPost', {}, false }, -- after loading a session file
+ { 'SessionWritePost', {}, false }, -- after writing a session file
+ { 'ShellCmdPost', {}, false }, -- after ":!cmd"
+ { 'ShellFilterPost', {}, true }, -- after ":1,2!cmd", ":w !cmd", ":r !cmd".
+ { 'Signal', {}, false }, -- after nvim process received a signal
+ { 'SourceCmd', {}, false }, -- sourcing a Vim script using command
+ { 'SourcePost', {}, false }, -- after sourcing a Vim script
+ { 'SourcePre', {}, false }, -- before sourcing a Vim script
+ { 'SpellFileMissing', {}, false }, -- spell file missing
+ { 'StdinReadPost', {}, false }, -- after reading from stdin
+ { 'StdinReadPre', {}, false }, -- before reading from stdin
+ { 'SwapExists', {}, false }, -- found existing swap file
+ { 'Syntax', {}, false }, -- syntax selected
+ { 'TabClosed', {}, false }, -- a tab has closed
+ { 'TabEnter', {}, false }, -- after entering a tab page
+ { 'TabLeave', {}, false }, -- before leaving a tab page
+ { 'TabNew', {}, false }, -- when creating a new tab
+ { 'TabNewEntered', {}, false }, -- after entering a new tab
+ { 'TermChanged', {}, false }, -- after changing 'term'
+ { 'TermClose', {}, false }, -- after the process exits
+ { 'TermEnter', {}, false }, -- after entering Terminal mode
+ { 'TermLeave', {}, false }, -- after leaving Terminal mode
+ { 'TermOpen', {}, false }, -- after opening a terminal buffer
+ { 'TermRequest', {}, false }, -- after an unhandled OSC sequence is emitted
+ { 'TermResponse', {}, false }, -- after setting "v:termresponse"
+ { 'TextChanged', {}, true }, -- text was modified
+ { 'TextChangedI', {}, true }, -- text was modified in Insert mode(no popup)
+ { 'TextChangedP', {}, true }, -- text was modified in Insert mode(popup)
+ { 'TextChangedT', {}, true }, -- text was modified in Terminal mode
+ { 'TextYankPost', {}, true }, -- after a yank or delete was done (y, d, c)
+ { 'UIEnter', {}, false }, -- after UI attaches
+ { 'UILeave', {}, false }, -- after UI detaches
+ { 'User', {}, false }, -- user defined autocommand
+ { 'VimEnter', {}, false }, -- after starting Vim
+ { 'VimLeave', {}, false }, -- before exiting Vim
+ { 'VimLeavePre', {}, false }, -- before exiting Vim and writing ShaDa file
+ { 'VimResized', {}, false }, -- after Vim window was resized
+ { 'VimResume', {}, false }, -- after Nvim is resumed
+ { 'VimSuspend', {}, false }, -- before Nvim is suspended
+ { 'WinClosed', {}, true }, -- after closing a window
+ { 'WinEnter', {}, true }, -- after entering a window
+ { 'WinLeave', {}, true }, -- before leaving a window
+ { 'WinNew', {}, false }, -- when entering a new window
+ { 'WinResized', {}, true }, -- after a window was resized
+ { 'WinScrolled', {}, true }, -- after a window was scrolled or resized
},
-- List of nvim-specific events or aliases for the purpose of generating
-- syntax file
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 96da4695de..ad27823667 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -634,7 +634,7 @@ event_T event_name2nr(const char *start, char **end)
if (event_names[i].name == NULL) {
return NUM_EVENTS;
}
- return event_names[i].event;
+ return (event_T)abs(event_names[i].event);
}
/// Return the event number for event name "str".
@@ -643,7 +643,7 @@ event_T event_name2nr_str(String str)
{
for (int i = 0; event_names[i].name != NULL; i++) {
if (str.size == event_names[i].len && STRNICMP(str.data, event_names[i].name, str.size) == 0) {
- return event_names[i].event;
+ return (event_T)abs(event_names[i].event);
}
}
return NUM_EVENTS;
@@ -658,25 +658,23 @@ const char *event_nr2name(event_T event)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
{
for (int i = 0; event_names[i].name != NULL; i++) {
- if (event_names[i].event == event) {
+ if ((event_T)abs(event_names[i].event) == event) {
return event_names[i].name;
}
}
return "Unknown";
}
-/// Return true if "event" is included in 'eventignore'.
+/// Return true if "event" is included in 'eventignore(win)'.
///
/// @param event event to check
-static bool event_ignored(event_T event)
+bool event_ignored(event_T event, char *ei)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- char *p = p_ei;
-
- while (*p != NUL) {
- if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
+ while (*ei != NUL) {
+ if (STRNICMP(ei, "all", 3) == 0 && (ei[3] == NUL || ei[3] == ',')) {
return true;
- } else if (event_name2nr(p, &p) == event) {
+ } else if (event_name2nr(ei, &ei) == event) {
return true;
}
}
@@ -684,19 +682,23 @@ static bool event_ignored(event_T event)
return false;
}
-// Return OK when the contents of p_ei is valid, FAIL otherwise.
-int check_ei(void)
+/// Return OK when the contents of 'eventignore' or 'eventignorewin' is valid,
+/// FAIL otherwise.
+int check_ei(char *ei)
{
- char *p = p_ei;
+ bool win = ei != p_ei;
- while (*p) {
- if (STRNICMP(p, "all", 3) == 0 && (p[3] == NUL || p[3] == ',')) {
- p += 3;
- if (*p == ',') {
- p++;
+ while (*ei) {
+ if (STRNICMP(ei, "all", 3) == 0 && (ei[3] == NUL || ei[3] == ',')) {
+ ei += 3;
+ if (*ei == ',') {
+ ei++;
+ }
+ } else {
+ event_T event = event_name2nr(ei, &ei);
+ if (event == NUM_EVENTS || (win && event_names[event].event > 0)) {
+ return FAIL;
}
- } else if (event_name2nr(p, &p) == NUM_EVENTS) {
- return FAIL;
}
}
@@ -1631,7 +1633,24 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
}
// Ignore events in 'eventignore'.
- if (event_ignored(event)) {
+ if (event_ignored(event, p_ei)) {
+ goto BYPASS_AU;
+ }
+
+ bool win_ignore = false;
+ // If event is allowed in 'eventignorewin', check if curwin or all windows
+ // into "buf" are ignoring the event.
+ if (buf == curbuf && event_names[event].event <= 0) {
+ win_ignore = event_ignored(event, curwin->w_p_eiw);
+ } else if (buf != NULL && event_names[event].event <= 0) {
+ for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
+ WinInfo *wip = kv_A(buf->b_wininfo, i);
+ if (wip->wi_win != NULL && wip->wi_win->w_buffer == buf) {
+ win_ignore = event_ignored(event, wip->wi_win->w_p_eiw);
+ }
+ }
+ }
+ if (win_ignore) {
goto BYPASS_AU;
}
@@ -2279,9 +2298,21 @@ char *expand_get_event_name(expand_T *xp, int idx)
/// Function given to ExpandGeneric() to obtain the list of event names. Don't
/// include groups.
-char *get_event_name_no_group(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+char *get_event_name_no_group(expand_T *xp FUNC_ATTR_UNUSED, int idx, bool win)
{
- return event_names[idx].name;
+ if (!win) {
+ return event_names[idx].name;
+ }
+
+ // Need to check subset of allowed values for 'eventignorewin'.
+ int j = 0;
+ for (int i = 0; i < NUM_EVENTS; i++) {
+ j += event_names[i].event <= 0;
+ if (j == idx + 1) {
+ return event_names[i].name;
+ }
+ }
+ return NULL;
}
/// Check whether given autocommand is supported
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index bffb29578f..28029d0249 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -96,6 +96,8 @@ typedef struct {
int wo_diff;
#define w_p_diff w_onebuf_opt.wo_diff // 'diff'
char *wo_fdc;
+#define w_p_eiw w_onebuf_opt.wo_eiw // 'eventignorewin'
+ char *wo_eiw;
#define w_p_fdc w_onebuf_opt.wo_fdc // 'foldcolumn'
char *wo_fdc_save;
#define w_p_fdc_save w_onebuf_opt.wo_fdc_save // 'fdc' saved for diff mode
diff --git a/src/nvim/generators/gen_events.lua b/src/nvim/generators/gen_events.lua
index ee48e918e8..8c87815a74 100644
--- a/src/nvim/generators/gen_events.lua
+++ b/src/nvim/generators/gen_events.lua
@@ -3,7 +3,6 @@ local names_file = arg[2]
local auevents = require('auevents')
local events = auevents.events
-local aliases = auevents.aliases
local enum_tgt = io.open(fileio_enum_file, 'w')
local names_tgt = io.open(names_file, 'w')
@@ -16,46 +15,28 @@ names_tgt:write([[
static const struct event_name {
size_t len;
char *name;
- event_T event;
+ int event;
} event_names[] = {]])
+local aliases = 0
for i, event in ipairs(events) do
- enum_tgt:write(('\n EVENT_%s = %u,'):format(event:upper(), i - 1))
- names_tgt:write(('\n {%u, "%s", EVENT_%s},'):format(#event, event, event:upper()))
+ enum_tgt:write(('\n EVENT_%s = %u,'):format(event[1]:upper(), i + aliases - 1))
+ -- Events with positive keys aren't allowed in 'eventignorewin'.
+ local event_int = ('%sEVENT_%s'):format(event[3] and '-' or '', event[1]:upper())
+ names_tgt:write(('\n {%u, "%s", %s},'):format(#event[1], event[1], event_int))
+ for _, alias in ipairs(event[2]) do
+ aliases = aliases + 1
+ names_tgt:write(('\n {%u, "%s", %s},'):format(#alias, alias, event_int))
+ enum_tgt:write(('\n EVENT_%s = %u,'):format(alias:upper(), i + aliases - 1))
+ end
if i == #events then -- Last item.
- enum_tgt:write(('\n NUM_EVENTS = %u,'):format(i))
+ enum_tgt:write(('\n NUM_EVENTS = %u,'):format(i + aliases))
end
end
-for _, v in ipairs(aliases) do
- local alias = v[1]
- local event = v[2]
- names_tgt:write(('\n {%u, "%s", EVENT_%s},'):format(#alias, alias, event:upper()))
-end
-
-names_tgt:write('\n {0, NULL, (event_T)0},')
+names_tgt:write('\n {0, NULL, (event_T)0},\n};\n')
+names_tgt:write('\nstatic AutoCmdVec autocmds[NUM_EVENTS] = { 0 };\n')
+names_tgt:close()
enum_tgt:write('\n} event_T;\n')
-names_tgt:write('\n};\n')
-
-do
- names_tgt:write('\nstatic AutoCmdVec autocmds[NUM_EVENTS] = {\n ')
- local line_len = 1
- for _ = 1, (#events - 1) do
- line_len = line_len + #' KV_INITIAL_VALUE,'
- if line_len > 80 then
- names_tgt:write('\n ')
- line_len = 1 + #' KV_INITIAL_VALUE,'
- end
- names_tgt:write(' KV_INITIAL_VALUE,')
- end
- if line_len + #' KV_INITIAL_VALUE' > 80 then
- names_tgt:write('\n KV_INITIAL_VALUE')
- else
- names_tgt:write(' KV_INITIAL_VALUE')
- end
- names_tgt:write('\n};\n')
-end
-
enum_tgt:close()
-names_tgt:close()
diff --git a/src/nvim/generators/gen_vimvim.lua b/src/nvim/generators/gen_vimvim.lua
index d8053822bf..3817735a55 100644
--- a/src/nvim/generators/gen_vimvim.lua
+++ b/src/nvim/generators/gen_vimvim.lua
@@ -114,19 +114,19 @@ local vimau_start = 'syn keyword vimAutoEvent contained '
w('\n\n' .. vimau_start)
for _, au in ipairs(auevents.events) do
- if not auevents.nvim_specific[au] then
+ if not auevents.nvim_specific[au[1]] then
if lld.line_length > 850 then
w('\n' .. vimau_start)
end
- w(' ' .. au)
- end
-end
-for _, au in pairs(auevents.aliases) do
- if lld.line_length > 850 then
- w('\n' .. vimau_start)
+ w(' ' .. au[1])
+ for _, alias in ipairs(au[2]) do
+ if lld.line_length > 850 then
+ w('\n' .. vimau_start)
+ end
+ -- au[1] is aliased to alias
+ w(' ' .. alias)
+ end
end
- -- au[1] is aliased to au[2]
- w(' ' .. au[1])
end
local nvimau_start = 'syn keyword nvimAutoEvent contained '
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 796165453c..f92ec349da 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4580,6 +4580,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
return &(win->w_p_cc);
case kOptDiff:
return &(win->w_p_diff);
+ case kOptEventignorewin:
+ return &(win->w_p_eiw);
case kOptFoldcolumn:
return &(win->w_p_fdc);
case kOptFoldenable:
@@ -4875,6 +4877,7 @@ void copy_winopt(winopt_T *from, winopt_T *to)
to->wo_cc = copy_option_val(from->wo_cc);
to->wo_diff = from->wo_diff;
to->wo_diff_saved = from->wo_diff_saved;
+ to->wo_eiw = copy_option_val(from->wo_eiw);
to->wo_cocu = copy_option_val(from->wo_cocu);
to->wo_cole = from->wo_cole;
to->wo_fdc = copy_option_val(from->wo_fdc);
@@ -4919,6 +4922,7 @@ static void check_winopt(winopt_T *wop)
check_string_option(&wop->wo_fde);
check_string_option(&wop->wo_fdt);
check_string_option(&wop->wo_fmr);
+ check_string_option(&wop->wo_eiw);
check_string_option(&wop->wo_scl);
check_string_option(&wop->wo_rlc);
check_string_option(&wop->wo_sbr);
@@ -4946,6 +4950,7 @@ void clear_winopt(winopt_T *wop)
clear_string_option(&wop->wo_fde);
clear_string_option(&wop->wo_fdt);
clear_string_option(&wop->wo_fmr);
+ clear_string_option(&wop->wo_eiw);
clear_string_option(&wop->wo_scl);
clear_string_option(&wop->wo_rlc);
clear_string_option(&wop->wo_sbr);
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 99ac9d61ad..36799e9a24 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2628,6 +2628,23 @@ local options = {
varname = 'p_ei',
},
{
+ abbreviation = 'eiw',
+ cb = 'did_set_eventignore',
+ defaults = '',
+ deny_duplicates = true,
+ desc = [=[
+ Similar to 'eventignore' but applies to a particular window and its
+ buffers, for which window and buffer related autocommands can be
+ ignored indefinitely without affecting the global 'eventignore'.
+ ]=],
+ expand_cb = 'expand_set_eventignore',
+ full_name = 'eventignorewin',
+ list = 'onecomma',
+ scope = { 'win' },
+ short_desc = N_('autocommand events that are ignored in a window'),
+ type = 'string',
+ },
+ {
abbreviation = 'et',
defaults = false,
desc = [=[
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 645bb23638..3a6b4c9936 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -1082,27 +1082,32 @@ int expand_set_encoding(optexpand_T *args, int *numMatches, char ***matches)
return expand_set_opt_generic(args, get_encoding_name, numMatches, matches);
}
-/// The 'eventignore' option is changed.
-const char *did_set_eventignore(optset_T *args FUNC_ATTR_UNUSED)
+/// The 'eventignore(win)' option is changed.
+const char *did_set_eventignore(optset_T *args)
{
- if (check_ei() == FAIL) {
+ char **varp = (char **)args->os_varp;
+
+ if (check_ei(*varp) == FAIL) {
return e_invarg;
}
return NULL;
}
+static bool expand_eiw = false;
+
static char *get_eventignore_name(expand_T *xp, int idx)
{
- // 'eventignore' allows special keyword "all" in addition to
+ // 'eventignore(win)' allows special keyword "all" in addition to
// all event names.
if (idx == 0) {
return "all";
}
- return get_event_name_no_group(xp, idx - 1);
+ return get_event_name_no_group(xp, idx - 1, expand_eiw);
}
int expand_set_eventignore(optexpand_T *args, int *numMatches, char ***matches)
{
+ expand_eiw = args->oe_varp != (char *)&p_ei;
return expand_set_opt_generic(args, get_eventignore_name, numMatches, matches);
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index fa2bfec138..1fa31f10b1 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -5530,31 +5530,20 @@ static dict_T *make_win_info_dict(int width, int height, int topline, int topfil
return NULL;
}
-/// Return values of check_window_scroll_resize():
-enum {
- CWSR_SCROLLED = 1, ///< at least one window scrolled
- CWSR_RESIZED = 2, ///< at least one window size changed
-};
-
/// This function is used for three purposes:
-/// 1. Goes over all windows in the current tab page and returns:
-/// 0 no scrolling and no size changes found
-/// CWSR_SCROLLED at least one window scrolled
-/// CWSR_RESIZED at least one window changed size
-/// CWSR_SCROLLED + CWSR_RESIZED both
-/// "size_count" is set to the nr of windows with size changes.
-/// "first_scroll_win" is set to the first window with any relevant changes.
-/// "first_size_win" is set to the first window with size changes.
+/// 1. Goes over all windows in the current tab page and sets:
+/// "size_count" to the nr of windows with size changes.
+/// "first_scroll_win" to the first window with any relevant changes.
+/// "first_size_win" to the first window with size changes.
///
/// 2. When the first three arguments are NULL and "winlist" is not NULL,
/// "winlist" is set to the list of window IDs with size changes.
///
/// 3. When the first three arguments are NULL and "v_event" is not NULL,
/// information about changed windows is added to "v_event".
-static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
- win_T **first_size_win, list_T *winlist, dict_T *v_event)
+static void check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
+ win_T **first_size_win, list_T *winlist, dict_T *v_event)
{
- int result = 0;
// int listidx = 0;
int tot_width = 0;
int tot_height = 0;
@@ -5576,10 +5565,11 @@ static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
continue;
}
- const bool size_changed = wp->w_last_width != wp->w_width
- || wp->w_last_height != wp->w_height;
+ const bool ignore_scroll = event_ignored(EVENT_WINSCROLLED, wp->w_p_eiw);
+ const bool size_changed = !event_ignored(EVENT_WINRESIZED, wp->w_p_eiw)
+ && (wp->w_last_width != wp->w_width
+ || wp->w_last_height != wp->w_height);
if (size_changed) {
- result |= CWSR_RESIZED;
if (winlist != NULL) {
// Add this window to the list of changed windows.
typval_T tv = {
@@ -5597,21 +5587,19 @@ static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
}
// For WinScrolled the first window with a size change is used
// even when it didn't scroll.
- if (*first_scroll_win == NULL) {
+ if (*first_scroll_win == NULL && !ignore_scroll) {
*first_scroll_win = wp;
}
}
}
- const bool scroll_changed = wp->w_last_topline != wp->w_topline
- || wp->w_last_topfill != wp->w_topfill
- || wp->w_last_leftcol != wp->w_leftcol
- || wp->w_last_skipcol != wp->w_skipcol;
- if (scroll_changed) {
- result |= CWSR_SCROLLED;
- if (first_scroll_win != NULL && *first_scroll_win == NULL) {
- *first_scroll_win = wp;
- }
+ const bool scroll_changed = !ignore_scroll
+ && (wp->w_last_topline != wp->w_topline
+ || wp->w_last_topfill != wp->w_topfill
+ || wp->w_last_leftcol != wp->w_leftcol
+ || wp->w_last_skipcol != wp->w_skipcol);
+ if (scroll_changed && first_scroll_win != NULL && *first_scroll_win == NULL) {
+ *first_scroll_win = wp;
}
if ((size_changed || scroll_changed) && v_event != NULL) {
@@ -5655,8 +5643,6 @@ static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
}
}
}
-
- return result;
}
/// Trigger WinScrolled and/or WinResized if any window in the current tab page
@@ -5676,11 +5662,9 @@ void may_trigger_win_scrolled_resized(void)
int size_count = 0;
win_T *first_scroll_win = NULL;
win_T *first_size_win = NULL;
- int cwsr = check_window_scroll_resize(&size_count,
- &first_scroll_win, &first_size_win,
- NULL, NULL);
+ check_window_scroll_resize(&size_count, &first_scroll_win, &first_size_win, NULL, NULL);
bool trigger_resize = do_resize && size_count > 0;
- bool trigger_scroll = do_scroll && cwsr != 0;
+ bool trigger_scroll = do_scroll && first_scroll_win != NULL;
if (!trigger_resize && !trigger_scroll) {
return; // no relevant changes
}