mirror of
https://github.com/vim/vim
synced 2025-07-18 10:11:58 +00:00
patch 9.1.0256: Finding autocmd events is inefficient
Problem: Finding autocmd events is inefficient Solution: Use binary search to find events, cache last found events, avoid use of strlen(), add SessionWritePost autocmd, fix test_codestyle and avoid endless loop (John Marriott) closes: #14287 Signed-off-by: John Marriott <basilisk@internode.on.net> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
16cdfa69e0
commit
78d742ab88
398
src/autocmd.c
398
src/autocmd.c
@ -74,153 +74,166 @@ typedef struct AutoPat
|
|||||||
char last; // last pattern for apply_autocmds()
|
char last; // last pattern for apply_autocmds()
|
||||||
} AutoPat;
|
} AutoPat;
|
||||||
|
|
||||||
static struct event_name
|
//
|
||||||
{
|
// special cases:
|
||||||
char *name; // event name
|
// BufNewFile and BufRead are searched for ALOT (especially at startup)
|
||||||
event_T event; // event number
|
// so we pre-determine their index into the event_tab[] table for fast access.
|
||||||
} event_names[] =
|
// Keep these values in sync with event_tab[]!
|
||||||
{
|
#define BUFNEWFILE_INDEX 9
|
||||||
{"BufAdd", EVENT_BUFADD},
|
#define BUFREAD_INDEX 10
|
||||||
{"BufCreate", EVENT_BUFADD},
|
|
||||||
{"BufDelete", EVENT_BUFDELETE},
|
// must be sorted by the 'value' field because it is used by bsearch()!
|
||||||
{"BufEnter", EVENT_BUFENTER},
|
static keyvalue_T event_tab[] = {
|
||||||
{"BufFilePost", EVENT_BUFFILEPOST},
|
KEYVALUE_ENTRY(EVENT_BUFADD, "BufAdd"),
|
||||||
{"BufFilePre", EVENT_BUFFILEPRE},
|
KEYVALUE_ENTRY(EVENT_BUFADD, "BufCreate"),
|
||||||
{"BufHidden", EVENT_BUFHIDDEN},
|
KEYVALUE_ENTRY(EVENT_BUFDELETE, "BufDelete"),
|
||||||
{"BufLeave", EVENT_BUFLEAVE},
|
KEYVALUE_ENTRY(EVENT_BUFENTER, "BufEnter"),
|
||||||
{"BufNew", EVENT_BUFNEW},
|
KEYVALUE_ENTRY(EVENT_BUFFILEPOST, "BufFilePost"),
|
||||||
{"BufNewFile", EVENT_BUFNEWFILE},
|
KEYVALUE_ENTRY(EVENT_BUFFILEPRE, "BufFilePre"),
|
||||||
{"BufRead", EVENT_BUFREADPOST},
|
KEYVALUE_ENTRY(EVENT_BUFHIDDEN, "BufHidden"),
|
||||||
{"BufReadCmd", EVENT_BUFREADCMD},
|
KEYVALUE_ENTRY(EVENT_BUFLEAVE, "BufLeave"),
|
||||||
{"BufReadPost", EVENT_BUFREADPOST},
|
KEYVALUE_ENTRY(EVENT_BUFNEW, "BufNew"),
|
||||||
{"BufReadPre", EVENT_BUFREADPRE},
|
KEYVALUE_ENTRY(EVENT_BUFNEWFILE, "BufNewFile"), // BUFNEWFILE_INDEX
|
||||||
{"BufUnload", EVENT_BUFUNLOAD},
|
KEYVALUE_ENTRY(EVENT_BUFREADPOST, "BufRead"), // BUFREAD_INDEX
|
||||||
{"BufWinEnter", EVENT_BUFWINENTER},
|
KEYVALUE_ENTRY(EVENT_BUFREADCMD, "BufReadCmd"),
|
||||||
{"BufWinLeave", EVENT_BUFWINLEAVE},
|
KEYVALUE_ENTRY(EVENT_BUFREADPOST, "BufReadPost"),
|
||||||
{"BufWipeout", EVENT_BUFWIPEOUT},
|
KEYVALUE_ENTRY(EVENT_BUFREADPRE, "BufReadPre"),
|
||||||
{"BufWrite", EVENT_BUFWRITEPRE},
|
KEYVALUE_ENTRY(EVENT_BUFUNLOAD, "BufUnload"),
|
||||||
{"BufWritePost", EVENT_BUFWRITEPOST},
|
KEYVALUE_ENTRY(EVENT_BUFWINENTER, "BufWinEnter"),
|
||||||
{"BufWritePre", EVENT_BUFWRITEPRE},
|
KEYVALUE_ENTRY(EVENT_BUFWINLEAVE, "BufWinLeave"),
|
||||||
{"BufWriteCmd", EVENT_BUFWRITECMD},
|
KEYVALUE_ENTRY(EVENT_BUFWIPEOUT, "BufWipeout"),
|
||||||
{"CmdlineChanged", EVENT_CMDLINECHANGED},
|
KEYVALUE_ENTRY(EVENT_BUFWRITEPRE, "BufWrite"),
|
||||||
{"CmdlineEnter", EVENT_CMDLINEENTER},
|
KEYVALUE_ENTRY(EVENT_BUFWRITECMD, "BufWriteCmd"),
|
||||||
{"CmdlineLeave", EVENT_CMDLINELEAVE},
|
KEYVALUE_ENTRY(EVENT_BUFWRITEPOST, "BufWritePost"),
|
||||||
{"CmdwinEnter", EVENT_CMDWINENTER},
|
KEYVALUE_ENTRY(EVENT_BUFWRITEPRE, "BufWritePre"),
|
||||||
{"CmdwinLeave", EVENT_CMDWINLEAVE},
|
KEYVALUE_ENTRY(EVENT_CMDLINECHANGED, "CmdlineChanged"),
|
||||||
{"CmdUndefined", EVENT_CMDUNDEFINED},
|
KEYVALUE_ENTRY(EVENT_CMDLINEENTER, "CmdlineEnter"),
|
||||||
{"ColorScheme", EVENT_COLORSCHEME},
|
KEYVALUE_ENTRY(EVENT_CMDLINELEAVE, "CmdlineLeave"),
|
||||||
{"ColorSchemePre", EVENT_COLORSCHEMEPRE},
|
KEYVALUE_ENTRY(EVENT_CMDUNDEFINED, "CmdUndefined"),
|
||||||
{"CompleteChanged", EVENT_COMPLETECHANGED},
|
KEYVALUE_ENTRY(EVENT_CMDWINENTER, "CmdwinEnter"),
|
||||||
{"CompleteDone", EVENT_COMPLETEDONE},
|
KEYVALUE_ENTRY(EVENT_CMDWINLEAVE, "CmdwinLeave"),
|
||||||
{"CompleteDonePre", EVENT_COMPLETEDONEPRE},
|
KEYVALUE_ENTRY(EVENT_COLORSCHEME, "ColorScheme"),
|
||||||
{"CursorHold", EVENT_CURSORHOLD},
|
KEYVALUE_ENTRY(EVENT_COLORSCHEMEPRE, "ColorSchemePre"),
|
||||||
{"CursorHoldI", EVENT_CURSORHOLDI},
|
KEYVALUE_ENTRY(EVENT_COMPLETECHANGED, "CompleteChanged"),
|
||||||
{"CursorMoved", EVENT_CURSORMOVED},
|
KEYVALUE_ENTRY(EVENT_COMPLETEDONE, "CompleteDone"),
|
||||||
{"CursorMovedI", EVENT_CURSORMOVEDI},
|
KEYVALUE_ENTRY(EVENT_COMPLETEDONEPRE, "CompleteDonePre"),
|
||||||
{"DiffUpdated", EVENT_DIFFUPDATED},
|
KEYVALUE_ENTRY(EVENT_CURSORHOLD, "CursorHold"),
|
||||||
{"DirChanged", EVENT_DIRCHANGED},
|
KEYVALUE_ENTRY(EVENT_CURSORHOLDI, "CursorHoldI"),
|
||||||
{"DirChangedPre", EVENT_DIRCHANGEDPRE},
|
KEYVALUE_ENTRY(EVENT_CURSORMOVED, "CursorMoved"),
|
||||||
{"EncodingChanged", EVENT_ENCODINGCHANGED},
|
KEYVALUE_ENTRY(EVENT_CURSORMOVEDI, "CursorMovedI"),
|
||||||
{"ExitPre", EVENT_EXITPRE},
|
KEYVALUE_ENTRY(EVENT_DIFFUPDATED, "DiffUpdated"),
|
||||||
{"FileEncoding", EVENT_ENCODINGCHANGED},
|
KEYVALUE_ENTRY(EVENT_DIRCHANGED, "DirChanged"),
|
||||||
{"FileAppendPost", EVENT_FILEAPPENDPOST},
|
KEYVALUE_ENTRY(EVENT_DIRCHANGEDPRE, "DirChangedPre"),
|
||||||
{"FileAppendPre", EVENT_FILEAPPENDPRE},
|
KEYVALUE_ENTRY(EVENT_ENCODINGCHANGED, "EncodingChanged"),
|
||||||
{"FileAppendCmd", EVENT_FILEAPPENDCMD},
|
KEYVALUE_ENTRY(EVENT_EXITPRE, "ExitPre"),
|
||||||
{"FileChangedShell",EVENT_FILECHANGEDSHELL},
|
KEYVALUE_ENTRY(EVENT_FILEAPPENDCMD, "FileAppendCmd"),
|
||||||
{"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
|
KEYVALUE_ENTRY(EVENT_FILEAPPENDPOST, "FileAppendPost"),
|
||||||
{"FileChangedRO", EVENT_FILECHANGEDRO},
|
KEYVALUE_ENTRY(EVENT_FILEAPPENDPRE, "FileAppendPre"),
|
||||||
{"FileReadPost", EVENT_FILEREADPOST},
|
KEYVALUE_ENTRY(EVENT_FILECHANGEDRO, "FileChangedRO"),
|
||||||
{"FileReadPre", EVENT_FILEREADPRE},
|
KEYVALUE_ENTRY(EVENT_FILECHANGEDSHELL, "FileChangedShell"),
|
||||||
{"FileReadCmd", EVENT_FILEREADCMD},
|
KEYVALUE_ENTRY(EVENT_FILECHANGEDSHELLPOST, "FileChangedShellPost"),
|
||||||
{"FileType", EVENT_FILETYPE},
|
KEYVALUE_ENTRY(EVENT_ENCODINGCHANGED, "FileEncoding"),
|
||||||
{"FileWritePost", EVENT_FILEWRITEPOST},
|
KEYVALUE_ENTRY(EVENT_FILEREADCMD, "FileReadCmd"),
|
||||||
{"FileWritePre", EVENT_FILEWRITEPRE},
|
KEYVALUE_ENTRY(EVENT_FILEREADPOST, "FileReadPost"),
|
||||||
{"FileWriteCmd", EVENT_FILEWRITECMD},
|
KEYVALUE_ENTRY(EVENT_FILEREADPRE, "FileReadPre"),
|
||||||
{"FilterReadPost", EVENT_FILTERREADPOST},
|
KEYVALUE_ENTRY(EVENT_FILETYPE, "FileType"),
|
||||||
{"FilterReadPre", EVENT_FILTERREADPRE},
|
KEYVALUE_ENTRY(EVENT_FILEWRITECMD, "FileWriteCmd"),
|
||||||
{"FilterWritePost", EVENT_FILTERWRITEPOST},
|
KEYVALUE_ENTRY(EVENT_FILEWRITEPOST, "FileWritePost"),
|
||||||
{"FilterWritePre", EVENT_FILTERWRITEPRE},
|
KEYVALUE_ENTRY(EVENT_FILEWRITEPRE, "FileWritePre"),
|
||||||
{"FocusGained", EVENT_FOCUSGAINED},
|
KEYVALUE_ENTRY(EVENT_FILTERREADPOST, "FilterReadPost"),
|
||||||
{"FocusLost", EVENT_FOCUSLOST},
|
KEYVALUE_ENTRY(EVENT_FILTERREADPRE, "FilterReadPre"),
|
||||||
{"FuncUndefined", EVENT_FUNCUNDEFINED},
|
KEYVALUE_ENTRY(EVENT_FILTERWRITEPOST, "FilterWritePost"),
|
||||||
{"GUIEnter", EVENT_GUIENTER},
|
KEYVALUE_ENTRY(EVENT_FILTERWRITEPRE, "FilterWritePre"),
|
||||||
{"GUIFailed", EVENT_GUIFAILED},
|
KEYVALUE_ENTRY(EVENT_FOCUSGAINED, "FocusGained"),
|
||||||
{"InsertChange", EVENT_INSERTCHANGE},
|
KEYVALUE_ENTRY(EVENT_FOCUSLOST, "FocusLost"),
|
||||||
{"InsertEnter", EVENT_INSERTENTER},
|
KEYVALUE_ENTRY(EVENT_FUNCUNDEFINED, "FuncUndefined"),
|
||||||
{"InsertLeave", EVENT_INSERTLEAVE},
|
KEYVALUE_ENTRY(EVENT_GUIENTER, "GUIEnter"),
|
||||||
{"InsertLeavePre", EVENT_INSERTLEAVEPRE},
|
KEYVALUE_ENTRY(EVENT_GUIFAILED, "GUIFailed"),
|
||||||
{"InsertCharPre", EVENT_INSERTCHARPRE},
|
KEYVALUE_ENTRY(EVENT_INSERTCHANGE, "InsertChange"),
|
||||||
{"MenuPopup", EVENT_MENUPOPUP},
|
KEYVALUE_ENTRY(EVENT_INSERTCHARPRE, "InsertCharPre"),
|
||||||
{"ModeChanged", EVENT_MODECHANGED},
|
KEYVALUE_ENTRY(EVENT_INSERTENTER, "InsertEnter"),
|
||||||
{"OptionSet", EVENT_OPTIONSET},
|
KEYVALUE_ENTRY(EVENT_INSERTLEAVE, "InsertLeave"),
|
||||||
{"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
|
KEYVALUE_ENTRY(EVENT_INSERTLEAVEPRE, "InsertLeavePre"),
|
||||||
{"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
|
KEYVALUE_ENTRY(EVENT_MENUPOPUP, "MenuPopup"),
|
||||||
{"QuitPre", EVENT_QUITPRE},
|
KEYVALUE_ENTRY(EVENT_MODECHANGED, "ModeChanged"),
|
||||||
{"RemoteReply", EVENT_REMOTEREPLY},
|
KEYVALUE_ENTRY(EVENT_OPTIONSET, "OptionSet"),
|
||||||
{"SafeState", EVENT_SAFESTATE},
|
KEYVALUE_ENTRY(EVENT_QUICKFIXCMDPOST, "QuickFixCmdPost"),
|
||||||
{"SafeStateAgain", EVENT_SAFESTATEAGAIN},
|
KEYVALUE_ENTRY(EVENT_QUICKFIXCMDPRE, "QuickFixCmdPre"),
|
||||||
{"SessionLoadPost", EVENT_SESSIONLOADPOST},
|
KEYVALUE_ENTRY(EVENT_QUITPRE, "QuitPre"),
|
||||||
{"SessionWritePost",EVENT_SESSIONWRITEPOST},
|
KEYVALUE_ENTRY(EVENT_REMOTEREPLY, "RemoteReply"),
|
||||||
{"ShellCmdPost", EVENT_SHELLCMDPOST},
|
KEYVALUE_ENTRY(EVENT_SAFESTATE, "SafeState"),
|
||||||
{"ShellFilterPost", EVENT_SHELLFILTERPOST},
|
KEYVALUE_ENTRY(EVENT_SAFESTATEAGAIN, "SafeStateAgain"),
|
||||||
{"SigUSR1", EVENT_SIGUSR1},
|
KEYVALUE_ENTRY(EVENT_SESSIONLOADPOST, "SessionLoadPost"),
|
||||||
{"SourceCmd", EVENT_SOURCECMD},
|
KEYVALUE_ENTRY(EVENT_SESSIONWRITEPOST, "SessionWritePost"),
|
||||||
{"SourcePre", EVENT_SOURCEPRE},
|
KEYVALUE_ENTRY(EVENT_SHELLCMDPOST, "ShellCmdPost"),
|
||||||
{"SourcePost", EVENT_SOURCEPOST},
|
KEYVALUE_ENTRY(EVENT_SHELLFILTERPOST, "ShellFilterPost"),
|
||||||
{"SpellFileMissing",EVENT_SPELLFILEMISSING},
|
KEYVALUE_ENTRY(EVENT_SIGUSR1, "SigUSR1"),
|
||||||
{"StdinReadPost", EVENT_STDINREADPOST},
|
KEYVALUE_ENTRY(EVENT_SOURCECMD, "SourceCmd"),
|
||||||
{"StdinReadPre", EVENT_STDINREADPRE},
|
KEYVALUE_ENTRY(EVENT_SOURCEPOST, "SourcePost"),
|
||||||
{"SwapExists", EVENT_SWAPEXISTS},
|
KEYVALUE_ENTRY(EVENT_SOURCEPRE, "SourcePre"),
|
||||||
{"Syntax", EVENT_SYNTAX},
|
KEYVALUE_ENTRY(EVENT_SPELLFILEMISSING, "SpellFileMissing"),
|
||||||
{"TabNew", EVENT_TABNEW},
|
KEYVALUE_ENTRY(EVENT_STDINREADPOST, "StdinReadPost"),
|
||||||
{"TabClosed", EVENT_TABCLOSED},
|
KEYVALUE_ENTRY(EVENT_STDINREADPRE, "StdinReadPre"),
|
||||||
{"TabEnter", EVENT_TABENTER},
|
KEYVALUE_ENTRY(EVENT_SWAPEXISTS, "SwapExists"),
|
||||||
{"TabLeave", EVENT_TABLEAVE},
|
KEYVALUE_ENTRY(EVENT_SYNTAX, "Syntax"),
|
||||||
{"TermChanged", EVENT_TERMCHANGED},
|
KEYVALUE_ENTRY(EVENT_TABCLOSED, "TabClosed"),
|
||||||
{"TerminalOpen", EVENT_TERMINALOPEN},
|
KEYVALUE_ENTRY(EVENT_TABENTER, "TabEnter"),
|
||||||
{"TerminalWinOpen", EVENT_TERMINALWINOPEN},
|
KEYVALUE_ENTRY(EVENT_TABLEAVE, "TabLeave"),
|
||||||
{"TermResponse", EVENT_TERMRESPONSE},
|
KEYVALUE_ENTRY(EVENT_TABNEW, "TabNew"),
|
||||||
{"TermResponseAll", EVENT_TERMRESPONSEALL},
|
KEYVALUE_ENTRY(EVENT_TERMCHANGED, "TermChanged"),
|
||||||
{"TextChanged", EVENT_TEXTCHANGED},
|
KEYVALUE_ENTRY(EVENT_TERMINALOPEN, "TerminalOpen"),
|
||||||
{"TextChangedI", EVENT_TEXTCHANGEDI},
|
KEYVALUE_ENTRY(EVENT_TERMINALWINOPEN, "TerminalWinOpen"),
|
||||||
{"TextChangedP", EVENT_TEXTCHANGEDP},
|
KEYVALUE_ENTRY(EVENT_TERMRESPONSE, "TermResponse"),
|
||||||
{"TextChangedT", EVENT_TEXTCHANGEDT},
|
KEYVALUE_ENTRY(EVENT_TERMRESPONSEALL, "TermResponseAll"),
|
||||||
{"User", EVENT_USER},
|
KEYVALUE_ENTRY(EVENT_TEXTCHANGED, "TextChanged"),
|
||||||
{"VimEnter", EVENT_VIMENTER},
|
KEYVALUE_ENTRY(EVENT_TEXTCHANGEDI, "TextChangedI"),
|
||||||
{"VimLeave", EVENT_VIMLEAVE},
|
KEYVALUE_ENTRY(EVENT_TEXTCHANGEDP, "TextChangedP"),
|
||||||
{"VimLeavePre", EVENT_VIMLEAVEPRE},
|
KEYVALUE_ENTRY(EVENT_TEXTCHANGEDT, "TextChangedT"),
|
||||||
{"WinNewPre", EVENT_WINNEWPRE},
|
KEYVALUE_ENTRY(EVENT_TEXTYANKPOST, "TextYankPost"),
|
||||||
{"WinNew", EVENT_WINNEW},
|
KEYVALUE_ENTRY(EVENT_USER, "User"),
|
||||||
{"WinClosed", EVENT_WINCLOSED},
|
KEYVALUE_ENTRY(EVENT_VIMENTER, "VimEnter"),
|
||||||
{"WinEnter", EVENT_WINENTER},
|
KEYVALUE_ENTRY(EVENT_VIMLEAVE, "VimLeave"),
|
||||||
{"WinLeave", EVENT_WINLEAVE},
|
KEYVALUE_ENTRY(EVENT_VIMLEAVEPRE, "VimLeavePre"),
|
||||||
{"WinResized", EVENT_WINRESIZED},
|
KEYVALUE_ENTRY(EVENT_VIMRESIZED, "VimResized"),
|
||||||
{"WinScrolled", EVENT_WINSCROLLED},
|
KEYVALUE_ENTRY(EVENT_VIMRESUME, "VimResume"),
|
||||||
{"VimResized", EVENT_VIMRESIZED},
|
KEYVALUE_ENTRY(EVENT_VIMSUSPEND, "VimSuspend"),
|
||||||
{"TextYankPost", EVENT_TEXTYANKPOST},
|
KEYVALUE_ENTRY(EVENT_WINCLOSED, "WinClosed"),
|
||||||
{"VimSuspend", EVENT_VIMSUSPEND},
|
KEYVALUE_ENTRY(EVENT_WINENTER, "WinEnter"),
|
||||||
{"VimResume", EVENT_VIMRESUME},
|
KEYVALUE_ENTRY(EVENT_WINLEAVE, "WinLeave"),
|
||||||
{NULL, (event_T)0}
|
KEYVALUE_ENTRY(EVENT_WINNEW, "WinNew"),
|
||||||
|
KEYVALUE_ENTRY(EVENT_WINNEWPRE, "WinNewPre"),
|
||||||
|
KEYVALUE_ENTRY(EVENT_WINRESIZED, "WinResized"),
|
||||||
|
KEYVALUE_ENTRY(EVENT_WINSCROLLED, "WinScrolled")
|
||||||
};
|
};
|
||||||
|
|
||||||
static AutoPat *first_autopat[NUM_EVENTS] =
|
static AutoPat *first_autopat[NUM_EVENTS] = {
|
||||||
{
|
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static AutoPat *last_autopat[NUM_EVENTS] =
|
static AutoPat *last_autopat[NUM_EVENTS] = {
|
||||||
{
|
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AUGROUP_DEFAULT (-1) // default autocmd group
|
#define AUGROUP_DEFAULT (-1) // default autocmd group
|
||||||
@ -266,6 +279,7 @@ static int current_augroup = AUGROUP_DEFAULT;
|
|||||||
|
|
||||||
static int au_need_clean = FALSE; // need to delete marked patterns
|
static int au_need_clean = FALSE; // need to delete marked patterns
|
||||||
|
|
||||||
|
static event_T event_name2nr(char_u *start, char_u **end);
|
||||||
static char_u *event_nr2name(event_T event);
|
static char_u *event_nr2name(event_T event);
|
||||||
static int au_get_grouparg(char_u **argp);
|
static int au_get_grouparg(char_u **argp);
|
||||||
static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group, int flags);
|
static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group, int flags);
|
||||||
@ -681,24 +695,35 @@ is_aucmd_win(win_T *win)
|
|||||||
event_name2nr(char_u *start, char_u **end)
|
event_name2nr(char_u *start, char_u **end)
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int i;
|
keyvalue_T target;
|
||||||
int len;
|
keyvalue_T *entry;
|
||||||
|
static keyvalue_T *bufnewfile = &event_tab[BUFNEWFILE_INDEX];
|
||||||
|
static keyvalue_T *bufread = &event_tab[BUFREAD_INDEX];
|
||||||
|
|
||||||
// the event name ends with end of line, '|', a blank or a comma
|
// the event name ends with end of line, '|', a blank or a comma
|
||||||
for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p)
|
for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p)
|
||||||
;
|
;
|
||||||
for (i = 0; event_names[i].name != NULL; ++i)
|
|
||||||
{
|
target.key = 0;
|
||||||
len = (int)STRLEN(event_names[i].name);
|
target.value = (char *)start;
|
||||||
if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
|
target.length = (size_t)(p - start);
|
||||||
break;
|
|
||||||
}
|
// special cases:
|
||||||
|
// BufNewFile and BufRead are searched for ALOT (especially at startup)
|
||||||
|
// so we check for them first.
|
||||||
|
if (cmp_keyvalue_value_ni(&target, bufnewfile) == 0)
|
||||||
|
entry = bufnewfile;
|
||||||
|
else
|
||||||
|
if (cmp_keyvalue_value_ni(&target, bufread) == 0)
|
||||||
|
entry = bufread;
|
||||||
|
else
|
||||||
|
entry = (keyvalue_T *)bsearch(&target, &event_tab, ARRAY_LENGTH(event_tab), sizeof(event_tab[0]), cmp_keyvalue_value_ni);
|
||||||
|
|
||||||
if (*p == ',')
|
if (*p == ',')
|
||||||
++p;
|
++p;
|
||||||
*end = p;
|
*end = p;
|
||||||
if (event_names[i].name == NULL)
|
|
||||||
return NUM_EVENTS;
|
return (entry == NULL) ? NUM_EVENTS : (event_T)entry->key;
|
||||||
return event_names[i].event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -708,11 +733,52 @@ event_name2nr(char_u *start, char_u **end)
|
|||||||
event_nr2name(event_T event)
|
event_nr2name(event_T event)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
#define CACHE_SIZE 12
|
||||||
|
static int cache_tab[CACHE_SIZE];
|
||||||
|
static int cache_last_index = -1;
|
||||||
|
|
||||||
for (i = 0; event_names[i].name != NULL; ++i)
|
if (cache_last_index < 0)
|
||||||
if (event_names[i].event == event)
|
{
|
||||||
return (char_u *)event_names[i].name;
|
for (i = 0; i < (int)ARRAY_LENGTH(cache_tab); ++i)
|
||||||
return (char_u *)"Unknown";
|
cache_tab[i] = -1;
|
||||||
|
cache_last_index = ARRAY_LENGTH(cache_tab) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first look in the cache
|
||||||
|
// the cache is circular. to search it we start at the most recent entry
|
||||||
|
// and go backwards wrapping around when we get to index 0.
|
||||||
|
for (i = cache_last_index; cache_tab[i] >= 0; )
|
||||||
|
{
|
||||||
|
if ((event_T)event_tab[cache_tab[i]].key == event)
|
||||||
|
return (char_u *)event_tab[cache_tab[i]].value;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
i = ARRAY_LENGTH(cache_tab) - 1;
|
||||||
|
else
|
||||||
|
--i;
|
||||||
|
|
||||||
|
// are we back at the start?
|
||||||
|
if (i == cache_last_index)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look in the event table itself
|
||||||
|
for (i = 0; i < (int)ARRAY_LENGTH(event_tab); ++i)
|
||||||
|
{
|
||||||
|
if ((event_T)event_tab[i].key == event)
|
||||||
|
{
|
||||||
|
// store the found entry in the next position in the cache,
|
||||||
|
// wrapping around when we get to the maximum index.
|
||||||
|
if (cache_last_index == ARRAY_LENGTH(cache_tab) - 1)
|
||||||
|
cache_last_index = 0;
|
||||||
|
else
|
||||||
|
++cache_last_index;
|
||||||
|
cache_tab[cache_last_index] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (i == (int)ARRAY_LENGTH(event_tab)) ? (char_u *)"Unknown" : (char_u *)event_tab[i].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -806,12 +872,14 @@ au_event_disable(char *what)
|
|||||||
{
|
{
|
||||||
char_u *new_ei;
|
char_u *new_ei;
|
||||||
char_u *save_ei;
|
char_u *save_ei;
|
||||||
|
size_t p_ei_len;
|
||||||
|
|
||||||
save_ei = vim_strsave(p_ei);
|
p_ei_len = STRLEN(p_ei);
|
||||||
|
save_ei = vim_strnsave(p_ei, p_ei_len);
|
||||||
if (save_ei == NULL)
|
if (save_ei == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
new_ei = vim_strnsave(p_ei, STRLEN(p_ei) + STRLEN(what));
|
new_ei = vim_strnsave(p_ei, p_ei_len + STRLEN(what));
|
||||||
if (new_ei == NULL)
|
if (new_ei == NULL)
|
||||||
{
|
{
|
||||||
vim_free(save_ei);
|
vim_free(save_ei);
|
||||||
@ -2774,6 +2842,8 @@ set_context_in_autocmd(
|
|||||||
char_u *
|
char_u *
|
||||||
get_event_name(expand_T *xp UNUSED, int idx)
|
get_event_name(expand_T *xp UNUSED, int idx)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if (idx < augroups.ga_len) // First list group names, if wanted
|
if (idx < augroups.ga_len) // First list group names, if wanted
|
||||||
{
|
{
|
||||||
if (!include_groups || AUGROUP_NAME(idx) == NULL
|
if (!include_groups || AUGROUP_NAME(idx) == NULL
|
||||||
@ -2781,7 +2851,12 @@ get_event_name(expand_T *xp UNUSED, int idx)
|
|||||||
return (char_u *)""; // skip deleted entries
|
return (char_u *)""; // skip deleted entries
|
||||||
return AUGROUP_NAME(idx); // return a name
|
return AUGROUP_NAME(idx); // return a name
|
||||||
}
|
}
|
||||||
return (char_u *)event_names[idx - augroups.ga_len].name;
|
|
||||||
|
i = idx - augroups.ga_len;
|
||||||
|
if (i < 0 || i >= (int)ARRAY_LENGTH(event_tab))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (char_u *)event_tab[i].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2791,7 +2866,10 @@ get_event_name(expand_T *xp UNUSED, int idx)
|
|||||||
char_u *
|
char_u *
|
||||||
get_event_name_no_group(expand_T *xp UNUSED, int idx)
|
get_event_name_no_group(expand_T *xp UNUSED, int idx)
|
||||||
{
|
{
|
||||||
return (char_u *)event_names[idx].name;
|
if (idx < 0 || idx >= (int)ARRAY_LENGTH(event_tab))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (char_u *)event_tab[idx].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3251,8 +3329,6 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv)
|
|||||||
// return only the autocmds for the specified event
|
// return only the autocmds for the specified event
|
||||||
if (dict_has_key(argvars[0].vval.v_dict, "event"))
|
if (dict_has_key(argvars[0].vval.v_dict, "event"))
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
name = dict_get_string(argvars[0].vval.v_dict, "event", TRUE);
|
name = dict_get_string(argvars[0].vval.v_dict, "event", TRUE);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return;
|
return;
|
||||||
@ -3261,16 +3337,20 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv)
|
|||||||
event_arg = NUM_EVENTS;
|
event_arg = NUM_EVENTS;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; event_names[i].name != NULL; i++)
|
keyvalue_T target;
|
||||||
if (STRICMP(event_names[i].name, name) == 0)
|
keyvalue_T *entry;
|
||||||
break;
|
|
||||||
if (event_names[i].name == NULL)
|
target.key = 0;
|
||||||
|
target.value = (char *)name;
|
||||||
|
target.length = (int)STRLEN(target.value);
|
||||||
|
entry = (keyvalue_T *)bsearch(&target, &event_tab, ARRAY_LENGTH(event_tab), sizeof(event_tab[0]), cmp_keyvalue_value_ni);
|
||||||
|
if (entry == NULL)
|
||||||
{
|
{
|
||||||
semsg(_(e_no_such_event_str), name);
|
semsg(_(e_no_such_event_str), name);
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event_arg = event_names[i].event;
|
event_arg = (event_T)entry->key;
|
||||||
}
|
}
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
}
|
}
|
||||||
|
42
src/misc2.c
42
src/misc2.c
@ -3069,3 +3069,45 @@ get_special_pty_type(void)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compare two keyvalue_T structs by case sensitive value
|
||||||
|
int
|
||||||
|
cmp_keyvalue_value(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
keyvalue_T *kv1 = (keyvalue_T *)a;
|
||||||
|
keyvalue_T *kv2 = (keyvalue_T *)b;
|
||||||
|
|
||||||
|
return STRCMP(kv1->value, kv2->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare two keyvalue_T structs by value with length
|
||||||
|
int
|
||||||
|
cmp_keyvalue_value_n(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
keyvalue_T *kv1 = (keyvalue_T *)a;
|
||||||
|
keyvalue_T *kv2 = (keyvalue_T *)b;
|
||||||
|
|
||||||
|
return STRNCMP(kv1->value, kv2->value, MAX(kv1->length, kv2->length));
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare two keyvalue_T structs by case insensitive value
|
||||||
|
int
|
||||||
|
cmp_keyvalue_value_i(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
keyvalue_T *kv1 = (keyvalue_T *)a;
|
||||||
|
keyvalue_T *kv2 = (keyvalue_T *)b;
|
||||||
|
|
||||||
|
return STRICMP(kv1->value, kv2->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare two keyvalue_T structs by case insensitive value
|
||||||
|
// with length
|
||||||
|
int
|
||||||
|
cmp_keyvalue_value_ni(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
keyvalue_T *kv1 = (keyvalue_T *)a;
|
||||||
|
keyvalue_T *kv2 = (keyvalue_T *)b;
|
||||||
|
|
||||||
|
return STRNICMP(kv1->value, kv2->value, MAX(kv1->length, kv2->length));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -61,4 +61,8 @@ int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc);
|
|||||||
int build_argv_from_string(char_u *cmd, char ***argv, int *argc);
|
int build_argv_from_string(char_u *cmd, char ***argv, int *argc);
|
||||||
int build_argv_from_list(list_T *l, char ***argv, int *argc);
|
int build_argv_from_list(list_T *l, char ***argv, int *argc);
|
||||||
int get_special_pty_type(void);
|
int get_special_pty_type(void);
|
||||||
|
int cmp_keyvalue_value(const void *a, const void *b);
|
||||||
|
int cmp_keyvalue_value_n(const void *a, const void *b);
|
||||||
|
int cmp_keyvalue_value_i(const void *a, const void *b);
|
||||||
|
int cmp_keyvalue_value_ni(const void *a, const void *b);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@ -5060,3 +5060,18 @@ typedef struct {
|
|||||||
linenr_T spv_capcol_lnum; // line number for "cap_col"
|
linenr_T spv_capcol_lnum; // line number for "cap_col"
|
||||||
#endif
|
#endif
|
||||||
} spellvars_T;
|
} spellvars_T;
|
||||||
|
|
||||||
|
// Return the length of a string literal
|
||||||
|
#define STRLEN_LITERAL(s) (sizeof(s) - 1)
|
||||||
|
|
||||||
|
// Store a key/value pair
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int key; // the key
|
||||||
|
char *value; // the value string
|
||||||
|
size_t length; // length of the value string
|
||||||
|
} keyvalue_T;
|
||||||
|
|
||||||
|
#define KEYVALUE_ENTRY(k, v) \
|
||||||
|
{(k), (v), STRLEN_LITERAL(v)}
|
||||||
|
|
||||||
|
@ -7,13 +7,17 @@ def s:ReportError(fname: string, lnum: number, msg: string)
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def s:PerformCheck(fname: string, pattern: string, msg: string, skip: string)
|
def s:PerformCheck(fname: string, pattern: string, msg: string, skip: string)
|
||||||
|
var prev_lnum = 1
|
||||||
var lnum = 1
|
var lnum = 1
|
||||||
while (lnum > 0)
|
while (lnum > 0)
|
||||||
cursor(lnum, 1)
|
cursor(lnum, 1)
|
||||||
lnum = search(pattern, 'W', 0, 0, skip)
|
lnum = search(pattern, 'W', 0, 0, skip)
|
||||||
ReportError(fname, lnum, msg)
|
if (prev_lnum == lnum)
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
prev_lnum = lnum
|
||||||
if (lnum > 0)
|
if (lnum > 0)
|
||||||
lnum += 1
|
ReportError(fname, lnum, msg)
|
||||||
endif
|
endif
|
||||||
endwhile
|
endwhile
|
||||||
enddef
|
enddef
|
||||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
256,
|
||||||
/**/
|
/**/
|
||||||
255,
|
255,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user