]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1295: clientserver: does not handle :stopinsert correctly v9.1.1295
authorChristian Brabandt <cb@256bit.org>
Sat, 12 Apr 2025 16:09:28 +0000 (18:09 +0200)
committerChristian Brabandt <cb@256bit.org>
Sat, 12 Apr 2025 16:09:28 +0000 (18:09 +0200)
Problem:  clientserver: When in insert mode, a :stopinsert command
          is not correctly processed (user202729)
Solution: If the :stopinsert command is received while waiting for
          input, stuff the NOP key into the type-ahead buffer and
          detect that :stopinsert was used in edit() so that the
          cursor position is decremented.

fixes: #17016
closes: #17024

Signed-off-by: Christian Brabandt <cb@256bit.org>
src/edit.c
src/ex_docmd.c
src/testdir/test_clientserver.vim
src/version.c

index 53428e0fbb1d774b4629cd7e80de3e0e68a15b5b..ab67fdc68b49cc58b1dcf2a369af3c910de45281 100644 (file)
@@ -608,7 +608,16 @@ edit(
                    if (c != K_IGNORE && c != K_NOP)
                        vungetc(c);
                    count = 0;
-                   nomove = TRUE;
+
+                   if (!bt_prompt(curwin->w_buffer)
+#ifdef FEAT_TERMINAL
+                           && !bt_terminal(curwin->w_buffer)
+#endif
+                           && stop_insert_mode)
+                       // :stopinsert command via callback or via server command
+                       nomove = FALSE;
+                   else
+                       nomove = TRUE;
                    ins_compl_prep(ESC);
                    goto doESCkey;
                }
index 03eaef420512993fa538816fbc26a08057497a0b..279a202cd391b35fd4baffdb270aab31df0eb52e 100644 (file)
@@ -9326,6 +9326,12 @@ ex_stopinsert(exarg_T *eap UNUSED)
 {
     restart_edit = 0;
     stop_insert_mode = TRUE;
+#if defined(FEAT_CLIENTSERVER) || defined(FEAT_EVAL)
+    // when called from remote_expr in insert mode, make sure insert mode is
+    // ended by adding K_NOP to the typeahead buffer
+    if (vgetc_busy)
+       ins_char_typebuf(K_NOP, 0);
+#endif
     clearmode();
 }
 
index 8be521b9f71c31c65e5001b32392e4d0aa1d9cbe..02b0c3921fe9c08f271a156ecbc1421432a2ad44 100644 (file)
@@ -191,6 +191,47 @@ func Test_client_server()
         \ has('unix') ? ['E573:.*abc'] : 'E258:')
 endfunc
 
+func Test_client_server_stopinsert()
+  " test does not work on MS-Windows
+  CheckNotMSWindows
+  let g:test_is_flaky = 1
+  let cmd = GetVimCommand()
+  if cmd == ''
+    throw 'GetVimCommand() failed'
+  endif
+  call Check_X11_Connection()
+  let fname = 'Xclientserver_stop.txt'
+  let name = 'XVIMTEST2'
+  call writefile(['one two three'], fname, 'D')
+
+  let cmd .= ' -c "set virtualedit=onemore"'
+  let cmd .= ' -c "call cursor(1, 14)"'
+  let cmd .= ' -c "startinsert"'
+  let cmd .= ' --servername ' . name
+  let cmd .= ' ' .. fname
+  let job = job_start(cmd, {'stoponexit': 'kill', 'out_io': 'null'})
+  call WaitForAssert({-> assert_equal("run", job_status(job))})
+
+  " Takes a short while for the server to be active.
+  " When using valgrind it takes much longer.
+  call WaitForAssert({-> assert_match(name, serverlist())})
+
+  call remote_expr(name, 'execute("stopinsert")')
+
+  call assert_equal('n', name->remote_expr("mode(1)"))
+  call assert_equal('13', name->remote_expr("col('.')"))
+
+  eval name->remote_send(":qa!\<CR>")
+  try
+    call WaitForAssert({-> assert_equal("dead", job_status(job))})
+  finally
+    if job_status(job) != 'dead'
+      call assert_report('Server did not exit')
+      call job_stop(job, 'kill')
+    endif
+  endtry
+endfunc
+
 " Uncomment this line to get a debugging log
 " call ch_logfile('channellog', 'w')
 
index 2e2debb9d8e782a69bfa6ae270ab822829be55a0..53b794173b85ebb1627aff5922379960d08baaf8 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1295,
 /**/
     1294,
 /**/