From 28e8f73ae2d90009fd62cd60f97c2643ba44de68 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 9 Feb 2022 12:58:20 +0000 Subject: 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) --- src/autocmd.c | 1 + src/ex_docmd.c | 54 +++++++++++++++++++++++++++++++------------- src/misc2.c | 3 +++ src/proto/ex_docmd.pro | 1 + src/testdir/test_autocmd.vim | 12 ++++++---- src/version.c | 2 ++ src/vim.h | 1 + 7 files changed, 54 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/autocmd.c b/src/autocmd.c index a10be9b928..97b27effd1 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -119,6 +119,7 @@ static struct event_name {"CursorMovedI", EVENT_CURSORMOVEDI}, {"DiffUpdated", EVENT_DIFFUPDATED}, {"DirChanged", EVENT_DIRCHANGED}, + {"DirChangedPre", EVENT_DIRCHANGEDPRE}, {"EncodingChanged", EVENT_ENCODINGCHANGED}, {"ExitPre", EVENT_EXITPRE}, {"FileEncoding", EVENT_ENCODINGCHANGED}, diff --git a/src/ex_docmd.c b/src/ex_docmd.c index d8adf85bcb..4003605537 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -7342,6 +7342,26 @@ post_chdir(cdscope_T scope) 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 * chdir() function. @@ -7358,7 +7378,7 @@ changedir_func( { char_u *pdir = NULL; int dir_differs; - char_u *acmd_fname; + char_u *acmd_fname = NULL; char_u **pp; if (new_dir == NULL || allbuf_locked()) @@ -7411,12 +7431,23 @@ changedir_func( new_dir = NameBuff; } dir_differs = pdir == NULL - || pathcmp((char *)pdir, (char *)new_dir, -1) != 0; - if (dir_differs && vim_chdir(new_dir)) + || pathcmp((char *)pdir, (char *)new_dir, -1) != 0; + if (dir_differs) { - emsg(_(e_command_failed)); - vim_free(pdir); - return FALSE; + 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"; + trigger_DirChangedPre(acmd_fname, new_dir); + + if (vim_chdir(new_dir)) + { + emsg(_(e_command_failed)); + vim_free(pdir); + return FALSE; + } } if (scope == CDSCOPE_WINDOW) @@ -7431,16 +7462,7 @@ changedir_func( post_chdir(scope); if (dir_differs) - { - 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); - } + apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE, curbuf); return TRUE; } diff --git a/src/misc2.c b/src/misc2.c index fac836fb76..38da7e59c4 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -1914,6 +1914,9 @@ vim_chdirfile(char_u *fname, char *trigger_autocmd) // nothing to do return OK; + if (trigger_autocmd != NULL) + trigger_DirChangedPre((char_u *)trigger_autocmd, new_dir); + if (mch_chdir((char *)new_dir) != 0) return FAIL; diff --git a/src/proto/ex_docmd.pro b/src/proto/ex_docmd.pro index 0fed2f02df..3be7471070 100644 --- a/src/proto/ex_docmd.pro +++ b/src/proto/ex_docmd.pro @@ -48,6 +48,7 @@ void tabpage_new(void); void do_exedit(exarg_T *eap, win_T *old_curwin); void free_cd_dir(void); 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); void ex_cd(exarg_T *eap); void do_sleep(long msec, int hide_cursor); diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 1ecb883079..3ff4c3cf5b 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -1922,14 +1922,16 @@ endfunc function Test_dirchanged_global() 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, expand("")) 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 assert_equal(["cd:", s:dir_foo], s:li) + call assert_equal(expected, s:li) 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() endfunc @@ -1950,6 +1952,7 @@ function Test_dirchanged_auto() CheckOption autochdir call s:Before_test_dirchanged() 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, expand("")) set acd @@ -1957,7 +1960,8 @@ function Test_dirchanged_auto() call assert_equal([], s:li) exe 'edit ' . s:dir_foo . '/Xfile' 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 bwipe! call s:After_test_dirchanged() diff --git a/src/version.c b/src/version.c index 9ef520ebcb..ab53d51200 100644 --- a/src/version.c +++ b/src/version.c @@ -746,6 +746,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4335, /**/ 4334, /**/ diff --git a/src/vim.h b/src/vim.h index 67b4e33c1b..166edf579f 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1304,6 +1304,7 @@ enum auto_event EVENT_CURSORMOVEDI, // cursor was moved in Insert mode EVENT_DIFFUPDATED, // after diffs were updated EVENT_DIRCHANGED, // after user changed directory + EVENT_DIRCHANGEDPRE, // before directory changes EVENT_ENCODINGCHANGED, // after changing the 'encoding' option EVENT_EXITPRE, // before exiting EVENT_FILEAPPENDCMD, // append to a file using command -- cgit v1.2.3