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.
|
ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary.
|
||||||
dict_T *tp_vars; ///< Internal variables, local to tab page.
|
dict_T *tp_vars; ///< Internal variables, local to tab page.
|
||||||
char_u *tp_localdir; ///< Absolute path of local cwd or NULL.
|
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!)
|
// out of range!)
|
||||||
int w_arg_idx_invalid; // editing another file than w_arg_idx
|
int w_arg_idx_invalid; // editing another file than w_arg_idx
|
||||||
|
|
||||||
char_u *w_localdir; /* absolute path of local directory or
|
char_u *w_localdir; // absolute path of local directory or NULL
|
||||||
NULL */
|
char_u *w_prevdir; // previous directory
|
||||||
// Options local to a window.
|
// Options local to a window.
|
||||||
// They are local because they influence the layout of the window or
|
// They are local because they influence the layout of the window or
|
||||||
// depend on the window layout.
|
// depend on the window layout.
|
||||||
|
@ -7707,6 +7707,21 @@ void free_cd_dir(void)
|
|||||||
|
|
||||||
#endif
|
#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.
|
/// Deal with the side effects of changing the current directory.
|
||||||
///
|
///
|
||||||
/// @param scope Scope of the function call (global, tab or window).
|
/// @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) {
|
if (scope < kCdScopeGlobal) {
|
||||||
|
char_u *pdir = get_prevdir(scope);
|
||||||
// If still in global directory, set CWD as the global directory.
|
// If still in global directory, set CWD as the global directory.
|
||||||
if (globaldir == NULL && prev_dir != NULL) {
|
if (globaldir == NULL && pdir != NULL) {
|
||||||
globaldir = vim_strsave(prev_dir);
|
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.
|
/// 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.
|
/// @return true if the directory is successfully changed.
|
||||||
bool changedir_func(char_u *new_dir, CdScope scope)
|
bool changedir_func(char_u *new_dir, CdScope scope)
|
||||||
{
|
{
|
||||||
char_u *tofree;
|
char_u *tofree;
|
||||||
|
char_u *pdir = NULL;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
if (new_dir == NULL || allbuf_locked()) {
|
if (new_dir == NULL || allbuf_locked()) {
|
||||||
@ -7766,19 +7785,32 @@ bool changedir_func(char_u *new_dir, CdScope scope)
|
|||||||
|
|
||||||
// ":cd -": Change to previous directory
|
// ":cd -": Change to previous directory
|
||||||
if (STRCMP(new_dir, "-") == 0) {
|
if (STRCMP(new_dir, "-") == 0) {
|
||||||
if (prev_dir == NULL) {
|
pdir = get_prevdir(scope);
|
||||||
|
if (pdir == NULL) {
|
||||||
EMSG(_("E186: No previous directory"));
|
EMSG(_("E186: No previous directory"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
new_dir = prev_dir;
|
new_dir = pdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save current directory for next ":cd -"
|
// Free the previous directory
|
||||||
tofree = prev_dir;
|
tofree = get_prevdir(scope);
|
||||||
|
|
||||||
if (os_dirname(NameBuff, MAXPATHL) == OK) {
|
if (os_dirname(NameBuff, MAXPATHL) == OK) {
|
||||||
prev_dir = vim_strsave(NameBuff);
|
pdir = vim_strsave(NameBuff);
|
||||||
} else {
|
} 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)
|
#if defined(UNIX)
|
||||||
@ -7790,12 +7822,12 @@ bool changedir_func(char_u *new_dir, CdScope scope)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool dir_differs = prev_dir == NULL || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0;
|
if (vim_chdir(new_dir) == 0) {
|
||||||
if (dir_differs && vim_chdir(new_dir)) {
|
bool dir_differs = pdir == NULL || pathcmp((char *)pdir, (char *)new_dir, -1) != 0;
|
||||||
EMSG(_(e_failed));
|
|
||||||
} else {
|
|
||||||
post_chdir(scope, dir_differs);
|
post_chdir(scope, dir_differs);
|
||||||
retval = true;
|
retval = true;
|
||||||
|
} else {
|
||||||
|
EMSG(_(e_failed));
|
||||||
}
|
}
|
||||||
xfree(tofree);
|
xfree(tofree);
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/file_search.h"
|
#include "nvim/file_search.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
|
#include "nvim/globals.h"
|
||||||
#include "nvim/memory.h"
|
#include "nvim/memory.h"
|
||||||
#include "nvim/message.h"
|
#include "nvim/message.h"
|
||||||
#include "nvim/misc1.h"
|
#include "nvim/misc1.h"
|
||||||
@ -1666,11 +1667,12 @@ int vim_chdirfile(char_u *fname, CdCause cause)
|
|||||||
NameBuff[0] = NUL;
|
NameBuff[0] = NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cause != kCdCauseOther && pathcmp(dir, (char *)NameBuff, -1) != 0) {
|
if (os_chdir(dir) == 0) {
|
||||||
if (os_chdir(dir) != 0) {
|
if (cause != kCdCauseOther && pathcmp(dir, (char *)NameBuff, -1) != 0) {
|
||||||
return FAIL;
|
do_autocmd_dirchanged(dir, kCdScopeWindow, cause);
|
||||||
}
|
}
|
||||||
do_autocmd_dirchanged(dir, kCdScopeWindow, cause);
|
} else {
|
||||||
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -43,6 +43,20 @@ func Test_cd_minus()
|
|||||||
call assert_equal(path_dotdot, getcwd())
|
call assert_equal(path_dotdot, getcwd())
|
||||||
cd -
|
cd -
|
||||||
call assert_equal(path, getcwd())
|
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
|
endfunc
|
||||||
|
|
||||||
func Test_cd_with_cpo_chdir()
|
func Test_cd_with_cpo_chdir()
|
||||||
@ -115,6 +129,69 @@ func Test_chdir_func()
|
|||||||
call delete('Xdir', 'rf')
|
call delete('Xdir', 'rf')
|
||||||
endfunc
|
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()
|
func Test_cd_from_non_existing_dir()
|
||||||
CheckNotMSWindows
|
CheckNotMSWindows
|
||||||
|
|
||||||
|
@ -3733,6 +3733,7 @@ void free_tabpage(tabpage_T *tp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfree(tp->tp_localdir);
|
xfree(tp->tp_localdir);
|
||||||
|
xfree(tp->tp_prevdir);
|
||||||
xfree(tp);
|
xfree(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4771,6 +4772,7 @@ static void win_free(win_T *wp, tabpage_T *tp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfree(wp->w_localdir);
|
xfree(wp->w_localdir);
|
||||||
|
xfree(wp->w_prevdir);
|
||||||
|
|
||||||
/* Remove the window from the b_wininfo lists, it may happen that the
|
/* Remove the window from the b_wininfo lists, it may happen that the
|
||||||
* freed memory is re-used for another window. */
|
* freed memory is re-used for another window. */
|
||||||
|
Loading…
Reference in New Issue
Block a user