# HG changeset patch # User Christian Brabandt # Date 1517676305 -3600 # Node ID 6559e98f3e74c57823451e63143dde97ff9fc2ff # Parent 570e10c8313d3f6a063df760e30f46a1d94f4ca9 patch 8.0.1459: cannot handle change of directory commit https://github.com/vim/vim/commit/b7407d3fc9496f9048fb65ab17b5ba3444965c0e Author: Bram Moolenaar Date: Sat Feb 3 17:36:27 2018 +0100 patch 8.0.1459: cannot handle change of directory Problem: Cannot handle change of directory. Solution: Add the DirChanged autocommand event. (Andy Massimino, closes #888) Avoid changing directory for 'autochdir' too often. diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -295,6 +295,8 @@ Name triggered by ~ |FileChangedShellPost| After handling a file changed since editing started |FileChangedRO| before making the first change to a read-only file +|DirChanged| after the working directory has changed + |ShellCmdPost| after executing a shell command |ShellFilterPost| after filtering with a shell command @@ -633,6 +635,16 @@ FileChangedRO Before making the first *E881* If the number of lines changes saving for undo may fail and the change will be aborted. + *DirChanged* +DirChanged The working directory has changed in response + to the |:cd| or |:lcd| commands, or as a + result of the 'autochdir' option. + The pattern can be: + "window" to trigger on `:lcd + "global" to trigger on `:cd` + "auto" to trigger on 'autochdir'. + "drop" to trigger on editing a file + is set to the new directory name. *FileChangedShell* FileChangedShell When Vim notices that the modification time of a file has changed since editing started. diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -595,7 +595,7 @@ aucmd_abort: #ifdef FEAT_DIFF if (diffopt_hiddenoff() && !unload_buf && buf->b_nwindows == 0) - diff_buf_delete(buf); /* Clear 'diff' for hidden buffer. */ + diff_buf_delete(buf); /* Clear 'diff' for hidden buffer. */ #endif /* Return when a window is displaying the buffer or when it's not @@ -657,9 +657,6 @@ aucmd_abort: --buf->b_nwindows; #endif - /* Change directories when the 'acd' option is set. */ - DO_AUTOCHDIR - /* * Remove the buffer from the list. */ @@ -1862,7 +1859,7 @@ do_autochdir(void) { if ((starting == 0 || test_autochdir) && curbuf->b_ffname != NULL - && vim_chdirfile(curbuf->b_ffname) == OK) + && vim_chdirfile(curbuf->b_ffname, "auto") == OK) shorten_fnames(TRUE); } #endif diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -9048,11 +9048,19 @@ ex_cd(exarg_T *eap) EMSG(_(e_failed)); else { - post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir); + int is_local_chdir = eap->cmdidx == CMD_lcd + || eap->cmdidx == CMD_lchdir; + + post_chdir(is_local_chdir); /* Echo the new current directory if the command was typed. */ if (KeyTyped || p_verbose >= 5) ex_pwd(eap); +#ifdef FEAT_AUTOCMD + apply_autocmds(EVENT_DIRCHANGED, + is_local_chdir ? (char_u *)"window" : (char_u *)"global", + new_dir, FALSE, curbuf); +#endif } vim_free(tofree); } @@ -9932,7 +9940,7 @@ ex_mkrc( *dirnow = NUL; if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) { - if (vim_chdirfile(fname) == OK) + if (vim_chdirfile(fname, NULL) == OK) shorten_fnames(TRUE); } else if (*dirnow != NUL diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -7798,6 +7798,7 @@ static struct event_name {"CursorHoldI", EVENT_CURSORHOLDI}, {"CursorMoved", EVENT_CURSORMOVED}, {"CursorMovedI", EVENT_CURSORMOVEDI}, + {"DirChanged", EVENT_DIRCHANGED}, {"EncodingChanged", EVENT_ENCODINGCHANGED}, {"FileEncoding", EVENT_ENCODINGCHANGED}, {"FileAppendPost", EVENT_FILEAPPENDPOST}, @@ -9588,7 +9589,7 @@ apply_autocmds_group( { sfname = vim_strsave(fname); /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID, - * ColorScheme or QuickFixCmd* */ + * ColorScheme, QuickFixCmd* or DirChanged */ if (event == EVENT_FILETYPE || event == EVENT_SYNTAX || event == EVENT_FUNCUNDEFINED @@ -9597,7 +9598,8 @@ apply_autocmds_group( || event == EVENT_QUICKFIXCMDPRE || event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET - || event == EVENT_QUICKFIXCMDPOST) + || event == EVENT_QUICKFIXCMDPOST + || event == EVENT_DIRCHANGED) fname = vim_strsave(fname); else fname = FullName_save(fname, FALSE); diff --git a/src/gui_mac.c b/src/gui_mac.c --- a/src/gui_mac.c +++ b/src/gui_mac.c @@ -1105,7 +1105,8 @@ HandleODocAE(const AppleEvent *theAEvent } /* Change directory to the location of the first file. */ - if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK) + if (GARGCOUNT > 0 + && vim_chdirfile(alist_name(&GARGLIST[0]), "drop") == OK) shorten_fnames(TRUE); goto finished; diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -264,7 +264,7 @@ main * Hint: to avoid this when typing a command use a forward slash. * If the cd fails, it doesn't matter. */ - (void)vim_chdirfile(params.fname); + (void)vim_chdirfile(params.fname, "drop"); if (start_dir != NULL) mch_dirname(start_dir, MAXPATHL); } @@ -314,7 +314,7 @@ main && STRCMP(NameBuff, "/") == 0) { if (params.fname != NULL) - (void)vim_chdirfile(params.fname); + (void)vim_chdirfile(params.fname, "drop"); else { expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); diff --git a/src/netbeans.c b/src/netbeans.c --- a/src/netbeans.c +++ b/src/netbeans.c @@ -2663,7 +2663,7 @@ netbeans_file_opened(buf_T *bufp) nbdebug(("EVT: %s", buffer)); nb_send(buffer, "netbeans_file_opened"); - if (p_acd && vim_chdirfile(bufp->b_ffname) == OK) + if (p_acd && vim_chdirfile(bufp->b_ffname, "auto") == OK) shorten_fnames(TRUE); } diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -7193,7 +7193,7 @@ fix_arg_enc(void) { do_cmdline_cmd((char_u *)":rewind"); if (GARGCOUNT == 1 && used_file_full_path) - (void)vim_chdirfile(alist_name(&GARGLIST[0])); + (void)vim_chdirfile(alist_name(&GARGLIST[0]), "drop"); } set_alist_count(); diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -82,7 +82,7 @@ int call_shell(char_u *cmd, int opt); int get_real_state(void); int after_pathsep(char_u *b, char_u *p); int same_directory(char_u *f1, char_u *f2); -int vim_chdirfile(char_u *fname); +int vim_chdirfile(char_u *fname, char *trigger_autocmd); int vim_stat(const char *name, stat_T *stp); char_u *parse_shape_opt(int what); int get_shape_idx(int mouse); diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -1190,3 +1190,59 @@ func Test_nocatch_wipe_dummy_buffer() call assert_fails('lvĀ½ /x', 'E480') au! 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("")) + 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("")) + 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("")) + 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 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1459, +/**/ 1458, /**/ 1457, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -1276,6 +1276,7 @@ enum auto_event EVENT_CMDWINLEAVE, /* before leaving the cmdline window */ EVENT_COLORSCHEME, /* after loading a colorscheme */ EVENT_COMPLETEDONE, /* after finishing insert complete */ + EVENT_DIRCHANGED, /* after changing directory as a result of user cmd */ EVENT_FILEAPPENDPOST, /* after appending to a file */ EVENT_FILEAPPENDPRE, /* before appending to a file */ EVENT_FILEAPPENDCMD, /* append to a file using command */