changeset 11325:77f3b7316d8b v8.0.0548

patch 8.0.0548: saving the redo buffer only works one time commit https://github.com/vim/vim/commit/d4863aa99e0527e9505c79cbeafc68a6832200bf Author: Bram Moolenaar <Bram@vim.org> Date: Fri Apr 7 19:50:12 2017 +0200 patch 8.0.0548: saving the redo buffer only works one time Problem: Saving the redo buffer only works one time, resulting in the "." command not working well for a function call inside another function call. (Ingo Karkat) Solution: Save the redo buffer at every user function call. (closes #1619)
author Christian Brabandt <cb@256bit.org>
date Fri, 07 Apr 2017 20:00:04 +0200
parents c9adf54ef624
children 76747bd3226c
files src/fileio.c src/getchar.c src/proto/getchar.pro src/structs.h src/testdir/test_functions.vim src/userfunc.c src/version.c
diffstat 7 files changed, 60 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -9316,6 +9316,7 @@ apply_autocmds_group(
     proftime_T	wait_time;
 #endif
     int		did_save_redobuff = FALSE;
+    save_redo_T	save_redo;
 
     /*
      * Quickly return if there are no autocommands for this event or
@@ -9521,7 +9522,7 @@ apply_autocmds_group(
 	if (!ins_compl_active())
 #endif
 	{
-	    saveRedobuff();
+	    saveRedobuff(&save_redo);
 	    did_save_redobuff = TRUE;
 	}
 	did_filetype = keep_filetype;
@@ -9624,7 +9625,7 @@ apply_autocmds_group(
     {
 	restore_search_patterns();
 	if (did_save_redobuff)
-	    restoreRedobuff();
+	    restoreRedobuff(&save_redo);
 	did_filetype = FALSE;
 	while (au_pending_free_buf != NULL)
 	{
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -42,10 +42,6 @@
 
 static buffheader_T redobuff = {{NULL, {NUL}}, NULL, 0, 0};
 static buffheader_T old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
-#if defined(FEAT_AUTOCMD) || defined(FEAT_EVAL) || defined(PROTO)
-static buffheader_T save_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
-static buffheader_T save_old_redobuff = {{NULL, {NUL}}, NULL, 0, 0};
-#endif
 static buffheader_T recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
 
 static int typeahead_char = 0;		/* typeahead char that's not flushed */
@@ -521,27 +517,22 @@ CancelRedo(void)
  * Save redobuff and old_redobuff to save_redobuff and save_old_redobuff.
  * Used before executing autocommands and user functions.
  */
-static int save_level = 0;
-
     void
-saveRedobuff(void)
+saveRedobuff(save_redo_T *save_redo)
 {
     char_u	*s;
 
-    if (save_level++ == 0)
+    save_redo->sr_redobuff = redobuff;
+    redobuff.bh_first.b_next = NULL;
+    save_redo->sr_old_redobuff = old_redobuff;
+    old_redobuff.bh_first.b_next = NULL;
+
+    /* Make a copy, so that ":normal ." in a function works. */
+    s = get_buffcont(&save_redo->sr_redobuff, FALSE);
+    if (s != NULL)
     {
-	save_redobuff = redobuff;
-	redobuff.bh_first.b_next = NULL;
-	save_old_redobuff = old_redobuff;
-	old_redobuff.bh_first.b_next = NULL;
-
-	/* Make a copy, so that ":normal ." in a function works. */
-	s = get_buffcont(&save_redobuff, FALSE);
-	if (s != NULL)
-	{
-	    add_buff(&redobuff, s, -1L);
-	    vim_free(s);
-	}
+	add_buff(&redobuff, s, -1L);
+	vim_free(s);
     }
 }
 
@@ -550,15 +541,12 @@ saveRedobuff(void)
  * Used after executing autocommands and user functions.
  */
     void
-restoreRedobuff(void)
+restoreRedobuff(save_redo_T *save_redo)
 {
-    if (--save_level == 0)
-    {
-	free_buff(&redobuff);
-	redobuff = save_redobuff;
-	free_buff(&old_redobuff);
-	old_redobuff = save_old_redobuff;
-    }
+    free_buff(&redobuff);
+    redobuff = save_redo->sr_redobuff;
+    free_buff(&old_redobuff);
+    old_redobuff = save_redo->sr_old_redobuff;
 }
 #endif
 
--- a/src/proto/getchar.pro
+++ b/src/proto/getchar.pro
@@ -8,8 +8,8 @@ void typeahead_noflush(int c);
 void flush_buffers(int flush_typeahead);
 void ResetRedobuff(void);
 void CancelRedo(void);
-void saveRedobuff(void);
-void restoreRedobuff(void);
+void saveRedobuff(save_redo_T *save_redo);
+void restoreRedobuff(save_redo_T *save_redo);
 void AppendToRedobuff(char_u *s);
 void AppendToRedobuffLit(char_u *str, int len);
 void AppendCharToRedobuff(int c);
--- a/src/structs.h
+++ b/src/structs.h
@@ -515,6 +515,12 @@ struct buffheader
     int		bh_space;	/* space in bh_curr for appending */
 };
 
+typedef struct
+{
+    buffheader_T sr_redobuff;
+    buffheader_T sr_old_redobuff;
+} save_redo_T;
+
 /*
  * used for completion on the command line
  */
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -756,3 +756,31 @@ func Test_setbufvar_options()
   call win_gotoid(dum1_id)
   bwipe!
 endfunc
+
+func Test_redo_in_nested_functions()
+  nnoremap g. :set opfunc=Operator<CR>g@
+  function Operator( type, ... )
+     let @x = 'XXX'
+     execute 'normal! g`[' . (a:type ==# 'line' ? 'V' : 'v') . 'g`]' . '"xp'
+  endfunction
+
+  function! Apply()
+      5,6normal! .
+  endfunction
+
+  new
+  call setline(1, repeat(['some "quoted" text', 'more "quoted" text'], 3))
+  1normal g.i"
+  call assert_equal('some "XXX" text', getline(1))
+  3,4normal .
+  call assert_equal('some "XXX" text', getline(3))
+  call assert_equal('more "XXX" text', getline(4))
+  call Apply()
+  call assert_equal('some "XXX" text', getline(5))
+  call assert_equal('more "XXX" text', getline(6))
+  bwipe!
+
+  nunmap g.
+  delfunc Operator
+  delfunc Apply
+endfunc
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1408,6 +1408,7 @@ call_func(
 		else
 		{
 		    int did_save_redo = FALSE;
+		    save_redo_T	save_redo;
 
 		    /*
 		     * Call the user function.
@@ -1419,7 +1420,7 @@ call_func(
 		    if (!ins_compl_active())
 #endif
 		    {
-			saveRedobuff();
+			saveRedobuff(&save_redo);
 			did_save_redo = TRUE;
 		    }
 		    ++fp->uf_calls;
@@ -1431,7 +1432,7 @@ call_func(
 			 * now. */
 			func_clear_free(fp, FALSE);
 		    if (did_save_redo)
-			restoreRedobuff();
+			restoreRedobuff(&save_redo);
 		    restore_search_patterns();
 		    error = ERROR_NONE;
 		}
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    548,
+/**/
     547,
 /**/
     546,