]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0909: cannot go back to the previous local directory v8.2.0909
authorBram Moolenaar <Bram@vim.org>
Fri, 5 Jun 2020 20:33:42 +0000 (22:33 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 5 Jun 2020 20:33:42 +0000 (22:33 +0200)
Problem:    Cannot go back to the previous local directory.
Solution:   Add "tcd -" and "lcd -". (Yegappan Lakshmanan, closes #4362)

runtime/doc/editing.txt
src/ex_docmd.c
src/filepath.c
src/structs.h
src/testdir/test_cd.vim
src/version.c
src/window.c

index f33ffb9954ea0c418a5c3a01226e594769c0a143..fae711810f0ff80cbac56ab95fbbe5831b8e9021 100644 (file)
@@ -1326,6 +1326,10 @@ present in 'cpoptions' and "!" is not used in the command.
                                                        *:tch* *:tchdir*
 :tch[dir][!]           Same as |:tcd|.
 
+                                                       *:tcd-*
+:tcd[!] -              Change to the previous current directory, before the
+                       last ":tcd {path}" command.
+
                                                        *:lc* *:lcd*
 :lc[d][!] {path}       Like |:cd|, but only set the current directory when
                        the cursor is in the current window.  The current
@@ -1335,6 +1339,10 @@ present in 'cpoptions' and "!" is not used in the command.
                                                        *:lch* *:lchdir*
 :lch[dir][!]           Same as |:lcd|.
 
+                                                       *:lcd-*
+:lcd[!] -              Change to the previous current directory, before the
+                       last ":lcd {path}" command.
+
                                                        *:pw* *:pwd* *E187*
 :pw[d]                 Print the current directory name.
                        Also see |getcwd()|.
index a98dc077d8c5a4ff117c4abe220ea89feaebf890..3a1a61491b71528fe55d303b33e1ba43a697b68a 100644 (file)
@@ -6581,6 +6581,19 @@ free_cd_dir(void)
 }
 #endif
 
+/*
+ * Get the previous directory for the given chdir scope.
+ */
+    static char_u *
+get_prevdir(cdscope_T scope)
+{
+    if (scope == CDSCOPE_WINDOW)
+       return curwin->w_prevdir;
+    else if (scope == CDSCOPE_TABPAGE)
+       return curtab->tp_prevdir;
+    return prev_dir;
+}
+
 /*
  * Deal with the side effects of changing the current directory.
  * When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command.
@@ -6595,10 +6608,13 @@ post_chdir(cdscope_T scope)
     VIM_CLEAR(curwin->w_localdir);
     if (scope != CDSCOPE_GLOBAL)
     {
-       // If still in global directory, need to remember current
-       // directory as global directory.
-       if (globaldir == NULL && prev_dir != NULL)
-           globaldir = vim_strsave(prev_dir);
+       char_u  *pdir = get_prevdir(scope);
+
+       // If still in the global directory, need to remember current
+       // directory as the global directory.
+       if (globaldir == NULL && pdir != NULL)
+           globaldir = vim_strsave(pdir);
+
        // Remember this local directory for the window.
        if (mch_dirname(NameBuff, MAXPATHL) == OK)
        {
@@ -6610,8 +6626,7 @@ post_chdir(cdscope_T scope)
     }
     else
     {
-       // We are now in the global directory, no need to remember its
-       // name.
+       // We are now in the global directory, no need to remember its name.
        VIM_CLEAR(globaldir);
     }
 
@@ -6633,6 +6648,7 @@ changedir_func(
        cdscope_T       scope)
 {
     char_u     *tofree;
+    char_u     *pdir = NULL;
     int                dir_differs;
     int                retval = FALSE;
 
@@ -6648,20 +6664,29 @@ changedir_func(
     // ":cd -": Change to previous directory
     if (STRCMP(new_dir, "-") == 0)
     {
-       if (prev_dir == NULL)
+       pdir = get_prevdir(scope);
+       if (pdir == NULL)
        {
            emsg(_("E186: No previous directory"));
            return FALSE;
        }
-       new_dir = prev_dir;
+       new_dir = pdir;
     }
 
+    // Free the previous directory
+    tofree = get_prevdir(scope);
+
     // Save current directory for next ":cd -"
-    tofree = prev_dir;
     if (mch_dirname(NameBuff, MAXPATHL) == OK)
-       prev_dir = vim_strsave(NameBuff);
+       pdir = vim_strsave(NameBuff);
+    else
+       pdir = NULL;
+    if (scope == CDSCOPE_WINDOW)
+       curwin->w_prevdir = pdir;
+    else if (scope == CDSCOPE_TABPAGE)
+       curtab->tp_prevdir = pdir;
     else
-       prev_dir = NULL;
+       prev_dir = pdir;
 
 #if defined(UNIX) || defined(VMS)
     // for UNIX ":cd" means: go to home directory
@@ -6682,8 +6707,8 @@ changedir_func(
        new_dir = NameBuff;
     }
 #endif
-    dir_differs = new_dir == NULL || prev_dir == NULL
-       || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0;
+    dir_differs = new_dir == NULL || pdir == NULL
+       || pathcmp((char *)pdir, (char *)new_dir, -1) != 0;
     if (new_dir == NULL || (dir_differs && vim_chdir(new_dir)))
        emsg(_(e_failed));
     else
index ad7b8b03d4ae82d9be063cf7d73e63f2f8ad89a8..8bc941d3542bf474716c3b67cde449f7e2e0af0e 100644 (file)
@@ -726,6 +726,7 @@ f_chdir(typval_T *argvars, typval_T *rettv)
 
     if (argvars[0].v_type != VAR_STRING)
        // Returning an empty string means it failed.
+       // No error message, for historic reasons.
        return;
 
     // Return the current directory
index 8fb14d7598b98ebe131ac8f4fe3ed0fdd6516c90..80b7cff1e5195a5141b5d32d874c2fcf037bc1a2 100644 (file)
@@ -2994,6 +2994,8 @@ struct tabpage_S
 
     char_u         *tp_localdir;       // absolute path of local directory or
                                        // NULL
+    char_u         *tp_prevdir;        // previous directory
+
 #ifdef FEAT_DIFF
     diff_T         *tp_first_diff;
     buf_T          *(tp_diffbuf[DB_COUNT]);
@@ -3397,6 +3399,7 @@ struct window_S
 
     char_u     *w_localdir;        // absolute path of local directory or
                                    // NULL
+    char_u     *w_prevdir;         // previous directory
 #ifdef FEAT_MENU
     vimmenu_T  *w_winbar;          // The root of the WinBar menu hierarchy.
     winbar_item_T *w_winbar_items;  // list of items in the WinBar
index ad25f3a32e114a1c4b468702d1902baeec6607f2..53f9c1081ee77290877543612b45689273c57d66 100644 (file)
@@ -129,6 +129,69 @@ func Test_chdir_func()
   call delete('Xdir', 'rf')
 endfunc
 
+" Test for changing to the previous directory '-'
+func Test_prev_dir()
+  let topdir = getcwd()
+  call mkdir('Xdir/a/b/c', 'p')
+
+  " Create a few tabpages and windows with different directories
+  new | only
+  tabnew | new
+  tabnew
+  tabfirst
+  cd Xdir
+  tabnext | wincmd t
+  tcd a
+  wincmd w
+  lcd b
+  tabnext
+  tcd a/b/c
+
+  " Change to the previous directory twice in all the windows.
+  tabfirst
+  cd - | cd -
+  tabnext | wincmd t
+  tcd - | tcd -
+  wincmd w
+  lcd - | lcd -
+  tabnext
+  tcd - | tcd -
+
+  " Check the directory of all the windows
+  tabfirst
+  call assert_equal('Xdir', fnamemodify(getcwd(), ':t'))
+  tabnext | wincmd t
+  call assert_equal('a', fnamemodify(getcwd(), ':t'))
+  wincmd w
+  call assert_equal('b', fnamemodify(getcwd(), ':t'))
+  tabnext
+  call assert_equal('c', fnamemodify(getcwd(), ':t'))
+
+  " Change to the previous directory using chdir()
+  tabfirst
+  call chdir("-") | call chdir("-")
+  tabnext | wincmd t
+  call chdir("-") | call chdir("-")
+  wincmd w
+  call chdir("-") | call chdir("-")
+  tabnext
+  call chdir("-") | call chdir("-")
+
+  " Check the directory of all the windows
+  tabfirst
+  call assert_equal('Xdir', fnamemodify(getcwd(), ':t'))
+  tabnext | wincmd t
+  call assert_equal('a', fnamemodify(getcwd(), ':t'))
+  wincmd w
+  call assert_equal('b', fnamemodify(getcwd(), ':t'))
+  tabnext
+  call assert_equal('c', fnamemodify(getcwd(), ':t'))
+
+  only | tabonly
+  call chdir(topdir)
+  call delete('Xdir', 'rf')
+endfunc
+
 func Test_cd_completion()
   call mkdir('XComplDir1', 'p')
   call mkdir('XComplDir2', 'p')
index 20c0e0dec4f0ca942586499aab7d4576d92747b3..5fca34bf29c26c16416b5b1968005eb9530f7403 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    909,
 /**/
     908,
 /**/
index ede2c6f281b8dfc06210f3ad621629cac3f6c0cd..931d86bdf60f03b2d7dd0089ee5825d6ebd37a75 100644 (file)
@@ -3809,6 +3809,7 @@ free_tabpage(tabpage_T *tp)
 #endif
 
     vim_free(tp->tp_localdir);
+    vim_free(tp->tp_prevdir);
 
 #ifdef FEAT_PYTHON
     python_tabpage_free(tp);
@@ -4974,6 +4975,7 @@ win_free(
        vim_free(wp->w_tagstack[i].user_data);
     }
     vim_free(wp->w_localdir);
+    vim_free(wp->w_prevdir);
 
     // Remove the window from the b_wininfo lists, it may happen that the
     // freed memory is re-used for another window.