0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

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)
This commit is contained in:
Bram Moolenaar
2015-09-01 19:26:12 +02:00
parent 5adfea1ac6
commit 8b5f65a527
5 changed files with 115 additions and 10 deletions

View File

@@ -377,6 +377,9 @@ CTRL-O execute one command, return to Insert mode *i_CTRL-O*
CTRL-\ CTRL-O like CTRL-O but don't move the cursor *i_CTRL-\_CTRL-O* CTRL-\ CTRL-O like CTRL-O but don't move the cursor *i_CTRL-\_CTRL-O*
CTRL-L when 'insertmode' is set: go to Normal mode *i_CTRL-L* CTRL-L when 'insertmode' is set: go to Normal mode *i_CTRL-L*
CTRL-G u break undo sequence, start new change *i_CTRL-G_u* CTRL-G u break undo sequence, start new change *i_CTRL-G_u*
CTRL-G U don't break undo with next left/right cursor *i_CTRL-G_U*
movement (but only if the cursor stays
within same the line)
----------------------------------------------------------------------- -----------------------------------------------------------------------
Note: If the cursor keys take you out of Insert mode, check the 'noesckeys' Note: If the cursor keys take you out of Insert mode, check the 'noesckeys'
@@ -416,6 +419,28 @@ that, with CTRL-O u. Another example: >
This breaks undo at each line break. It also expands abbreviations before This breaks undo at each line break. It also expands abbreviations before
this. this.
An example for using CTRL-G U: >
inoremap <Left> <C-G>U<Left>
inoremap <Right> <C-G>U<Right>
inoremap <expr> <Home> col('.') == match(getline('.'), '\S') + 1 ?
\ repeat('<C-G>U<Left>', col('.') - 1) :
\ (col('.') < match(getline('.'), '\S') ?
\ repeat('<C-G>U<Right>', match(getline('.'), '\S') + 0) :
\ repeat('<C-G>U<Left>', col('.') - 1 - match(getline('.'), '\S')))
inoremap <expr> <End> repeat('<C-G>U<Right>', col('$') - col('.'))
inoremap ( ()<C-G>U<Left>
This makes it possible to use the cursor keys in Insert mode, without breaking
the undo sequence and therefore using |.| (redo) will work as expected.
Also entering a text like (with the "(" mapping from above): >
Lorem ipsum (dolor
will be repeatable by the |.|to the expected
Lorem ipsum (dolor)
Using CTRL-O splits undo: the text typed before and after it is undone Using CTRL-O splits undo: the text typed before and after it is undone
separately. If you want to avoid this (e.g., in a mapping) you might be able separately. If you want to avoid this (e.g., in a mapping) you might be able
to use CTRL-R = |i_CTRL-R|. E.g., to call a function: > to use CTRL-R = |i_CTRL-R|. E.g., to call a function: >

View File

@@ -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 check_auto_format __ARGS((int));
static void redo_literal __ARGS((int c)); static void redo_literal __ARGS((int c));
static void start_arrow __ARGS((pos_T *end_insert_pos)); 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 #ifdef FEAT_SPELL
static void check_spell_redraw __ARGS((void)); static void check_spell_redraw __ARGS((void));
static void spell_back_to_badword __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) #if defined(FEAT_GUI_TABLINE) || defined(PROTO)
static void ins_tabline __ARGS((int c)); static void ins_tabline __ARGS((int c));
#endif #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_home __ARGS((int c));
static void ins_end __ARGS((int c)); static void ins_end __ARGS((int c));
static void ins_s_left __ARGS((void)); 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_s_right __ARGS((void));
static void ins_up __ARGS((int startcol)); static void ins_up __ARGS((int startcol));
static void ins_pageup __ARGS((void)); 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 static int did_add_space = FALSE; /* auto_format() added an extra space
under the cursor */ 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. * edit(): Start inserting text.
@@ -767,6 +771,12 @@ edit(cmdchar, startln, count)
*/ */
if (c != K_CURSORHOLD) if (c != K_CURSORHOLD)
lastc = c; /* remember the previous char for CTRL-D */ 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 do
{ {
c = safe_vgetc(); c = safe_vgetc();
@@ -1237,7 +1247,7 @@ doESCkey:
if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
ins_s_left(); ins_s_left();
else else
ins_left(); ins_left(dont_sync_undo == FALSE);
break; break;
case K_S_LEFT: /* <S-Left> */ case K_S_LEFT: /* <S-Left> */
@@ -1249,7 +1259,7 @@ doESCkey:
if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL)) if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
ins_s_right(); ins_s_right();
else else
ins_right(); ins_right(dont_sync_undo == FALSE);
break; break;
case K_S_RIGHT: /* <S-Right> */ case K_S_RIGHT: /* <S-Right> */
@@ -6789,7 +6799,32 @@ redo_literal(c)
start_arrow(end_insert_pos) start_arrow(end_insert_pos)
pos_T *end_insert_pos; /* can be NULL */ pos_T *end_insert_pos; /* can be NULL */
{ {
if (!arrow_used) /* something has been inserted */ 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 */
{
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); AppendToRedobuff(ESC_STR);
stop_insert(end_insert_pos, FALSE, FALSE); stop_insert(end_insert_pos, FALSE, FALSE);
@@ -8359,6 +8394,13 @@ ins_ctrl_g()
Insstart = curwin->w_cursor; Insstart = curwin->w_cursor;
break; 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. */ /* Unknown CTRL-G command, reserved for future expansion. */
default: vim_beep(BO_CTRLG); default: vim_beep(BO_CTRLG);
} }
@@ -9440,7 +9482,8 @@ ins_horscroll()
#endif #endif
static void static void
ins_left() ins_left(end_change)
int end_change; /* end undoable change */
{ {
pos_T tpos; pos_T tpos;
@@ -9457,7 +9500,11 @@ ins_left()
* break undo. K_LEFT is inserted in im_correct_cursor(). */ * break undo. K_LEFT is inserted in im_correct_cursor(). */
if (!im_is_preediting()) if (!im_is_preediting())
#endif #endif
start_arrow(&tpos); {
start_arrow_with_change(&tpos, end_change);
if (!end_change)
AppendCharToRedobuff(K_LEFT);
}
#ifdef FEAT_RIGHTLEFT #ifdef FEAT_RIGHTLEFT
/* If exit reversed string, position is fixed */ /* If exit reversed string, position is fixed */
if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol) 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) 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); start_arrow(&tpos);
--(curwin->w_cursor.lnum); --(curwin->w_cursor.lnum);
coladvance((colnr_T)MAXCOL); coladvance((colnr_T)MAXCOL);
@@ -9479,6 +9527,7 @@ ins_left()
} }
else else
vim_beep(BO_CRSR); vim_beep(BO_CRSR);
dont_sync_undo = FALSE;
} }
static void static void
@@ -9542,7 +9591,8 @@ ins_s_left()
} }
static void static void
ins_right() ins_right(end_change)
int end_change; /* end undoable change */
{ {
#ifdef FEAT_FOLDING #ifdef FEAT_FOLDING
if ((fdo_flags & FDO_HOR) && KeyTyped) if ((fdo_flags & FDO_HOR) && KeyTyped)
@@ -9555,7 +9605,9 @@ ins_right()
#endif #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; curwin->w_set_curswant = TRUE;
#ifdef FEAT_VIRTUALEDIT #ifdef FEAT_VIRTUALEDIT
if (virtual_active()) if (virtual_active())
@@ -9589,6 +9641,7 @@ ins_right()
} }
else else
vim_beep(BO_CRSR); vim_beep(BO_CRSR);
dont_sync_undo = FALSE;
} }
static void static void

View File

@@ -45,6 +45,21 @@ o+
:/^a b :/^a b
0qqdw.ifooqj0@q:unmap . 0qqdw.ifooqj0@q:unmap .
:" <c-g>U<cursor> works only within a single line
:imapclear
:imap ( ()<c-g>U<left>
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\<C-G>U\<Right>new line here\<esc>\<up>\<up>."
:/^test/,$w! test.out :/^test/,$w! test.out
:qa! :qa!

View File

@@ -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

View File

@@ -741,6 +741,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
849,
/**/ /**/
848, 848,
/**/ /**/