diff options
author | zeertzjq <zeertzjq@outlook.com> | 2021-10-17 22:04:53 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2021-10-17 22:04:53 +0800 |
commit | 60584c0245a55d72422686aa702132814145b0c1 (patch) | |
tree | 0bb558f11c5bd9e5bb0b4a51ea77530899767dd7 | |
parent | 34cfe745681189bbd8ec2543971a49e013bfebf9 (diff) | |
download | rneovim-60584c0245a55d72422686aa702132814145b0c1.tar.gz rneovim-60584c0245a55d72422686aa702132814145b0c1.tar.bz2 rneovim-60584c0245a55d72422686aa702132814145b0c1.zip |
vim-patch:8.2.0909: cannot go back to the previous local directory
Problem: Cannot go back to the previous local directory.
Solution: Add "tcd -" and "lcd -". (Yegappan Lakshmanan, closes vim/vim#4362)
https://github.com/vim/vim/commit/002bc79991286934a9593b80635c27d4238cdfc4
-rw-r--r-- | src/nvim/buffer_defs.h | 5 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 56 | ||||
-rw-r--r-- | src/nvim/file_search.c | 10 | ||||
-rw-r--r-- | src/nvim/testdir/test_cd.vim | 77 | ||||
-rw-r--r-- | src/nvim/window.c | 2 |
5 files changed, 132 insertions, 18 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 2c411553b8..19b0a3c5c6 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -953,6 +953,7 @@ struct tabpage_S { ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary. dict_T *tp_vars; ///< Internal variables, local to tab page. char_u *tp_localdir; ///< Absolute path of local cwd or NULL. + char_u *tp_prevdir; ///< Previous directory. }; /* @@ -1381,8 +1382,8 @@ struct window_S { // out of range!) int w_arg_idx_invalid; // editing another file than w_arg_idx - char_u *w_localdir; /* absolute path of local directory or - NULL */ + char_u *w_localdir; // absolute path of local directory or NULL + char_u *w_prevdir; // previous directory // Options local to a window. // They are local because they influence the layout of the window or // depend on the window layout. diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 06e94fea99..26c06b2675 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -7707,6 +7707,21 @@ void free_cd_dir(void) #endif +// Get the previous directory for the given chdir scope. +static char_u *get_prevdir(CdScope scope) +{ + switch (scope) { + case kCdScopeTab: + return curtab->tp_prevdir; + break; + case kCdScopeWindow: + return curwin->w_prevdir; + break; + default: + return prev_dir; + } +} + /// Deal with the side effects of changing the current directory. /// /// @param scope Scope of the function call (global, tab or window). @@ -7721,9 +7736,10 @@ void post_chdir(CdScope scope, bool trigger_dirchanged) } if (scope < kCdScopeGlobal) { + char_u *pdir = get_prevdir(scope); // If still in global directory, set CWD as the global directory. - if (globaldir == NULL && prev_dir != NULL) { - globaldir = vim_strsave(prev_dir); + if (globaldir == NULL && pdir != NULL) { + globaldir = vim_strsave(pdir); } } @@ -7754,10 +7770,13 @@ void post_chdir(CdScope scope, bool trigger_dirchanged) } /// Change directory function used by :cd/:tcd/:lcd Ex commands and the chdir() function. +/// @param new_dir The directory to change to. +/// @param scope Scope of the function call (global, tab or window). /// @return true if the directory is successfully changed. bool changedir_func(char_u *new_dir, CdScope scope) { char_u *tofree; + char_u *pdir = NULL; bool retval = false; if (new_dir == NULL || allbuf_locked()) { @@ -7766,19 +7785,32 @@ bool changedir_func(char_u *new_dir, CdScope scope) // ":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; } - // Save current directory for next ":cd -" - tofree = prev_dir; + // Free the previous directory + tofree = get_prevdir(scope); + if (os_dirname(NameBuff, MAXPATHL) == OK) { - prev_dir = vim_strsave(NameBuff); + pdir = vim_strsave(NameBuff); } else { - prev_dir = NULL; + pdir = NULL; + } + + switch (scope) { + case kCdScopeTab: + curtab->tp_prevdir = pdir; + break; + case kCdScopeWindow: + curwin->w_prevdir = pdir; + break; + default: + prev_dir = pdir; } #if defined(UNIX) @@ -7790,12 +7822,12 @@ bool changedir_func(char_u *new_dir, CdScope scope) } #endif - bool dir_differs = prev_dir == NULL || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0; - if (dir_differs && vim_chdir(new_dir)) { - EMSG(_(e_failed)); - } else { + if (vim_chdir(new_dir) == 0) { + bool dir_differs = pdir == NULL || pathcmp((char *)pdir, (char *)new_dir, -1) != 0; post_chdir(scope, dir_differs); retval = true; + } else { + EMSG(_(e_failed)); } xfree(tofree); diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 22c7b35fa9..0922017e2b 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -54,6 +54,7 @@ #include "nvim/eval.h" #include "nvim/file_search.h" #include "nvim/fileio.h" +#include "nvim/globals.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" @@ -1666,11 +1667,12 @@ int vim_chdirfile(char_u *fname, CdCause cause) NameBuff[0] = NUL; } - if (cause != kCdCauseOther && pathcmp(dir, (char *)NameBuff, -1) != 0) { - if (os_chdir(dir) != 0) { - return FAIL; + if (os_chdir(dir) == 0) { + if (cause != kCdCauseOther && pathcmp(dir, (char *)NameBuff, -1) != 0) { + do_autocmd_dirchanged(dir, kCdScopeWindow, cause); } - do_autocmd_dirchanged(dir, kCdScopeWindow, cause); + } else { + return FAIL; } return OK; diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim index c6eda58284..36135b52ce 100644 --- a/src/nvim/testdir/test_cd.vim +++ b/src/nvim/testdir/test_cd.vim @@ -43,6 +43,20 @@ func Test_cd_minus() call assert_equal(path_dotdot, getcwd()) cd - call assert_equal(path, getcwd()) + + " Test for :cd - without a previous directory + let lines =<< trim [SCRIPT] + call assert_fails('cd -', 'E186:') + call assert_fails('call chdir("-")', 'E186:') + call writefile(v:errors, 'Xresult') + qall! + [SCRIPT] + call writefile(lines, 'Xscript') + if RunVim([], [], '--clean -S Xscript') + call assert_equal([], readfile('Xresult')) + endif + call delete('Xscript') + call delete('Xresult') endfunc func Test_cd_with_cpo_chdir() @@ -115,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_from_non_existing_dir() CheckNotMSWindows diff --git a/src/nvim/window.c b/src/nvim/window.c index 49d7c9c9f5..db71512a3b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3733,6 +3733,7 @@ void free_tabpage(tabpage_T *tp) } xfree(tp->tp_localdir); + xfree(tp->tp_prevdir); xfree(tp); } @@ -4771,6 +4772,7 @@ static void win_free(win_T *wp, tabpage_T *tp) } xfree(wp->w_localdir); + xfree(wp->w_prevdir); /* Remove the window from the b_wininfo lists, it may happen that the * freed memory is re-used for another window. */ |