diff options
author | zeertzjq <zeertzjq@outlook.com> | 2021-10-17 22:04:53 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2021-10-17 22:04:53 +0800 |
commit | 920473d2f228fb33c63c092c825b182a7434f25f (patch) | |
tree | 66286a9b6d460810d0d9d596f593c501a953be2c | |
parent | 30af69509dc91552dc41451857b18907f018c1bd (diff) | |
download | rneovim-920473d2f228fb33c63c092c825b182a7434f25f.tar.gz rneovim-920473d2f228fb33c63c092c825b182a7434f25f.tar.bz2 rneovim-920473d2f228fb33c63c092c825b182a7434f25f.zip |
vim-patch:8.0.1459: cannot handle change of directory
Problem: Cannot handle change of directory.
Solution: Add the DirChanged autocommand event. (Andy Massimino,
closes vim/vim#888) Avoid changing directory for 'autochdir' too often.
https://github.com/vim/vim/commit/b7407d3fc9496f9048fb65ab17b5ba3444965c0e
Only add "auto" pattern. "window" and "global" are already implemented.
Skip `Test_dirchanged_auto` using `CheckFunction test_autochdir`.
Part of PR #15952. More information can be found there.
N/A patches for version.c:
vim-patch:8.0.1460: missing file in patch
Problem: Missing file in patch.
Solution: Add changes to missing file.
https://github.com/vim/vim/commit/b5cb65ba2bcc6bbc6d2798a2dea18b95f0b38f5e
vim-patch:8.0.1461: missing another file in patch
Problem: Missing another file in patch.
Solution: Add changes to missing file.
https://github.com/vim/vim/commit/15833239a4131279935a4bd574b74fe3a2b0f49f
-rw-r--r-- | runtime/doc/autocmd.txt | 6 | ||||
-rw-r--r-- | runtime/doc/vim_diff.txt | 1 | ||||
-rw-r--r-- | src/nvim/buffer.c | 5 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_session.c | 2 | ||||
-rw-r--r-- | src/nvim/file_search.c | 24 | ||||
-rw-r--r-- | src/nvim/globals.h | 8 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 56 | ||||
-rw-r--r-- | src/nvim/window.c | 4 |
9 files changed, 94 insertions, 14 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 5923dada43..b7df0fba54 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -519,11 +519,17 @@ DiffUpdated After diffs have been updated. Depending on change or when doing |:diffupdate|. *DirChanged* DirChanged After the |current-directory| was changed. + The pattern can be: + "window" to trigger on `:lcd` + "tab" to trigger on `:tcd` + "global" to trigger on `:cd` + "auto" to trigger on 'autochdir'. Sets these |v:event| keys: cwd: current working directory scope: "global", "tab", "window" changed_window: v:true if we fired the event switching window (or tab) + <afile> is set to the new directory name. Non-recursive (event cannot trigger itself). *FileAppendCmd* FileAppendCmd Before appending to a file. Should do the diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 64824b2e3f..c85cae4004 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -180,6 +180,7 @@ Commands: |:match| can be invoked before highlight group is defined Events: + |DirChanged| can be triggered when switching to another window |Signal| |TabNewEntered| |TermClose| diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 37cc854959..386714b05a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -593,9 +593,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last) buf->b_nwindows--; } - // Change directories when the 'acd' option is set. - do_autochdir(); - // Disable buffer-updates for the current buffer. // No need to check `unload_buf`: in that case the function returned above. buf_updates_unload(buf, false); @@ -1628,7 +1625,7 @@ void do_autochdir(void) if (p_acd) { if (starting == 0 && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) { + && vim_chdirfile(curbuf->b_ffname, kCdCauseAuto) == OK) { post_chdir(kCdScopeGlobal, false); shorten_fnames(true); } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 16a9b78c6a..5d83e2218b 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7749,7 +7749,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged) shorten_fnames(true); if (trigger_dirchanged) { - do_autocmd_dirchanged(cwd, scope, false); + do_autocmd_dirchanged(cwd, scope, kCdCauseManual); } } diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 1e1da6a9a3..0dfd7e1edd 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -963,7 +963,7 @@ void ex_mkrc(exarg_T *eap) *dirnow = NUL; } if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) { - if (vim_chdirfile((char_u *)fname) == OK) { + if (vim_chdirfile((char_u *)fname, kCdCauseOther) == OK) { shorten_fnames(true); } } else if (*dirnow != NUL diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 5458d8acf2..e7c4785beb 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1590,7 +1590,7 @@ theend: return file_name; } -void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window) +void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause) { static bool recursive = false; @@ -1621,10 +1621,22 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window) } 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"), changed_window); + 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); + switch (cause) { + case kCdCauseManual: + case kCdCauseWindow: + break; + case kCdCauseAuto: + snprintf(buf, sizeof(buf), "auto"); + break; + case kCdCauseOther: + // Should never happen. + abort(); + } + apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false, curbuf); @@ -1636,7 +1648,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, bool changed_window) /// Change to a file's directory. /// Caller must call shorten_fnames()! /// @return OK or FAIL -int vim_chdirfile(char_u *fname) +int vim_chdirfile(char_u *fname, CdCause cause) { char dir[MAXPATHL]; @@ -1654,8 +1666,8 @@ int vim_chdirfile(char_u *fname) #ifdef BACKSLASH_IN_FILENAME slash_adjust((char_u *)dir); #endif - if (!strequal(dir, (char *)NameBuff)) { - do_autocmd_dirchanged(dir, kCdScopeWindow, false); + if (cause != kCdCauseOther && !strequal(dir, (char *)NameBuff)) { + do_autocmd_dirchanged(dir, kCdScopeWindow, cause); } return OK; diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 8a36b3bedd..e04856e85f 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1042,6 +1042,14 @@ typedef enum { #define MIN_CD_SCOPE kCdScopeWindow #define MAX_CD_SCOPE kCdScopeGlobal +/// What caused the current directory to change. +typedef enum { + kCdCauseOther = -1, + kCdCauseManual, ///< Using `:cd`, `:tcd`, `:lcd` or `chdir()`. + kCdCauseWindow, ///< Switching to another window. + kCdCauseAuto, ///< On 'autochdir'. +} CdCause; + // Only filled for Win32. EXTERN char windowsVersion[20] INIT(= { 0 }); diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 015979e1be..d174b11a9c 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -1328,6 +1328,62 @@ func Test_autocommand_all_events() call assert_fails('au * x bwipe', 'E1155:') endfunc +function s:Before_test_dirchanged() + augroup test_dirchanged + autocmd! + augroup END + let s:li = [] + let s:dir_this = getcwd() + let s:dir_other = s:dir_this . '/foo' + call mkdir(s:dir_other) +endfunc + +function s:After_test_dirchanged() + exe 'cd' s:dir_this + call delete(s:dir_other, 'd') + augroup test_dirchanged + autocmd! + augroup END +endfunc + +function Test_dirchanged_global() + call s:Before_test_dirchanged() + autocmd test_dirchanged DirChanged global call add(s:li, "cd:") + autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>")) + exe 'cd' s:dir_other + call assert_equal(["cd:", s:dir_other], s:li) + exe 'lcd' s:dir_other + call assert_equal(["cd:", s:dir_other], s:li) + call s:After_test_dirchanged() +endfunc + +function Test_dirchanged_local() + call s:Before_test_dirchanged() + autocmd test_dirchanged DirChanged window call add(s:li, "lcd:") + autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>")) + exe 'cd' s:dir_other + call assert_equal([], s:li) + exe 'lcd' s:dir_other + call assert_equal(["lcd:", s:dir_other], s:li) + call s:After_test_dirchanged() +endfunc + +function Test_dirchanged_auto() + call s:Before_test_dirchanged() + call test_autochdir() + autocmd test_dirchanged DirChanged auto call add(s:li, "auto:") + autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>")) + set acd + exe 'cd ..' + call assert_equal([], s:li) + exe 'edit ' . s:dir_other . '/Xfile' + call assert_equal(s:dir_other, getcwd()) + call assert_equal(["auto:", s:dir_other], s:li) + set noacd + bwipe! + call s:After_test_dirchanged() +endfunc + " Test TextChangedI and TextChangedP " See test/functional/viml/completion_spec.lua' func Test_ChangedP() diff --git a/src/nvim/window.c b/src/nvim/window.c index 1fe4aa1add..a7470889b3 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4542,7 +4542,7 @@ static void win_enter_ext(win_T *const wp, const int flags) if (os_chdir(new_dir) == 0) { if (!p_acd && !strequal(new_dir, cwd)) { do_autocmd_dirchanged(new_dir, curwin->w_localdir - ? kCdScopeWindow : kCdScopeTab, true); + ? kCdScopeWindow : kCdScopeTab, kCdCauseWindow); } shorten_fnames(true); } @@ -4551,7 +4551,7 @@ static void win_enter_ext(win_T *const wp, const int flags) // directory: Change to the global directory. if (os_chdir((char *)globaldir) == 0) { if (!p_acd && !strequal((char *)globaldir, cwd)) { - do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, true); + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal, kCdCauseWindow); } } XFREE_CLEAR(globaldir); |