comparison 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
comparison
equal deleted inserted replaced
16575:e0baba49b677 16576:bcc343175103
7511 } 7511 }
7512 #endif 7512 #endif
7513 7513
7514 /* 7514 /*
7515 * Deal with the side effects of changing the current directory. 7515 * Deal with the side effects of changing the current directory.
7516 * When "tablocal" is TRUE then this was after an ":tcd" command. 7516 * When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command.
7517 * When "winlocal" is TRUE then this was after an ":lcd" command. 7517 * When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command.
7518 */ 7518 */
7519 void 7519 void
7520 post_chdir(int tablocal, int winlocal) 7520 post_chdir(cdscope_T scope)
7521 { 7521 {
7522 if (!winlocal) 7522 if (scope != CDSCOPE_WINDOW)
7523 // Clear tab local directory for both :cd and :tcd 7523 // Clear tab local directory for both :cd and :tcd
7524 VIM_CLEAR(curtab->tp_localdir); 7524 VIM_CLEAR(curtab->tp_localdir);
7525 VIM_CLEAR(curwin->w_localdir); 7525 VIM_CLEAR(curwin->w_localdir);
7526 if (winlocal || tablocal) 7526 if (scope != CDSCOPE_GLOBAL)
7527 { 7527 {
7528 /* If still in global directory, need to remember current 7528 /* If still in global directory, need to remember current
7529 * directory as global directory. */ 7529 * directory as global directory. */
7530 if (globaldir == NULL && prev_dir != NULL) 7530 if (globaldir == NULL && prev_dir != NULL)
7531 globaldir = vim_strsave(prev_dir); 7531 globaldir = vim_strsave(prev_dir);
7532 /* Remember this local directory for the window. */ 7532 /* Remember this local directory for the window. */
7533 if (mch_dirname(NameBuff, MAXPATHL) == OK) 7533 if (mch_dirname(NameBuff, MAXPATHL) == OK)
7534 { 7534 {
7535 if (tablocal) 7535 if (scope == CDSCOPE_TABPAGE)
7536 curtab->tp_localdir = vim_strsave(NameBuff); 7536 curtab->tp_localdir = vim_strsave(NameBuff);
7537 else 7537 else
7538 curwin->w_localdir = vim_strsave(NameBuff); 7538 curwin->w_localdir = vim_strsave(NameBuff);
7539 } 7539 }
7540 } 7540 }
7546 } 7546 }
7547 7547
7548 shorten_fnames(TRUE); 7548 shorten_fnames(TRUE);
7549 } 7549 }
7550 7550
7551 /*
7552 * Change directory function used by :cd/:tcd/:lcd Ex commands and the
7553 * chdir() function. If 'winlocaldir' is TRUE, then changes the window-local
7554 * directory. If 'tablocaldir' is TRUE, then changes the tab-local directory.
7555 * Otherwise changes the global directory.
7556 * Returns TRUE if the directory is successfully changed.
7557 */
7558 int
7559 changedir_func(
7560 char_u *new_dir,
7561 int forceit,
7562 cdscope_T scope)
7563 {
7564 char_u *tofree;
7565 int dir_differs;
7566 int retval = FALSE;
7567
7568 if (allbuf_locked())
7569 return FALSE;
7570
7571 if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !forceit)
7572 {
7573 emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)"));
7574 return FALSE;
7575 }
7576
7577 // ":cd -": Change to previous directory
7578 if (STRCMP(new_dir, "-") == 0)
7579 {
7580 if (prev_dir == NULL)
7581 {
7582 emsg(_("E186: No previous directory"));
7583 return FALSE;
7584 }
7585 new_dir = prev_dir;
7586 }
7587
7588 // Save current directory for next ":cd -"
7589 tofree = prev_dir;
7590 if (mch_dirname(NameBuff, MAXPATHL) == OK)
7591 prev_dir = vim_strsave(NameBuff);
7592 else
7593 prev_dir = NULL;
7594
7595 #if defined(UNIX) || defined(VMS)
7596 // for UNIX ":cd" means: go to home directory
7597 if (*new_dir == NUL)
7598 {
7599 // use NameBuff for home directory name
7600 # ifdef VMS
7601 char_u *p;
7602
7603 p = mch_getenv((char_u *)"SYS$LOGIN");
7604 if (p == NULL || *p == NUL) // empty is the same as not set
7605 NameBuff[0] = NUL;
7606 else
7607 vim_strncpy(NameBuff, p, MAXPATHL - 1);
7608 # else
7609 expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
7610 # endif
7611 new_dir = NameBuff;
7612 }
7613 #endif
7614 dir_differs = new_dir == NULL || prev_dir == NULL
7615 || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0;
7616 if (new_dir == NULL || (dir_differs && vim_chdir(new_dir)))
7617 emsg(_(e_failed));
7618 else
7619 {
7620 char_u *acmd_fname;
7621
7622 post_chdir(scope);
7623
7624 if (dir_differs)
7625 {
7626 if (scope == CDSCOPE_WINDOW)
7627 acmd_fname = (char_u *)"window";
7628 else if (scope == CDSCOPE_TABPAGE)
7629 acmd_fname = (char_u *)"tabpage";
7630 else
7631 acmd_fname = (char_u *)"global";
7632 apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE,
7633 curbuf);
7634 }
7635 retval = TRUE;
7636 }
7637 vim_free(tofree);
7638
7639 return retval;
7640 }
7551 7641
7552 /* 7642 /*
7553 * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir". 7643 * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir".
7554 */ 7644 */
7555 void 7645 void
7556 ex_cd(exarg_T *eap) 7646 ex_cd(exarg_T *eap)
7557 { 7647 {
7558 char_u *new_dir; 7648 char_u *new_dir;
7559 char_u *tofree;
7560 int dir_differs;
7561 7649
7562 new_dir = eap->arg; 7650 new_dir = eap->arg;
7563 #if !defined(UNIX) && !defined(VMS) 7651 #if !defined(UNIX) && !defined(VMS)
7564 /* for non-UNIX ":cd" means: print current directory */ 7652 // for non-UNIX ":cd" means: print current directory
7565 if (*new_dir == NUL) 7653 if (*new_dir == NUL)
7566 ex_pwd(NULL); 7654 ex_pwd(NULL);
7567 else 7655 else
7568 #endif 7656 #endif
7569 { 7657 {
7570 if (allbuf_locked()) 7658 cdscope_T scope = CDSCOPE_GLOBAL;
7571 return; 7659
7572 if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() 7660 if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir)
7573 && !eap->forceit) 7661 scope = CDSCOPE_WINDOW;
7574 { 7662 else if (eap->cmdidx == CMD_tcd || eap->cmdidx == CMD_tchdir)
7575 emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)")); 7663 scope = CDSCOPE_TABPAGE;
7576 return; 7664
7577 } 7665 if (changedir_func(new_dir, eap->forceit, scope))
7578 7666 {
7579 /* ":cd -": Change to previous directory */ 7667 // Echo the new current directory if the command was typed.
7580 if (STRCMP(new_dir, "-") == 0)
7581 {
7582 if (prev_dir == NULL)
7583 {
7584 emsg(_("E186: No previous directory"));
7585 return;
7586 }
7587 new_dir = prev_dir;
7588 }
7589
7590 /* Save current directory for next ":cd -" */
7591 tofree = prev_dir;
7592 if (mch_dirname(NameBuff, MAXPATHL) == OK)
7593 prev_dir = vim_strsave(NameBuff);
7594 else
7595 prev_dir = NULL;
7596
7597 #if defined(UNIX) || defined(VMS)
7598 /* for UNIX ":cd" means: go to home directory */
7599 if (*new_dir == NUL)
7600 {
7601 /* use NameBuff for home directory name */
7602 # ifdef VMS
7603 char_u *p;
7604
7605 p = mch_getenv((char_u *)"SYS$LOGIN");
7606 if (p == NULL || *p == NUL) /* empty is the same as not set */
7607 NameBuff[0] = NUL;
7608 else
7609 vim_strncpy(NameBuff, p, MAXPATHL - 1);
7610 # else
7611 expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
7612 # endif
7613 new_dir = NameBuff;
7614 }
7615 #endif
7616 dir_differs = new_dir == NULL || prev_dir == NULL
7617 || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0;
7618 if (new_dir == NULL || (dir_differs && vim_chdir(new_dir)))
7619 emsg(_(e_failed));
7620 else
7621 {
7622 char_u *acmd_fname;
7623 int is_winlocal_chdir = eap->cmdidx == CMD_lcd
7624 || eap->cmdidx == CMD_lchdir;
7625 int is_tablocal_chdir = eap->cmdidx == CMD_tcd
7626 || eap->cmdidx == CMD_tchdir;
7627
7628 post_chdir(is_tablocal_chdir, is_winlocal_chdir);
7629
7630 /* Echo the new current directory if the command was typed. */
7631 if (KeyTyped || p_verbose >= 5) 7668 if (KeyTyped || p_verbose >= 5)
7632 ex_pwd(eap); 7669 ex_pwd(eap);
7633 7670 }
7634 if (dir_differs)
7635 {
7636 if (is_winlocal_chdir)
7637 acmd_fname = (char_u *)"window";
7638 else if (is_tablocal_chdir)
7639 acmd_fname = (char_u *)"tabpage";
7640 else
7641 acmd_fname = (char_u *)"global";
7642 apply_autocmds(EVENT_DIRCHANGED, acmd_fname,
7643 new_dir, FALSE, curbuf);
7644 }
7645 }
7646 vim_free(tofree);
7647 } 7671 }
7648 } 7672 }
7649 7673
7650 /* 7674 /*
7651 * ":pwd". 7675 * ":pwd".