]> granicus.if.org Git - vim/commitdiff
patch 8.2.4335: no autocommand event triggered before changing directory v8.2.4335
authorBram Moolenaar <Bram@vim.org>
Wed, 9 Feb 2022 12:58:20 +0000 (12:58 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 9 Feb 2022 12:58:20 +0000 (12:58 +0000)
Problem:    No autocommand event triggered before changing directory. (Ronnie
            Magatti)
Solution:   Add DirChangedPre. (closes #9721)

runtime/doc/autocmd.txt
src/autocmd.c
src/ex_docmd.c
src/misc2.c
src/proto/ex_docmd.pro
src/testdir/test_autocmd.vim
src/version.c
src/vim.h

index 37b4a3d9cc6fe1415778235b1a6d9f4167c60b1a..c410ae67e58205f39964e9104772fb277c2c6fb1 100644 (file)
@@ -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
index a10be9b9283c144920ce1dd60d7c024a9bf1768e..97b27effd1ef2203722c19ca0195934b09e9b21a 100644 (file)
@@ -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},
index d8adf85bcbfc68e40e119ab600437f8f74145df3..4003605537d28c97e907aa192a59e79c1bdcdbbf 100644 (file)
@@ -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;
 }
 
index fac836fb765b0894681334a03977bb545fd9a397..38da7e59c4c48bd46287e065fc8e0c95a0ba0495 100644 (file)
@@ -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;
 
index 0fed2f02df9c71025407e990b71e8b6a61db97e4..3be7471070f83358ff5ba758399a70b77b40bc6c 100644 (file)
@@ -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);
index 1ecb8830797a2586710f361f7bffb7f69dba8a02..3ff4c3cf5bfd678b46ccb00a46f16932ad19a9f1 100644 (file)
@@ -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()
index 9ef520ebcbe14bdedb49ea8a383d92634b23a285..ab53d512003391ffb3779e28d6eb2e19dedce479 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4335,
 /**/
     4334,
 /**/
index 67b4e33c1b48aee713e43f7f02291b996fe3f052..166edf579f34b873453fe205f3ea7597308ad1dd 100644 (file)
--- 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