On Di, 04 Aug 2015, Bram Moolenaar wrote:

> Jacob Niehus wrote:
> 
> > I would love to see this in mainline as well. I've been using it quite
> > extensively for four months now with these maps to move the cursor
> > left/right by word/WORD and to the first column, first non-blank, and
> > last column without breaking undo:
> > 
> > " Move cursor in insert mode without splitting undo
> > 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('.'))
> > imap <C-b> <Home>
> > imap <C-e> <End>
> > 
> > Here's an update to the patch that applies cleanly to Vim 7.4.803.
> 
> This appears to be OK to include.  However, a test is missing.
> Especially that using this at the end of the line, then a cursor-right
> should work as before, because it moves to the next line.

Here is an update, including 3 tests.

Mit freundlichen Grüßen
Christian
-- 
Viele Menschen versäumen das kleine Glück, während sie auf das große
vergebens warten.
                -- Pearl Sydenstricker Buck (Pseudonym: Sedges, John)

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
# HG changeset patch
# Parent e5298cdcba7cd36f422816c9e879047d5ff066a9
Do not break undo on left/right with <C-G>U

From https://groups.google.com/d/msg/vim_use/klj6nlDOriI/aeNjtWp_U80J
This will allow to use <C-G>U<Left> and <C-G>U<Right> to move the cursor 
without breaking the undo sequence.
However, a new undo change will be created if left/right move across lines, so 
that undo is still workable.

This should fix the problem to undo/redo delimate like plugins (hopefully).

Example:

imap ( ()<C-G>U<Left>

Now enter foobar(eins

'.' on a new empty line will now repeat to:

foobar(eins)

Suggested mappings:

" Move cursor in insert mode without splitting undo
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('.'))
imap <C-b> <Home>
imap <C-e> <End>

diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -377,6 +377,9 @@ CTRL-O              execute one command, return to I
 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-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*
+               (but only if the cursor stays within same
+               the line)
 -----------------------------------------------------------------------
 
 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.
 
+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: >
+
+   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
 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: >
diff --git a/src/edit.c b/src/edit.c
--- a/src/edit.c
+++ b/src/edit.c
@@ -201,7 +201,7 @@ static void insert_special __ARGS((int, 
 static void internal_format __ARGS((int textwidth, int second_indent, int 
flags, int format_only, int c));
 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 __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 +241,11 @@ static void ins_mousescroll __ARGS((int 
 #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 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 change));
 static void ins_s_right __ARGS((void));
 static void ins_up __ARGS((int startcol));
 static void ins_pageup __ARGS((void));
@@ -297,6 +297,8 @@ static int  ins_need_undo;          /* call u_sav
 
 static int     did_add_space = FALSE;  /* auto_format() added an extra space
                                           under the cursor */
+static int     stop_sync_undo = FALSE; /* CTRL-G U prevents syncing undo for
+                                          the next left/right cursor */
 
 /*
  * edit(): Start inserting text.
@@ -767,6 +769,11 @@ edit(cmdchar, startln, count)
         */
        if (c != K_CURSORHOLD)
            lastc = c;          /* remember the previous char for CTRL-D */
+
+       if (stop_sync_undo == MAYBE)    /* cursor might come next */
+           stop_sync_undo = TRUE;
+       else
+           stop_sync_undo = FALSE;     /* sync undo with next char, if needed 
*/
        do
        {
            c = safe_vgetc();
@@ -1237,7 +1244,7 @@ doESCkey:
            if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
                ins_s_left();
            else
-               ins_left();
+               ins_left(stop_sync_undo == FALSE);
            break;
 
        case K_S_LEFT:  /* <S-Left> */
@@ -1249,7 +1256,7 @@ doESCkey:
            if (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))
                ins_s_right();
            else
-               ins_right();
+               ins_right(stop_sync_undo == FALSE);
            break;
 
        case K_S_RIGHT: /* <S-Right> */
@@ -6786,10 +6793,11 @@ redo_literal(c)
  * For undo/redo it resembles hitting the <ESC> key.
  */
     static void
-start_arrow(end_insert_pos)
+start_arrow(end_insert_pos, change)
     pos_T    *end_insert_pos;      /* can be NULL */
-{
-    if (!arrow_used)       /* something has been inserted */
+    int              change;               /* if true, start a new change */
+{
+    if (!arrow_used && change)     /* something has been inserted */
     {
        AppendToRedobuff(ESC_STR);
        stop_insert(end_insert_pos, FALSE, FALSE);
@@ -6828,7 +6836,7 @@ spell_back_to_badword()
 
     spell_bad_len = spell_move_to(curwin, BACKWARD, TRUE, TRUE, NULL);
     if (curwin->w_cursor.col != tpos.col)
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 }
 #endif
 
@@ -8359,6 +8367,12 @@ 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 */
+                 stop_sync_undo = MAYBE;
+                 break;
+
        /* Unknown CTRL-G command, reserved for future expansion. */
        default:  vim_beep(BO_CTRLG);
     }
@@ -9267,7 +9281,7 @@ ins_mouse(c)
            curbuf = curwin->w_buffer;
        }
 #endif
-       start_arrow(curwin == old_curwin ? &tpos : NULL);
+       start_arrow(curwin == old_curwin ? &tpos : NULL, TRUE);
 #ifdef FEAT_WINDOWS
        if (curwin != new_curwin && win_valid(new_curwin))
        {
@@ -9371,7 +9385,7 @@ ins_mousescroll(dir)
 
     if (!equalpos(curwin->w_cursor, tpos))
     {
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 # ifdef FEAT_CINDENT
        can_cindent = TRUE;
 # endif
@@ -9389,7 +9403,7 @@ ins_tabline(c)
                || (current_tab != 0 && current_tab != tabpage_index(curtab)))
     {
        undisplay_dollar();
-       start_arrow(&curwin->w_cursor);
+       start_arrow(&curwin->w_cursor, TRUE);
 # ifdef FEAT_CINDENT
        can_cindent = TRUE;
 # endif
@@ -9415,7 +9429,7 @@ ins_scroll()
     tpos = curwin->w_cursor;
     if (gui_do_scroll())
     {
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 # ifdef FEAT_CINDENT
        can_cindent = TRUE;
 # endif
@@ -9431,7 +9445,7 @@ ins_horscroll()
     tpos = curwin->w_cursor;
     if (gui_do_horiz_scroll(scrollbar_value, FALSE))
     {
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 # ifdef FEAT_CINDENT
        can_cindent = TRUE;
 # endif
@@ -9440,7 +9454,8 @@ ins_horscroll()
 #endif
 
     static void
-ins_left()
+ins_left(change)
+    int            change; /* start a new change */
 {
     pos_T      tpos;
 
@@ -9457,7 +9472,15 @@ ins_left()
         * break undo.  K_LEFT is inserted in im_correct_cursor(). */
        if (!im_is_preediting())
 #endif
-           start_arrow(&tpos);
+       {
+           start_arrow(&tpos, change);
+           if (!change)
+           {
+               AppendCharToRedobuff(Ctrl_G);
+               AppendCharToRedobuff('U');
+               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,13 +9495,15 @@ ins_left()
      */
     else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
     {
-       start_arrow(&tpos);
+       /* always break undo when moving upwards/downwards, else undo may break 
*/
+       start_arrow(&tpos, TRUE);
        --(curwin->w_cursor.lnum);
        coladvance((colnr_T)MAXCOL);
        curwin->w_set_curswant = TRUE;  /* so we stay at the end */
     }
     else
        vim_beep(BO_CRSR);
+    stop_sync_undo = FALSE;
 }
 
     static void
@@ -9500,7 +9525,7 @@ ins_home(c)
     curwin->w_cursor.coladd = 0;
 #endif
     curwin->w_curswant = 0;
-    start_arrow(&tpos);
+    start_arrow(&tpos, TRUE);
 }
 
     static void
@@ -9520,7 +9545,7 @@ ins_end(c)
     coladvance((colnr_T)MAXCOL);
     curwin->w_curswant = MAXCOL;
 
-    start_arrow(&tpos);
+    start_arrow(&tpos, TRUE);
 }
 
     static void
@@ -9533,7 +9558,7 @@ ins_s_left()
     undisplay_dollar();
     if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
     {
-       start_arrow(&curwin->w_cursor);
+       start_arrow(&curwin->w_cursor, TRUE);
        (void)bck_word(1L, FALSE, FALSE);
        curwin->w_set_curswant = TRUE;
     }
@@ -9542,7 +9567,8 @@ ins_s_left()
 }
 
     static void
-ins_right()
+ins_right(change)
+    int            change; /* start a new change */
 {
 #ifdef FEAT_FOLDING
     if ((fdo_flags & FDO_HOR) && KeyTyped)
@@ -9555,7 +9581,13 @@ ins_right()
 #endif
            )
     {
-       start_arrow(&curwin->w_cursor);
+       start_arrow(&curwin->w_cursor, change);
+       if (!change)
+           {
+               AppendCharToRedobuff(Ctrl_G);
+               AppendCharToRedobuff('U');
+               AppendCharToRedobuff(K_RIGHT);
+           }
        curwin->w_set_curswant = TRUE;
 #ifdef FEAT_VIRTUALEDIT
        if (virtual_active())
@@ -9582,13 +9614,14 @@ ins_right()
     else if (vim_strchr(p_ww, ']') != NULL
            && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
     {
-       start_arrow(&curwin->w_cursor);
+       start_arrow(&curwin->w_cursor, TRUE);
        curwin->w_set_curswant = TRUE;
        ++curwin->w_cursor.lnum;
        curwin->w_cursor.col = 0;
     }
     else
        vim_beep(BO_CRSR);
+    stop_sync_undo = FALSE;
 }
 
     static void
@@ -9602,7 +9635,7 @@ ins_s_right()
     if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
            || gchar_cursor() != NUL)
     {
-       start_arrow(&curwin->w_cursor);
+       start_arrow(&curwin->w_cursor, TRUE);
        (void)fwd_word(1L, FALSE, 0);
        curwin->w_set_curswant = TRUE;
     }
@@ -9632,7 +9665,7 @@ ins_up(startcol)
 #endif
                )
            redraw_later(VALID);
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 #ifdef FEAT_CINDENT
        can_cindent = TRUE;
 #endif
@@ -9654,7 +9687,7 @@ ins_pageup()
        /* <C-PageUp>: tab page back */
        if (first_tabpage->tp_next != NULL)
        {
-           start_arrow(&curwin->w_cursor);
+           start_arrow(&curwin->w_cursor, TRUE);
            goto_tabpage(-1);
        }
        return;
@@ -9664,7 +9697,7 @@ ins_pageup()
     tpos = curwin->w_cursor;
     if (onepage(BACKWARD, 1L) == OK)
     {
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 #ifdef FEAT_CINDENT
        can_cindent = TRUE;
 #endif
@@ -9695,7 +9728,7 @@ ins_down(startcol)
 #endif
                )
            redraw_later(VALID);
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 #ifdef FEAT_CINDENT
        can_cindent = TRUE;
 #endif
@@ -9717,7 +9750,7 @@ ins_pagedown()
        /* <C-PageDown>: tab page forward */
        if (first_tabpage->tp_next != NULL)
        {
-           start_arrow(&curwin->w_cursor);
+           start_arrow(&curwin->w_cursor, TRUE);
            goto_tabpage(0);
        }
        return;
@@ -9727,7 +9760,7 @@ ins_pagedown()
     tpos = curwin->w_cursor;
     if (onepage(FORWARD, 1L) == OK)
     {
-       start_arrow(&tpos);
+       start_arrow(&tpos, TRUE);
 #ifdef FEAT_CINDENT
        can_cindent = TRUE;
 #endif
diff --git a/src/testdir/test_mapping.in b/src/testdir/test_mapping.in
--- a/src/testdir/test_mapping.in
+++ b/src/testdir/test_mapping.in
@@ -45,6 +45,21 @@ o+
 :/^a b
 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
 :qa!
diff --git a/src/testdir/test_mapping.ok b/src/testdir/test_mapping.ok
--- 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

Raspunde prin e-mail lui