Skip to content
Permalink
Browse files

patch 8.1.1218: cannot set a directory for a tab page

Problem:    Cannot set a directory for a tab page.
Solution:   Add the tab-local directory. (Yegappan Lakshmanan, closes #4212)
  • Loading branch information...
brammool committed Apr 27, 2019
1 parent 2155a6a commit 00aa069db8132851a91cfc5ca7f58ef945c75c73
@@ -1,4 +1,4 @@
*autocmd.txt* For Vim version 8.1. Last change: 2019 Apr 08
*autocmd.txt* For Vim version 8.1. Last change: 2019 Apr 27


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -690,13 +690,14 @@ DiffUpdated After diffs have been updated. Depending on
change or when doing |:diffupdate|.
*DirChanged*
DirChanged The working directory has changed in response
to the |:cd| or |:lcd| commands, or as a
result of the 'autochdir' option.
to the |:cd| or |:tcd| or |:lcd| commands, or
as a result of the 'autochdir' option.
The pattern can be:
"window" to trigger on `:lcd`
"global" to trigger on `:cd`
"auto" to trigger on 'autochdir'.
"drop" to trigger on editing a file
"window" to trigger on `:lcd`
"tabpage" to trigger on `:tcd`
"global" to trigger on `:cd`
"auto" to trigger on 'autochdir'.
"drop" to trigger on editing a file
<afile> is set to the new directory name.
*ExitPre*
ExitPre When using `:quit`, `:wq` in a way it makes
@@ -1304,9 +1304,10 @@ use has("browsefilter"): >
==============================================================================
7. The current directory *current-directory*

You may use the |:cd| and |:lcd| commands to change to another directory, so
you will not have to type that directory name in front of the file names. It
also makes a difference for executing external commands, e.g. ":!ls".
You can use the |:cd|, |:tcd| and |:lcd| commands to change to another
directory, so you will not have to type that directory name in front of the
file names. It also makes a difference for executing external commands, e.g.
":!ls".

Changing directory fails when the current buffer is modified, the '.' flag is
present in 'cpoptions' and "!" is not used in the command.
@@ -1334,6 +1335,17 @@ present in 'cpoptions' and "!" is not used in the command.
*:chd* *:chdir*
:chd[ir][!] [path] Same as |:cd|.

*:tcd*
:tcd[!] {path} Like |:cd|, but only set the directory for the current
tab. The current window will also use this directory.
The current directory is not changed for windows in
other tabs and for windows in the current tab that
have their own window-local directory.
{not in Vi}

*:tch* *:tchdir*
:tch[dir][!] Same as |:tcd|. {not in Vi}

*:lc* *:lcd*
:lc[d][!] {path} Like |:cd|, but only set the current directory when
the cursor is in the current window. The current
@@ -1348,17 +1360,26 @@ present in 'cpoptions' and "!" is not used in the command.
:pw[d] Print the current directory name. {Vi: no pwd}
Also see |getcwd()|.

So long as no |:lcd| command has been used, all windows share the same current
directory. Using a command to jump to another window doesn't change anything
for the current directory.
So long as no |:lcd| or |:tcd| command has been used, all windows share the
same current directory. Using a command to jump to another window doesn't
change anything for the current directory.

When a |:lcd| command has been used for a window, the specified directory
becomes the current directory for that window. Windows where the |:lcd|
command has not been used stick to the global current directory. When jumping
to another window the current directory will become the last specified local
current directory. If none was specified, the global current directory is
used.
When a |:cd| command is used, the current window will lose his local current
directory and will use the global current directory from now on.
command has not been used stick to the global or tab-local current directory.
When jumping to another window the current directory will become the last
specified local current directory. If none was specified, the global or
tab-local current directory is used.

When a |:tcd| command has been used for a tab page, the specified directory
becomes the current directory for the current tab page and the current window.
The current directory of other tab pages is not affected. When jumping to
another tab page, the current directory will become the last specified local
directory for that tab page. If the current tab has no local current directory
the global current directory is used.

When a |:cd| command is used, the current window and tab page will lose the
local current directory and will use the global current directory from now on.

After using |:cd| the full path name will be used for reading and writing
files. On some networked file systems this may cause problems. The result of
@@ -2398,6 +2398,7 @@ has({feature}) Number |TRUE| if feature {feature} supported
has_key({dict}, {key}) Number |TRUE| if {dict} has entry {key}
haslocaldir([{winnr} [, {tabnr}]])
Number |TRUE| if the window executed |:lcd|
or |:tcd|
hasmapto({what} [, {mode} [, {abbr}]])
Number |TRUE| if mapping to {what} exists
histadd({history}, {item}) String add an item to a history
@@ -4918,9 +4919,28 @@ getcwd([{winnr} [, {tabnr}]])
directory. See also |haslocaldir()|.

With {winnr} and {tabnr} return the local current directory of
the window in the specified tab page.
the window in the specified tab page. If {winnr} is -1 return
the working directory of the tabpage.
If {winnr} is zero use the current window, if {tabnr} is zero
use the current tabpage.
Without any arguments, return the working directory of the
current window.
Return an empty string if the arguments are invalid.

Examples: >
" Get the working directory of the current window
:echo getcwd()
:echo getcwd(0)
:echo getcwd(0, 0)
" Get the working directory of window 3 in tabpage 2
:echo getcwd(3, 2)
" Get the global working directory
:echo getcwd(-1)
" Get the working directory of tabpage 3
:echo getcwd(-1, 3)
" Get the working directory of current tabpage
:echo getcwd(-1, 0)
<
getfsize({fname}) *getfsize()*
The result is a Number, which is the size in bytes of the
given file {fname}.
@@ -5478,16 +5498,39 @@ has_key({dict}, {key}) *has_key()*
an entry with key {key}. Zero otherwise.

haslocaldir([{winnr} [, {tabnr}]]) *haslocaldir()*
The result is a Number, which is 1 when the window has set a
local path via |:lcd|, and 0 otherwise.
The result is a Number:
1 when the window has set a local directory via |:lcd|
2 when the tab-page has set a local directory via |:tcd|
0 otherwise.

Without arguments use the current window.
With {winnr} use this window in the current tab page.
With {winnr} and {tabnr} use the window in the specified tab
page.
{winnr} can be the window number or the |window-ID|.
If {winnr} is -1 it is ignored and only the tabpage is used.
Return 0 if the arguments are invalid.
Examples: >
if haslocaldir() == 1
" window local directory case
elseif haslocaldir() == 2
" tab-local directory case
else
" global directory case
endif

" current window
:echo haslocaldir()
:echo haslocaldir(0)
:echo haslocaldir(0, 0)
" window n in current tab page
:echo haslocaldir(n)
:echo haslocaldir(n, 0)
" window n in tab page m
:echo haslocaldir(n, m)
" tab page m
:echo haslocaldir(-1, m)
<
hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()*
The result is a Number, which is 1 if there is a mapping that
contains {what} in somewhere in the rhs (what it is mapped to)
@@ -1623,6 +1623,8 @@ tag command action ~
|:tab| :tab create new tab when opening new window
|:tag| :ta[g] jump to tag
|:tags| :tags show the contents of the tag stack
|:tcd| :tcd change directory for tab page
|:tchdir| :tch[dir] change directory for tab page
|:tcl| :tc[l] execute Tcl command
|:tcldo| :tcld[o] execute Tcl command for each line
|:tclfile| :tclf[ile] execute Tcl script file
@@ -1455,9 +1455,9 @@ A jump table for the options with a short description can be found at |Q_op|.
{not available when compiled without the
|+file_in_path| feature}
This is a list of directories which will be searched when using the
|:cd| and |:lcd| commands, provided that the directory being searched
for has a relative path, not an absolute part starting with "/", "./"
or "../", the 'cdpath' option is not used then.
|:cd|, |:tcd| and |:lcd| commands, provided that the directory being
searched for has a relative path, not an absolute part starting with
"/", "./" or "../", the 'cdpath' option is not used then.
The 'cdpath' option's value has the same form and semantics as
|'path'|. Also see |file-searching|.
The default value is taken from $CDPATH, with a "," prepended to look
@@ -202,14 +202,28 @@ the other window. This is called a local directory. >
:pwd
/home/Bram/VeryLongFileName

So long as no ":lcd" command has been used, all windows share the same current
directory. Doing a ":cd" command in one window will also change the current
So long as no `:lcd` command has been used, all windows share the same current
directory. Doing a `:cd` command in one window will also change the current
directory of the other window.
For a window where ":lcd" has been used a different current directory is
remembered. Using ":cd" or ":lcd" in other windows will not change it.
When using a ":cd" command in a window that uses a different current
For a window where `:lcd` has been used a different current directory is
remembered. Using `:cd` or `:lcd` in other windows will not change it.
When using a `:cd` command in a window that uses a different current
directory, it will go back to using the shared directory.


TAB LOCAL DIRECTORY

When you open a new tab page, it uses the directory of the window in the
previous tab page from which the new tab page was opened. You can change the
directory of the current tab page using the `:tcd` command. All the windows in
a tab page share this directory except for windows with a window-local
directory. Any new windows opened in this tab page will use this directory as
the current working directory. Using a `:cd` command in a tab page will not
change the working directory of tab pages which have a tab local directory.
When the global working directory is changed using the ":cd" command in a tab
page, it will also change the current tab page working directory.


==============================================================================
*22.3* Finding a file

@@ -766,7 +766,7 @@ System functions and manipulation of files:
isdirectory() check if a directory exists
getfsize() get the size of a file
getcwd() get the current working directory
haslocaldir() check if current window used |:lcd|
haslocaldir() check if current window used |:lcd| or |:tcd|
tempname() get the name of a temporary file
mkdir() create a new directory
delete() delete a file
@@ -8704,11 +8704,13 @@ find_win_by_nr_or_id(typval_T *vp)

/*
* Find window specified by "wvp" in tabpage "tvp".
* Returns the tab page in 'ptp'
*/
win_T *
find_tabwin(
typval_T *wvp, /* VAR_UNKNOWN for current window */
typval_T *tvp) /* VAR_UNKNOWN for current tab page */
typval_T *wvp, // VAR_UNKNOWN for current window
typval_T *tvp, // VAR_UNKNOWN for current tab page
tabpage_T **ptp)
{
win_T *wp = NULL;
tabpage_T *tp = NULL;
@@ -8726,10 +8728,22 @@ find_tabwin(
tp = curtab;

if (tp != NULL)
{
wp = find_win_by_nr(wvp, tp);
if (wp == NULL && wvp->v_type == VAR_NUMBER
&& wvp->vval.v_number != -1)
// A window with the specified number is not found
tp = NULL;
}
}
else
{
wp = curwin;
tp = curtab;
}

if (ptp != NULL)
*ptp = tp;

return wp;
}
@@ -1529,7 +1529,7 @@ f_arglistid(typval_T *argvars, typval_T *rettv)
win_T *wp;

rettv->vval.v_number = -1;
wp = find_tabwin(&argvars[0], &argvars[1]);
wp = find_tabwin(&argvars[0], &argvars[1], NULL);
if (wp != NULL)
rettv->vval.v_number = wp->w_alist->id;
}
@@ -5126,25 +5126,44 @@ f_getcompletion(typval_T *argvars, typval_T *rettv)

/*
* "getcwd()" function
*
* Return the current working directory of a window in a tab page.
* First optional argument 'winnr' is the window number or -1 and the second
* optional argument 'tabnr' is the tab page number.
*
* If no arguments are supplied, then return the directory of the current
* window.
* If only 'winnr' is specified and is not -1 or 0 then return the directory of
* the specified window.
* If 'winnr' is 0 then return the directory of the current window.
* If both 'winnr and 'tabnr' are specified and 'winnr' is -1 then return the
* directory of the specified tab page. Otherwise return the directory of the
* specified window in the specified tab page.
* If the window or the tab page doesn't exist then return NULL.
*/
static void
f_getcwd(typval_T *argvars, typval_T *rettv)
{
win_T *wp = NULL;
tabpage_T *tp = NULL;
char_u *cwd;
int global = FALSE;

rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;

if (argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number == -1)
if (argvars[0].v_type == VAR_NUMBER
&& argvars[0].vval.v_number == -1
&& argvars[1].v_type == VAR_UNKNOWN)
global = TRUE;
else
wp = find_tabwin(&argvars[0], &argvars[1]);
wp = find_tabwin(&argvars[0], &argvars[1], &tp);

if (wp != NULL && wp->w_localdir != NULL)
rettv->vval.v_string = vim_strsave(wp->w_localdir);
else if (wp != NULL || global)
else if (tp != NULL && tp->tp_localdir != NULL)
rettv->vval.v_string = vim_strsave(tp->tp_localdir);
else if (wp != NULL || tp != NULL || global)
{
if (globaldir != NULL)
rettv->vval.v_string = vim_strsave(globaldir);
@@ -5333,7 +5352,7 @@ f_getjumplist(typval_T *argvars, typval_T *rettv)
return;

#ifdef FEAT_JUMPLIST
wp = find_tabwin(&argvars[0], &argvars[1]);
wp = find_tabwin(&argvars[0], &argvars[1], NULL);
if (wp == NULL)
return;

@@ -6824,10 +6843,18 @@ f_has_key(typval_T *argvars, typval_T *rettv)
static void
f_haslocaldir(typval_T *argvars, typval_T *rettv)
{
tabpage_T *tp = NULL;
win_T *wp = NULL;

wp = find_tabwin(&argvars[0], &argvars[1]);
rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL);
wp = find_tabwin(&argvars[0], &argvars[1], &tp);

// Check for window-local and tab-local directories
if (wp != NULL && wp->w_localdir != NULL)
rettv->vval.v_number = 1;
else if (tp != NULL && tp->tp_localdir != NULL)
rettv->vval.v_number = 2;
else
rettv->vval.v_number = 0;
}

/*
@@ -25,12 +25,12 @@ static const unsigned short cmdidxs1[26] =
/* r */ 351,
/* s */ 371,
/* t */ 439,
/* u */ 482,
/* v */ 493,
/* w */ 511,
/* x */ 525,
/* y */ 534,
/* z */ 535
/* u */ 484,
/* v */ 495,
/* w */ 513,
/* x */ 527,
/* y */ 536,
/* z */ 537
};

/*
@@ -60,7 +60,7 @@ static const unsigned char cmdidxs2[26][26] =
/* q */ { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* r */ { 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 19, 0, 0, 0, 0 },
/* s */ { 2, 6, 15, 0, 19, 23, 0, 25, 26, 0, 0, 29, 31, 35, 39, 41, 0, 49, 0, 50, 0, 62, 63, 0, 64, 0 },
/* t */ { 2, 0, 19, 0, 22, 24, 0, 25, 0, 26, 0, 27, 31, 34, 36, 37, 0, 38, 40, 0, 41, 0, 0, 0, 0, 0 },
/* t */ { 2, 0, 19, 0, 24, 26, 0, 27, 0, 28, 0, 29, 33, 36, 38, 39, 0, 40, 42, 0, 43, 0, 0, 0, 0, 0 },
/* u */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* v */ { 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 12, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0 },
/* w */ { 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 8, 0, 9, 10, 0, 0, 0, 12, 13, 0, 0, 0, 0 },
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

static const int command_count = 548;
static const int command_count = 550;

0 comments on commit 00aa069

Please sign in to comment.
You can’t perform that action at this time.