diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/edit.c | 77 | ||||
-rw-r--r-- | src/nvim/version.c | 2 |
2 files changed, 59 insertions, 20 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 2d6dcf4f80..b2f9601f82 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -228,6 +228,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. @@ -611,6 +613,13 @@ edit ( * Get a character for Insert mode. Ignore K_IGNORE. */ lastc = c; /* remember 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; + input_enable_events(); do { c = safe_vgetc(); @@ -988,7 +997,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: /* <S-Left> */ @@ -1000,7 +1009,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: /* <S-Right> */ @@ -5627,16 +5636,31 @@ static void redo_literal(int c) AppendCharToRedobuff(c); } -/* - * start_arrow() is called when an arrow key is used in insert mode. - * For undo/redo it resembles hitting the <ESC> key. - */ -static void -start_arrow ( - pos_T *end_insert_pos /* can be NULL */ -) +// start_arrow() is called when an arrow key is used in insert mode. +// For undo/redo it resembles hitting the <ESC> key. +static void start_arrow(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. +/// @param end_insert_pos can be NULL +/// @param end_change end undoable change +static void start_arrow_with_change(pos_T *end_insert_pos, bool end_change) { - if (!arrow_used) { /* something has been inserted */ + start_arrow_common(end_insert_pos, end_change); + if (!end_change) { + AppendCharToRedobuff(Ctrl_G); + AppendCharToRedobuff('U'); + } +} + +/// @param end_insert_pos can be NULL +/// @param end_change end undoable change +static void start_arrow_common(pos_T *end_insert_pos, bool end_change) +{ + if (!arrow_used && end_change) { // something has been inserted AppendToRedobuff(ESC_STR); stop_insert(end_insert_pos, FALSE, FALSE); arrow_used = TRUE; /* this means we stopped the current insert */ @@ -6903,6 +6927,13 @@ static void ins_ctrl_g(void) 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); } @@ -7649,7 +7680,7 @@ static void ins_mousescroll(int dir) -static void ins_left(void) +static void ins_left(bool end_change) { pos_T tpos; @@ -7658,7 +7689,10 @@ static void ins_left(void) undisplay_dollar(); tpos = curwin->w_cursor; if (oneleft() == OK) { - start_arrow(&tpos); + start_arrow_with_change(&tpos, end_change); + if (!end_change) { + AppendCharToRedobuff(K_LEFT); + } /* If exit reversed string, position is fixed */ if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) revins_legal++; @@ -7669,6 +7703,7 @@ static void ins_left(void) * previous line */ 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); @@ -7676,6 +7711,7 @@ static void ins_left(void) } else { vim_beep(BO_CRSR); } + dont_sync_undo = false; } static void ins_home(int c) @@ -7724,16 +7760,18 @@ static void ins_s_left(void) } } -static void ins_right(void) +/// @param end_change end undoable change +static void ins_right(bool end_change) { if ((fdo_flags & FDO_HOR) && KeyTyped) foldOpenCursor(); undisplay_dollar(); - if (gchar_cursor() != NUL - || virtual_active() - ) { - start_arrow(&curwin->w_cursor); - curwin->w_set_curswant = TRUE; + if (gchar_cursor() != NUL || virtual_active()) { + start_arrow_with_change(&curwin->w_cursor, end_change); + if (!end_change) { + AppendCharToRedobuff(K_RIGHT); + } + curwin->w_set_curswant = true; if (virtual_active()) oneright(); else { @@ -7758,6 +7796,7 @@ static void ins_right(void) } else { vim_beep(BO_CRSR); } + dont_sync_undo = false; } static void ins_s_right(void) diff --git a/src/nvim/version.c b/src/nvim/version.c index 3b80336817..7cc72705b6 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -72,7 +72,7 @@ static char *features[] = { // clang-format off static int included_patches[] = { // 850, - // 849, + 849, // 848, // 847, // 846, |