summaryrefslogtreecommitdiffstats
path: root/src/ex_docmd.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-05-07 22:06:52 +0200
committerBram Moolenaar <Bram@vim.org>2019-05-07 22:06:52 +0200
commit1063f3d2008f22d02ccfa9dab83a23db52febbdc (patch)
treeed4a5e7fddc01bdf2abb1d0d7931010c724d4ac5 /src/ex_docmd.c
parentfd31e45e4bccd7070d02e4d20bcab1f45b271600 (diff)
patch 8.1.1291: not easy to change directory and restorev8.1.1291
Problem: Not easy to change directory and restore. Solution: Add the chdir() function. (Yegappan Lakshmanan, closes #4358)
Diffstat (limited to 'src/ex_docmd.c')
-rw-r--r--src/ex_docmd.c180
1 files changed, 102 insertions, 78 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 1393d0e2f7..a2b302d922 100644
--- a/src/ex_docmd.c
+++ b/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,102 +7548,126 @@ post_chdir(int tablocal, int winlocal)
shorten_fnames(TRUE);
}
-
/*
- * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
+ * 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.
*/
- void
-ex_cd(exarg_T *eap)
+ int
+changedir_func(
+ char_u *new_dir,
+ int forceit,
+ cdscope_T scope)
{
- char_u *new_dir;
char_u *tofree;
int dir_differs;
+ int retval = FALSE;
- new_dir = eap->arg;
-#if !defined(UNIX) && !defined(VMS)
- /* for non-UNIX ":cd" means: print current directory */
- if (*new_dir == NUL)
- ex_pwd(NULL);
- else
-#endif
+ if (allbuf_locked())
+ return FALSE;
+
+ if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !forceit)
{
- if (allbuf_locked())
- return;
- if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged()
- && !eap->forceit)
- {
- emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
- return;
- }
+ emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
+ return FALSE;
+ }
- /* ":cd -": Change to previous directory */
- if (STRCMP(new_dir, "-") == 0)
+ // ":cd -": Change to previous directory
+ if (STRCMP(new_dir, "-") == 0)
+ {
+ if (prev_dir == NULL)
{
- if (prev_dir == NULL)
- {
- emsg(_("E186: No previous directory"));
- return;
- }
- new_dir = prev_dir;
+ 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;
+ // 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 */
+ // for UNIX ":cd" means: go to home directory
+ if (*new_dir == NUL)
+ {
+ // use NameBuff for home directory name
# ifdef VMS
- char_u *p;
+ 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);
+ 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);
+ expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
# endif
- new_dir = NameBuff;
- }
+ 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
+ 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)
{
- 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;
+ 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".
+ */
+ void
+ex_cd(exarg_T *eap)
+{
+ char_u *new_dir;
- post_chdir(is_tablocal_chdir, is_winlocal_chdir);
+ new_dir = eap->arg;
+#if !defined(UNIX) && !defined(VMS)
+ // for non-UNIX ":cd" means: print current directory
+ if (*new_dir == NUL)
+ ex_pwd(NULL);
+ else
+#endif
+ {
+ cdscope_T scope = CDSCOPE_GLOBAL;
- /* Echo the new current directory if the command was typed. */
+ 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))
+ {
+ // 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);
}
}