diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-02-09 12:58:20 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-02-09 12:58:20 +0000 |
commit | 28e8f73ae2d90009fd62cd60f97c2643ba44de68 (patch) | |
tree | dd381874612b06d380a05c01c6c4b510c861d885 | |
parent | 68cc2b8a37197872e737fb61244069e13b7227a2 (diff) | |
download | vim-git-28e8f73ae2d90009fd62cd60f97c2643ba44de68.tar.gz |
patch 8.2.4335: no autocommand event triggered before changing directoryv8.2.4335
Problem: No autocommand event triggered before changing directory. (Ronnie
Magatti)
Solution: Add DirChangedPre. (closes #9721)
-rw-r--r-- | runtime/doc/autocmd.txt | 6 | ||||
-rw-r--r-- | src/autocmd.c | 1 | ||||
-rw-r--r-- | src/ex_docmd.c | 54 | ||||
-rw-r--r-- | src/misc2.c | 3 | ||||
-rw-r--r-- | src/proto/ex_docmd.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_autocmd.vim | 12 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim.h | 1 |
8 files changed, 60 insertions, 20 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 37b4a3d9c..c410ae67e 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -326,6 +326,7 @@ Name triggered by ~ |FileChangedRO| before making the first change to a read-only file |DiffUpdated| after diffs have been updated +|DirChangedPre| before the working directory will change |DirChanged| after the working directory has changed |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 external) this can be triggered on every 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 The working directory has changed in response to the |:cd| or |:tcd| or |:lcd| commands, or diff --git a/src/autocmd.c b/src/autocmd.c index a10be9b92..97b27effd 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 d8adf85bc..400360553 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -7343,6 +7343,26 @@ post_chdir(cdscope_T scope) } /* + * 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. * scope == CDSCOPE_WINDOW: changes the window-local directory @@ -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 fac836fb7..38da7e59c 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 0fed2f02d..3be747107 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 1ecb88307..3ff4c3cf5 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("<afile>")) 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("<afile>")) 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 9ef520ebc..ab53d5120 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4335, +/**/ 4334, /**/ 4333, @@ -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 |