To: vim_dev@googlegroups.com Subject: Patch 7.4.1126 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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) Files: src/Makefile, src/testdir/Make_all.mak, src/testdir/test_getcwd.in, src/testdir/test_getcwd.ok, runtime/doc/eval.txt, patching file src/eval.c *** ../vim-7.4.1125/src/Makefile 2016-01-16 21:50:32.586161476 +0100 --- src/Makefile 2016-01-17 21:28:52.162346195 +0100 *************** *** 1946,1951 **** --- 1946,1952 ---- test_erasebackword \ test_eval \ test_fixeol \ + test_getcwd \ test_insertcount \ test_listchars \ test_listlbr \ *** ../vim-7.4.1125/src/testdir/Make_all.mak 2016-01-17 21:15:17.843322552 +0100 --- src/testdir/Make_all.mak 2016-01-17 21:29:08.646164479 +0100 *************** *** 103,108 **** --- 103,109 ---- test_erasebackword.out \ test_eval.out \ test_fixeol.out \ + test_getcwd.out \ test_insertcount.out \ test_listchars.out \ test_listlbr.out \ *** ../vim-7.4.1125/src/testdir/test_getcwd.in 2016-01-17 21:46:42.638552834 +0100 --- src/testdir/test_getcwd.in 2016-01-17 21:28:04.398872762 +0100 *************** *** 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 + + *** ../vim-7.4.1125/src/testdir/test_getcwd.ok 2016-01-17 21:46:42.646552746 +0100 --- src/testdir/test_getcwd.ok 2016-01-17 21:28:04.398872762 +0100 *************** *** 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 *** ../vim-7.4.1125/runtime/doc/eval.txt 2016-01-17 21:15:17.839322597 +0100 --- runtime/doc/eval.txt 2016-01-17 21:38:39.355875311 +0100 *************** *** 1842,1848 **** 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 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} --- 1851,1857 ---- getcmdtype() String return current command-line type getcmdwintype() String return current command-line window type getcurpos() List position of the cursor ! 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} *************** *** 1873,1879 **** 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| hasmapto( {what} [, {mode} [, {abbr}]]) Number TRUE if mapping to {what} exists histadd( {history},{item}) String add an item to a history --- 1882,1889 ---- 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( [{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 *************** *** 3466,3490 **** ? backward search command @ |input()| command - |:insert| or |:append| command Only works when editing the command line, thus requires use of |c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping. Returns an empty string otherwise. Also see |getcmdpos()|, |setcmdpos()| and |getcmdline()|. *getcurpos()* getcurpos() Get the position of the cursor. This is like getpos('.'), but includes an extra item in the list: ! [bufnum, lnum, col, off, curswant] The "curswant" number is the preferred column when moving the cursor vertically. This can be used to save and restore the cursor position: > let save_cursor = getcurpos() MoveTheCursorAround call setpos('.', save_cursor) ! *getcwd()* ! getcwd() The result is a String, which is the name of the current working directory. getfsize({fname}) *getfsize()* The result is a Number, which is the size in bytes of the --- 3500,3538 ---- ? backward search command @ |input()| command - |:insert| or |:append| command + = |i_CTRL-R_=| Only works when editing the command line, thus requires use of |c_CTRL-\_e| or |c_CTRL-R_=| or an expression mapping. Returns an empty string otherwise. Also see |getcmdpos()|, |setcmdpos()| and |getcmdline()|. + getcmdwintype() *getcmdwintype()* + Return the current |command-line-window| type. Possible return + values are the same as |getcmdtype()|. Returns an empty string + when not in the command-line window. + *getcurpos()* getcurpos() Get the position of the cursor. This is like getpos('.'), but includes an extra item in the list: ! [bufnum, lnum, col, off, curswant] ~ The "curswant" number is the preferred column when moving the cursor vertically. This can be used to save and restore the cursor position: > let save_cursor = getcurpos() MoveTheCursorAround call setpos('.', save_cursor) ! < *getcwd()* ! 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 *************** *** 3787,3795 **** 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. hasmapto({what} [, {mode} [, {abbr}]]) *hasmapto()* The result is a Number, which is 1 if there is a mapping that --- 3868,3882 ---- The result is a Number, which is 1 if |Dictionary| {dict} has 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. ! ! 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 *** ../vim-7.4.1125/src/eval.c 2016-01-17 21:15:17.843322552 +0100 --- src/eval.c 2016-01-17 21:33:57.878976609 +0100 *************** *** 861,866 **** --- 861,867 ---- 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,3693 **** { listitem_T *li; listitem_T *ll_li = lp->ll_li; ! int ll_n1 = lp->ll_n1; while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) { --- 3688,3694 ---- { listitem_T *li; listitem_T *ll_li = lp->ll_li; ! int ll_n1 = lp->ll_n1; while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) { *************** *** 8183,8189 **** {"getcmdtype", 0, 0, f_getcmdtype}, {"getcmdwintype", 0, 0, f_getcmdwintype}, {"getcurpos", 0, 0, f_getcurpos}, ! {"getcwd", 0, 0, f_getcwd}, {"getfontname", 0, 1, f_getfontname}, {"getfperm", 1, 1, f_getfperm}, {"getfsize", 1, 1, f_getfsize}, --- 8184,8190 ---- {"getcmdtype", 0, 0, f_getcmdtype}, {"getcmdwintype", 0, 0, f_getcmdwintype}, {"getcurpos", 0, 0, f_getcurpos}, ! {"getcwd", 0, 2, f_getcwd}, {"getfontname", 0, 1, f_getfontname}, {"getfperm", 1, 1, f_getfperm}, {"getfsize", 1, 1, f_getfsize}, *************** *** 8207,8213 **** {"globpath", 2, 5, f_globpath}, {"has", 1, 1, f_has}, {"has_key", 2, 2, f_has_key}, ! {"haslocaldir", 0, 0, f_haslocaldir}, {"hasmapto", 1, 3, f_hasmapto}, {"highlightID", 1, 1, f_hlID}, /* obsolete */ {"highlight_exists",1, 1, f_hlexists}, /* obsolete */ --- 8208,8214 ---- {"globpath", 2, 5, f_globpath}, {"has", 1, 1, f_has}, {"has_key", 2, 2, f_has_key}, ! {"haslocaldir", 0, 2, f_haslocaldir}, {"hasmapto", 1, 3, f_hasmapto}, {"highlightID", 1, 1, f_hlID}, /* obsolete */ {"highlight_exists",1, 1, f_hlexists}, /* obsolete */ *************** *** 9127,9156 **** 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; } /* --- 9128,9138 ---- typval_T *rettv; { win_T *wp; rettv->vval.v_number = -1; ! wp = find_tabwin(&argvars[0], &argvars[1]); ! if (wp != NULL) ! rettv->vval.v_number = wp->w_alist->id; } /* *************** *** 12061,12085 **** */ static void f_getcwd(argvars, rettv) ! typval_T *argvars UNUSED; typval_T *rettv; { 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); #ifdef BACKSLASH_IN_FILENAME ! if (rettv->vval.v_string != NULL) ! slash_adjust(rettv->vval.v_string); #endif - } - vim_free(cwd); } } --- 12043,12078 ---- */ static void f_getcwd(argvars, rettv) ! typval_T *argvars; typval_T *rettv; { + win_T *wp = NULL; char_u *cwd; rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; ! ! 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 } } *************** *** 12709,12714 **** --- 12702,12739 ---- } /* + * 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,13552 **** */ static void f_haslocaldir(argvars, rettv) ! typval_T *argvars UNUSED; typval_T *rettv; { ! rettv->vval.v_number = (curwin->w_localdir != NULL); } /* --- 13568,13580 ---- */ static void f_haslocaldir(argvars, rettv) ! 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,21865 **** 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; ! } } return funccal; } --- 21879,21893 ---- 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; ! } } return funccal; } *************** *** 23379,23386 **** * 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_NO_AUTOLOAD: do not use script autoloading * Advances "pp" to just after the function name (if no error). */ --- 23407,23414 ---- * 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_NO_AUTOLOAD: do not use script autoloading * Advances "pp" to just after the function name (if no error). */ *** ../vim-7.4.1125/src/version.c 2016-01-17 21:15:17.843322552 +0100 --- src/version.c 2016-01-17 21:39:08.659552505 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 1126, /**/ -- An alien life briefly visits earth. Just before departing it leaves a message in the dust on the back of a white van. The world is shocked and wants to know what it means. After months of studies the worlds best linguistic scientists are able to decipher the message: "Wash me!". /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///