mirror of
https://github.com/vim/vim
synced 2025-07-18 18:21:55 +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()
|
||||
} AutoPat;
|
||||
|
||||
static struct event_name
|
||||
{
|
||||
char *name; // event name
|
||||
event_T event; // event number
|
||||
} event_names[] =
|
||||
{
|
||||
{"BufAdd", EVENT_BUFADD},
|
||||
{"BufCreate", EVENT_BUFADD},
|
||||
{"BufDelete", EVENT_BUFDELETE},
|
||||
{"BufEnter", EVENT_BUFENTER},
|
||||
{"BufFilePost", EVENT_BUFFILEPOST},
|
||||
{"BufFilePre", EVENT_BUFFILEPRE},
|
||||
{"BufHidden", EVENT_BUFHIDDEN},
|
||||
{"BufLeave", EVENT_BUFLEAVE},
|
||||
{"BufNew", EVENT_BUFNEW},
|
||||
{"BufNewFile", EVENT_BUFNEWFILE},
|
||||
{"BufRead", EVENT_BUFREADPOST},
|
||||
{"BufReadCmd", EVENT_BUFREADCMD},
|
||||
{"BufReadPost", EVENT_BUFREADPOST},
|
||||
{"BufReadPre", EVENT_BUFREADPRE},
|
||||
{"BufUnload", EVENT_BUFUNLOAD},
|
||||
{"BufWinEnter", EVENT_BUFWINENTER},
|
||||
{"BufWinLeave", EVENT_BUFWINLEAVE},
|
||||
{"BufWipeout", EVENT_BUFWIPEOUT},
|
||||
{"BufWrite", EVENT_BUFWRITEPRE},
|
||||
{"BufWritePost", EVENT_BUFWRITEPOST},
|
||||
{"BufWritePre", EVENT_BUFWRITEPRE},
|
||||
{"BufWriteCmd", EVENT_BUFWRITECMD},
|
||||
{"CmdlineChanged", EVENT_CMDLINECHANGED},
|
||||
{"CmdlineEnter", EVENT_CMDLINEENTER},
|
||||
{"CmdlineLeave", EVENT_CMDLINELEAVE},
|
||||
{"CmdwinEnter", EVENT_CMDWINENTER},
|
||||
{"CmdwinLeave", EVENT_CMDWINLEAVE},
|
||||
{"CmdUndefined", EVENT_CMDUNDEFINED},
|
||||
{"ColorScheme", EVENT_COLORSCHEME},
|
||||
{"ColorSchemePre", EVENT_COLORSCHEMEPRE},
|
||||
{"CompleteChanged", EVENT_COMPLETECHANGED},
|
||||
{"CompleteDone", EVENT_COMPLETEDONE},
|
||||
{"CompleteDonePre", EVENT_COMPLETEDONEPRE},
|
||||
{"CursorHold", EVENT_CURSORHOLD},
|
||||
{"CursorHoldI", EVENT_CURSORHOLDI},
|
||||
{"CursorMoved", EVENT_CURSORMOVED},
|
||||
{"CursorMovedI", EVENT_CURSORMOVEDI},
|
||||
{"DiffUpdated", EVENT_DIFFUPDATED},
|
||||
{"DirChanged", EVENT_DIRCHANGED},
|
||||
{"DirChangedPre", EVENT_DIRCHANGEDPRE},
|
||||
{"EncodingChanged", EVENT_ENCODINGCHANGED},
|
||||
{"ExitPre", EVENT_EXITPRE},
|
||||
{"FileEncoding", EVENT_ENCODINGCHANGED},
|
||||
{"FileAppendPost", EVENT_FILEAPPENDPOST},
|
||||
{"FileAppendPre", EVENT_FILEAPPENDPRE},
|
||||
{"FileAppendCmd", EVENT_FILEAPPENDCMD},
|
||||
{"FileChangedShell",EVENT_FILECHANGEDSHELL},
|
||||
{"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST},
|
||||
{"FileChangedRO", EVENT_FILECHANGEDRO},
|
||||
{"FileReadPost", EVENT_FILEREADPOST},
|
||||
{"FileReadPre", EVENT_FILEREADPRE},
|
||||
{"FileReadCmd", EVENT_FILEREADCMD},
|
||||
{"FileType", EVENT_FILETYPE},
|
||||
{"FileWritePost", EVENT_FILEWRITEPOST},
|
||||
{"FileWritePre", EVENT_FILEWRITEPRE},
|
||||
{"FileWriteCmd", EVENT_FILEWRITECMD},
|
||||
{"FilterReadPost", EVENT_FILTERREADPOST},
|
||||
{"FilterReadPre", EVENT_FILTERREADPRE},
|
||||
{"FilterWritePost", EVENT_FILTERWRITEPOST},
|
||||
{"FilterWritePre", EVENT_FILTERWRITEPRE},
|
||||
{"FocusGained", EVENT_FOCUSGAINED},
|
||||
{"FocusLost", EVENT_FOCUSLOST},
|
||||
{"FuncUndefined", EVENT_FUNCUNDEFINED},
|
||||
{"GUIEnter", EVENT_GUIENTER},
|
||||
{"GUIFailed", EVENT_GUIFAILED},
|
||||
{"InsertChange", EVENT_INSERTCHANGE},
|
||||
{"InsertEnter", EVENT_INSERTENTER},
|
||||
{"InsertLeave", EVENT_INSERTLEAVE},
|
||||
{"InsertLeavePre", EVENT_INSERTLEAVEPRE},
|
||||
{"InsertCharPre", EVENT_INSERTCHARPRE},
|
||||
{"MenuPopup", EVENT_MENUPOPUP},
|
||||
{"ModeChanged", EVENT_MODECHANGED},
|
||||
{"OptionSet", EVENT_OPTIONSET},
|
||||
{"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
|
||||
{"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
|
||||
{"QuitPre", EVENT_QUITPRE},
|
||||
{"RemoteReply", EVENT_REMOTEREPLY},
|
||||
{"SafeState", EVENT_SAFESTATE},
|
||||
{"SafeStateAgain", EVENT_SAFESTATEAGAIN},
|
||||
{"SessionLoadPost", EVENT_SESSIONLOADPOST},
|
||||
{"SessionWritePost",EVENT_SESSIONWRITEPOST},
|
||||
{"ShellCmdPost", EVENT_SHELLCMDPOST},
|
||||
{"ShellFilterPost", EVENT_SHELLFILTERPOST},
|
||||
{"SigUSR1", EVENT_SIGUSR1},
|
||||
{"SourceCmd", EVENT_SOURCECMD},
|
||||
{"SourcePre", EVENT_SOURCEPRE},
|
||||
{"SourcePost", EVENT_SOURCEPOST},
|
||||
{"SpellFileMissing",EVENT_SPELLFILEMISSING},
|
||||
{"StdinReadPost", EVENT_STDINREADPOST},
|
||||
{"StdinReadPre", EVENT_STDINREADPRE},
|
||||
{"SwapExists", EVENT_SWAPEXISTS},
|
||||
{"Syntax", EVENT_SYNTAX},
|
||||
{"TabNew", EVENT_TABNEW},
|
||||
{"TabClosed", EVENT_TABCLOSED},
|
||||
{"TabEnter", EVENT_TABENTER},
|
||||
{"TabLeave", EVENT_TABLEAVE},
|
||||
{"TermChanged", EVENT_TERMCHANGED},
|
||||
{"TerminalOpen", EVENT_TERMINALOPEN},
|
||||
{"TerminalWinOpen", EVENT_TERMINALWINOPEN},
|
||||
{"TermResponse", EVENT_TERMRESPONSE},
|
||||
{"TermResponseAll", EVENT_TERMRESPONSEALL},
|
||||
{"TextChanged", EVENT_TEXTCHANGED},
|
||||
{"TextChangedI", EVENT_TEXTCHANGEDI},
|
||||
{"TextChangedP", EVENT_TEXTCHANGEDP},
|
||||
{"TextChangedT", EVENT_TEXTCHANGEDT},
|
||||
{"User", EVENT_USER},
|
||||
{"VimEnter", EVENT_VIMENTER},
|
||||
{"VimLeave", EVENT_VIMLEAVE},
|
||||
{"VimLeavePre", EVENT_VIMLEAVEPRE},
|
||||
{"WinNewPre", EVENT_WINNEWPRE},
|
||||
{"WinNew", EVENT_WINNEW},
|
||||
{"WinClosed", EVENT_WINCLOSED},
|
||||
{"WinEnter", EVENT_WINENTER},
|
||||
{"WinLeave", EVENT_WINLEAVE},
|
||||
{"WinResized", EVENT_WINRESIZED},
|
||||
{"WinScrolled", EVENT_WINSCROLLED},
|
||||
{"VimResized", EVENT_VIMRESIZED},
|
||||
{"TextYankPost", EVENT_TEXTYANKPOST},
|
||||
{"VimSuspend", EVENT_VIMSUSPEND},
|
||||
{"VimResume", EVENT_VIMRESUME},
|
||||
{NULL, (event_T)0}
|
||||
//
|
||||
// special cases:
|
||||
// BufNewFile and BufRead are searched for ALOT (especially at startup)
|
||||
// so we pre-determine their index into the event_tab[] table for fast access.
|
||||
// Keep these values in sync with event_tab[]!
|
||||
#define BUFNEWFILE_INDEX 9
|
||||
#define BUFREAD_INDEX 10
|
||||
|
||||
// must be sorted by the 'value' field because it is used by bsearch()!
|
||||
static keyvalue_T event_tab[] = {
|
||||
KEYVALUE_ENTRY(EVENT_BUFADD, "BufAdd"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFADD, "BufCreate"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFDELETE, "BufDelete"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFENTER, "BufEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFFILEPOST, "BufFilePost"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFFILEPRE, "BufFilePre"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFHIDDEN, "BufHidden"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFLEAVE, "BufLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFNEW, "BufNew"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFNEWFILE, "BufNewFile"), // BUFNEWFILE_INDEX
|
||||
KEYVALUE_ENTRY(EVENT_BUFREADPOST, "BufRead"), // BUFREAD_INDEX
|
||||
KEYVALUE_ENTRY(EVENT_BUFREADCMD, "BufReadCmd"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFREADPOST, "BufReadPost"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFREADPRE, "BufReadPre"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFUNLOAD, "BufUnload"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWINENTER, "BufWinEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWINLEAVE, "BufWinLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWIPEOUT, "BufWipeout"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWRITEPRE, "BufWrite"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWRITECMD, "BufWriteCmd"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWRITEPOST, "BufWritePost"),
|
||||
KEYVALUE_ENTRY(EVENT_BUFWRITEPRE, "BufWritePre"),
|
||||
KEYVALUE_ENTRY(EVENT_CMDLINECHANGED, "CmdlineChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_CMDLINEENTER, "CmdlineEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_CMDLINELEAVE, "CmdlineLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_CMDUNDEFINED, "CmdUndefined"),
|
||||
KEYVALUE_ENTRY(EVENT_CMDWINENTER, "CmdwinEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_CMDWINLEAVE, "CmdwinLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_COLORSCHEME, "ColorScheme"),
|
||||
KEYVALUE_ENTRY(EVENT_COLORSCHEMEPRE, "ColorSchemePre"),
|
||||
KEYVALUE_ENTRY(EVENT_COMPLETECHANGED, "CompleteChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_COMPLETEDONE, "CompleteDone"),
|
||||
KEYVALUE_ENTRY(EVENT_COMPLETEDONEPRE, "CompleteDonePre"),
|
||||
KEYVALUE_ENTRY(EVENT_CURSORHOLD, "CursorHold"),
|
||||
KEYVALUE_ENTRY(EVENT_CURSORHOLDI, "CursorHoldI"),
|
||||
KEYVALUE_ENTRY(EVENT_CURSORMOVED, "CursorMoved"),
|
||||
KEYVALUE_ENTRY(EVENT_CURSORMOVEDI, "CursorMovedI"),
|
||||
KEYVALUE_ENTRY(EVENT_DIFFUPDATED, "DiffUpdated"),
|
||||
KEYVALUE_ENTRY(EVENT_DIRCHANGED, "DirChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_DIRCHANGEDPRE, "DirChangedPre"),
|
||||
KEYVALUE_ENTRY(EVENT_ENCODINGCHANGED, "EncodingChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_EXITPRE, "ExitPre"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEAPPENDCMD, "FileAppendCmd"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEAPPENDPOST, "FileAppendPost"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEAPPENDPRE, "FileAppendPre"),
|
||||
KEYVALUE_ENTRY(EVENT_FILECHANGEDRO, "FileChangedRO"),
|
||||
KEYVALUE_ENTRY(EVENT_FILECHANGEDSHELL, "FileChangedShell"),
|
||||
KEYVALUE_ENTRY(EVENT_FILECHANGEDSHELLPOST, "FileChangedShellPost"),
|
||||
KEYVALUE_ENTRY(EVENT_ENCODINGCHANGED, "FileEncoding"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEREADCMD, "FileReadCmd"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEREADPOST, "FileReadPost"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEREADPRE, "FileReadPre"),
|
||||
KEYVALUE_ENTRY(EVENT_FILETYPE, "FileType"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEWRITECMD, "FileWriteCmd"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEWRITEPOST, "FileWritePost"),
|
||||
KEYVALUE_ENTRY(EVENT_FILEWRITEPRE, "FileWritePre"),
|
||||
KEYVALUE_ENTRY(EVENT_FILTERREADPOST, "FilterReadPost"),
|
||||
KEYVALUE_ENTRY(EVENT_FILTERREADPRE, "FilterReadPre"),
|
||||
KEYVALUE_ENTRY(EVENT_FILTERWRITEPOST, "FilterWritePost"),
|
||||
KEYVALUE_ENTRY(EVENT_FILTERWRITEPRE, "FilterWritePre"),
|
||||
KEYVALUE_ENTRY(EVENT_FOCUSGAINED, "FocusGained"),
|
||||
KEYVALUE_ENTRY(EVENT_FOCUSLOST, "FocusLost"),
|
||||
KEYVALUE_ENTRY(EVENT_FUNCUNDEFINED, "FuncUndefined"),
|
||||
KEYVALUE_ENTRY(EVENT_GUIENTER, "GUIEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_GUIFAILED, "GUIFailed"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTCHANGE, "InsertChange"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTCHARPRE, "InsertCharPre"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTENTER, "InsertEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTLEAVE, "InsertLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_INSERTLEAVEPRE, "InsertLeavePre"),
|
||||
KEYVALUE_ENTRY(EVENT_MENUPOPUP, "MenuPopup"),
|
||||
KEYVALUE_ENTRY(EVENT_MODECHANGED, "ModeChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_OPTIONSET, "OptionSet"),
|
||||
KEYVALUE_ENTRY(EVENT_QUICKFIXCMDPOST, "QuickFixCmdPost"),
|
||||
KEYVALUE_ENTRY(EVENT_QUICKFIXCMDPRE, "QuickFixCmdPre"),
|
||||
KEYVALUE_ENTRY(EVENT_QUITPRE, "QuitPre"),
|
||||
KEYVALUE_ENTRY(EVENT_REMOTEREPLY, "RemoteReply"),
|
||||
KEYVALUE_ENTRY(EVENT_SAFESTATE, "SafeState"),
|
||||
KEYVALUE_ENTRY(EVENT_SAFESTATEAGAIN, "SafeStateAgain"),
|
||||
KEYVALUE_ENTRY(EVENT_SESSIONLOADPOST, "SessionLoadPost"),
|
||||
KEYVALUE_ENTRY(EVENT_SESSIONWRITEPOST, "SessionWritePost"),
|
||||
KEYVALUE_ENTRY(EVENT_SHELLCMDPOST, "ShellCmdPost"),
|
||||
KEYVALUE_ENTRY(EVENT_SHELLFILTERPOST, "ShellFilterPost"),
|
||||
KEYVALUE_ENTRY(EVENT_SIGUSR1, "SigUSR1"),
|
||||
KEYVALUE_ENTRY(EVENT_SOURCECMD, "SourceCmd"),
|
||||
KEYVALUE_ENTRY(EVENT_SOURCEPOST, "SourcePost"),
|
||||
KEYVALUE_ENTRY(EVENT_SOURCEPRE, "SourcePre"),
|
||||
KEYVALUE_ENTRY(EVENT_SPELLFILEMISSING, "SpellFileMissing"),
|
||||
KEYVALUE_ENTRY(EVENT_STDINREADPOST, "StdinReadPost"),
|
||||
KEYVALUE_ENTRY(EVENT_STDINREADPRE, "StdinReadPre"),
|
||||
KEYVALUE_ENTRY(EVENT_SWAPEXISTS, "SwapExists"),
|
||||
KEYVALUE_ENTRY(EVENT_SYNTAX, "Syntax"),
|
||||
KEYVALUE_ENTRY(EVENT_TABCLOSED, "TabClosed"),
|
||||
KEYVALUE_ENTRY(EVENT_TABENTER, "TabEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_TABLEAVE, "TabLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_TABNEW, "TabNew"),
|
||||
KEYVALUE_ENTRY(EVENT_TERMCHANGED, "TermChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_TERMINALOPEN, "TerminalOpen"),
|
||||
KEYVALUE_ENTRY(EVENT_TERMINALWINOPEN, "TerminalWinOpen"),
|
||||
KEYVALUE_ENTRY(EVENT_TERMRESPONSE, "TermResponse"),
|
||||
KEYVALUE_ENTRY(EVENT_TERMRESPONSEALL, "TermResponseAll"),
|
||||
KEYVALUE_ENTRY(EVENT_TEXTCHANGED, "TextChanged"),
|
||||
KEYVALUE_ENTRY(EVENT_TEXTCHANGEDI, "TextChangedI"),
|
||||
KEYVALUE_ENTRY(EVENT_TEXTCHANGEDP, "TextChangedP"),
|
||||
KEYVALUE_ENTRY(EVENT_TEXTCHANGEDT, "TextChangedT"),
|
||||
KEYVALUE_ENTRY(EVENT_TEXTYANKPOST, "TextYankPost"),
|
||||
KEYVALUE_ENTRY(EVENT_USER, "User"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMENTER, "VimEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMLEAVE, "VimLeave"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMLEAVEPRE, "VimLeavePre"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMRESIZED, "VimResized"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMRESUME, "VimResume"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMSUSPEND, "VimSuspend"),
|
||||
KEYVALUE_ENTRY(EVENT_WINCLOSED, "WinClosed"),
|
||||
KEYVALUE_ENTRY(EVENT_WINENTER, "WinEnter"),
|
||||
KEYVALUE_ENTRY(EVENT_WINLEAVE, "WinLeave"),
|
||||
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
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
#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 event_T event_name2nr(char_u *start, char_u **end);
|
||||
static char_u *event_nr2name(event_T event);
|
||||
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);
|
||||
@ -681,24 +695,35 @@ is_aucmd_win(win_T *win)
|
||||
event_name2nr(char_u *start, char_u **end)
|
||||
{
|
||||
char_u *p;
|
||||
int i;
|
||||
int len;
|
||||
keyvalue_T target;
|
||||
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
|
||||
for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p)
|
||||
;
|
||||
for (i = 0; event_names[i].name != NULL; ++i)
|
||||
{
|
||||
len = (int)STRLEN(event_names[i].name);
|
||||
if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
target.key = 0;
|
||||
target.value = (char *)start;
|
||||
target.length = (size_t)(p - start);
|
||||
|
||||
// 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 == ',')
|
||||
++p;
|
||||
*end = p;
|
||||
if (event_names[i].name == NULL)
|
||||
return NUM_EVENTS;
|
||||
return event_names[i].event;
|
||||
|
||||
return (entry == NULL) ? NUM_EVENTS : (event_T)entry->key;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -708,11 +733,52 @@ event_name2nr(char_u *start, char_u **end)
|
||||
event_nr2name(event_T event)
|
||||
{
|
||||
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 (event_names[i].event == event)
|
||||
return (char_u *)event_names[i].name;
|
||||
return (char_u *)"Unknown";
|
||||
if (cache_last_index < 0)
|
||||
{
|
||||
for (i = 0; i < (int)ARRAY_LENGTH(cache_tab); ++i)
|
||||
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 *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)
|
||||
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)
|
||||
{
|
||||
vim_free(save_ei);
|
||||
@ -2774,6 +2842,8 @@ set_context_in_autocmd(
|
||||
char_u *
|
||||
get_event_name(expand_T *xp UNUSED, int idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (idx < augroups.ga_len) // First list group names, if wanted
|
||||
{
|
||||
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 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 *
|
||||
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
|
||||
if (dict_has_key(argvars[0].vval.v_dict, "event"))
|
||||
{
|
||||
int i;
|
||||
|
||||
name = dict_get_string(argvars[0].vval.v_dict, "event", TRUE);
|
||||
if (name == NULL)
|
||||
return;
|
||||
@ -3261,16 +3337,20 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv)
|
||||
event_arg = NUM_EVENTS;
|
||||
else
|
||||
{
|
||||
for (i = 0; event_names[i].name != NULL; i++)
|
||||
if (STRICMP(event_names[i].name, name) == 0)
|
||||
break;
|
||||
if (event_names[i].name == NULL)
|
||||
keyvalue_T target;
|
||||
keyvalue_T *entry;
|
||||
|
||||
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);
|
||||
vim_free(name);
|
||||
return;
|
||||
}
|
||||
event_arg = event_names[i].event;
|
||||
event_arg = (event_T)entry->key;
|
||||
}
|
||||
vim_free(name);
|
||||
}
|
||||
|
42
src/misc2.c
42
src/misc2.c
@ -3069,3 +3069,45 @@ get_special_pty_type(void)
|
||||
return 0;
|
||||
#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_list(list_T *l, char ***argv, int *argc);
|
||||
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 : */
|
||||
|
@ -5060,3 +5060,18 @@ typedef struct {
|
||||
linenr_T spv_capcol_lnum; // line number for "cap_col"
|
||||
#endif
|
||||
} 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
|
||||
|
||||
def s:PerformCheck(fname: string, pattern: string, msg: string, skip: string)
|
||||
var prev_lnum = 1
|
||||
var lnum = 1
|
||||
while (lnum > 0)
|
||||
cursor(lnum, 1)
|
||||
lnum = search(pattern, 'W', 0, 0, skip)
|
||||
ReportError(fname, lnum, msg)
|
||||
if (prev_lnum == lnum)
|
||||
break
|
||||
endif
|
||||
prev_lnum = lnum
|
||||
if (lnum > 0)
|
||||
lnum += 1
|
||||
ReportError(fname, lnum, msg)
|
||||
endif
|
||||
endwhile
|
||||
enddef
|
||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
256,
|
||||
/**/
|
||||
255,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user