Skip to content

Commit 00aa069

Browse files
committed
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)
1 parent 2155a6a commit 00aa069

File tree

20 files changed

+441
-66
lines changed

20 files changed

+441
-66
lines changed

runtime/doc/autocmd.txt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*autocmd.txt* For Vim version 8.1. Last change: 2019 Apr 08
1+
*autocmd.txt* For Vim version 8.1. Last change: 2019 Apr 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -690,13 +690,14 @@ DiffUpdated After diffs have been updated. Depending on
690690
change or when doing |:diffupdate|.
691691
*DirChanged*
692692
DirChanged The working directory has changed in response
693-
to the |:cd| or |:lcd| commands, or as a
694-
result of the 'autochdir' option.
693+
to the |:cd| or |:tcd| or |:lcd| commands, or
694+
as a result of the 'autochdir' option.
695695
The pattern can be:
696-
"window" to trigger on `:lcd`
697-
"global" to trigger on `:cd`
698-
"auto" to trigger on 'autochdir'.
699-
"drop" to trigger on editing a file
696+
"window" to trigger on `:lcd`
697+
"tabpage" to trigger on `:tcd`
698+
"global" to trigger on `:cd`
699+
"auto" to trigger on 'autochdir'.
700+
"drop" to trigger on editing a file
700701
<afile> is set to the new directory name.
701702
*ExitPre*
702703
ExitPre When using `:quit`, `:wq` in a way it makes

runtime/doc/editing.txt

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,9 +1304,10 @@ use has("browsefilter"): >
13041304
==============================================================================
13051305
7. The current directory *current-directory*
13061306

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

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

1338+
*:tcd*
1339+
:tcd[!] {path} Like |:cd|, but only set the directory for the current
1340+
tab. The current window will also use this directory.
1341+
The current directory is not changed for windows in
1342+
other tabs and for windows in the current tab that
1343+
have their own window-local directory.
1344+
{not in Vi}
1345+
1346+
*:tch* *:tchdir*
1347+
:tch[dir][!] Same as |:tcd|. {not in Vi}
1348+
13371349
*:lc* *:lcd*
13381350
:lc[d][!] {path} Like |:cd|, but only set the current directory when
13391351
the cursor is in the current window. The current
@@ -1348,17 +1360,26 @@ present in 'cpoptions' and "!" is not used in the command.
13481360
:pw[d] Print the current directory name. {Vi: no pwd}
13491361
Also see |getcwd()|.
13501362

1351-
So long as no |:lcd| command has been used, all windows share the same current
1352-
directory. Using a command to jump to another window doesn't change anything
1353-
for the current directory.
1363+
So long as no |:lcd| or |:tcd| command has been used, all windows share the
1364+
same current directory. Using a command to jump to another window doesn't
1365+
change anything for the current directory.
1366+
13541367
When a |:lcd| command has been used for a window, the specified directory
13551368
becomes the current directory for that window. Windows where the |:lcd|
1356-
command has not been used stick to the global current directory. When jumping
1357-
to another window the current directory will become the last specified local
1358-
current directory. If none was specified, the global current directory is
1359-
used.
1360-
When a |:cd| command is used, the current window will lose his local current
1361-
directory and will use the global current directory from now on.
1369+
command has not been used stick to the global or tab-local current directory.
1370+
When jumping to another window the current directory will become the last
1371+
specified local current directory. If none was specified, the global or
1372+
tab-local current directory is used.
1373+
1374+
When a |:tcd| command has been used for a tab page, the specified directory
1375+
becomes the current directory for the current tab page and the current window.
1376+
The current directory of other tab pages is not affected. When jumping to
1377+
another tab page, the current directory will become the last specified local
1378+
directory for that tab page. If the current tab has no local current directory
1379+
the global current directory is used.
1380+
1381+
When a |:cd| command is used, the current window and tab page will lose the
1382+
local current directory and will use the global current directory from now on.
13621383

13631384
After using |:cd| the full path name will be used for reading and writing
13641385
files. On some networked file systems this may cause problems. The result of

runtime/doc/eval.txt

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,7 @@ has({feature}) Number |TRUE| if feature {feature} supported
23982398
has_key({dict}, {key}) Number |TRUE| if {dict} has entry {key}
23992399
haslocaldir([{winnr} [, {tabnr}]])
24002400
Number |TRUE| if the window executed |:lcd|
2401+
or |:tcd|
24012402
hasmapto({what} [, {mode} [, {abbr}]])
24022403
Number |TRUE| if mapping to {what} exists
24032404
histadd({history}, {item}) String add an item to a history
@@ -4918,9 +4919,28 @@ getcwd([{winnr} [, {tabnr}]])
49184919
directory. See also |haslocaldir()|.
49194920

49204921
With {winnr} and {tabnr} return the local current directory of
4921-
the window in the specified tab page.
4922+
the window in the specified tab page. If {winnr} is -1 return
4923+
the working directory of the tabpage.
4924+
If {winnr} is zero use the current window, if {tabnr} is zero
4925+
use the current tabpage.
4926+
Without any arguments, return the working directory of the
4927+
current window.
49224928
Return an empty string if the arguments are invalid.
49234929

4930+
Examples: >
4931+
" Get the working directory of the current window
4932+
:echo getcwd()
4933+
:echo getcwd(0)
4934+
:echo getcwd(0, 0)
4935+
" Get the working directory of window 3 in tabpage 2
4936+
:echo getcwd(3, 2)
4937+
" Get the global working directory
4938+
:echo getcwd(-1)
4939+
" Get the working directory of tabpage 3
4940+
:echo getcwd(-1, 3)
4941+
" Get the working directory of current tabpage
4942+
:echo getcwd(-1, 0)
4943+
<
49244944
getfsize({fname}) *getfsize()*
49254945
The result is a Number, which is the size in bytes of the
49264946
given file {fname}.
@@ -5478,16 +5498,39 @@ has_key({dict}, {key}) *has_key()*
54785498
an entry with key {key}. Zero otherwise.
54795499

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

54845506
Without arguments use the current window.
54855507
With {winnr} use this window in the current tab page.
54865508
With {winnr} and {tabnr} use the window in the specified tab
54875509
page.
54885510
{winnr} can be the window number or the |window-ID|.
5511+
If {winnr} is -1 it is ignored and only the tabpage is used.
54895512
Return 0 if the arguments are invalid.
5513+
Examples: >
5514+
if haslocaldir() == 1
5515+
" window local directory case
5516+
elseif haslocaldir() == 2
5517+
" tab-local directory case
5518+
else
5519+
" global directory case
5520+
endif
54905521
5522+
" current window
5523+
:echo haslocaldir()
5524+
:echo haslocaldir(0)
5525+
:echo haslocaldir(0, 0)
5526+
" window n in current tab page
5527+
:echo haslocaldir(n)
5528+
:echo haslocaldir(n, 0)
5529+
" window n in tab page m
5530+
:echo haslocaldir(n, m)
5531+
" tab page m
5532+
:echo haslocaldir(-1, m)
5533+
<
54915534
hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()*
54925535
The result is a Number, which is 1 if there is a mapping that
54935536
contains {what} in somewhere in the rhs (what it is mapped to)

runtime/doc/index.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,8 @@ tag command action ~
16231623
|:tab| :tab create new tab when opening new window
16241624
|:tag| :ta[g] jump to tag
16251625
|:tags| :tags show the contents of the tag stack
1626+
|:tcd| :tcd change directory for tab page
1627+
|:tchdir| :tch[dir] change directory for tab page
16261628
|:tcl| :tc[l] execute Tcl command
16271629
|:tcldo| :tcld[o] execute Tcl command for each line
16281630
|:tclfile| :tclf[ile] execute Tcl script file

runtime/doc/options.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,9 +1455,9 @@ A jump table for the options with a short description can be found at |Q_op|.
14551455
{not available when compiled without the
14561456
|+file_in_path| feature}
14571457
This is a list of directories which will be searched when using the
1458-
|:cd| and |:lcd| commands, provided that the directory being searched
1459-
for has a relative path, not an absolute part starting with "/", "./"
1460-
or "../", the 'cdpath' option is not used then.
1458+
|:cd|, |:tcd| and |:lcd| commands, provided that the directory being
1459+
searched for has a relative path, not an absolute part starting with
1460+
"/", "./" or "../", the 'cdpath' option is not used then.
14611461
The 'cdpath' option's value has the same form and semantics as
14621462
|'path'|. Also see |file-searching|.
14631463
The default value is taken from $CDPATH, with a "," prepended to look

runtime/doc/usr_22.txt

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,28 @@ the other window. This is called a local directory. >
202202
:pwd
203203
/home/Bram/VeryLongFileName
204204
205-
So long as no ":lcd" command has been used, all windows share the same current
206-
directory. Doing a ":cd" command in one window will also change the current
205+
So long as no `:lcd` command has been used, all windows share the same current
206+
directory. Doing a `:cd` command in one window will also change the current
207207
directory of the other window.
208-
For a window where ":lcd" has been used a different current directory is
209-
remembered. Using ":cd" or ":lcd" in other windows will not change it.
210-
When using a ":cd" command in a window that uses a different current
208+
For a window where `:lcd` has been used a different current directory is
209+
remembered. Using `:cd` or `:lcd` in other windows will not change it.
210+
When using a `:cd` command in a window that uses a different current
211211
directory, it will go back to using the shared directory.
212212

213+
214+
TAB LOCAL DIRECTORY
215+
216+
When you open a new tab page, it uses the directory of the window in the
217+
previous tab page from which the new tab page was opened. You can change the
218+
directory of the current tab page using the `:tcd` command. All the windows in
219+
a tab page share this directory except for windows with a window-local
220+
directory. Any new windows opened in this tab page will use this directory as
221+
the current working directory. Using a `:cd` command in a tab page will not
222+
change the working directory of tab pages which have a tab local directory.
223+
When the global working directory is changed using the ":cd" command in a tab
224+
page, it will also change the current tab page working directory.
225+
226+
213227
==============================================================================
214228
*22.3* Finding a file
215229

runtime/doc/usr_41.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ System functions and manipulation of files:
766766
isdirectory() check if a directory exists
767767
getfsize() get the size of a file
768768
getcwd() get the current working directory
769-
haslocaldir() check if current window used |:lcd|
769+
haslocaldir() check if current window used |:lcd| or |:tcd|
770770
tempname() get the name of a temporary file
771771
mkdir() create a new directory
772772
delete() delete a file

src/eval.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8704,11 +8704,13 @@ find_win_by_nr_or_id(typval_T *vp)
87048704

87058705
/*
87068706
* Find window specified by "wvp" in tabpage "tvp".
8707+
* Returns the tab page in 'ptp'
87078708
*/
87088709
win_T *
87098710
find_tabwin(
8710-
typval_T *wvp, /* VAR_UNKNOWN for current window */
8711-
typval_T *tvp) /* VAR_UNKNOWN for current tab page */
8711+
typval_T *wvp, // VAR_UNKNOWN for current window
8712+
typval_T *tvp, // VAR_UNKNOWN for current tab page
8713+
tabpage_T **ptp)
87128714
{
87138715
win_T *wp = NULL;
87148716
tabpage_T *tp = NULL;
@@ -8726,10 +8728,22 @@ find_tabwin(
87268728
tp = curtab;
87278729

87288730
if (tp != NULL)
8731+
{
87298732
wp = find_win_by_nr(wvp, tp);
8733+
if (wp == NULL && wvp->v_type == VAR_NUMBER
8734+
&& wvp->vval.v_number != -1)
8735+
// A window with the specified number is not found
8736+
tp = NULL;
8737+
}
87308738
}
87318739
else
8740+
{
87328741
wp = curwin;
8742+
tp = curtab;
8743+
}
8744+
8745+
if (ptp != NULL)
8746+
*ptp = tp;
87338747

87348748
return wp;
87358749
}

src/evalfunc.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,7 +1529,7 @@ f_arglistid(typval_T *argvars, typval_T *rettv)
15291529
win_T *wp;
15301530

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

51275127
/*
51285128
* "getcwd()" function
5129+
*
5130+
* Return the current working directory of a window in a tab page.
5131+
* First optional argument 'winnr' is the window number or -1 and the second
5132+
* optional argument 'tabnr' is the tab page number.
5133+
*
5134+
* If no arguments are supplied, then return the directory of the current
5135+
* window.
5136+
* If only 'winnr' is specified and is not -1 or 0 then return the directory of
5137+
* the specified window.
5138+
* If 'winnr' is 0 then return the directory of the current window.
5139+
* If both 'winnr and 'tabnr' are specified and 'winnr' is -1 then return the
5140+
* directory of the specified tab page. Otherwise return the directory of the
5141+
* specified window in the specified tab page.
5142+
* If the window or the tab page doesn't exist then return NULL.
51295143
*/
51305144
static void
51315145
f_getcwd(typval_T *argvars, typval_T *rettv)
51325146
{
51335147
win_T *wp = NULL;
5148+
tabpage_T *tp = NULL;
51345149
char_u *cwd;
51355150
int global = FALSE;
51365151

51375152
rettv->v_type = VAR_STRING;
51385153
rettv->vval.v_string = NULL;
51395154

5140-
if (argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number == -1)
5155+
if (argvars[0].v_type == VAR_NUMBER
5156+
&& argvars[0].vval.v_number == -1
5157+
&& argvars[1].v_type == VAR_UNKNOWN)
51415158
global = TRUE;
51425159
else
5143-
wp = find_tabwin(&argvars[0], &argvars[1]);
5160+
wp = find_tabwin(&argvars[0], &argvars[1], &tp);
51445161

51455162
if (wp != NULL && wp->w_localdir != NULL)
51465163
rettv->vval.v_string = vim_strsave(wp->w_localdir);
5147-
else if (wp != NULL || global)
5164+
else if (tp != NULL && tp->tp_localdir != NULL)
5165+
rettv->vval.v_string = vim_strsave(tp->tp_localdir);
5166+
else if (wp != NULL || tp != NULL || global)
51485167
{
51495168
if (globaldir != NULL)
51505169
rettv->vval.v_string = vim_strsave(globaldir);
@@ -5333,7 +5352,7 @@ f_getjumplist(typval_T *argvars, typval_T *rettv)
53335352
return;
53345353

53355354
#ifdef FEAT_JUMPLIST
5336-
wp = find_tabwin(&argvars[0], &argvars[1]);
5355+
wp = find_tabwin(&argvars[0], &argvars[1], NULL);
53375356
if (wp == NULL)
53385357
return;
53395358

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

6829-
wp = find_tabwin(&argvars[0], &argvars[1]);
6830-
rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL);
6849+
wp = find_tabwin(&argvars[0], &argvars[1], &tp);
6850+
6851+
// Check for window-local and tab-local directories
6852+
if (wp != NULL && wp->w_localdir != NULL)
6853+
rettv->vval.v_number = 1;
6854+
else if (tp != NULL && tp->tp_localdir != NULL)
6855+
rettv->vval.v_number = 2;
6856+
else
6857+
rettv->vval.v_number = 0;
68316858
}
68326859

68336860
/*

src/ex_cmdidxs.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ static const unsigned short cmdidxs1[26] =
2525
/* r */ 351,
2626
/* s */ 371,
2727
/* t */ 439,
28-
/* u */ 482,
29-
/* v */ 493,
30-
/* w */ 511,
31-
/* x */ 525,
32-
/* y */ 534,
33-
/* z */ 535
28+
/* u */ 484,
29+
/* v */ 495,
30+
/* w */ 513,
31+
/* x */ 527,
32+
/* y */ 536,
33+
/* z */ 537
3434
};
3535

3636
/*
@@ -60,7 +60,7 @@ static const unsigned char cmdidxs2[26][26] =
6060
/* 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 },
6161
/* 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 },
6262
/* 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 },
63-
/* 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 },
63+
/* 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 },
6464
/* 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 },
6565
/* 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 },
6666
/* 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] =
6969
/* 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 }
7070
};
7171

72-
static const int command_count = 548;
72+
static const int command_count = 550;

0 commit comments

Comments
 (0)