Sunday, August 2, 2015

Re: Any automatic bracket-insertion plugins not breaking undo?

# HG changeset patch
# Parent 691a69ae71349cc2f6bd796055c0c9a759228f81
Make <M-Left> and <M-Right> move the cursor in insert mode without breaking undo

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 changae 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).

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-\ 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'
diff --git a/src/edit.c b/src/edit.c
--- a/src/edit.c
+++ b/src/edit.c
@@ -201,7 +201,7 @@
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 @@
#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 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 @@
*/
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 @@
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 @@
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 @@
* 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_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 @@
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 @@
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 @@

if (!equalpos(curwin->w_cursor, tpos))
{
- start_arrow(&tpos);
+ start_arrow(&tpos, TRUE);
# ifdef FEAT_CINDENT
can_cindent = TRUE;
# endif
@@ -9389,7 +9403,7 @@
|| (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 @@
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 @@
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 @@
#endif

static void
-ins_left()
+ins_left(change)
+ int change; /* start a new change */
{
pos_T tpos;

@@ -9457,7 +9472,15 @@
* 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 @@
*/
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 @@
curwin->w_cursor.coladd = 0;
#endif
curwin->w_curswant = 0;
- start_arrow(&tpos);
+ start_arrow(&tpos, TRUE);
}

static void
@@ -9520,7 +9545,7 @@
coladvance((colnr_T)MAXCOL);
curwin->w_curswant = MAXCOL;

- start_arrow(&tpos);
+ start_arrow(&tpos, TRUE);
}

static void
@@ -9533,7 +9558,7 @@
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 @@
}

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 @@
#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 @@
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 @@
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 @@
#endif
)
redraw_later(VALID);
- start_arrow(&tpos);
+ start_arrow(&tpos, TRUE);
#ifdef FEAT_CINDENT
can_cindent = TRUE;
#endif
@@ -9654,7 +9687,7 @@
/* <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 @@
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 @@
#endif
)
redraw_later(VALID);
- start_arrow(&tpos);
+ start_arrow(&tpos, TRUE);
#ifdef FEAT_CINDENT
can_cindent = TRUE;
#endif
@@ -9717,7 +9750,7 @@
/* <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 @@
tpos = curwin->w_cursor;
if (onepage(FORWARD, 1L) == OK)
{
- start_arrow(&tpos);
+ start_arrow(&tpos, TRUE);
#ifdef FEAT_CINDENT
can_cindent = TRUE;
#endif
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.

-Jake

--
--
You received this message from the "vim_use" 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_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment