mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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)
002bc79991
This commit is contained in:
parent
34cfe74568
commit
60584c0245
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user