forked from aniani/vim
patch 8.1.1291: not easy to change directory and restore
Problem: Not easy to change directory and restore. Solution: Add the chdir() function. (Yegappan Lakshmanan, closes #4358)
This commit is contained in:
188
src/ex_docmd.c
188
src/ex_docmd.c
@@ -7513,17 +7513,17 @@ free_cd_dir(void)
|
||||
|
||||
/*
|
||||
* Deal with the side effects of changing the current directory.
|
||||
* When "tablocal" is TRUE then this was after an ":tcd" command.
|
||||
* When "winlocal" is TRUE then this was after an ":lcd" command.
|
||||
* When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command.
|
||||
* When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command.
|
||||
*/
|
||||
void
|
||||
post_chdir(int tablocal, int winlocal)
|
||||
post_chdir(cdscope_T scope)
|
||||
{
|
||||
if (!winlocal)
|
||||
if (scope != CDSCOPE_WINDOW)
|
||||
// Clear tab local directory for both :cd and :tcd
|
||||
VIM_CLEAR(curtab->tp_localdir);
|
||||
VIM_CLEAR(curwin->w_localdir);
|
||||
if (winlocal || tablocal)
|
||||
if (scope != CDSCOPE_GLOBAL)
|
||||
{
|
||||
/* If still in global directory, need to remember current
|
||||
* directory as global directory. */
|
||||
@@ -7532,7 +7532,7 @@ post_chdir(int tablocal, int winlocal)
|
||||
/* Remember this local directory for the window. */
|
||||
if (mch_dirname(NameBuff, MAXPATHL) == OK)
|
||||
{
|
||||
if (tablocal)
|
||||
if (scope == CDSCOPE_TABPAGE)
|
||||
curtab->tp_localdir = vim_strsave(NameBuff);
|
||||
else
|
||||
curwin->w_localdir = vim_strsave(NameBuff);
|
||||
@@ -7548,6 +7548,96 @@ post_chdir(int tablocal, int winlocal)
|
||||
shorten_fnames(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change directory function used by :cd/:tcd/:lcd Ex commands and the
|
||||
* chdir() function. If 'winlocaldir' is TRUE, then changes the window-local
|
||||
* directory. If 'tablocaldir' is TRUE, then changes the tab-local directory.
|
||||
* Otherwise changes the global directory.
|
||||
* Returns TRUE if the directory is successfully changed.
|
||||
*/
|
||||
int
|
||||
changedir_func(
|
||||
char_u *new_dir,
|
||||
int forceit,
|
||||
cdscope_T scope)
|
||||
{
|
||||
char_u *tofree;
|
||||
int dir_differs;
|
||||
int retval = FALSE;
|
||||
|
||||
if (allbuf_locked())
|
||||
return FALSE;
|
||||
|
||||
if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !forceit)
|
||||
{
|
||||
emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ":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
|
||||
if (*new_dir == NUL)
|
||||
{
|
||||
// use NameBuff for home directory name
|
||||
# ifdef VMS
|
||||
char_u *p;
|
||||
|
||||
p = mch_getenv((char_u *)"SYS$LOGIN");
|
||||
if (p == NULL || *p == NUL) // empty is the same as not set
|
||||
NameBuff[0] = NUL;
|
||||
else
|
||||
vim_strncpy(NameBuff, p, MAXPATHL - 1);
|
||||
# else
|
||||
expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
|
||||
# endif
|
||||
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
|
||||
{
|
||||
char_u *acmd_fname;
|
||||
|
||||
post_chdir(scope);
|
||||
|
||||
if (dir_differs)
|
||||
{
|
||||
if (scope == CDSCOPE_WINDOW)
|
||||
acmd_fname = (char_u *)"window";
|
||||
else if (scope == CDSCOPE_TABPAGE)
|
||||
acmd_fname = (char_u *)"tabpage";
|
||||
else
|
||||
acmd_fname = (char_u *)"global";
|
||||
apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE,
|
||||
curbuf);
|
||||
}
|
||||
retval = TRUE;
|
||||
}
|
||||
vim_free(tofree);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
|
||||
@@ -7556,94 +7646,28 @@ post_chdir(int tablocal, int winlocal)
|
||||
ex_cd(exarg_T *eap)
|
||||
{
|
||||
char_u *new_dir;
|
||||
char_u *tofree;
|
||||
int dir_differs;
|
||||
|
||||
new_dir = eap->arg;
|
||||
#if !defined(UNIX) && !defined(VMS)
|
||||
/* for non-UNIX ":cd" means: print current directory */
|
||||
// for non-UNIX ":cd" means: print current directory
|
||||
if (*new_dir == NUL)
|
||||
ex_pwd(NULL);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (allbuf_locked())
|
||||
return;
|
||||
if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged()
|
||||
&& !eap->forceit)
|
||||
cdscope_T scope = CDSCOPE_GLOBAL;
|
||||
|
||||
if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
|
||||
scope = CDSCOPE_WINDOW;
|
||||
else if (eap->cmdidx == CMD_tcd || eap->cmdidx == CMD_tchdir)
|
||||
scope = CDSCOPE_TABPAGE;
|
||||
|
||||
if (changedir_func(new_dir, eap->forceit, scope))
|
||||
{
|
||||
emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* ":cd -": Change to previous directory */
|
||||
if (STRCMP(new_dir, "-") == 0)
|
||||
{
|
||||
if (prev_dir == NULL)
|
||||
{
|
||||
emsg(_("E186: No previous directory"));
|
||||
return;
|
||||
}
|
||||
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 */
|
||||
if (*new_dir == NUL)
|
||||
{
|
||||
/* use NameBuff for home directory name */
|
||||
# ifdef VMS
|
||||
char_u *p;
|
||||
|
||||
p = mch_getenv((char_u *)"SYS$LOGIN");
|
||||
if (p == NULL || *p == NUL) /* empty is the same as not set */
|
||||
NameBuff[0] = NUL;
|
||||
else
|
||||
vim_strncpy(NameBuff, p, MAXPATHL - 1);
|
||||
# else
|
||||
expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
|
||||
# endif
|
||||
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
|
||||
{
|
||||
char_u *acmd_fname;
|
||||
int is_winlocal_chdir = eap->cmdidx == CMD_lcd
|
||||
|| eap->cmdidx == CMD_lchdir;
|
||||
int is_tablocal_chdir = eap->cmdidx == CMD_tcd
|
||||
|| eap->cmdidx == CMD_tchdir;
|
||||
|
||||
post_chdir(is_tablocal_chdir, is_winlocal_chdir);
|
||||
|
||||
/* Echo the new current directory if the command was typed. */
|
||||
// Echo the new current directory if the command was typed.
|
||||
if (KeyTyped || p_verbose >= 5)
|
||||
ex_pwd(eap);
|
||||
|
||||
if (dir_differs)
|
||||
{
|
||||
if (is_winlocal_chdir)
|
||||
acmd_fname = (char_u *)"window";
|
||||
else if (is_tablocal_chdir)
|
||||
acmd_fname = (char_u *)"tabpage";
|
||||
else
|
||||
acmd_fname = (char_u *)"global";
|
||||
apply_autocmds(EVENT_DIRCHANGED, acmd_fname,
|
||||
new_dir, FALSE, curbuf);
|
||||
}
|
||||
}
|
||||
vim_free(tofree);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user