]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0827: :startinsert enters Insert mode in a non-modifiable buffer v9.2.0827
authorHirohito Higashi <h.east.727@gmail.com>
Wed, 22 Jul 2026 09:23:31 +0000 (09:23 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 22 Jul 2026 09:23:31 +0000 (09:23 +0000)
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:  #20804
closes: #20806

Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/ex_docmd.c
src/testdir/test_edit.vim
src/version.c

index 55db2d8d4d5c88ba4cf05893edd123bd9b4c00a2..b23504a85bd993bf65ca97e588fbac206e0d5e18 100644 (file)
@@ -9372,6 +9372,17 @@ ex_normal(exarg_T *eap)
     static void
 ex_startinsert(exarg_T *eap)
 {
+#ifdef FEAT_TERMINAL
+    // Ignore this when running in an active terminal.
+    if (term_job_running(curbuf->b_term))
+       return;
+#endif
+    if (!curbuf->b_p_ma && !p_im)
+    {
+       // Only give this error when 'insertmode' is off.
+       emsg(_(e_cannot_make_changes_modifiable_is_off));
+       return;
+    }
     if (eap->forceit)
     {
        // cursor line can be zero on startup
@@ -9379,11 +9390,6 @@ ex_startinsert(exarg_T *eap)
            curwin->w_cursor.lnum = 1;
        set_cursor_for_append_to_line();
     }
-#ifdef FEAT_TERMINAL
-    // Ignore this when running in an active terminal.
-    if (term_job_running(curbuf->b_term))
-       return;
-#endif
 
     // Ignore the command when already in Insert mode.  Inserting an
     // expression register that invokes a function can do this.
index f76b9196febbf0ba0c1daa2f73ce38ef8ce17552..ef68d66336121bcebb99bd2a8f5eee0b7c01019c 100644 (file)
@@ -1766,10 +1766,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
@@ -1783,6 +1823,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
 
index 0d42fff436b51560363c390a4a436b3c72cef496..9c342a64190172e86a282347bf634ed225c797e6 100644 (file)
@@ -759,6 +759,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    827,
 /**/
     826,
 /**/