vim-patch:9.2.0415: Wrong behavior when executing register that ends in Insert mode (#39518)

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:  vim/vim#20085
closes: vim/vim#20091

6453a7c440
This commit is contained in:
zeertzjq
2026-04-30 19:14:28 +08:00
committed by GitHub
parent c79d5f5028
commit 071f9748c0
2 changed files with 35 additions and 15 deletions

View File

@@ -539,19 +539,19 @@ static int put_in_typebuf(char *s, bool esc, bool colon, int silent)
/// used only after other typeahead has been processed.
static void put_reedit_in_typebuf(int silent)
{
uint8_t buf[3];
if (restart_edit == NUL) {
return;
}
if (restart_edit == 'V') {
buf[0] = 'g';
buf[1] = 'R';
buf[2] = NUL;
} else {
buf[0] = (uint8_t)(restart_edit == 'I' ? 'i' : restart_edit);
buf[1] = NUL;
uint8_t 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((char *)buf, REMAP_NONE, 0, true, silent) == OK) {
restart_edit = NUL;

View File

@@ -529,21 +529,41 @@ func Test_clipboard_regs()
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