From 8b5f65a527c353b9942e362e719687c3a7592309 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 1 Sep 2015 19:26:12 +0200 Subject: patch 7.4.849 Problem: Moving the cursor in Insert mode starts new undo sequence. Solution: Add CTRL-G U to keep the undo sequence for the following cursor movement command. (Christian Brabandt) --- src/edit.c | 73 ++++++++++++++++++++++++++++++++++++++------- src/testdir/test_mapping.in | 15 ++++++++++ src/testdir/test_mapping.ok | 10 +++++++ src/version.c | 2 ++ 4 files changed, 90 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/edit.c b/src/edit.c index b48a2176f7..db4a079e40 100644 --- a/src/edit.c +++ b/src/edit.c @@ -202,6 +202,8 @@ static void internal_format __ARGS((int textwidth, int second_indent, int flags, static void check_auto_format __ARGS((int)); static void redo_literal __ARGS((int c)); static void start_arrow __ARGS((pos_T *end_insert_pos)); +static void start_arrow_with_change __ARGS((pos_T *end_insert_pos, int change)); +static void start_arrow_common __ARGS((pos_T *end_insert_pos, int change)); #ifdef FEAT_SPELL static void check_spell_redraw __ARGS((void)); static void spell_back_to_badword __ARGS((void)); @@ -241,11 +243,11 @@ static void ins_mousescroll __ARGS((int dir)); #if defined(FEAT_GUI_TABLINE) || defined(PROTO) static void ins_tabline __ARGS((int c)); #endif -static void ins_left __ARGS((void)); +static void ins_left __ARGS((int end_change)); static void ins_home __ARGS((int c)); static void ins_end __ARGS((int c)); static void ins_s_left __ARGS((void)); -static void ins_right __ARGS((void)); +static void ins_right __ARGS((int end_change)); static void ins_s_right __ARGS((void)); static void ins_up __ARGS((int startcol)); static void ins_pageup __ARGS((void)); @@ -297,6 +299,8 @@ static int ins_need_undo; /* call u_save() before inserting a static int did_add_space = FALSE; /* auto_format() added an extra space under the cursor */ +static int dont_sync_undo = FALSE; /* CTRL-G U prevents syncing undo for + the next left/right cursor */ /* * edit(): Start inserting text. @@ -767,6 +771,12 @@ edit(cmdchar, startln, count) */ if (c != K_CURSORHOLD) lastc = c; /* remember the previous char for CTRL-D */ + + /* After using CTRL-G U the next cursor key will not break undo. */ + if (dont_sync_undo == MAYBE) + dont_sync_undo = TRUE; + else + dont_sync_undo = FALSE; do { c = safe_vgetc(); @@ -1237,7 +1247,7 @@ doESCkey: if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) ins_s_left(); else - ins_left(); + ins_left(dont_sync_undo == FALSE); break; case K_S_LEFT: /* */ @@ -1249,7 +1259,7 @@ doESCkey: if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) ins_s_right(); else - ins_right(); + ins_right(dont_sync_undo == FALSE); break; case K_S_RIGHT: /* */ @@ -6787,9 +6797,34 @@ redo_literal(c) */ static void start_arrow(end_insert_pos) - pos_T *end_insert_pos; /* can be NULL */ + pos_T *end_insert_pos; /* can be NULL */ +{ + start_arrow_common(end_insert_pos, TRUE); +} + +/* + * Like start_arrow() but with end_change argument. + * Will prepare for redo of CTRL-G U if "end_change" is FALSE. + */ + static void +start_arrow_with_change(end_insert_pos, end_change) + pos_T *end_insert_pos; /* can be NULL */ + int end_change; /* end undoable change */ { - if (!arrow_used) /* something has been inserted */ + start_arrow_common(end_insert_pos, end_change); + if (!end_change) + { + AppendCharToRedobuff(Ctrl_G); + AppendCharToRedobuff('U'); + } +} + + static void +start_arrow_common(end_insert_pos, end_change) + pos_T *end_insert_pos; /* can be NULL */ + int end_change; /* end undoable change */ +{ + if (!arrow_used && end_change) /* something has been inserted */ { AppendToRedobuff(ESC_STR); stop_insert(end_insert_pos, FALSE, FALSE); @@ -8359,6 +8394,13 @@ ins_ctrl_g() Insstart = curwin->w_cursor; break; + /* CTRL-G U: do not break undo with the next char */ + case 'U': + /* Allow one left/right cursor movement with the next char, + * without breaking undo. */ + dont_sync_undo = MAYBE; + break; + /* Unknown CTRL-G command, reserved for future expansion. */ default: vim_beep(BO_CTRLG); } @@ -9440,7 +9482,8 @@ ins_horscroll() #endif static void -ins_left() +ins_left(end_change) + int end_change; /* end undoable change */ { pos_T tpos; @@ -9457,7 +9500,11 @@ ins_left() * break undo. K_LEFT is inserted in im_correct_cursor(). */ if (!im_is_preediting()) #endif - start_arrow(&tpos); + { + start_arrow_with_change(&tpos, end_change); + if (!end_change) + AppendCharToRedobuff(K_LEFT); + } #ifdef FEAT_RIGHTLEFT /* If exit reversed string, position is fixed */ if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) @@ -9472,6 +9519,7 @@ ins_left() */ else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1) { + /* always break undo when moving upwards/downwards, else undo may break */ start_arrow(&tpos); --(curwin->w_cursor.lnum); coladvance((colnr_T)MAXCOL); @@ -9479,6 +9527,7 @@ ins_left() } else vim_beep(BO_CRSR); + dont_sync_undo = FALSE; } static void @@ -9542,7 +9591,8 @@ ins_s_left() } static void -ins_right() +ins_right(end_change) + int end_change; /* end undoable change */ { #ifdef FEAT_FOLDING if ((fdo_flags & FDO_HOR) && KeyTyped) @@ -9555,7 +9605,9 @@ ins_right() #endif ) { - start_arrow(&curwin->w_cursor); + start_arrow_with_change(&curwin->w_cursor, end_change); + if (!end_change) + AppendCharToRedobuff(K_RIGHT); curwin->w_set_curswant = TRUE; #ifdef FEAT_VIRTUALEDIT if (virtual_active()) @@ -9589,6 +9641,7 @@ ins_right() } else vim_beep(BO_CRSR); + dont_sync_undo = FALSE; } static void diff --git a/src/testdir/test_mapping.in b/src/testdir/test_mapping.in index d6c1b2d5db..f900f421e2 100644 --- a/src/testdir/test_mapping.in +++ b/src/testdir/test_mapping.in @@ -45,6 +45,21 @@ o+ :/^a b 0qqdw.ifooqj0@q:unmap . +:" U works only within a single line +:imapclear +:imap ( ()U +G2oki +Test1: text with a (here some more textk. +:" test undo +G2oki +Test2: text wit a (here some more text [und undo]uk.u +:" +:imapclear +:set whichwrap=<,>,[,] +G3o2k +:exe ":norm! iTest3: text with a (parenthesis here\U\new line here\\\." + + :/^test/,$w! test.out :qa! diff --git a/src/testdir/test_mapping.ok b/src/testdir/test_mapping.ok index 51cc49bf7d..b493cff2b1 100644 --- a/src/testdir/test_mapping.ok +++ b/src/testdir/test_mapping.ok @@ -10,3 +10,13 @@ vmap works + + + + +Test1: text with a (here some more text) +Test1: text with a (here some more text) + + +Test2: text wit a (here some more text [und undo]) + +new line here +Test3: text with a (parenthesis here +new line here diff --git a/src/version.c b/src/version.c index b50521b626..eac1f1b173 100644 --- a/src/version.c +++ b/src/version.c @@ -741,6 +741,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 849, /**/ 848, /**/ -- cgit v1.2.3