Mercurial > vim
diff src/ex_docmd.c @ 16576:bcc343175103 v8.1.1291
patch 8.1.1291: not easy to change directory and restore
commit https://github.com/vim/vim/commit/1063f3d2008f22d02ccfa9dab83a23db52febbdc
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue May 7 22:06:52 2019 +0200
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 https://github.com/vim/vim/issues/4358)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 07 May 2019 22:15:05 +0200 |
parents | 6e87a69b8e0c |
children | 0422b14bce58 |
line wrap: on
line diff
--- 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) -{ - if (!winlocal) +post_chdir(cdscope_T scope) +{ + 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) - { - 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. */ + 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)) + { + // 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); + } } }