diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/vim.c | 10 | ||||
-rw-r--r-- | src/nvim/auevents.lua | 5 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 13 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 15 | ||||
-rw-r--r-- | src/nvim/file_search.c | 21 | ||||
-rw-r--r-- | src/nvim/getchar.c | 29 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 20 | ||||
-rw-r--r-- | src/nvim/window.c | 23 |
8 files changed, 79 insertions, 57 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index f4909b0801..11bb1750e4 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -497,8 +497,12 @@ ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err) int flags = DIP_DIRFILE | (all ? DIP_ALL : 0); - do_in_runtimepath((char_u *)(name.size ? name.data : ""), - flags, find_runtime_cb, &rv); + TRY_WRAP({ + try_start(); + do_in_runtimepath((char_u *)(name.size ? name.data : ""), + flags, find_runtime_cb, &rv); + try_end(err); + }); return rv; } @@ -1584,7 +1588,7 @@ ArrayOf(Dictionary) nvim_get_keymap(uint64_t channel_id, String mode) /// @param rhs Right-hand-side |{rhs}| of the mapping. /// @param opts Optional parameters map. Accepts all |:map-arguments| /// as keys excluding |<buffer>| but including |noremap| and "desc". -/// |desc| can be used to give a description to keymap. +/// "desc" can be used to give a description to keymap. /// When called from Lua, also accepts a "callback" key that takes /// a Lua function to call when the mapping is executed. /// Values are Booleans. Unknown key is an error. diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 8fe623fc96..518d0b52b2 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -40,6 +40,7 @@ return { 'DiagnosticChanged', -- diagnostics in a buffer were modified 'DiffUpdated', -- diffs have been updated 'DirChanged', -- directory changed + 'DirChangedPre', -- directory is going to change 'EncodingChanged', -- after changing the 'encoding' option 'ExitPre', -- before exiting 'FileAppendCmd', -- append to a file using command @@ -132,18 +133,14 @@ return { nvim_specific = { BufModifiedSet=true, DiagnosticChanged=true, - DirChanged=true, RecordingEnter=true, RecordingLeave=true, Signal=true, - TabClosed=true, - TabNew=true, TabNewEntered=true, TermClose=true, TermOpen=true, UIEnter=true, UILeave=true, - WinClosed=true, WinScrolled=true, }, } diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index dfba18b11d..9117dde089 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1517,12 +1517,13 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, || event == EVENT_CMDLINELEAVE || event == EVENT_CMDWINENTER || event == EVENT_CMDWINLEAVE || event == EVENT_CMDUNDEFINED || event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEMEPRE - || event == EVENT_DIRCHANGED || event == EVENT_FILETYPE - || event == EVENT_FUNCUNDEFINED || event == EVENT_MODECHANGED - || event == EVENT_OPTIONSET || event == EVENT_QUICKFIXCMDPOST - || event == EVENT_QUICKFIXCMDPRE || event == EVENT_REMOTEREPLY - || event == EVENT_SPELLFILEMISSING || event == EVENT_SYNTAX - || event == EVENT_SIGNAL || event == EVENT_TABCLOSED + || event == EVENT_DIRCHANGED || event == EVENT_DIRCHANGEDPRE + || event == EVENT_FILETYPE || event == EVENT_FUNCUNDEFINED + || event == EVENT_MODECHANGED || event == EVENT_OPTIONSET + || event == EVENT_QUICKFIXCMDPOST || event == EVENT_QUICKFIXCMDPRE + || event == EVENT_REMOTEREPLY || event == EVENT_SPELLFILEMISSING + || event == EVENT_SYNTAX || event == EVENT_SIGNAL + || event == EVENT_TABCLOSED || event == EVENT_USER || event == EVENT_WINCLOSED) { fname = vim_strsave(fname); } else { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 87f8865133..9991584862 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7797,7 +7797,7 @@ static char_u *get_prevdir(CdScope scope) /// Deal with the side effects of changing the current directory. /// /// @param scope Scope of the function call (global, tab or window). -void post_chdir(CdScope scope, bool trigger_dirchanged) +static void post_chdir(CdScope scope, bool trigger_dirchanged) { // Always overwrite the window-local CWD. XFREE_CLEAR(curwin->w_localdir); @@ -7838,7 +7838,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged) shorten_fnames(true); if (trigger_dirchanged) { - do_autocmd_dirchanged(cwd, scope, kCdCauseManual); + do_autocmd_dirchanged(cwd, scope, kCdCauseManual, false); } } @@ -7882,10 +7882,13 @@ bool changedir_func(char_u *new_dir, CdScope scope) } bool dir_differs = pdir == NULL || pathcmp((char *)pdir, (char *)new_dir, -1) != 0; - if (dir_differs && vim_chdir(new_dir) != 0) { - emsg(_(e_failed)); - xfree(pdir); - return false; + if (dir_differs) { + do_autocmd_dirchanged((char *)new_dir, scope, kCdCauseManual, true); + if (vim_chdir(new_dir) != 0) { + emsg(_(e_failed)); + xfree(pdir); + return false; + } } char_u **pp; diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 25dbf680de..d0f7a91d6c 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1600,11 +1600,13 @@ theend: return file_name; } -void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause) +void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause, bool pre) { static bool recursive = false; - if (recursive || !has_event(EVENT_DIRCHANGED)) { + event_T event = pre ? EVENT_DIRCHANGEDPRE : EVENT_DIRCHANGED; + + if (recursive || !has_event(event)) { // No autocommand was defined or we changed // the directory from this autocommand. return; @@ -1638,8 +1640,12 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause) new_dir = new_dir_buf; #endif + if (pre) { + tv_dict_add_str(dict, S_LEN("directory"), new_dir); + } else { + tv_dict_add_str(dict, S_LEN("cwd"), new_dir); + } tv_dict_add_str(dict, S_LEN("scope"), buf); // -V614 - tv_dict_add_str(dict, S_LEN("cwd"), new_dir); tv_dict_add_bool(dict, S_LEN("changed_window"), cause == kCdCauseWindow); tv_dict_set_keys_readonly(dict); @@ -1655,8 +1661,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause) abort(); } - apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false, - curbuf); + apply_autocmds(event, (char_u *)buf, (char_u *)new_dir, false, curbuf); restore_v_event(dict, &save_v_event); @@ -1682,12 +1687,16 @@ int vim_chdirfile(char_u *fname, CdCause cause) return OK; } + if (cause != kCdCauseOther) { + do_autocmd_dirchanged(dir, kCdScopeWindow, cause, true); + } + if (os_chdir(dir) != 0) { return FAIL; } if (cause != kCdCauseOther) { - do_autocmd_dirchanged(dir, kCdScopeWindow, cause); + do_autocmd_dirchanged(dir, kCdScopeWindow, cause, false); } return OK; diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 5d8a8ddbfe..741fc6d803 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1004,20 +1004,9 @@ int ins_char_typebuf(int c, int modifier) buf[len + 2] = (char_u)K_THIRD(c); buf[len + 3] = NUL; } else { - char_u *p = buf + len; - int char_len = utf_char2bytes(c, p); - len += char_len; - // If the character contains K_SPECIAL bytes they need escaping. - for (int i = char_len; --i >= 0; p++) { - if ((uint8_t)(*p) == K_SPECIAL) { - memmove(p + 3, p + 1, (size_t)i); - *p++ = K_SPECIAL; - *p++ = KS_SPECIAL; - *p = KE_FILLER; - len += 2; - } - } - *p = NUL; + char_u *end = add_char2buf(c, buf + len); + *end = NUL; + len = (int)(end - buf); } (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent); return len; @@ -2679,8 +2668,7 @@ void set_maparg_lhs_rhs(const char_u *orig_lhs, const size_t orig_lhs_len, mapargs->orig_rhs_len = 0; // stores <lua>ref_no<cr> in map_str mapargs->rhs_len = (size_t)vim_snprintf(S_LEN(tmp_buf), "%c%c%c%d\r", K_SPECIAL, - (char_u)KEY2TERMCAP0(K_LUA), KEY2TERMCAP1(K_LUA), - rhs_lua); + (char_u)KS_EXTRA, KE_LUA, rhs_lua); mapargs->rhs = vim_strsave((char_u *)tmp_buf); } @@ -3434,8 +3422,8 @@ static void showmap(mapblock_T *mp, bool local) { size_t len = 1; - if (message_filtered(mp->m_keys) - && mp->m_str != NULL && message_filtered(mp->m_str)) { + if (message_filtered(mp->m_keys) && message_filtered(mp->m_str) + && (mp->m_desc == NULL || message_filtered((char_u *)mp->m_desc))) { return; } @@ -3484,7 +3472,7 @@ static void showmap(mapblock_T *mp, bool local) char msg[100]; snprintf(msg, sizeof(msg), "<Lua function %d>", mp->m_luaref); msg_puts_attr(msg, HL_ATTR(HLF_8)); - } else if (mp->m_str == NULL) { + } else if (mp->m_str[0] == NUL) { msg_puts_attr("<Nop>", HL_ATTR(HLF_8)); } else { // Remove escaping of K_SPECIAL, because "m_str" is in a format to be used @@ -3584,8 +3572,7 @@ int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr) mp = maphash[hash]; } for (; mp; mp = mp->m_next) { - if ((mp->m_mode & mode) - && mp->m_str != NULL && strstr((char *)mp->m_str, rhs) != NULL) { + if ((mp->m_mode & mode) && strstr((char *)mp->m_str, rhs) != NULL) { return true; } } diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index a8d51ef598..0146c06109 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1827,6 +1827,14 @@ func Test_autocommand_all_events() call assert_fails('au * x bwipe', 'E1155:') endfunc +func Test_autocmd_user() + au User MyEvent let s:res = [expand("<afile>"), expand("<amatch>")] + doautocmd User MyEvent + call assert_equal(['MyEvent', 'MyEvent'], s:res) + au! User + unlet s:res +endfunc + function s:Before_test_dirchanged() augroup test_dirchanged autocmd! @@ -1850,14 +1858,16 @@ endfunc function Test_dirchanged_global() call s:Before_test_dirchanged() + autocmd test_dirchanged DirChangedPre global call add(s:li, expand("<amatch>") .. " pre cd " .. v:event.directory) autocmd test_dirchanged DirChanged global call add(s:li, "cd:") autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>")) call chdir(s:dir_foo) - call assert_equal(["cd:", s:dir_foo], s:li) + let expected = ["global pre cd " .. s:dir_foo, "cd:", s:dir_foo] + call assert_equal(expected, s:li) call chdir(s:dir_foo) - call assert_equal(["cd:", s:dir_foo], s:li) + call assert_equal(expected, s:li) exe 'lcd ' .. fnameescape(s:dir_bar) - call assert_equal(["cd:", s:dir_foo], s:li) + call assert_equal(expected, s:li) call s:After_test_dirchanged() endfunc @@ -1879,6 +1889,7 @@ function Test_dirchanged_auto() CheckOption autochdir call s:Before_test_dirchanged() call test_autochdir() + autocmd test_dirchanged DirChangedPre auto call add(s:li, "pre cd " .. v:event.directory) autocmd test_dirchanged DirChanged auto call add(s:li, "auto:") autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>")) set acd @@ -1886,7 +1897,8 @@ function Test_dirchanged_auto() call assert_equal([], s:li) exe 'edit ' . s:dir_foo . '/Xfile' call assert_equal(s:dir_foo, getcwd()) - call assert_equal(["auto:", s:dir_foo], s:li) + let expected = ["pre cd " .. s:dir_foo, "auto:", s:dir_foo] + call assert_equal(expected, s:li) set noacd bwipe! call s:After_test_dirchanged() diff --git a/src/nvim/window.c b/src/nvim/window.c index 1e737d2083..43667377c5 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4688,20 +4688,29 @@ void fix_current_dir(void) globaldir = (char_u *)xstrdup(cwd); } } + bool dir_differs = pathcmp(new_dir, cwd, -1) != 0; + if (!p_acd && dir_differs) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir ? kCdScopeWindow : kCdScopeTabpage, + kCdCauseWindow, true); + } if (os_chdir(new_dir) == 0) { - if (!p_acd && pathcmp(new_dir, cwd, -1) != 0) { - do_autocmd_dirchanged(new_dir, curwin->w_localdir - ? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow); + if (!p_acd && dir_differs) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir ? kCdScopeWindow : kCdScopeTabpage, + kCdCauseWindow, false); } - last_chdir_reason = NULL; - shorten_fnames(true); } + last_chdir_reason = NULL; + shorten_fnames(true); } else if (globaldir != NULL) { // Window doesn't have a local directory and we are not in the global // directory: Change to the global directory. + bool dir_differs = pathcmp((char *)globaldir, cwd, -1) != 0; + if (!p_acd && dir_differs) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, true); + } if (os_chdir((char *)globaldir) == 0) { - if (!p_acd && pathcmp((char *)globaldir, cwd, -1) != 0) { - do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow); + if (!p_acd && dir_differs) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow, false); } } XFREE_CLEAR(globaldir); |