vim-patch:9.2.0827: :startinsert enters Insert mode in a non-modifiable buffer (#40906)

Problem:  ":startinsert" enters Insert mode in a buffer where
          'modifiable' is off, the error only appears when a character
          is typed.  Typing "i" gives the error right away (Barrett Ruth)
Solution: Give the error when the buffer is not modifiable, like "i"
          does.  Keep ignoring the command in a terminal window, where
          ":startinsert" is documented to be ineffective, and keep
          accepting it when 'insertmode' is set, like "i" does
          (Hirohito Higashi).

fixes:  vim/vim#20804
closes: vim/vim#20806

6ab1976e49

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
This commit is contained in:
zeertzjq
2026-07-22 22:03:05 +08:00
committed by GitHub
parent bd73d8c011
commit 47e97c1ad6
2 changed files with 57 additions and 0 deletions

View File

@@ -7380,6 +7380,10 @@ static void ex_normal(exarg_T *eap)
/// ":startinsert", ":startreplace" and ":startgreplace"
static void ex_startinsert(exarg_T *eap)
{
if (!curbuf->b_p_ma && !curbuf->terminal) {
emsg(_(e_modifiable));
return;
}
if (eap->forceit) {
// cursor line can be zero on startup
if (!curwin->w_cursor.lnum) {

View File

@@ -1780,10 +1780,50 @@ func Test_edit_startinsert()
call feedkeys(":startinsert!\<CR>\<C-U>\<Esc>", 'xt')
call assert_equal('', getline(1))
call setline(1, 'foobar')
setl nomodifiable
call assert_fails('startinsert', 'E21:')
call cursor(1, 1)
call assert_fails('startinsert!', 'E21:')
call assert_equal(1, col('.'))
set backspace&
bwipe!
endfunc
" ":startinsert" is ineffective in a terminal window: it must not give an
" error and with "!" it must not move the cursor.
func Test_edit_startinsert_in_terminal()
CheckFeature terminal
let buf = Run_shell_in_terminal({})
" Fill the terminal with text.
if has('win32')
call feedkeys("dir\<CR>", 'xt')
else
call feedkeys("ls\<CR>", 'xt')
endif
call WaitForAssert({-> assert_notequal('', term_getline(buf, 1))})
" Go to Terminal-Normal mode and put the cursor on a line with text.
call feedkeys("\<C-W>N", 'xt')
call assert_notequal(0, search('\S', 'w'))
call cursor(line('.'), 1)
startinsert
startinsert!
call assert_equal(1, col('.'))
" Clear "restart_edit" in case the commands were not ignored.
stopinsert
call feedkeys("i", 'xt')
call StopShellInTerminal(buf)
bwipe!
endfunc
" Test for :startreplace and :startgreplace
func Test_edit_startreplace()
new
@@ -1797,6 +1837,19 @@ func Test_edit_startreplace()
call assert_equal("axyz\tb", getline(1))
call feedkeys("0i\<C-R>=execute('startreplace')\<CR>12\e", 'xt')
call assert_equal("12axyz\tb", getline(1))
call setline(1, 'abc')
setl nomodifiable
call assert_fails('startreplace', 'E21:')
call assert_fails('startgreplace', 'E21:')
call cursor(1, 1)
call assert_fails('startreplace!', 'E21:')
call assert_equal(1, col('.'))
call cursor(1, 1)
call assert_fails('startgreplace!', 'E21:')
call assert_equal(1, col('.'))
bw!
endfunc