Skip to content

Commit b7407d3

Browse files
committed
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.
1 parent ddb3493 commit b7407d3

12 files changed

Lines changed: 94 additions & 15 deletions

File tree

runtime/doc/autocmd.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ Name triggered by ~
295295
|FileChangedShellPost| After handling a file changed since editing started
296296
|FileChangedRO| before making the first change to a read-only file
297297

298+
|DirChanged| after the working directory has changed
299+
298300
|ShellCmdPost| after executing a shell command
299301
|ShellFilterPost| after filtering with a shell command
300302

@@ -633,6 +635,16 @@ FileChangedRO Before making the first change to a read-only
633635
*E881*
634636
If the number of lines changes saving for undo
635637
may fail and the change will be aborted.
638+
*DirChanged*
639+
DirChanged The working directory has changed in response
640+
to the |:cd| or |:lcd| commands, or as a
641+
result of the 'autochdir' option.
642+
The pattern can be:
643+
"window" to trigger on `:lcd
644+
"global" to trigger on `:cd`
645+
"auto" to trigger on 'autochdir'.
646+
"drop" to trigger on editing a file
647+
<afile> is set to the new directory name.
636648
*FileChangedShell*
637649
FileChangedShell When Vim notices that the modification time of
638650
a file has changed since editing started.

src/buffer.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ close_buffer(
595595

596596
#ifdef FEAT_DIFF
597597
if (diffopt_hiddenoff() && !unload_buf && buf->b_nwindows == 0)
598-
diff_buf_delete(buf); /* Clear 'diff' for hidden buffer. */
598+
diff_buf_delete(buf); /* Clear 'diff' for hidden buffer. */
599599
#endif
600600

601601
/* Return when a window is displaying the buffer or when it's not
@@ -657,9 +657,6 @@ close_buffer(
657657
--buf->b_nwindows;
658658
#endif
659659

660-
/* Change directories when the 'acd' option is set. */
661-
DO_AUTOCHDIR
662-
663660
/*
664661
* Remove the buffer from the list.
665662
*/
@@ -1862,7 +1859,7 @@ do_autochdir(void)
18621859
{
18631860
if ((starting == 0 || test_autochdir)
18641861
&& curbuf->b_ffname != NULL
1865-
&& vim_chdirfile(curbuf->b_ffname) == OK)
1862+
&& vim_chdirfile(curbuf->b_ffname, "auto") == OK)
18661863
shorten_fnames(TRUE);
18671864
}
18681865
#endif

src/ex_docmd.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9048,11 +9048,19 @@ ex_cd(exarg_T *eap)
90489048
EMSG(_(e_failed));
90499049
else
90509050
{
9051-
post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir);
9051+
int is_local_chdir = eap->cmdidx == CMD_lcd
9052+
|| eap->cmdidx == CMD_lchdir;
9053+
9054+
post_chdir(is_local_chdir);
90529055

90539056
/* Echo the new current directory if the command was typed. */
90549057
if (KeyTyped || p_verbose >= 5)
90559058
ex_pwd(eap);
9059+
#ifdef FEAT_AUTOCMD
9060+
apply_autocmds(EVENT_DIRCHANGED,
9061+
is_local_chdir ? (char_u *)"window" : (char_u *)"global",
9062+
new_dir, FALSE, curbuf);
9063+
#endif
90569064
}
90579065
vim_free(tofree);
90589066
}
@@ -9932,7 +9940,7 @@ ex_mkrc(
99329940
*dirnow = NUL;
99339941
if (*dirnow != NUL && (ssop_flags & SSOP_SESDIR))
99349942
{
9935-
if (vim_chdirfile(fname) == OK)
9943+
if (vim_chdirfile(fname, NULL) == OK)
99369944
shorten_fnames(TRUE);
99379945
}
99389946
else if (*dirnow != NUL

src/fileio.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7798,6 +7798,7 @@ static struct event_name
77987798
{"CursorHoldI", EVENT_CURSORHOLDI},
77997799
{"CursorMoved", EVENT_CURSORMOVED},
78007800
{"CursorMovedI", EVENT_CURSORMOVEDI},
7801+
{"DirChanged", EVENT_DIRCHANGED},
78017802
{"EncodingChanged", EVENT_ENCODINGCHANGED},
78027803
{"FileEncoding", EVENT_ENCODINGCHANGED},
78037804
{"FileAppendPost", EVENT_FILEAPPENDPOST},
@@ -9588,7 +9589,7 @@ apply_autocmds_group(
95889589
{
95899590
sfname = vim_strsave(fname);
95909591
/* Don't try expanding FileType, Syntax, FuncUndefined, WindowID,
9591-
* ColorScheme or QuickFixCmd* */
9592+
* ColorScheme, QuickFixCmd* or DirChanged */
95929593
if (event == EVENT_FILETYPE
95939594
|| event == EVENT_SYNTAX
95949595
|| event == EVENT_FUNCUNDEFINED
@@ -9597,7 +9598,8 @@ apply_autocmds_group(
95979598
|| event == EVENT_QUICKFIXCMDPRE
95989599
|| event == EVENT_COLORSCHEME
95999600
|| event == EVENT_OPTIONSET
9600-
|| event == EVENT_QUICKFIXCMDPOST)
9601+
|| event == EVENT_QUICKFIXCMDPOST
9602+
|| event == EVENT_DIRCHANGED)
96019603
fname = vim_strsave(fname);
96029604
else
96039605
fname = FullName_save(fname, FALSE);

src/gui_mac.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,8 @@ HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
11051105
}
11061106

11071107
/* Change directory to the location of the first file. */
1108-
if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK)
1108+
if (GARGCOUNT > 0
1109+
&& vim_chdirfile(alist_name(&GARGLIST[0]), "drop") == OK)
11091110
shorten_fnames(TRUE);
11101111

11111112
goto finished;

src/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ main
264264
* Hint: to avoid this when typing a command use a forward slash.
265265
* If the cd fails, it doesn't matter.
266266
*/
267-
(void)vim_chdirfile(params.fname);
267+
(void)vim_chdirfile(params.fname, "drop");
268268
if (start_dir != NULL)
269269
mch_dirname(start_dir, MAXPATHL);
270270
}
@@ -314,7 +314,7 @@ main
314314
&& STRCMP(NameBuff, "/") == 0)
315315
{
316316
if (params.fname != NULL)
317-
(void)vim_chdirfile(params.fname);
317+
(void)vim_chdirfile(params.fname, "drop");
318318
else
319319
{
320320
expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);

src/netbeans.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2663,7 +2663,7 @@ netbeans_file_opened(buf_T *bufp)
26632663
nbdebug(("EVT: %s", buffer));
26642664

26652665
nb_send(buffer, "netbeans_file_opened");
2666-
if (p_acd && vim_chdirfile(bufp->b_ffname) == OK)
2666+
if (p_acd && vim_chdirfile(bufp->b_ffname, "auto") == OK)
26672667
shorten_fnames(TRUE);
26682668
}
26692669

src/os_win32.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7193,7 +7193,7 @@ fix_arg_enc(void)
71937193
{
71947194
do_cmdline_cmd((char_u *)":rewind");
71957195
if (GARGCOUNT == 1 && used_file_full_path)
7196-
(void)vim_chdirfile(alist_name(&GARGLIST[0]));
7196+
(void)vim_chdirfile(alist_name(&GARGLIST[0]), "drop");
71977197
}
71987198

71997199
set_alist_count();

src/proto/misc2.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ int call_shell(char_u *cmd, int opt);
8282
int get_real_state(void);
8383
int after_pathsep(char_u *b, char_u *p);
8484
int same_directory(char_u *f1, char_u *f2);
85-
int vim_chdirfile(char_u *fname);
85+
int vim_chdirfile(char_u *fname, char *trigger_autocmd);
8686
int vim_stat(const char *name, stat_T *stp);
8787
char_u *parse_shape_opt(int what);
8888
int get_shape_idx(int mouse);

src/testdir/test_autocmd.vim

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,3 +1190,59 @@ func Test_nocatch_wipe_dummy_buffer()
11901190
call assert_fails('lv½ /x', 'E480')
11911191
au!
11921192
endfunc
1193+
1194+
function s:Before_test_dirchanged()
1195+
augroup test_dirchanged
1196+
autocmd!
1197+
augroup END
1198+
let s:li = []
1199+
let s:dir_this = getcwd()
1200+
let s:dir_other = s:dir_this . '/foo'
1201+
call mkdir(s:dir_other)
1202+
endfunc
1203+
1204+
function s:After_test_dirchanged()
1205+
exe 'cd' s:dir_this
1206+
call delete(s:dir_other, 'd')
1207+
augroup test_dirchanged
1208+
autocmd!
1209+
augroup END
1210+
endfunc
1211+
1212+
function Test_dirchanged_global()
1213+
call s:Before_test_dirchanged()
1214+
autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
1215+
autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
1216+
exe 'cd' s:dir_other
1217+
call assert_equal(["cd:", s:dir_other], s:li)
1218+
exe 'lcd' s:dir_other
1219+
call assert_equal(["cd:", s:dir_other], s:li)
1220+
call s:After_test_dirchanged()
1221+
endfunc
1222+
1223+
function Test_dirchanged_local()
1224+
call s:Before_test_dirchanged()
1225+
autocmd test_dirchanged DirChanged window call add(s:li, "lcd:")
1226+
autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>"))
1227+
exe 'cd' s:dir_other
1228+
call assert_equal([], s:li)
1229+
exe 'lcd' s:dir_other
1230+
call assert_equal(["lcd:", s:dir_other], s:li)
1231+
call s:After_test_dirchanged()
1232+
endfunc
1233+
1234+
function Test_dirchanged_auto()
1235+
call s:Before_test_dirchanged()
1236+
call test_autochdir()
1237+
autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
1238+
autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
1239+
set acd
1240+
exe 'cd ..'
1241+
call assert_equal([], s:li)
1242+
exe 'edit ' . s:dir_other . '/Xfile'
1243+
call assert_equal(s:dir_other, getcwd())
1244+
call assert_equal(["auto:", s:dir_other], s:li)
1245+
set noacd
1246+
bwipe!
1247+
call s:After_test_dirchanged()
1248+
endfunc

0 commit comments

Comments
 (0)