@@ -202,6 +202,8 @@ static void internal_format __ARGS((int textwidth, int second_indent, int flags,
202202static void check_auto_format __ARGS ((int ));
203203static void redo_literal __ARGS ((int c ));
204204static void start_arrow __ARGS ((pos_T * end_insert_pos ));
205+ static void start_arrow_with_change __ARGS ((pos_T * end_insert_pos , int change ));
206+ static void start_arrow_common __ARGS ((pos_T * end_insert_pos , int change ));
205207#ifdef FEAT_SPELL
206208static void check_spell_redraw __ARGS ((void ));
207209static void spell_back_to_badword __ARGS ((void ));
@@ -241,11 +243,11 @@ static void ins_mousescroll __ARGS((int dir));
241243#if defined(FEAT_GUI_TABLINE ) || defined(PROTO )
242244static void ins_tabline __ARGS ((int c ));
243245#endif
244- static void ins_left __ARGS ((void ));
246+ static void ins_left __ARGS ((int end_change ));
245247static void ins_home __ARGS ((int c ));
246248static void ins_end __ARGS ((int c ));
247249static void ins_s_left __ARGS ((void ));
248- static void ins_right __ARGS ((void ));
250+ static void ins_right __ARGS ((int end_change ));
249251static void ins_s_right __ARGS ((void ));
250252static void ins_up __ARGS ((int startcol ));
251253static void ins_pageup __ARGS ((void ));
@@ -297,6 +299,8 @@ static int ins_need_undo; /* call u_save() before inserting a
297299
298300static int did_add_space = FALSE; /* auto_format() added an extra space
299301 under the cursor */
302+ static int dont_sync_undo = FALSE; /* CTRL-G U prevents syncing undo for
303+ the next left/right cursor */
300304
301305/*
302306 * edit(): Start inserting text.
@@ -767,6 +771,12 @@ edit(cmdchar, startln, count)
767771 */
768772 if (c != K_CURSORHOLD )
769773 lastc = c ; /* remember the previous char for CTRL-D */
774+
775+ /* After using CTRL-G U the next cursor key will not break undo. */
776+ if (dont_sync_undo == MAYBE )
777+ dont_sync_undo = TRUE;
778+ else
779+ dont_sync_undo = FALSE;
770780 do
771781 {
772782 c = safe_vgetc ();
@@ -1237,7 +1247,7 @@ edit(cmdchar, startln, count)
12371247 if (mod_mask & (MOD_MASK_SHIFT |MOD_MASK_CTRL ))
12381248 ins_s_left ();
12391249 else
1240- ins_left ();
1250+ ins_left (dont_sync_undo == FALSE );
12411251 break ;
12421252
12431253 case K_S_LEFT : /* <S-Left> */
@@ -1249,7 +1259,7 @@ edit(cmdchar, startln, count)
12491259 if (mod_mask & (MOD_MASK_SHIFT |MOD_MASK_CTRL ))
12501260 ins_s_right ();
12511261 else
1252- ins_right ();
1262+ ins_right (dont_sync_undo == FALSE );
12531263 break ;
12541264
12551265 case K_S_RIGHT : /* <S-Right> */
@@ -6787,9 +6797,34 @@ redo_literal(c)
67876797 */
67886798 static void
67896799start_arrow (end_insert_pos )
6790- pos_T * end_insert_pos ; /* can be NULL */
6800+ pos_T * end_insert_pos ; /* can be NULL */
6801+ {
6802+ start_arrow_common (end_insert_pos , TRUE);
6803+ }
6804+
6805+ /*
6806+ * Like start_arrow() but with end_change argument.
6807+ * Will prepare for redo of CTRL-G U if "end_change" is FALSE.
6808+ */
6809+ static void
6810+ start_arrow_with_change (end_insert_pos , end_change )
6811+ pos_T * end_insert_pos ; /* can be NULL */
6812+ int end_change ; /* end undoable change */
67916813{
6792- if (!arrow_used ) /* something has been inserted */
6814+ start_arrow_common (end_insert_pos , end_change );
6815+ if (!end_change )
6816+ {
6817+ AppendCharToRedobuff (Ctrl_G );
6818+ AppendCharToRedobuff ('U' );
6819+ }
6820+ }
6821+
6822+ static void
6823+ start_arrow_common (end_insert_pos , end_change )
6824+ pos_T * end_insert_pos ; /* can be NULL */
6825+ int end_change ; /* end undoable change */
6826+ {
6827+ if (!arrow_used && end_change ) /* something has been inserted */
67936828 {
67946829 AppendToRedobuff (ESC_STR );
67956830 stop_insert (end_insert_pos , FALSE, FALSE);
@@ -8359,6 +8394,13 @@ ins_ctrl_g()
83598394 Insstart = curwin -> w_cursor ;
83608395 break ;
83618396
8397+ /* CTRL-G U: do not break undo with the next char */
8398+ case 'U' :
8399+ /* Allow one left/right cursor movement with the next char,
8400+ * without breaking undo. */
8401+ dont_sync_undo = MAYBE ;
8402+ break ;
8403+
83628404 /* Unknown CTRL-G command, reserved for future expansion. */
83638405 default : vim_beep (BO_CTRLG );
83648406 }
@@ -9440,7 +9482,8 @@ ins_horscroll()
94409482#endif
94419483
94429484 static void
9443- ins_left ()
9485+ ins_left (end_change )
9486+ int end_change ; /* end undoable change */
94449487{
94459488 pos_T tpos ;
94469489
@@ -9457,7 +9500,11 @@ ins_left()
94579500 * break undo. K_LEFT is inserted in im_correct_cursor(). */
94589501 if (!im_is_preediting ())
94599502#endif
9460- start_arrow (& tpos );
9503+ {
9504+ start_arrow_with_change (& tpos , end_change );
9505+ if (!end_change )
9506+ AppendCharToRedobuff (K_LEFT );
9507+ }
94619508#ifdef FEAT_RIGHTLEFT
94629509 /* If exit reversed string, position is fixed */
94639510 if (revins_scol != -1 && (int )curwin -> w_cursor .col >= revins_scol )
@@ -9472,13 +9519,15 @@ ins_left()
94729519 */
94739520 else if (vim_strchr (p_ww , '[' ) != NULL && curwin -> w_cursor .lnum > 1 )
94749521 {
9522+ /* always break undo when moving upwards/downwards, else undo may break */
94759523 start_arrow (& tpos );
94769524 -- (curwin -> w_cursor .lnum );
94779525 coladvance ((colnr_T )MAXCOL );
94789526 curwin -> w_set_curswant = TRUE; /* so we stay at the end */
94799527 }
94809528 else
94819529 vim_beep (BO_CRSR );
9530+ dont_sync_undo = FALSE;
94829531}
94839532
94849533 static void
@@ -9542,7 +9591,8 @@ ins_s_left()
95429591}
95439592
95449593 static void
9545- ins_right ()
9594+ ins_right (end_change )
9595+ int end_change ; /* end undoable change */
95469596{
95479597#ifdef FEAT_FOLDING
95489598 if ((fdo_flags & FDO_HOR ) && KeyTyped )
@@ -9555,7 +9605,9 @@ ins_right()
95559605#endif
95569606 )
95579607 {
9558- start_arrow (& curwin -> w_cursor );
9608+ start_arrow_with_change (& curwin -> w_cursor , end_change );
9609+ if (!end_change )
9610+ AppendCharToRedobuff (K_RIGHT );
95599611 curwin -> w_set_curswant = TRUE;
95609612#ifdef FEAT_VIRTUALEDIT
95619613 if (virtual_active ())
@@ -9589,6 +9641,7 @@ ins_right()
95899641 }
95909642 else
95919643 vim_beep (BO_CRSR );
9644+ dont_sync_undo = FALSE;
95929645}
95939646
95949647 static void
0 commit comments