summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Marriott <basilisk@internode.on.net>2024-04-02 20:26:01 +0200
committerChristian Brabandt <cb@256bit.org>2024-04-02 20:26:01 +0200
commit78d742ab8845578f78039ddd71a6444c6929257c (patch)
treed782bcc5d36c4259b05f29fe1d41e1845c9578e2
parent16cdfa69e07190674a8e85a48144a467472ca2f4 (diff)
patch 9.1.0256: Finding autocmd events is inefficientv9.1.0256
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>
-rw-r--r--src/autocmd.c398
-rw-r--r--src/misc2.c42
-rw-r--r--src/proto/misc2.pro4
-rw-r--r--src/structs.h15
-rw-r--r--src/testdir/test_codestyle.vim8
-rw-r--r--src/version.c2
6 files changed, 308 insertions, 161 deletions
diff --git a/src/autocmd.c b/src/autocmd.c
index 9632c74d49..b1c74cb853 100644
--- a/src/autocmd.c
+++ b/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);
}
diff --git a/src/misc2.c b/src/misc2.c
index 6df0d39100..c07ed8065c 100644
--- a/src/misc2.c
+++ b/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));
+}
+
diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro
index f596ffafaf..7a5b36736d 100644
--- a/src/proto/misc2.pro
+++ b/src/proto/misc2.pro
@@ -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 : */
diff --git a/src/structs.h b/src/structs.h
index 2218de7037..3ce13ff0fb 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -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)}
+
diff --git a/src/testdir/test_codestyle.vim b/src/testdir/test_codestyle.vim
index 359410d2d0..a455264de7 100644
--- a/src/testdir/test_codestyle.vim
+++ b/src/testdir/test_codestyle.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 22a1e31a54..3d0474aad2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 256,
+/**/
255,
/**/
254,