summaryrefslogtreecommitdiffstats
path: root/src/autocmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/autocmd.c')
-rw-r--r--src/autocmd.c422
1 files changed, 260 insertions, 162 deletions
diff --git a/src/autocmd.c b/src/autocmd.c
index 8e43b34..bce57cb 100644
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -74,152 +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},
- {"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
@@ -265,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);
@@ -680,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;
}
/*
@@ -707,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;
+
+ 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;
+ }
- 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";
+ // 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;
}
/*
@@ -805,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);
@@ -1591,6 +1660,11 @@ aucmd_prepbuf(
win_init_popup_win(auc_win, buf);
+ // Make sure tp_localdir and globaldir are NULL to avoid a
+ // chdir() in win_enter_ext().
+ // win_init_popup_win() has already set w_localdir to NULL.
+ aco->tp_localdir = curtab->tp_localdir;
+ curtab->tp_localdir = NULL;
aco->globaldir = globaldir;
globaldir = NULL;
@@ -1704,6 +1778,12 @@ win_found:
vars_clear(&awp->w_vars->dv_hashtab); // free all w: variables
hash_init(&awp->w_vars->dv_hashtab); // re-use the hashtab
#endif
+ // If :lcd has been used in the autocommand window, correct current
+ // directory before restoring tp_localdir and globaldir.
+ if (awp->w_localdir != NULL)
+ win_fix_current_dir();
+ vim_free(curtab->tp_localdir);
+ curtab->tp_localdir = aco->tp_localdir;
vim_free(globaldir);
globaldir = aco->globaldir;
@@ -2257,7 +2337,7 @@ apply_autocmds_group(
saveRedobuff(&save_redo);
did_save_redobuff = TRUE;
}
- did_filetype = keep_filetype;
+ curbuf->b_did_filetype = curbuf->b_keep_filetype;
}
/*
@@ -2269,7 +2349,7 @@ apply_autocmds_group(
// Remember that FileType was triggered. Used for did_filetype().
if (event == EVENT_FILETYPE)
- did_filetype = TRUE;
+ curbuf->b_did_filetype = TRUE;
tail = gettail(fname);
@@ -2378,7 +2458,7 @@ apply_autocmds_group(
restore_search_patterns();
if (did_save_redobuff)
restoreRedobuff(&save_redo);
- did_filetype = FALSE;
+ curbuf->b_did_filetype = FALSE;
while (au_pending_free_buf != NULL)
{
buf_T *b = au_pending_free_buf->b_next;
@@ -2420,7 +2500,7 @@ BYPASS_AU:
aubuflocal_remove(buf);
if (retval == OK && event == EVENT_FILETYPE)
- au_did_filetype = TRUE;
+ curbuf->b_au_did_filetype = TRUE;
return retval;
}
@@ -2773,6 +2853,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
@@ -2780,7 +2862,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;
}
/*
@@ -2790,7 +2877,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;
}
@@ -3250,8 +3340,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;
@@ -3260,16 +3348,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);
}
@@ -3314,7 +3406,10 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv)
event_dict = dict_alloc();
if (event_dict == NULL
|| list_append_dict(event_list, event_dict) == FAIL)
+ {
+ vim_free(pat);
return;
+ }
if (dict_add_string(event_dict, "event", event_name) == FAIL
|| dict_add_string(event_dict, "group",
@@ -3329,7 +3424,10 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv)
|| dict_add_bool(event_dict, "once", ac->once) == FAIL
|| dict_add_bool(event_dict, "nested",
ac->nested) == FAIL)
+ {
+ vim_free(pat);
return;
+ }
}
}
}