Implement tab-local working directory feature.

New ex commands: 'tcd', 'tchdir'
Changed Vimscript functions: 'haslocaldir', 'getcwd'

The ex-commands ':tcd' and ':tchdir' are the tab-local equivalents of
':lcd' and ':lchdir'. There are no new Vimscript functions introduced,
instead the functions 'haslocaldir' and 'getcwd' take in optional
arguments. See the documentation for details

Since there is now different levels of local directory a simple boolean
at source level is no longer sufficient; a new enumeration type is used
for the scope-level from now on.

The documentation has been accommodated for these new commands and
functional tests have been written to test the feature.
This commit is contained in:
HiPhish
2015-08-24 12:58:28 +02:00
parent a7a0bf54e3
commit ec71d87b81
10 changed files with 557 additions and 78 deletions

View File

@@ -2958,8 +2958,11 @@ set_one_cmd_context (
case CMD_chdir:
case CMD_lcd:
case CMD_lchdir:
if (xp->xp_context == EXPAND_FILES)
case CMD_tcd:
case CMD_tchdir:
if (xp->xp_context == EXPAND_FILES) {
xp->xp_context = EXPAND_DIRECTORIES;
}
break;
case CMD_help:
xp->xp_context = EXPAND_HELP;
@@ -6814,36 +6817,55 @@ void free_cd_dir(void)
#endif
/*
* Deal with the side effects of changing the current directory.
* When "local" is TRUE then this was after an ":lcd" command.
*/
void post_chdir(int local)
/// Deal with the side effects of changing the current directory.
///
/// @param scope Scope of the function call (global, tab or window).
void post_chdir(CdScope scope)
{
// The local directory of the current window is always overwritten.
xfree(curwin->w_localdir);
curwin->w_localdir = NULL;
if (local) {
/* If still in global directory, need to remember current
* directory as global directory. */
if (globaldir == NULL && prev_dir != NULL)
// Overwrite the local directory of the current tab page for `cd` and `tcd`
if (scope >= kCdScopeTab) {
xfree(curtab->localdir);
curtab->localdir = NULL;
}
if (scope < kCdScopeGlobal) {
// If still in global directory, need to remember current directory as
// global directory.
if (globaldir == NULL && prev_dir != NULL) {
globaldir = vim_strsave(prev_dir);
/* Remember this local directory for the window. */
if (os_dirname(NameBuff, MAXPATHL) == OK)
curwin->w_localdir = vim_strsave(NameBuff);
} else {
/* We are now in the global directory, no need to remember its
* name. */
}
}
switch (scope) {
case kCdScopeGlobal:
// We are now in the global directory, no need to remember its name.
xfree(globaldir);
globaldir = NULL;
break;
case kCdScopeTab:
// Remember this local directory for the tab page.
if (os_dirname(NameBuff, MAXPATHL) == OK) {
curtab->localdir = vim_strsave(NameBuff);
}
break;
case kCdScopeWindow:
// Remember this local directory for the window.
if (os_dirname(NameBuff, MAXPATHL) == OK) {
curwin->w_localdir = vim_strsave(NameBuff);
}
break;
}
shorten_fnames(TRUE);
}
/*
* ":cd", ":lcd", ":chdir" and ":lchdir".
*/
/// `:cd`, `:tcd`, `:lcd`, `:chdir`, `:tchdir` and `:lchdir`.
void ex_cd(exarg_T *eap)
{
char_u *new_dir;
@@ -6884,10 +6906,25 @@ void ex_cd(exarg_T *eap)
new_dir = NameBuff;
}
#endif
if (new_dir == NULL || vim_chdir(new_dir))
if (vim_chdir(new_dir)) {
EMSG(_(e_failed));
else {
post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir);
} else {
CdScope scope = kCdScopeGlobal; // Depends on command invoked
switch (eap->cmdidx) {
case CMD_tcd:
case CMD_tchdir:
scope = kCdScopeTab;
break;
case CMD_lcd:
case CMD_lchdir:
scope = kCdScopeWindow;
break;
default:
break;
}
post_chdir(scope);
/* Echo the new current directory if the command was typed. */
if (KeyTyped || p_verbose >= 5)