To: vim_dev@googlegroups.com Subject: Patch 8.2.0909 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0909 Problem: Cannot go back to the previous local directory. Solution: Add "tcd -" and "lcd -". (Yegappan Lakshmanan, closes #4362) Files: runtime/doc/editing.txt, src/filepath.c, src/ex_docmd.c, src/structs.h, src/testdir/test_cd.vim, src/window.c *** ../vim-8.2.0908/runtime/doc/editing.txt 2020-06-01 16:26:15.338852818 +0200 --- runtime/doc/editing.txt 2020-06-05 22:28:33.434428568 +0200 *************** *** 1315,1320 **** --- 1326,1335 ---- *: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 *************** *** 1324,1329 **** --- 1339,1348 ---- *: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()|. *** ../vim-8.2.0908/src/filepath.c 2020-06-01 16:09:30.266292734 +0200 --- src/filepath.c 2020-06-05 22:20:38.463486225 +0200 *************** *** 726,731 **** --- 726,732 ---- 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 *** ../vim-8.2.0908/src/ex_docmd.c 2020-06-01 21:13:08.520030259 +0200 --- src/ex_docmd.c 2020-06-05 22:22:52.659212940 +0200 *************** *** 6582,6587 **** --- 6582,6600 ---- #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. * When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command. *************** *** 6595,6604 **** 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); // Remember this local directory for the window. if (mch_dirname(NameBuff, MAXPATHL) == OK) { --- 6608,6620 ---- VIM_CLEAR(curwin->w_localdir); if (scope != CDSCOPE_GLOBAL) { ! 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,6617 **** } else { ! // We are now in the global directory, no need to remember its ! // name. VIM_CLEAR(globaldir); } --- 6626,6632 ---- } else { ! // We are now in the global directory, no need to remember its name. VIM_CLEAR(globaldir); } *************** *** 6633,6638 **** --- 6648,6654 ---- cdscope_T scope) { char_u *tofree; + char_u *pdir = NULL; int dir_differs; int retval = FALSE; *************** *** 6648,6667 **** // ":cd -": Change to previous directory if (STRCMP(new_dir, "-") == 0) { ! if (prev_dir == NULL) { emsg(_("E186: No previous directory")); return FALSE; } ! new_dir = prev_dir; } // Save current directory for next ":cd -" - tofree = prev_dir; if (mch_dirname(NameBuff, MAXPATHL) == OK) ! prev_dir = vim_strsave(NameBuff); else ! prev_dir = NULL; #if defined(UNIX) || defined(VMS) // for UNIX ":cd" means: go to home directory --- 6664,6692 ---- // ":cd -": Change to previous directory if (STRCMP(new_dir, "-") == 0) { ! pdir = get_prevdir(scope); ! if (pdir == NULL) { emsg(_("E186: No previous directory")); return FALSE; } ! new_dir = pdir; } + // Free the previous directory + tofree = get_prevdir(scope); + // Save current directory for next ":cd -" if (mch_dirname(NameBuff, MAXPATHL) == OK) ! 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 = pdir; #if defined(UNIX) || defined(VMS) // for UNIX ":cd" means: go to home directory *************** *** 6682,6689 **** new_dir = NameBuff; } #endif ! dir_differs = new_dir == NULL || prev_dir == NULL ! || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0; if (new_dir == NULL || (dir_differs && vim_chdir(new_dir))) emsg(_(e_failed)); else --- 6707,6714 ---- new_dir = NameBuff; } #endif ! 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 *** ../vim-8.2.0908/src/structs.h 2020-05-31 19:48:49.314871091 +0200 --- src/structs.h 2020-06-05 22:19:03.447662048 +0200 *************** *** 2994,2999 **** --- 2994,3001 ---- 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,3402 **** --- 3399,3405 ---- 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 *** ../vim-8.2.0908/src/testdir/test_cd.vim 2020-06-01 16:26:15.338852818 +0200 --- src/testdir/test_cd.vim 2020-06-05 22:25:01.202929740 +0200 *************** *** 129,134 **** --- 129,197 ---- 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') *** ../vim-8.2.0908/src/window.c 2020-05-13 13:40:12.690995638 +0200 --- src/window.c 2020-06-05 22:19:03.451662041 +0200 *************** *** 3809,3814 **** --- 3809,3815 ---- #endif vim_free(tp->tp_localdir); + vim_free(tp->tp_prevdir); #ifdef FEAT_PYTHON python_tabpage_free(tp); *************** *** 4974,4979 **** --- 4975,4981 ---- 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. *** ../vim-8.2.0908/src/version.c 2020-06-05 21:06:06.607601386 +0200 --- src/version.c 2020-06-05 22:27:10.542628565 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 909, /**/ -- The greatest lies of all time: (1) The check is in the mail. (2) We have a really challenging assignment for you. (3) I love you. (4) All bugs have been fixed. (5) This won't hurt a bit. (6) Honey, I just need to debug this program and be home in 5 minutes. (7) I have just sent you an e-mail about that. (8) Of course I'll respect you in the morning. (9) I'm from the government, and I'm here to help you. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///