diff options
Diffstat (limited to 'src/autocmd.c')
-rw-r--r-- | src/autocmd.c | 422 |
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; + } } } } |