# HG changeset patch # User Christian Brabandt # Date 1453064405 -3600 # Node ID d4370fef0175025571c350103e98667b6e2dec96 # Parent a6555549858df88edb6ef92a7c89c648702bac2e commit https://github.com/vim/vim/commit/c970330676eaae7ba7cd05cfa46df5a413853ef9 Author: Bram Moolenaar Date: Sun Jan 17 21:49:33 2016 +0100 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) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1851,7 +1851,7 @@ getcmdpos() Number return cursor posit getcmdtype() String return current command-line type getcmdwintype() String return current command-line window type getcurpos() List position of the cursor -getcwd() String the current working directory +getcwd( [{winnr} [, {tabnr}]]) String get the current working directory getfontname( [{name}]) String name of font being used getfperm( {fname}) String file permissions of file {fname} getfsize( {fname}) Number size in bytes of file {fname} @@ -1882,7 +1882,8 @@ globpath( {path}, {expr} [, {nosuf} [, { String do glob({expr}) for all dirs in {path} has( {feature}) Number TRUE if feature {feature} supported has_key( {dict}, {key}) Number TRUE if {dict} has entry {key} -haslocaldir() Number TRUE if current window executed |:lcd| +haslocaldir( [{winnr} [, {tabnr}]]) + Number TRUE if the window executed |:lcd| hasmapto( {what} [, {mode} [, {abbr}]]) Number TRUE if mapping to {what} exists histadd( {history},{item}) String add an item to a history @@ -3522,8 +3523,16 @@ getcurpos() Get the position of the curs call setpos('.', save_cursor) < *getcwd()* -getcwd() The result is a String, which is the name of the current +getcwd([{winnr} [, {tabnr}]]) + The result is a String, which is the name of the current working directory. + Without arguments, for the current window. + + With {winnr} return the local current directory of this window + in the current tab page. + With {winnr} and {tabnr} return the local current directory of + the window in the specified tab page. + Return an empty string if the arguments are invalid. getfsize({fname}) *getfsize()* The result is a Number, which is the size in bytes of the @@ -3859,9 +3868,15 @@ has_key({dict}, {key}) *has_key()* The result is a Number, which is 1 if |Dictionary| {dict} has an entry with key {key}. Zero otherwise. -haslocaldir() *haslocaldir()* - The result is a Number, which is 1 when the current - window has set a local path via |:lcd|, and 0 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. + + 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. + Return 0 if the arguments are invalid. hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()* The result is a Number, which is 1 if there is a mapping that diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile @@ -1946,6 +1946,7 @@ test1 \ test_erasebackword \ test_eval \ test_fixeol \ + test_getcwd \ test_insertcount \ test_listchars \ test_listlbr \ diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -861,6 +861,7 @@ static int can_free_funccal __ARGS((func static void free_funccal __ARGS((funccall_T *fc, int free_val)); static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)); static win_T *find_win_by_nr __ARGS((typval_T *vp, tabpage_T *tp)); +static win_T *find_tabwin __ARGS((typval_T *wvp, typval_T *tvp)); static void getwinvar __ARGS((typval_T *argvars, typval_T *rettv, int off)); static int searchpair_cmn __ARGS((typval_T *argvars, pos_T *match_pos)); 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) { listitem_T *li; listitem_T *ll_li = lp->ll_li; - int ll_n1 = lp->ll_n1; + int ll_n1 = lp->ll_n1; while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) { @@ -8183,7 +8184,7 @@ static struct fst {"getcmdtype", 0, 0, f_getcmdtype}, {"getcmdwintype", 0, 0, f_getcmdwintype}, {"getcurpos", 0, 0, f_getcurpos}, - {"getcwd", 0, 0, f_getcwd}, + {"getcwd", 0, 2, f_getcwd}, {"getfontname", 0, 1, f_getfontname}, {"getfperm", 1, 1, f_getfperm}, {"getfsize", 1, 1, f_getfsize}, @@ -8207,7 +8208,7 @@ static struct fst {"globpath", 2, 5, f_globpath}, {"has", 1, 1, f_has}, {"has_key", 2, 2, f_has_key}, - {"haslocaldir", 0, 0, f_haslocaldir}, + {"haslocaldir", 0, 2, f_haslocaldir}, {"hasmapto", 1, 3, f_hasmapto}, {"highlightID", 1, 1, f_hlID}, /* obsolete */ {"highlight_exists",1, 1, f_hlexists}, /* obsolete */ @@ -9127,30 +9128,11 @@ f_arglistid(argvars, rettv) typval_T *rettv; { win_T *wp; - tabpage_T *tp = NULL; - long n; rettv->vval.v_number = -1; - if (argvars[0].v_type != VAR_UNKNOWN) - { - if (argvars[1].v_type != VAR_UNKNOWN) - { - n = get_tv_number(&argvars[1]); - if (n >= 0) - tp = find_tabpage(n); - } - else - tp = curtab; - - if (tp != NULL) - { - wp = find_win_by_nr(&argvars[0], tp); - if (wp != NULL) - rettv->vval.v_number = wp->w_alist->id; - } - } - else - rettv->vval.v_number = curwin->w_alist->id; + wp = find_tabwin(&argvars[0], &argvars[1]); + if (wp != NULL) + rettv->vval.v_number = wp->w_alist->id; } /* @@ -12061,25 +12043,36 @@ f_getcmdwintype(argvars, rettv) */ static void f_getcwd(argvars, rettv) - typval_T *argvars UNUSED; - typval_T *rettv; -{ + typval_T *argvars; + typval_T *rettv; +{ + win_T *wp = NULL; char_u *cwd; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - cwd = alloc(MAXPATHL); - if (cwd != NULL) - { - if (mch_dirname(cwd, MAXPATHL) != FAIL) - { - rettv->vval.v_string = vim_strsave(cwd); + + wp = find_tabwin(&argvars[0], &argvars[1]); + if (wp != NULL) + { + if (wp->w_localdir != NULL) + rettv->vval.v_string = vim_strsave(wp->w_localdir); + else if(globaldir != NULL) + rettv->vval.v_string = vim_strsave(globaldir); + else + { + cwd = alloc(MAXPATHL); + if (cwd != NULL) + { + if (mch_dirname(cwd, MAXPATHL) != FAIL) + rettv->vval.v_string = vim_strsave(cwd); + vim_free(cwd); + } + } #ifdef BACKSLASH_IN_FILENAME - if (rettv->vval.v_string != NULL) - slash_adjust(rettv->vval.v_string); -#endif - } - vim_free(cwd); + if (rettv->vval.v_string != NULL) + slash_adjust(rettv->vval.v_string); +#endif } } @@ -12709,6 +12702,38 @@ find_win_by_nr(vp, tp) } /* + * Find window specified by "wvp" in tabpage "tvp". + */ + static win_T * +find_tabwin(wvp, tvp) + typval_T *wvp; /* VAR_UNKNOWN for current window */ + typval_T *tvp; /* VAR_UNKNOWN for current tab page */ +{ + win_T *wp = NULL; + tabpage_T *tp = NULL; + long n; + + if (wvp->v_type != VAR_UNKNOWN) + { + if (tvp->v_type != VAR_UNKNOWN) + { + n = get_tv_number(tvp); + if (n >= 0) + tp = find_tabpage(n); + } + else + tp = curtab; + + if (tp != NULL) + wp = find_win_by_nr(wvp, tp); + } + else + wp = curwin; + + return wp; +} + +/* * "getwinvar()" function */ static void @@ -13543,10 +13568,13 @@ f_has_key(argvars, rettv) */ static void f_haslocaldir(argvars, rettv) - typval_T *argvars UNUSED; - typval_T *rettv; -{ - rettv->vval.v_number = (curwin->w_localdir != NULL); + typval_T *argvars; + typval_T *rettv; +{ + win_T *wp = NULL; + + wp = find_tabwin(&argvars[0], &argvars[1]); + rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL); } /* @@ -21851,15 +21879,15 @@ get_funccal() funccal = current_funccal; if (debug_backtrace_level > 0) { - for (i = 0; i < debug_backtrace_level; i++) - { - temp_funccal = funccal->caller; - if (temp_funccal) - funccal = temp_funccal; - else - /* backtrace level overflow. reset to max */ - debug_backtrace_level = i; - } + for (i = 0; i < debug_backtrace_level; i++) + { + temp_funccal = funccal->caller; + if (temp_funccal) + funccal = temp_funccal; + else + /* backtrace level overflow. reset to max */ + debug_backtrace_level = i; + } } return funccal; } @@ -23379,8 +23407,8 @@ ret_free: * Also handles a Funcref in a List or Dictionary. * Returns the function name in allocated memory, or NULL for failure. * flags: - * TFN_INT: internal function name OK - * TFN_QUIET: be quiet + * TFN_INT: internal function name OK + * TFN_QUIET: be quiet * TFN_NO_AUTOLOAD: do not use script autoloading * Advances "pp" to just after the function name (if no error). */ diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -103,6 +103,7 @@ SCRIPTS_ALL = \ test_erasebackword.out \ test_eval.out \ test_fixeol.out \ + test_getcwd.out \ test_insertcount.out \ test_listchars.out \ test_listlbr.out \ diff --git a/src/testdir/test_getcwd.in b/src/testdir/test_getcwd.in new file mode 100644 --- /dev/null +++ b/src/testdir/test_getcwd.in @@ -0,0 +1,101 @@ +Tests for getcwd(), haslocaldir(), and :lcd vim: set ft=vim : + +STARTTEST +:so small.vim +:" Do all test in a separate window to avoid E211 when we recursively +:" delete the Xtopdir directory during cleanup +:" +:" This will cause a few errors, do it silently. +:set visualbell +:set nocp viminfo+=nviminfo +:" +:function! DeleteDirectory(dir) +: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32") +: exec "silent !rmdir /Q /S " . a:dir +: else +: exec "silent !rm -rf " . a:dir +: endif +:endfun +:" +:function! GetCwdInfo(win, tab) +: let tab_changed = 0 +: let mod = ":t" +: if a:tab > 0 && a:tab != tabpagenr() +: let tab_changed = 1 +: exec "tabnext " . a:tab +: endif +: let bufname = fnamemodify(bufname(winbufnr(a:win)), mod) +: if tab_changed +: tabprevious +: endif +: if a:win == 0 && a:tab == 0 +: let dirname = fnamemodify(getcwd(), mod) +: let lflag = haslocaldir() +: elseif a:tab == 0 +: let dirname = fnamemodify(getcwd(a:win), mod) +: let lflag = haslocaldir(a:win) +: else +: let dirname = fnamemodify(getcwd(a:win, a:tab), mod) +: let lflag = haslocaldir(a:win, a:tab) +: endif +: return bufname . ' ' . dirname . ' ' . lflag +:endfunction +:" On windows a stale "Xtopdir" directory may exist, remove it so that +:" we start from a clean state. +:call DeleteDirectory("Xtopdir") +:let r=[] +:new +:let cwd=getcwd() +:let test_out = cwd . '/test.out' +:call mkdir('Xtopdir') +:cd Xtopdir +:call mkdir('Xdir1') +:call mkdir('Xdir2') +:call mkdir('Xdir3') +:new a +:new b +:new c +:3wincmd w +:lcd Xdir1 +:call add(r, GetCwdInfo(0, 0)) +:wincmd W +:call add(r, GetCwdInfo(0, 0)) +:wincmd W +:lcd Xdir3 +:call add(r, GetCwdInfo(0, 0)) +:call add(r, GetCwdInfo(bufwinnr("a"), 0)) +:call add(r, GetCwdInfo(bufwinnr("b"), 0)) +:call add(r, GetCwdInfo(bufwinnr("c"), 0)) +:wincmd W +:call add(r, GetCwdInfo(bufwinnr("a"), tabpagenr())) +:call add(r, GetCwdInfo(bufwinnr("b"), tabpagenr())) +:call add(r, GetCwdInfo(bufwinnr("c"), tabpagenr())) +:" +:tabnew x +:new y +:new z +:3wincmd w +:call add(r, GetCwdInfo(0, 0)) +:wincmd W +:lcd Xdir2 +:call add(r, GetCwdInfo(0, 0)) +:wincmd W +:lcd Xdir3 +:call add(r, GetCwdInfo(0, 0)) +:call add(r, GetCwdInfo(bufwinnr("x"), 0)) +:call add(r, GetCwdInfo(bufwinnr("y"), 0)) +:call add(r, GetCwdInfo(bufwinnr("z"), 0)) +:let tp_nr = tabpagenr() +:tabrewind +:call add(r, GetCwdInfo(3, tp_nr)) +:call add(r, GetCwdInfo(2, tp_nr)) +:call add(r, GetCwdInfo(1, tp_nr)) +:" +:call writefile(r, test_out, "a") +:q +:exec "cd " . cwd +:call DeleteDirectory("Xtopdir") +:qa! +ENDTEST + + diff --git a/src/testdir/test_getcwd.ok b/src/testdir/test_getcwd.ok new file mode 100644 --- /dev/null +++ b/src/testdir/test_getcwd.ok @@ -0,0 +1,18 @@ +a Xdir1 1 +b Xtopdir 0 +c Xdir3 1 +a Xdir1 1 +b Xtopdir 0 +c Xdir3 1 +a Xdir1 1 +b Xtopdir 0 +c Xdir3 1 +x Xtopdir 0 +y Xdir2 1 +z Xdir3 1 +x Xtopdir 0 +y Xdir2 1 +z Xdir3 1 +x Xtopdir 0 +y Xdir2 1 +z Xdir3 1 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1126, +/**/ 1125, /**/ 1124,