changeset 14485:c71d65c3672f v8.1.0256

patch 8.1.0256: using setline() in TextChangedI splits undo commit https://github.com/vim/vim/commit/9fa9506853516c82851baec643aa47458cb8b3bc Author: Bram Moolenaar <Bram@vim.org> Date: Wed Aug 8 22:08:32 2018 +0200 patch 8.1.0256: using setline() in TextChangedI splits undo Problem: Using setline() in TextChangedI splits undo. Solution: Use another solution for undo not working properly.
author Christian Brabandt <cb@256bit.org>
date Wed, 08 Aug 2018 22:15:05 +0200
parents c7016941d02a
children 4e34a56ce9ee
files src/edit.c src/testdir/test_autocmd.vim src/version.c
diffstat 3 files changed, 39 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/edit.c
+++ b/src/edit.c
@@ -279,6 +279,7 @@ static colnr_T get_nolist_virtcol(void);
 #if defined(FEAT_EVAL)
 static char_u *do_insert_char_pre(int c);
 #endif
+static int ins_apply_autocmds(event_T event);
 
 static colnr_T	Insstart_textlen;	/* length of line when insert started */
 static colnr_T	Insstart_blank_vcol;	/* vcol for first inserted blank */
@@ -411,7 +412,7 @@ edit(
 	set_vim_var_string(VV_INSERTMODE, ptr, 1);
 	set_vim_var_string(VV_CHAR, NULL, -1);  /* clear v:char */
 #endif
-	apply_autocmds(EVENT_INSERTENTER, NULL, NULL, FALSE, curbuf);
+	ins_apply_autocmds(EVENT_INSERTENTER);
 
 	/* Make sure the cursor didn't move.  Do call check_cursor_col() in
 	 * case the text was modified.  Since Insert mode was not started yet
@@ -1061,8 +1062,7 @@ doESCkey:
 	    if (ins_esc(&count, cmdchar, nomove))
 	    {
 		if (cmdchar != 'r' && cmdchar != 'v')
-		    apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL,
-							       FALSE, curbuf);
+		    ins_apply_autocmds(EVENT_INSERTLEAVE);
 		did_cursorhold = FALSE;
 		return (c == Ctrl_O);
 	    }
@@ -1275,7 +1275,7 @@ doESCkey:
 	    break;
 
 	case K_CURSORHOLD:	/* Didn't type something for a while. */
-	    apply_autocmds(EVENT_CURSORHOLDI, NULL, NULL, FALSE, curbuf);
+	    ins_apply_autocmds(EVENT_CURSORHOLDI);
 	    did_cursorhold = TRUE;
 	    break;
 
@@ -1698,7 +1698,7 @@ ins_redraw(
 	    /* Make sure curswant is correct, an autocommand may call
 	     * getcurpos(). */
 	    update_curswant();
-	    apply_autocmds(EVENT_CURSORMOVEDI, NULL, NULL, FALSE, curbuf);
+	    ins_apply_autocmds(EVENT_CURSORMOVEDI);
 	}
 # ifdef FEAT_CONCEAL
 	if (curwin->w_p_cole > 0)
@@ -1721,24 +1721,16 @@ ins_redraw(
 	    )
     {
 	aco_save_T	aco;
-
-#ifdef FEAT_EVAL
-	// Sync undo when the autocommand calls setline() or append(), so that
-	// it can be undone separately.
-	u_sync_once = 2;
-#endif
+	varnumber_T	tick = CHANGEDTICK(curbuf);
 
 	// save and restore curwin and curbuf, in case the autocmd changes them
 	aucmd_prepbuf(&aco, curbuf);
 	apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
 	aucmd_restbuf(&aco);
 	curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
-
-#ifdef FEAT_EVAL
-	if (u_sync_once == 1)
-	    ins_need_undo = TRUE;
-	u_sync_once = 0;
-#endif
+	if (tick != CHANGEDTICK(curbuf))  // see ins_apply_autocmds()
+	    u_save(curwin->w_cursor.lnum,
+					(linenr_T)(curwin->w_cursor.lnum + 1));
     }
 
 #ifdef FEAT_INS_EXPAND
@@ -1750,12 +1742,16 @@ ins_redraw(
 	    && pum_visible())
     {
 	aco_save_T	aco;
+	varnumber_T	tick = CHANGEDTICK(curbuf);
 
 	// save and restore curwin and curbuf, in case the autocmd changes them
 	aucmd_prepbuf(&aco, curbuf);
 	apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf);
 	aucmd_restbuf(&aco);
 	curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf);
+	if (tick != CHANGEDTICK(curbuf))  // see ins_apply_autocmds()
+	    u_save(curwin->w_cursor.lnum,
+					(linenr_T)(curwin->w_cursor.lnum + 1));
     }
 #endif
 
@@ -4124,13 +4120,13 @@ ins_compl_prep(int c)
 #endif
 	    /* Trigger the CompleteDone event to give scripts a chance to act
 	     * upon the completion. */
-	    apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf);
+	    ins_apply_autocmds(EVENT_COMPLETEDONE);
 	}
     }
     else if (ctrl_x_mode == CTRL_X_LOCAL_MSG)
 	/* Trigger the CompleteDone event to give scripts a chance to act
 	 * upon the (possibly failed) completion. */
-	apply_autocmds(EVENT_COMPLETEDONE, NULL, NULL, FALSE, curbuf);
+	ins_apply_autocmds(EVENT_COMPLETEDONE);
 
     /* reset continue_* if we left expansion-mode, if we stay they'll be
      * (re)set properly in ins_complete() */
@@ -8944,7 +8940,7 @@ ins_insert(int replaceState)
 		          : replaceState == VREPLACE ? "v"
 						     : "r"), 1);
 # endif
-    apply_autocmds(EVENT_INSERTCHANGE, NULL, NULL, FALSE, curbuf);
+    ins_apply_autocmds(EVENT_INSERTCHANGE);
     if (State & REPLACE_FLAG)
 	State = INSERT | (State & LANGMAP);
     else
@@ -10738,7 +10734,7 @@ do_insert_char_pre(int c)
     set_vim_var_string(VV_CHAR, buf, -1);  /* set v:char */
 
     res = NULL;
-    if (apply_autocmds(EVENT_INSERTCHARPRE, NULL, NULL, FALSE, curbuf))
+    if (ins_apply_autocmds(EVENT_INSERTCHARPRE))
     {
 	/* Get the value of v:char.  It may be empty or more than one
 	 * character.  Only use it when changed, otherwise continue with the
@@ -10753,3 +10749,22 @@ do_insert_char_pre(int c)
     return res;
 }
 #endif
+
+/*
+ * Trigger "event" and take care of fixing undo.
+ */
+    static int
+ins_apply_autocmds(event_T event)
+{
+    varnumber_T	tick = CHANGEDTICK(curbuf);
+    int r;
+
+    r = apply_autocmds(event, NULL, NULL, FALSE, curbuf);
+
+    // If u_savesub() was called then we are not prepared to start
+    // a new line.  Call u_save() with no contents to fix that.
+    if (tick != CHANGEDTICK(curbuf))
+	u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1));
+
+    return r;
+}
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -1329,10 +1329,8 @@ func Test_TextChangedI_with_setline()
   call assert_equal('(', getline(1))
   call assert_equal('x)', getline(2))
   undo
-  call assert_equal('(', getline(1))
+  call assert_equal('', getline(1))
   call assert_equal('', getline(2))
-  undo
-  call assert_equal('', getline(1))
 
   call test_override('starting', 0)
   bwipe!
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    256,
+/**/
     255,
 /**/
     254,