summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.1291
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.1291')
-rw-r--r--data/vim/patches/8.1.1291561
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 ///