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

patch 8.2.4335: no autocommand event triggered before changing directory

Problem:    No autocommand event triggered before changing directory. (Ronnie
            Magatti)
Solution:   Add DirChangedPre. (closes #9721)
This commit is contained in:
Bram Moolenaar 2022-02-09 12:58:20 +00:00
parent 68cc2b8a37
commit 28e8f73ae2
8 changed files with 60 additions and 20 deletions

View File

@ -326,6 +326,7 @@ Name triggered by ~
|FileChangedRO| before making the first change to a read-only file |FileChangedRO| before making the first change to a read-only file
|DiffUpdated| after diffs have been updated |DiffUpdated| after diffs have been updated
|DirChangedPre| before the working directory will change
|DirChanged| after the working directory has changed |DirChanged| after the working directory has changed
|ShellCmdPost| after executing a shell command |ShellCmdPost| after executing a shell command
@ -738,6 +739,11 @@ DiffUpdated After diffs have been updated. Depending on
what kind of diff is being used (internal or what kind of diff is being used (internal or
external) this can be triggered on every external) this can be triggered on every
change or when doing |:diffupdate|. change or when doing |:diffupdate|.
*DirChangedPre*
DirChangedPre The working directory is going to be changed,
as with ||DirChanged|. The pattern is like
with |DirChanged|. The new directory can be
found in v:event.directory.
*DirChanged* *DirChanged*
DirChanged The working directory has changed in response DirChanged The working directory has changed in response
to the |:cd| or |:tcd| or |:lcd| commands, or to the |:cd| or |:tcd| or |:lcd| commands, or

View File

@ -119,6 +119,7 @@ static struct event_name
{"CursorMovedI", EVENT_CURSORMOVEDI}, {"CursorMovedI", EVENT_CURSORMOVEDI},
{"DiffUpdated", EVENT_DIFFUPDATED}, {"DiffUpdated", EVENT_DIFFUPDATED},
{"DirChanged", EVENT_DIRCHANGED}, {"DirChanged", EVENT_DIRCHANGED},
{"DirChangedPre", EVENT_DIRCHANGEDPRE},
{"EncodingChanged", EVENT_ENCODINGCHANGED}, {"EncodingChanged", EVENT_ENCODINGCHANGED},
{"ExitPre", EVENT_EXITPRE}, {"ExitPre", EVENT_EXITPRE},
{"FileEncoding", EVENT_ENCODINGCHANGED}, {"FileEncoding", EVENT_ENCODINGCHANGED},

View File

@ -7342,6 +7342,26 @@ post_chdir(cdscope_T scope)
shorten_fnames(TRUE); shorten_fnames(TRUE);
} }
/*
* Trigger DirChangedPre for "acmd_fname" with directory "new_dir".
*/
void
trigger_DirChangedPre(char_u *acmd_fname, char_u *new_dir)
{
#ifdef FEAT_EVAL
dict_T *v_event;
save_v_event_T save_v_event;
v_event = get_v_event(&save_v_event);
(void)dict_add_string(v_event, "directory", new_dir);
dict_set_items_ro(v_event);
#endif
apply_autocmds(EVENT_DIRCHANGEDPRE, acmd_fname, new_dir, FALSE, curbuf);
#ifdef FEAT_EVAL
restore_v_event(v_event, &save_v_event);
#endif
}
/* /*
* Change directory function used by :cd/:tcd/:lcd Ex commands and the * Change directory function used by :cd/:tcd/:lcd Ex commands and the
* chdir() function. * chdir() function.
@ -7358,7 +7378,7 @@ changedir_func(
{ {
char_u *pdir = NULL; char_u *pdir = NULL;
int dir_differs; int dir_differs;
char_u *acmd_fname; char_u *acmd_fname = NULL;
char_u **pp; char_u **pp;
if (new_dir == NULL || allbuf_locked()) if (new_dir == NULL || allbuf_locked())
@ -7411,12 +7431,23 @@ changedir_func(
new_dir = NameBuff; new_dir = NameBuff;
} }
dir_differs = pdir == NULL dir_differs = pdir == NULL
|| pathcmp((char *)pdir, (char *)new_dir, -1) != 0; || pathcmp((char *)pdir, (char *)new_dir, -1) != 0;
if (dir_differs && vim_chdir(new_dir)) if (dir_differs)
{ {
emsg(_(e_command_failed)); if (scope == CDSCOPE_WINDOW)
vim_free(pdir); acmd_fname = (char_u *)"window";
return FALSE; else if (scope == CDSCOPE_TABPAGE)
acmd_fname = (char_u *)"tabpage";
else
acmd_fname = (char_u *)"global";
trigger_DirChangedPre(acmd_fname, new_dir);
if (vim_chdir(new_dir))
{
emsg(_(e_command_failed));
vim_free(pdir);
return FALSE;
}
} }
if (scope == CDSCOPE_WINDOW) if (scope == CDSCOPE_WINDOW)
@ -7431,16 +7462,7 @@ changedir_func(
post_chdir(scope); post_chdir(scope);
if (dir_differs) if (dir_differs)
{ apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE, curbuf);
if (scope == CDSCOPE_WINDOW)
acmd_fname = (char_u *)"window";
else if (scope == CDSCOPE_TABPAGE)
acmd_fname = (char_u *)"tabpage";
else
acmd_fname = (char_u *)"global";
apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE,
curbuf);
}
return TRUE; return TRUE;
} }

View File

@ -1914,6 +1914,9 @@ vim_chdirfile(char_u *fname, char *trigger_autocmd)
// nothing to do // nothing to do
return OK; return OK;
if (trigger_autocmd != NULL)
trigger_DirChangedPre((char_u *)trigger_autocmd, new_dir);
if (mch_chdir((char *)new_dir) != 0) if (mch_chdir((char *)new_dir) != 0)
return FAIL; return FAIL;

View File

@ -48,6 +48,7 @@ void tabpage_new(void);
void do_exedit(exarg_T *eap, win_T *old_curwin); void do_exedit(exarg_T *eap, win_T *old_curwin);
void free_cd_dir(void); void free_cd_dir(void);
void post_chdir(cdscope_T scope); void post_chdir(cdscope_T scope);
void trigger_DirChangedPre(char_u *acmd_fname, char_u *new_dir);
int changedir_func(char_u *new_dir, int forceit, cdscope_T scope); int changedir_func(char_u *new_dir, int forceit, cdscope_T scope);
void ex_cd(exarg_T *eap); void ex_cd(exarg_T *eap);
void do_sleep(long msec, int hide_cursor); void do_sleep(long msec, int hide_cursor);

View File

@ -1922,14 +1922,16 @@ endfunc
function Test_dirchanged_global() function Test_dirchanged_global()
call s:Before_test_dirchanged() call s:Before_test_dirchanged()
autocmd test_dirchanged DirChangedPre global call add(s:li, "pre cd " .. v:event.directory)
autocmd test_dirchanged DirChanged global call add(s:li, "cd:") autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>")) autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
call chdir(s:dir_foo) call chdir(s:dir_foo)
call assert_equal(["cd:", s:dir_foo], s:li) let expected = ["pre cd " .. s:dir_foo, "cd:", s:dir_foo]
call assert_equal(expected, s:li)
call chdir(s:dir_foo) 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) 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() call s:After_test_dirchanged()
endfunc endfunc
@ -1950,6 +1952,7 @@ function Test_dirchanged_auto()
CheckOption autochdir CheckOption autochdir
call s:Before_test_dirchanged() call s:Before_test_dirchanged()
call test_autochdir() 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, "auto:")
autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>")) autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
set acd set acd
@ -1957,7 +1960,8 @@ function Test_dirchanged_auto()
call assert_equal([], s:li) call assert_equal([], s:li)
exe 'edit ' . s:dir_foo . '/Xfile' exe 'edit ' . s:dir_foo . '/Xfile'
call assert_equal(s:dir_foo, getcwd()) 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 set noacd
bwipe! bwipe!
call s:After_test_dirchanged() call s:After_test_dirchanged()

View File

@ -746,6 +746,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 */
/**/
4335,
/**/ /**/
4334, 4334,
/**/ /**/

View File

@ -1304,6 +1304,7 @@ enum auto_event
EVENT_CURSORMOVEDI, // cursor was moved in Insert mode EVENT_CURSORMOVEDI, // cursor was moved in Insert mode
EVENT_DIFFUPDATED, // after diffs were updated EVENT_DIFFUPDATED, // after diffs were updated
EVENT_DIRCHANGED, // after user changed directory EVENT_DIRCHANGED, // after user changed directory
EVENT_DIRCHANGEDPRE, // before directory changes
EVENT_ENCODINGCHANGED, // after changing the 'encoding' option EVENT_ENCODINGCHANGED, // after changing the 'encoding' option
EVENT_EXITPRE, // before exiting EVENT_EXITPRE, // before exiting
EVENT_FILEAPPENDCMD, // append to a file using command EVENT_FILEAPPENDCMD, // append to a file using command