Mercurial > vim
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". |