]> granicus.if.org Git - vim/commitdiff
patch 8.2.3828: when opening a terminal from a timer first typed char is lost v8.2.3828
authorBram Moolenaar <Bram@vim.org>
Thu, 16 Dec 2021 18:02:07 +0000 (18:02 +0000)
committerBram Moolenaar <Bram@vim.org>
Thu, 16 Dec 2021 18:02:07 +0000 (18:02 +0000)
Problem:    when opening a terminal from a timer the first typed character
            is lost. (Virginia Senioria)
Solution:   When opening a terminal while waiting for a character put K_IGNORE
            in the input buffer.

src/edit.c
src/terminal.c
src/testdir/test_terminal.vim
src/version.c

index 40d5c4e5830d58e4d0add38ef05e6e6c8c2dc8ae..9ff1c184e23565107bd5ecf5db408ef946a4b4b0 100644 (file)
@@ -598,9 +598,14 @@ edit(
            {
                c = safe_vgetc();
 
-               if (stop_insert_mode)
+               if (stop_insert_mode
+#ifdef FEAT_TERMINAL
+                       || (c == K_IGNORE && term_use_loop())
+#endif
+                  )
                {
-                   // Insert mode ended, possibly from a callback.
+                   // Insert mode ended, possibly from a callback, or a timer
+                   // must have opened a terminal window.
                    if (c != K_IGNORE && c != K_NOP)
                        vungetc(c);
                    count = 0;
index 7efe071eb538c80064a1e293df0a805e180ac4ae..8f80f9fa263aba9077a2f110b182e0348e693171 100644 (file)
@@ -739,6 +739,23 @@ term_start(
            curwin->w_buffer = curbuf;
            ++curbuf->b_nwindows;
        }
+       else if (vgetc_busy
+#ifdef FEAT_TIMERS
+               || timer_busy
+#endif
+               || input_busy)
+       {
+           char_u ignore[4];
+
+           // When waiting for input need to return and possibly end up in
+           // terminal_loop() instead.
+           ignore[0] = K_SPECIAL;
+           ignore[1] = KS_EXTRA;
+           ignore[2] = KE_IGNORE;
+           ignore[3] = NUL;
+           ins_typebuf(ignore, REMAP_NONE, 0, TRUE, FALSE);
+           typebuf_was_filled = TRUE;
+       }
     }
     else
     {
index 3dc7776a9d110825fadfadb456d4ac26cd5056fd..3fda75dfb61ad355878946c8772ca162be4c450f 100644 (file)
@@ -1596,6 +1596,7 @@ endfunc
 " 4. 0.5 sec later: should be done, clean up
 func Test_terminal_statusline()
   CheckUnix
+  CheckFeature timers
 
   set statusline=x
   terminal
@@ -1611,6 +1612,31 @@ func Test_terminal_statusline()
   set statusline=
 endfunc
 
+func CheckTerminalWindowWorks(buf)
+  call WaitForAssert({-> assert_match('!sh \[running\]', term_getline(a:buf, 10))})
+  call term_sendkeys(a:buf, "exit\<CR>")
+  call WaitForAssert({-> assert_match('!sh \[finished\]', term_getline(a:buf, 10))})
+  call term_sendkeys(a:buf, ":q\<CR>")
+  call WaitForAssert({-> assert_match('^\~', term_getline(a:buf, 10))})
+endfunc
+
+func Test_start_terminal_from_timer()
+  CheckUnix
+  CheckFeature timers
+
+  " Open a terminal window from a timer, typed text goes to the terminal
+  call writefile(["call timer_start(100, { -> term_start('sh') })"], 'XtimerTerm')
+  let buf = RunVimInTerminal('-S XtimerTerm', {})
+  call CheckTerminalWindowWorks(buf)
+
+  " do the same in Insert mode
+  call term_sendkeys(buf, ":call timer_start(200, { -> term_start('sh') })\<CR>a")
+  call CheckTerminalWindowWorks(buf)
+
+  call StopVimInTerminal(buf)
+  call delete('XtimerTerm')
+endfunc
+
 func Test_terminal_window_focus()
   let winid1 = win_getid()
   terminal
index c95477604e91174ad673b60e2887c39324e69af5..f7187769c868eada83f8f4de1a635680ba92d020 100644 (file)
@@ -749,6 +749,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3828,
 /**/
     3827,
 /**/