diff options
Diffstat (limited to 'data/vim/patches/8.1.1291')
-rw-r--r-- | data/vim/patches/8.1.1291 | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.1291 b/data/vim/patches/8.1.1291 new file mode 100644 index 000000000..2cb567dfc --- /dev/null +++ b/data/vim/patches/8.1.1291 @@ -0,0 +1,561 @@ +To: vim_dev@googlegroups.com +Subject: Patch 8.1.1291 +Fcc: outbox +From: Bram Moolenaar <Bram@moolenaar.net> +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 8.1.1291 +Problem: Not easy to change directory and restore. +Solution: Add the chdir() function. (Yegappan Lakshmanan, closes #4358) +Files: runtime/doc/eval.txt, runtime/doc/todo.txt, + runtime/doc/usr_41.txt, src/evalfunc.c, src/ex_docmd.c, + src/if_py_both.h, src/proto/ex_docmd.pro, src/structs.h, + src/testdir/test_cd.vim + + +*** ../vim-8.1.1290/runtime/doc/eval.txt 2019-05-05 18:11:46.312590682 +0200 +--- runtime/doc/eval.txt 2019-05-07 22:00:01.205510545 +0200 +*************** +*** 2273,2278 **** +--- 2273,2279 ---- + String status of channel {handle} + changenr() Number current change number + char2nr({expr} [, {utf8}]) Number ASCII/UTF8 value of first char in {expr} ++ chdir({dir}) String change current working directory + cindent({lnum}) Number C indent for line {lnum} + clearmatches([{win}]) none clear all matches + col({expr}) Number column nr of cursor or mark +*************** +*** 3469,3474 **** +--- 3470,3496 ---- + let list = map(split(str, '\zs'), {_, val -> char2nr(val)}) + < Result: [65, 66, 67] + ++ chdir({dir}) *chdir()* ++ Change the current working directory to {dir}. The scope of ++ the directory change depends on the directory of the current ++ window: ++ - If the current window has a window-local directory ++ (|:lcd|), then changes the window local directory. ++ - Otherwise, if the current tabpage has a local ++ directory (|:tcd|) then changes the tabpage local ++ directory. ++ - Otherwise, changes the global directory. ++ If successful, returns the previous working directory. Pass ++ this to another chdir() to restore the directory. ++ On failure, returns an empty string. ++ ++ Example: > ++ let save_dir = chdir(newdir) ++ if save_dir ++ " ... do some work ++ call chdir(save_dir) ++ endif ++ < + cindent({lnum}) *cindent()* + Get the amount of indent for line {lnum} according the C + indenting rules, as with 'cindent'. +*** ../vim-8.1.1290/runtime/doc/usr_41.txt 2019-05-05 18:11:46.328590595 +0200 +--- runtime/doc/usr_41.txt 2019-05-07 21:56:20.282699661 +0200 +*************** +*** 769,774 **** +--- 769,775 ---- + haslocaldir() check if current window used |:lcd| or |:tcd| + tempname() get the name of a temporary file + mkdir() create a new directory ++ chdir() change current working directory + delete() delete a file + rename() rename a file + system() get the result of a shell command as a string +*** ../vim-8.1.1290/src/evalfunc.c 2019-05-07 16:28:08.177289442 +0200 +--- src/evalfunc.c 2019-05-07 21:56:20.286699640 +0200 +*************** +*** 107,112 **** +--- 107,113 ---- + #endif + static void f_changenr(typval_T *argvars, typval_T *rettv); + static void f_char2nr(typval_T *argvars, typval_T *rettv); ++ static void f_chdir(typval_T *argvars, typval_T *rettv); + static void f_cindent(typval_T *argvars, typval_T *rettv); + static void f_clearmatches(typval_T *argvars, typval_T *rettv); + static void f_col(typval_T *argvars, typval_T *rettv); +*************** +*** 597,602 **** +--- 598,604 ---- + #endif + {"changenr", 0, 0, f_changenr}, + {"char2nr", 1, 2, f_char2nr}, ++ {"chdir", 1, 1, f_chdir}, + {"cindent", 1, 1, f_cindent}, + {"clearmatches", 0, 1, f_clearmatches}, + {"col", 1, 1, f_col}, +*************** +*** 2491,2496 **** +--- 2493,2537 ---- + } + + /* ++ * "chdir(dir)" function ++ */ ++ static void ++ f_chdir(typval_T *argvars, typval_T *rettv) ++ { ++ char_u *cwd; ++ cdscope_T scope = CDSCOPE_GLOBAL; ++ ++ rettv->v_type = VAR_STRING; ++ rettv->vval.v_string = NULL; ++ ++ if (argvars[0].v_type != VAR_STRING) ++ return; ++ ++ // Return the current directory ++ cwd = alloc(MAXPATHL); ++ if (cwd != NULL) ++ { ++ if (mch_dirname(cwd, MAXPATHL) != FAIL) ++ { ++ #ifdef BACKSLASH_IN_FILENAME ++ slash_adjust(cwd); ++ #endif ++ rettv->vval.v_string = vim_strsave(cwd); ++ } ++ vim_free(cwd); ++ } ++ ++ if (curwin->w_localdir != NULL) ++ scope = CDSCOPE_WINDOW; ++ else if (curtab->tp_localdir != NULL) ++ scope = CDSCOPE_TABPAGE; ++ ++ if (!changedir_func(argvars[0].vval.v_string, TRUE, scope)) ++ // Directory change failed ++ VIM_CLEAR(rettv->vval.v_string); ++ } ++ ++ /* + * "cindent(lnum)" function + */ + static void +*** ../vim-8.1.1290/src/ex_docmd.c 2019-05-04 15:05:24.927269310 +0200 +--- src/ex_docmd.c 2019-05-07 21:56:20.286699640 +0200 +*************** +*** 7513,7529 **** + + /* + * Deal with the side effects of changing the current directory. +! * When "tablocal" is TRUE then this was after an ":tcd" command. +! * When "winlocal" is TRUE then this was after an ":lcd" command. + */ + void +! post_chdir(int tablocal, int winlocal) + { +! if (!winlocal) + // Clear tab local directory for both :cd and :tcd + VIM_CLEAR(curtab->tp_localdir); + VIM_CLEAR(curwin->w_localdir); +! if (winlocal || tablocal) + { + /* If still in global directory, need to remember current + * directory as global directory. */ +--- 7513,7529 ---- + + /* + * Deal with the side effects of changing the current directory. +! * When 'scope' is CDSCOPE_TABPAGE then this was after an ":tcd" command. +! * When 'scope' is CDSCOPE_WINDOW then this was after an ":lcd" command. + */ + void +! post_chdir(cdscope_T scope) + { +! if (scope != CDSCOPE_WINDOW) + // Clear tab local directory for both :cd and :tcd + VIM_CLEAR(curtab->tp_localdir); + VIM_CLEAR(curwin->w_localdir); +! if (scope != CDSCOPE_GLOBAL) + { + /* If still in global directory, need to remember current + * directory as global directory. */ +*************** +*** 7532,7538 **** + /* Remember this local directory for the window. */ + if (mch_dirname(NameBuff, MAXPATHL) == OK) + { +! if (tablocal) + curtab->tp_localdir = vim_strsave(NameBuff); + else + curwin->w_localdir = vim_strsave(NameBuff); +--- 7532,7538 ---- + /* Remember this local directory for the window. */ + if (mch_dirname(NameBuff, MAXPATHL) == OK) + { +! if (scope == CDSCOPE_TABPAGE) + curtab->tp_localdir = vim_strsave(NameBuff); + else + curwin->w_localdir = vim_strsave(NameBuff); +*************** +*** 7548,7649 **** + shorten_fnames(TRUE); + } + +- + /* +! * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir". + */ +! void +! ex_cd(exarg_T *eap) + { +- char_u *new_dir; + char_u *tofree; + int dir_differs; + +! new_dir = eap->arg; +! #if !defined(UNIX) && !defined(VMS) +! /* for non-UNIX ":cd" means: print current directory */ +! if (*new_dir == NUL) +! ex_pwd(NULL); +! else +! #endif + { +! if (allbuf_locked()) +! return; +! if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() +! && !eap->forceit) +! { +! emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)")); +! return; +! } + +! /* ":cd -": Change to previous directory */ +! if (STRCMP(new_dir, "-") == 0) + { +! if (prev_dir == NULL) +! { +! emsg(_("E186: No previous directory")); +! return; +! } +! new_dir = prev_dir; + } + +! /* Save current directory for next ":cd -" */ +! tofree = prev_dir; +! if (mch_dirname(NameBuff, MAXPATHL) == OK) +! prev_dir = vim_strsave(NameBuff); +! else +! prev_dir = NULL; + + #if defined(UNIX) || defined(VMS) +! /* for UNIX ":cd" means: go to home directory */ +! if (*new_dir == NUL) +! { +! /* use NameBuff for home directory name */ + # ifdef VMS +! char_u *p; + +! p = mch_getenv((char_u *)"SYS$LOGIN"); +! if (p == NULL || *p == NUL) /* empty is the same as not set */ +! NameBuff[0] = NUL; +! else +! vim_strncpy(NameBuff, p, MAXPATHL - 1); + # else +! expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); + # endif +! new_dir = NameBuff; +! } + #endif +! dir_differs = new_dir == NULL || prev_dir == NULL +! || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0; +! if (new_dir == NULL || (dir_differs && vim_chdir(new_dir))) +! emsg(_(e_failed)); +! else + { +! char_u *acmd_fname; +! int is_winlocal_chdir = eap->cmdidx == CMD_lcd +! || eap->cmdidx == CMD_lchdir; +! int is_tablocal_chdir = eap->cmdidx == CMD_tcd +! || eap->cmdidx == CMD_tchdir; + +! post_chdir(is_tablocal_chdir, is_winlocal_chdir); + +! /* Echo the new current directory if the command was typed. */ + if (KeyTyped || p_verbose >= 5) + ex_pwd(eap); +- +- if (dir_differs) +- { +- if (is_winlocal_chdir) +- acmd_fname = (char_u *)"window"; +- else if (is_tablocal_chdir) +- acmd_fname = (char_u *)"tabpage"; +- else +- acmd_fname = (char_u *)"global"; +- apply_autocmds(EVENT_DIRCHANGED, acmd_fname, +- new_dir, FALSE, curbuf); +- } + } +- vim_free(tofree); + } + } + +--- 7548,7673 ---- + shorten_fnames(TRUE); + } + + /* +! * Change directory function used by :cd/:tcd/:lcd Ex commands and the +! * chdir() function. If 'winlocaldir' is TRUE, then changes the window-local +! * directory. If 'tablocaldir' is TRUE, then changes the tab-local directory. +! * Otherwise changes the global directory. +! * Returns TRUE if the directory is successfully changed. + */ +! int +! changedir_func( +! char_u *new_dir, +! int forceit, +! cdscope_T scope) + { + char_u *tofree; + int dir_differs; ++ int retval = FALSE; + +! if (allbuf_locked()) +! return FALSE; +! +! if (vim_strchr(p_cpo, CPO_CHDIR) != NULL && curbufIsChanged() && !forceit) + { +! emsg(_("E747: Cannot change directory, buffer is modified (add ! to override)")); +! return FALSE; +! } + +! // ":cd -": Change to previous directory +! if (STRCMP(new_dir, "-") == 0) +! { +! if (prev_dir == NULL) + { +! emsg(_("E186: No previous directory")); +! return FALSE; + } ++ new_dir = prev_dir; ++ } + +! // Save current directory for next ":cd -" +! tofree = prev_dir; +! if (mch_dirname(NameBuff, MAXPATHL) == OK) +! prev_dir = vim_strsave(NameBuff); +! else +! prev_dir = NULL; + + #if defined(UNIX) || defined(VMS) +! // for UNIX ":cd" means: go to home directory +! if (*new_dir == NUL) +! { +! // use NameBuff for home directory name + # ifdef VMS +! char_u *p; + +! p = mch_getenv((char_u *)"SYS$LOGIN"); +! if (p == NULL || *p == NUL) // empty is the same as not set +! NameBuff[0] = NUL; +! else +! vim_strncpy(NameBuff, p, MAXPATHL - 1); + # else +! expand_env((char_u *)"$HOME", NameBuff, MAXPATHL); + # endif +! new_dir = NameBuff; +! } + #endif +! dir_differs = new_dir == NULL || prev_dir == NULL +! || pathcmp((char *)prev_dir, (char *)new_dir, -1) != 0; +! if (new_dir == NULL || (dir_differs && vim_chdir(new_dir))) +! emsg(_(e_failed)); +! else +! { +! char_u *acmd_fname; +! +! post_chdir(scope); +! +! if (dir_differs) + { +! if (scope == CDSCOPE_WINDOW) +! acmd_fname = (char_u *)"window"; +! else if (scope == CDSCOPE_TABPAGE) +! acmd_fname = (char_u *)"tabpage"; +! else +! acmd_fname = (char_u *)"global"; +! apply_autocmds(EVENT_DIRCHANGED, acmd_fname, new_dir, FALSE, +! curbuf); +! } +! retval = TRUE; +! } +! vim_free(tofree); + +! return retval; +! } + +! /* +! * ":cd", ":tcd", ":lcd", ":chdir" ":tchdir" and ":lchdir". +! */ +! void +! ex_cd(exarg_T *eap) +! { +! char_u *new_dir; +! +! new_dir = eap->arg; +! #if !defined(UNIX) && !defined(VMS) +! // for non-UNIX ":cd" means: print current directory +! if (*new_dir == NUL) +! ex_pwd(NULL); +! else +! #endif +! { +! cdscope_T scope = CDSCOPE_GLOBAL; +! +! if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir) +! scope = CDSCOPE_WINDOW; +! else if (eap->cmdidx == CMD_tcd || eap->cmdidx == CMD_tchdir) +! scope = CDSCOPE_TABPAGE; +! +! if (changedir_func(new_dir, eap->forceit, scope)) +! { +! // Echo the new current directory if the command was typed. + if (KeyTyped || p_verbose >= 5) + ex_pwd(eap); + } + } + } + +*** ../vim-8.1.1290/src/if_py_both.h 2019-04-27 20:36:52.530303581 +0200 +--- src/if_py_both.h 2019-05-07 21:56:20.286699640 +0200 +*************** +*** 1032,1038 **** + Py_DECREF(newwd); + Py_XDECREF(todecref); + +! post_chdir(FALSE, FALSE); + + if (VimTryEnd()) + { +--- 1032,1038 ---- + Py_DECREF(newwd); + Py_XDECREF(todecref); + +! post_chdir(CDSCOPE_GLOBAL); + + if (VimTryEnd()) + { +*** ../vim-8.1.1290/src/proto/ex_docmd.pro 2019-04-27 20:36:52.534303564 +0200 +--- src/proto/ex_docmd.pro 2019-05-07 21:56:20.286699640 +0200 +*************** +*** 37,43 **** + void tabpage_new(void); + void do_exedit(exarg_T *eap, win_T *old_curwin); + void free_cd_dir(void); +! void post_chdir(int tablocal, int winlocal); + void ex_cd(exarg_T *eap); + void do_sleep(long msec); + void ex_may_print(exarg_T *eap); +--- 37,44 ---- + void tabpage_new(void); + void do_exedit(exarg_T *eap, win_T *old_curwin); + void free_cd_dir(void); +! void post_chdir(cdscope_T cdscope); +! int changedir_func(char_u *new_dir, int forceit, cdscope_T cdscope); + void ex_cd(exarg_T *eap); + void do_sleep(long msec); + void ex_may_print(exarg_T *eap); +*** ../vim-8.1.1290/src/structs.h 2019-05-05 15:47:37.825923529 +0200 +--- src/structs.h 2019-05-07 22:01:54.424899979 +0200 +*************** +*** 3555,3557 **** +--- 3555,3564 ---- + varnumber_T vv_count; + varnumber_T vv_count1; + } vimvars_save_T; ++ ++ // Scope for changing directory ++ typedef enum { ++ CDSCOPE_GLOBAL, // :cd ++ CDSCOPE_TABPAGE, // :tcd ++ CDSCOPE_WINDOW // :lcd ++ } cdscope_T; +*** ../vim-8.1.1290/src/testdir/test_cd.vim 2018-07-03 18:36:23.037340552 +0200 +--- src/testdir/test_cd.vim 2019-05-07 21:56:20.286699640 +0200 +*************** +*** 1,4 **** +! " Test for :cd + + func Test_cd_large_path() + " This used to crash with a heap write overflow. +--- 1,4 ---- +! " Test for :cd and chdir() + + func Test_cd_large_path() + " This used to crash with a heap write overflow. +*************** +*** 65,67 **** +--- 65,108 ---- + set cpo& + bw! + endfunc ++ ++ " Test for chdir() ++ func Test_chdir_func() ++ let topdir = getcwd() ++ call mkdir('Xdir/y/z', 'p') ++ ++ " Create a few tabpages and windows with different directories ++ new ++ cd Xdir ++ tabnew ++ tcd y ++ below new ++ below new ++ lcd z ++ ++ tabfirst ++ call chdir('..') ++ call assert_equal('y', fnamemodify(getcwd(1, 2), ':t')) ++ call assert_equal('z', fnamemodify(getcwd(3, 2), ':t')) ++ tabnext | wincmd t ++ call chdir('..') ++ call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t')) ++ call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t')) ++ call assert_equal('z', fnamemodify(getcwd(3, 2), ':t')) ++ call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t')) ++ 3wincmd w ++ call chdir('..') ++ call assert_equal('Xdir', fnamemodify(getcwd(1, 2), ':t')) ++ call assert_equal('Xdir', fnamemodify(getcwd(2, 2), ':t')) ++ call assert_equal('y', fnamemodify(getcwd(3, 2), ':t')) ++ call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t')) ++ ++ " Error case ++ call assert_fails("call chdir('dir-abcd')", 'E472:') ++ silent! let d = chdir("dir_abcd") ++ call assert_equal("", d) ++ ++ only | tabonly ++ exe 'cd ' . topdir ++ call delete('Xdir', 'rf') ++ endfunc +*** ../vim-8.1.1290/src/version.c 2019-05-07 21:48:15.629291397 +0200 +--- src/version.c 2019-05-07 22:06:10.403517496 +0200 +*************** +*** 769,770 **** +--- 769,772 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 1291, + /**/ + +-- +Violators can be fined, arrested or jailed for making ugly faces at a dog. + [real standing law in Oklahoma, United States of America] + + /// 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 /// |