Skip to content

Commit c970330

Browse files
committed
patch 7.4.1126
Problem: Can only get the directory of the current window. Solution: Add window and tab arguments to getcwd() and haslocaldir(). (Thinca, Hirohito Higashi)
1 parent e9b892e commit c970330

File tree

7 files changed

+218
-52
lines changed

7 files changed

+218
-52
lines changed

runtime/doc/eval.txt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,7 @@ getcmdpos() Number return cursor position in command-line
18511851
getcmdtype() String return current command-line type
18521852
getcmdwintype() String return current command-line window type
18531853
getcurpos() List position of the cursor
1854-
getcwd() String the current working directory
1854+
getcwd( [{winnr} [, {tabnr}]]) String get the current working directory
18551855
getfontname( [{name}]) String name of font being used
18561856
getfperm( {fname}) String file permissions of file {fname}
18571857
getfsize( {fname}) Number size in bytes of file {fname}
@@ -1882,7 +1882,8 @@ globpath( {path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]])
18821882
String do glob({expr}) for all dirs in {path}
18831883
has( {feature}) Number TRUE if feature {feature} supported
18841884
has_key( {dict}, {key}) Number TRUE if {dict} has entry {key}
1885-
haslocaldir() Number TRUE if current window executed |:lcd|
1885+
haslocaldir( [{winnr} [, {tabnr}]])
1886+
Number TRUE if the window executed |:lcd|
18861887
hasmapto( {what} [, {mode} [, {abbr}]])
18871888
Number TRUE if mapping to {what} exists
18881889
histadd( {history},{item}) String add an item to a history
@@ -3522,8 +3523,16 @@ getcurpos() Get the position of the cursor. This is like getpos('.'), but
35223523
call setpos('.', save_cursor)
35233524
<
35243525
*getcwd()*
3525-
getcwd() The result is a String, which is the name of the current
3526+
getcwd([{winnr} [, {tabnr}]])
3527+
The result is a String, which is the name of the current
35263528
working directory.
3529+
Without arguments, for the current window.
3530+
3531+
With {winnr} return the local current directory of this window
3532+
in the current tab page.
3533+
With {winnr} and {tabnr} return the local current directory of
3534+
the window in the specified tab page.
3535+
Return an empty string if the arguments are invalid.
35273536

35283537
getfsize({fname}) *getfsize()*
35293538
The result is a Number, which is the size in bytes of the
@@ -3859,9 +3868,15 @@ has_key({dict}, {key}) *has_key()*
38593868
The result is a Number, which is 1 if |Dictionary| {dict} has
38603869
an entry with key {key}. Zero otherwise.
38613870

3862-
haslocaldir() *haslocaldir()*
3863-
The result is a Number, which is 1 when the current
3864-
window has set a local path via |:lcd|, and 0 otherwise.
3871+
haslocaldir([{winnr} [, {tabnr}]]) *haslocaldir()*
3872+
The result is a Number, which is 1 when the window has set a
3873+
local path via |:lcd|, and 0 otherwise.
3874+
3875+
Without arguments use the current window.
3876+
With {winnr} use this window in the current tab page.
3877+
With {winnr} and {tabnr} use the window in the specified tab
3878+
page.
3879+
Return 0 if the arguments are invalid.
38653880

38663881
hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()*
38673882
The result is a Number, which is 1 if there is a mapping that

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,6 +1946,7 @@ test1 \
19461946
test_erasebackword \
19471947
test_eval \
19481948
test_fixeol \
1949+
test_getcwd \
19491950
test_insertcount \
19501951
test_listchars \
19511952
test_listlbr \

src/eval.c

Lines changed: 74 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,7 @@ static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
861861
static void free_funccal __ARGS((funccall_T *fc, int free_val));
862862
static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
863863
static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp));
864+
static win_T *find_tabwin __ARGS((typval_T *wvp, typval_T *tvp));
864865
static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off));
865866
static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos));
866867
static int search_cmn __ARGS((typval_T *argvars, pos_T *match_pos, int *flagsp));
@@ -3687,7 +3688,7 @@ do_unlet_var(lp, name_end, forceit)
36873688
{
36883689
listitem_T *li;
36893690
listitem_T *ll_li = lp->ll_li;
3690-
int ll_n1 = lp->ll_n1;
3691+
int ll_n1 = lp->ll_n1;
36913692

36923693
while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1))
36933694
{
@@ -8183,7 +8184,7 @@ static struct fst
81838184
{"getcmdtype", 0, 0, f_getcmdtype},
81848185
{"getcmdwintype", 0, 0, f_getcmdwintype},
81858186
{"getcurpos", 0, 0, f_getcurpos},
8186-
{"getcwd", 0, 0, f_getcwd},
8187+
{"getcwd", 0, 2, f_getcwd},
81878188
{"getfontname", 0, 1, f_getfontname},
81888189
{"getfperm", 1, 1, f_getfperm},
81898190
{"getfsize", 1, 1, f_getfsize},
@@ -8207,7 +8208,7 @@ static struct fst
82078208
{"globpath", 2, 5, f_globpath},
82088209
{"has", 1, 1, f_has},
82098210
{"has_key", 2, 2, f_has_key},
8210-
{"haslocaldir", 0, 0, f_haslocaldir},
8211+
{"haslocaldir", 0, 2, f_haslocaldir},
82118212
{"hasmapto", 1, 3, f_hasmapto},
82128213
{"highlightID", 1, 1, f_hlID}, /* obsolete */
82138214
{"highlight_exists",1, 1, f_hlexists}, /* obsolete */
@@ -9127,30 +9128,11 @@ f_arglistid(argvars, rettv)
91279128
typval_T *rettv;
91289129
{
91299130
win_T *wp;
9130-
tabpage_T *tp = NULL;
9131-
long n;
91329131

91339132
rettv->vval.v_number = -1;
9134-
if (argvars[0].v_type != VAR_UNKNOWN)
9135-
{
9136-
if (argvars[1].v_type != VAR_UNKNOWN)
9137-
{
9138-
n = get_tv_number(&argvars[1]);
9139-
if (n >= 0)
9140-
tp = find_tabpage(n);
9141-
}
9142-
else
9143-
tp = curtab;
9144-
9145-
if (tp != NULL)
9146-
{
9147-
wp = find_win_by_nr(&argvars[0], tp);
9148-
if (wp != NULL)
9149-
rettv->vval.v_number = wp->w_alist->id;
9150-
}
9151-
}
9152-
else
9153-
rettv->vval.v_number = curwin->w_alist->id;
9133+
wp = find_tabwin(&argvars[0], &argvars[1]);
9134+
if (wp != NULL)
9135+
rettv->vval.v_number = wp->w_alist->id;
91549136
}
91559137

91569138
/*
@@ -12061,25 +12043,36 @@ f_getcmdwintype(argvars, rettv)
1206112043
*/
1206212044
static void
1206312045
f_getcwd(argvars, rettv)
12064-
typval_T *argvars UNUSED;
12046+
typval_T *argvars;
1206512047
typval_T *rettv;
1206612048
{
12049+
win_T *wp = NULL;
1206712050
char_u *cwd;
1206812051

1206912052
rettv->v_type = VAR_STRING;
1207012053
rettv->vval.v_string = NULL;
12071-
cwd = alloc(MAXPATHL);
12072-
if (cwd != NULL)
12054+
12055+
wp = find_tabwin(&argvars[0], &argvars[1]);
12056+
if (wp != NULL)
1207312057
{
12074-
if (mch_dirname(cwd, MAXPATHL) != FAIL)
12058+
if (wp->w_localdir != NULL)
12059+
rettv->vval.v_string = vim_strsave(wp->w_localdir);
12060+
else if(globaldir != NULL)
12061+
rettv->vval.v_string = vim_strsave(globaldir);
12062+
else
1207512063
{
12076-
rettv->vval.v_string = vim_strsave(cwd);
12064+
cwd = alloc(MAXPATHL);
12065+
if (cwd != NULL)
12066+
{
12067+
if (mch_dirname(cwd, MAXPATHL) != FAIL)
12068+
rettv->vval.v_string = vim_strsave(cwd);
12069+
vim_free(cwd);
12070+
}
12071+
}
1207712072
#ifdef BACKSLASH_IN_FILENAME
12078-
if (rettv->vval.v_string != NULL)
12079-
slash_adjust(rettv->vval.v_string);
12073+
if (rettv->vval.v_string != NULL)
12074+
slash_adjust(rettv->vval.v_string);
1208012075
#endif
12081-
}
12082-
vim_free(cwd);
1208312076
}
1208412077
}
1208512078

@@ -12708,6 +12701,38 @@ find_win_by_nr(vp, tp)
1270812701
#endif
1270912702
}
1271012703

12704+
/*
12705+
* Find window specified by "wvp" in tabpage "tvp".
12706+
*/
12707+
static win_T *
12708+
find_tabwin(wvp, tvp)
12709+
typval_T *wvp; /* VAR_UNKNOWN for current window */
12710+
typval_T *tvp; /* VAR_UNKNOWN for current tab page */
12711+
{
12712+
win_T *wp = NULL;
12713+
tabpage_T *tp = NULL;
12714+
long n;
12715+
12716+
if (wvp->v_type != VAR_UNKNOWN)
12717+
{
12718+
if (tvp->v_type != VAR_UNKNOWN)
12719+
{
12720+
n = get_tv_number(tvp);
12721+
if (n >= 0)
12722+
tp = find_tabpage(n);
12723+
}
12724+
else
12725+
tp = curtab;
12726+
12727+
if (tp != NULL)
12728+
wp = find_win_by_nr(wvp, tp);
12729+
}
12730+
else
12731+
wp = curwin;
12732+
12733+
return wp;
12734+
}
12735+
1271112736
/*
1271212737
* "getwinvar()" function
1271312738
*/
@@ -13543,10 +13568,13 @@ f_has_key(argvars, rettv)
1354313568
*/
1354413569
static void
1354513570
f_haslocaldir(argvars, rettv)
13546-
typval_T *argvars UNUSED;
13571+
typval_T *argvars;
1354713572
typval_T *rettv;
1354813573
{
13549-
rettv->vval.v_number = (curwin->w_localdir != NULL);
13574+
win_T *wp = NULL;
13575+
13576+
wp = find_tabwin(&argvars[0], &argvars[1]);
13577+
rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL);
1355013578
}
1355113579

1355213580
/*
@@ -21851,15 +21879,15 @@ get_funccal()
2185121879
funccal = current_funccal;
2185221880
if (debug_backtrace_level > 0)
2185321881
{
21854-
for (i = 0; i < debug_backtrace_level; i++)
21855-
{
21856-
temp_funccal = funccal->caller;
21857-
if (temp_funccal)
21858-
funccal = temp_funccal;
21882+
for (i = 0; i < debug_backtrace_level; i++)
21883+
{
21884+
temp_funccal = funccal->caller;
21885+
if (temp_funccal)
21886+
funccal = temp_funccal;
2185921887
else
21860-
/* backtrace level overflow. reset to max */
21861-
debug_backtrace_level = i;
21862-
}
21888+
/* backtrace level overflow. reset to max */
21889+
debug_backtrace_level = i;
21890+
}
2186321891
}
2186421892
return funccal;
2186521893
}
@@ -23379,8 +23407,8 @@ ex_function(eap)
2337923407
* Also handles a Funcref in a List or Dictionary.
2338023408
* Returns the function name in allocated memory, or NULL for failure.
2338123409
* flags:
23382-
* TFN_INT: internal function name OK
23383-
* TFN_QUIET: be quiet
23410+
* TFN_INT: internal function name OK
23411+
* TFN_QUIET: be quiet
2338423412
* TFN_NO_AUTOLOAD: do not use script autoloading
2338523413
* Advances "pp" to just after the function name (if no error).
2338623414
*/

src/testdir/Make_all.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ SCRIPTS_ALL = \
103103
test_erasebackword.out \
104104
test_eval.out \
105105
test_fixeol.out \
106+
test_getcwd.out \
106107
test_insertcount.out \
107108
test_listchars.out \
108109
test_listlbr.out \

src/testdir/test_getcwd.in

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Tests for getcwd(), haslocaldir(), and :lcd vim: set ft=vim :
2+
3+
STARTTEST
4+
:so small.vim
5+
:" Do all test in a separate window to avoid E211 when we recursively
6+
:" delete the Xtopdir directory during cleanup
7+
:"
8+
:" This will cause a few errors, do it silently.
9+
:set visualbell
10+
:set nocp viminfo+=nviminfo
11+
:"
12+
:function! DeleteDirectory(dir)
13+
: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32")
14+
: exec "silent !rmdir /Q /S " . a:dir
15+
: else
16+
: exec "silent !rm -rf " . a:dir
17+
: endif
18+
:endfun
19+
:"
20+
:function! GetCwdInfo(win, tab)
21+
: let tab_changed = 0
22+
: let mod = ":t"
23+
: if a:tab > 0 && a:tab != tabpagenr()
24+
: let tab_changed = 1
25+
: exec "tabnext " . a:tab
26+
: endif
27+
: let bufname = fnamemodify(bufname(winbufnr(a:win)), mod)
28+
: if tab_changed
29+
: tabprevious
30+
: endif
31+
: if a:win == 0 && a:tab == 0
32+
: let dirname = fnamemodify(getcwd(), mod)
33+
: let lflag = haslocaldir()
34+
: elseif a:tab == 0
35+
: let dirname = fnamemodify(getcwd(a:win), mod)
36+
: let lflag = haslocaldir(a:win)
37+
: else
38+
: let dirname = fnamemodify(getcwd(a:win, a:tab), mod)
39+
: let lflag = haslocaldir(a:win, a:tab)
40+
: endif
41+
: return bufname . ' ' . dirname . ' ' . lflag
42+
:endfunction
43+
:" On windows a stale "Xtopdir" directory may exist, remove it so that
44+
:" we start from a clean state.
45+
:call DeleteDirectory("Xtopdir")
46+
:let r=[]
47+
:new
48+
:let cwd=getcwd()
49+
:let test_out = cwd . '/test.out'
50+
:call mkdir('Xtopdir')
51+
:cd Xtopdir
52+
:call mkdir('Xdir1')
53+
:call mkdir('Xdir2')
54+
:call mkdir('Xdir3')
55+
:new a
56+
:new b
57+
:new c
58+
:3wincmd w
59+
:lcd Xdir1
60+
:call add(r, GetCwdInfo(0, 0))
61+
:wincmd W
62+
:call add(r, GetCwdInfo(0, 0))
63+
:wincmd W
64+
:lcd Xdir3
65+
:call add(r, GetCwdInfo(0, 0))
66+
:call add(r, GetCwdInfo(bufwinnr("a"), 0))
67+
:call add(r, GetCwdInfo(bufwinnr("b"), 0))
68+
:call add(r, GetCwdInfo(bufwinnr("c"), 0))
69+
:wincmd W
70+
:call add(r, GetCwdInfo(bufwinnr("a"), tabpagenr()))
71+
:call add(r, GetCwdInfo(bufwinnr("b"), tabpagenr()))
72+
:call add(r, GetCwdInfo(bufwinnr("c"), tabpagenr()))
73+
:"
74+
:tabnew x
75+
:new y
76+
:new z
77+
:3wincmd w
78+
:call add(r, GetCwdInfo(0, 0))
79+
:wincmd W
80+
:lcd Xdir2
81+
:call add(r, GetCwdInfo(0, 0))
82+
:wincmd W
83+
:lcd Xdir3
84+
:call add(r, GetCwdInfo(0, 0))
85+
:call add(r, GetCwdInfo(bufwinnr("x"), 0))
86+
:call add(r, GetCwdInfo(bufwinnr("y"), 0))
87+
:call add(r, GetCwdInfo(bufwinnr("z"), 0))
88+
:let tp_nr = tabpagenr()
89+
:tabrewind
90+
:call add(r, GetCwdInfo(3, tp_nr))
91+
:call add(r, GetCwdInfo(2, tp_nr))
92+
:call add(r, GetCwdInfo(1, tp_nr))
93+
:"
94+
:call writefile(r, test_out, "a")
95+
:q
96+
:exec "cd " . cwd
97+
:call DeleteDirectory("Xtopdir")
98+
:qa!
99+
ENDTEST
100+
101+

src/testdir/test_getcwd.ok

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
a Xdir1 1
2+
b Xtopdir 0
3+
c Xdir3 1
4+
a Xdir1 1
5+
b Xtopdir 0
6+
c Xdir3 1
7+
a Xdir1 1
8+
b Xtopdir 0
9+
c Xdir3 1
10+
x Xtopdir 0
11+
y Xdir2 1
12+
z Xdir3 1
13+
x Xtopdir 0
14+
y Xdir2 1
15+
z Xdir3 1
16+
x Xtopdir 0
17+
y Xdir2 1
18+
z Xdir3 1

0 commit comments

Comments
 (0)