0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

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.
This commit is contained in:
Bram Moolenaar 2018-02-03 17:36:27 +01:00
parent ddb349369d
commit b7407d3fc9
12 changed files with 94 additions and 15 deletions

View File

@ -295,6 +295,8 @@ Name triggered by ~
|FileChangedShellPost| After handling a file changed since editing started |FileChangedShellPost| After handling a file changed since editing started
|FileChangedRO| before making the first change to a read-only file |FileChangedRO| before making the first change to a read-only file
|DirChanged| after the working directory has changed
|ShellCmdPost| after executing a shell command |ShellCmdPost| after executing a shell command
|ShellFilterPost| after filtering with a shell command |ShellFilterPost| after filtering with a shell command
@ -633,6 +635,16 @@ FileChangedRO Before making the first change to a read-only
*E881* *E881*
If the number of lines changes saving for undo If the number of lines changes saving for undo
may fail and the change will be aborted. 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
<afile> is set to the new directory name.
*FileChangedShell* *FileChangedShell*
FileChangedShell When Vim notices that the modification time of FileChangedShell When Vim notices that the modification time of
a file has changed since editing started. a file has changed since editing started.

View File

@ -595,7 +595,7 @@ aucmd_abort:
#ifdef FEAT_DIFF #ifdef FEAT_DIFF
if (diffopt_hiddenoff() && !unload_buf && buf->b_nwindows == 0) 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 #endif
/* Return when a window is displaying the buffer or when it's not /* Return when a window is displaying the buffer or when it's not
@ -657,9 +657,6 @@ aucmd_abort:
--buf->b_nwindows; --buf->b_nwindows;
#endif #endif
/* Change directories when the 'acd' option is set. */
DO_AUTOCHDIR
/* /*
* Remove the buffer from the list. * Remove the buffer from the list.
*/ */
@ -1862,7 +1859,7 @@ do_autochdir(void)
{ {
if ((starting == 0 || test_autochdir) if ((starting == 0 || test_autochdir)
&& curbuf->b_ffname != NULL && curbuf->b_ffname != NULL
&& vim_chdirfile(curbuf->b_ffname) == OK) && vim_chdirfile(curbuf->b_ffname, "auto") == OK)
shorten_fnames(TRUE); shorten_fnames(TRUE);
} }
#endif #endif

View File

@ -9048,11 +9048,19 @@ ex_cd(exarg_T *eap)
EMSG(_(e_failed)); EMSG(_(e_failed));
else 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. */ /* Echo the new current directory if the command was typed. */
if (KeyTyped || p_verbose >= 5) if (KeyTyped || p_verbose >= 5)
ex_pwd(eap); 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); vim_free(tofree);
} }
@ -9932,7 +9940,7 @@ ex_mkrc(
*dirnow = NUL; *dirnow = NUL;
if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR)) if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
{ {
if (vim_chdirfile(fname) == OK) if (vim_chdirfile(fname, NULL) == OK)
shorten_fnames(TRUE); shorten_fnames(TRUE);
} }
else if (*dirnow != NUL else if (*dirnow != NUL

View File

@ -7798,6 +7798,7 @@ static struct event_name
{"CursorHoldI", EVENT_CURSORHOLDI}, {"CursorHoldI", EVENT_CURSORHOLDI},
{"CursorMoved", EVENT_CURSORMOVED}, {"CursorMoved", EVENT_CURSORMOVED},
{"CursorMovedI", EVENT_CURSORMOVEDI}, {"CursorMovedI", EVENT_CURSORMOVEDI},
{"DirChanged", EVENT_DIRCHANGED},
{"EncodingChanged", EVENT_ENCODINGCHANGED}, {"EncodingChanged", EVENT_ENCODINGCHANGED},
{"FileEncoding", EVENT_ENCODINGCHANGED}, {"FileEncoding", EVENT_ENCODINGCHANGED},
{"FileAppendPost", EVENT_FILEAPPENDPOST}, {"FileAppendPost", EVENT_FILEAPPENDPOST},
@ -9588,7 +9589,7 @@ apply_autocmds_group(
{ {
sfname = vim_strsave(fname); sfname = vim_strsave(fname);
/* Don't try expanding FileType, Syntax, FuncUndefined, WindowID, /* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
* ColorScheme or QuickFixCmd* */ * ColorScheme, QuickFixCmd* or DirChanged */
if (event == EVENT_FILETYPE if (event == EVENT_FILETYPE
|| event == EVENT_SYNTAX || event == EVENT_SYNTAX
|| event == EVENT_FUNCUNDEFINED || event == EVENT_FUNCUNDEFINED
@ -9597,7 +9598,8 @@ apply_autocmds_group(
|| event == EVENT_QUICKFIXCMDPRE || event == EVENT_QUICKFIXCMDPRE
|| event == EVENT_COLORSCHEME || event == EVENT_COLORSCHEME
|| event == EVENT_OPTIONSET || event == EVENT_OPTIONSET
|| event == EVENT_QUICKFIXCMDPOST) || event == EVENT_QUICKFIXCMDPOST
|| event == EVENT_DIRCHANGED)
fname = vim_strsave(fname); fname = vim_strsave(fname);
else else
fname = FullName_save(fname, FALSE); fname = FullName_save(fname, FALSE);

View File

@ -1105,7 +1105,8 @@ HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
} }
/* Change directory to the location of the first file. */ /* 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); shorten_fnames(TRUE);
goto finished; goto finished;

View File

@ -264,7 +264,7 @@ main
* Hint: to avoid this when typing a command use a forward slash. * Hint: to avoid this when typing a command use a forward slash.
* If the cd fails, it doesn't matter. * If the cd fails, it doesn't matter.
*/ */
(void)vim_chdirfile(params.fname); (void)vim_chdirfile(params.fname, "drop");
if (start_dir != NULL) if (start_dir != NULL)
mch_dirname(start_dir, MAXPATHL); mch_dirname(start_dir, MAXPATHL);
} }
@ -314,7 +314,7 @@ main
&& STRCMP(NameBuff, "/") == 0) && STRCMP(NameBuff, "/") == 0)
{ {
if (params.fname != NULL) if (params.fname != NULL)
(void)vim_chdirfile(params.fname); (void)vim_chdirfile(params.fname, "drop");
else else
{ {
expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);

View File

@ -2663,7 +2663,7 @@ netbeans_file_opened(buf_T *bufp)
nbdebug(("EVT: %s", buffer)); nbdebug(("EVT: %s", buffer));
nb_send(buffer, "netbeans_file_opened"); 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); shorten_fnames(TRUE);
} }

View File

@ -7193,7 +7193,7 @@ fix_arg_enc(void)
{ {
do_cmdline_cmd((char_u *)":rewind"); do_cmdline_cmd((char_u *)":rewind");
if (GARGCOUNT == 1 && used_file_full_path) 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(); set_alist_count();

View File

@ -82,7 +82,7 @@ int call_shell(char_u *cmd, int opt);
int get_real_state(void); int get_real_state(void);
int after_pathsep(char_u *b, char_u *p); int after_pathsep(char_u *b, char_u *p);
int same_directory(char_u *f1, char_u *f2); 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); int vim_stat(const char *name, stat_T *stp);
char_u *parse_shape_opt(int what); char_u *parse_shape_opt(int what);
int get_shape_idx(int mouse); int get_shape_idx(int mouse);

View File

@ -1190,3 +1190,59 @@ func Test_nocatch_wipe_dummy_buffer()
call assert_fails('lv½ /x', 'E480') call assert_fails('lv½ /x', 'E480')
au! au!
endfunc 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

View File

@ -771,6 +771,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1459,
/**/ /**/
1458, 1458,
/**/ /**/

View File

@ -1276,6 +1276,7 @@ enum auto_event
EVENT_CMDWINLEAVE, /* before leaving the cmdline window */ EVENT_CMDWINLEAVE, /* before leaving the cmdline window */
EVENT_COLORSCHEME, /* after loading a colorscheme */ EVENT_COLORSCHEME, /* after loading a colorscheme */
EVENT_COMPLETEDONE, /* after finishing insert complete */ 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_FILEAPPENDPOST, /* after appending to a file */
EVENT_FILEAPPENDPRE, /* before appending to a file */ EVENT_FILEAPPENDPRE, /* before appending to a file */
EVENT_FILEAPPENDCMD, /* append to a file using command */ EVENT_FILEAPPENDCMD, /* append to a file using command */