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:
@@ -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: >
|
||||||
|
71
src/edit.c
71
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 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
|
||||||
|
@@ -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!
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user