Commit: patch 9.2.0415: Wrong behavior when executing register that ends in Insert mode

6 views
Skip to first unread message

Christian Brabandt

unread,
Apr 29, 2026, 12:15:16 PMApr 29
to vim...@googlegroups.com
patch 9.2.0415: Wrong behavior when executing register that ends in Insert mode

Commit: https://github.com/vim/vim/commit/6453a7c440648f938a9bde83213ffcf3903f44be
Author: zeertzjq <zeer...@outlook.com>
Date: Wed Apr 29 16:10:04 2026 +0000

patch 9.2.0415: Wrong behavior when executing register that ends in Insert mode

Problem: Wrong behavior when executing register that ends in Insert
mode from Ctrl-O (Emilien Breton)
Solution: Use :startinsert etc. to restore Insert mode after executing
the register contents (zeertzjq).

fixes: #20085
closes: #20091

Signed-off-by: zeertzjq <zeer...@outlook.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/register.c b/src/register.c
index 9eeb88f44..9f0e06b54 100644
--- a/src/register.c
+++ b/src/register.c
@@ -787,22 +787,18 @@ do_execreg(
static void
put_reedit_in_typebuf(int silent)
{
- char_u buf[3];
-
if (restart_edit == NUL)
return;

- if (restart_edit == 'V')
- {
- buf[0] = 'g';
- buf[1] = 'R';
- buf[2] = NUL;
- }
- else
- {
- buf[0] = restart_edit == 'I' ? 'i' : restart_edit;
- buf[1] = NUL;
- }
+ char_u buf[] = { K_SPECIAL, KS_EXTRA, KE_COMMAND,
+ // :startinsert
+ 's', 't', 'a', 'r', 't', 'i', CAR, NUL };
+ if (restart_edit == 'R')
+ buf[8] = 'r'; // :startreplace
+ else if (restart_edit == 'V')
+ buf[8] = 'g'; // :startgreplace
+ else if (restart_edit == 'A')
+ buf[8] = '!'; // :startinsert!
if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, silent) == OK)
restart_edit = NUL;
}
diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim
index 245340c82..bb1dd31f3 100644
--- a/src/testdir/test_registers.vim
+++ b/src/testdir/test_registers.vim
@@ -582,21 +582,41 @@ func Test_clipboard_regs_both_unnamed()
bwipe!
endfunc

-" Test for restarting the current mode (insert or virtual replace) after
+" Test for restarting the current mode (insert or (virtual) replace) after
" executing the contents of a register
-func Test_put_reg_restart_mode()
+func Test_exec_reg_restart_mode()
new
- call append(0, 'editor')
- normal gg
+
let @r = "ivim \<Esc>"
- call feedkeys("i\<C-O>@r\<C-R>=mode()\<CR>", 'xt')
+
+ call setline(1, 'editor')
+ normal gg
+ call feedkeys("i\<C-O>@r\<C-R>=mode(1)\<CR>", 'xt')
call assert_equal('vimi editor', getline(1))

call setline(1, 'editor')
normal gg
- call feedkeys("gR\<C-O>@r\<C-R>=mode()\<CR>", 'xt')
+ call feedkeys("R\<C-O>@r\<C-R>=mode(1)\<CR>", 'xt')
call assert_equal('vimReditor', getline(1))

+ call setline(1, 'editor')
+ normal gg
+ call feedkeys("gR\<C-O>@r\<C-R>=mode(1)\<CR>", 'xt')
+ call assert_equal('vimRvditor', getline(1))
+
+ " If the register doesn't return to Normal mode, Vim should stay in whatever
+ " mode the register ends up with, and should not insert extra text. #20085
+ for [s0, expected] in
+ \ [['i', 'vim editor,i'], ['R', 'vim or,R'], ['gR', 'vim or,Rv']]
+ let @r = $"{s0}vim "
+ for s1 in ['i', 'R', 'gR']
+ call setline(1, 'editor')
+ normal gg
+ call feedkeys($"{s1}\<C-O>@r\<End>,\<C-R>=mode(1)\<CR>", 'xt')
+ call assert_equal(expected, getline(1))
+ endfor
+ endfor
+
bwipe!
endfunc

diff --git a/src/version.c b/src/version.c
index 08ebffbb5..c54177a4a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 415,
/**/
414,
/**/
Reply all
Reply to author
Forward
0 new messages