Greetings:

Note that this bug report and patch is not my work.  This solution was
provided to me by a colleague named "Brandon Pfeifer" to submit to this
list.  Please credit him in the commit message and changelog if this
patch is accepted.

To reproduce...

  - latest vim build as of this writing (v8.2.1145)
  - gnome-terminal (Ubuntu 18.04) or konsole (Debian 10)

  1. VIMRUNTIME=../runtime ./vim --clean
  2. :set hidden<CR>
  3. itest<ESC>
  4. :e buffer.c<CR>  (or some other file...)
  5. :confirm wq<CR>
  6. Now type "ccccc......"

Brandon discovered that the reason for this is that the do_dialog()
function is not always executed when the terminal is in raw mode, like
one would expect.  Sometimes, this function is executed in cooked mode,
which results in this undesirable behavior.

Specifically, the problem is observable in the debugger at the select()
call in the RealWaitForChar() function in os_unix.c.  Cooked mode causes
this function to wait for a line feed character.

Two patches are attached to fix this bug.

  1. test.diff - formal demonstration of bug with a test
  2. fix.diff - causes do_dialog() to set correct mode (saves/restores)

Email me with any questions.

Thanks!

-- 
Jason Franklin

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/af23d726-e98b-80d8-6287-33a64f3a8d13%40quoininc.com.
diff --git a/src/testdir/test_excmd.vim b/src/testdir/test_excmd.vim
index 2428e9d02..615e232da 100644
--- a/src/testdir/test_excmd.vim
+++ b/src/testdir/test_excmd.vim
@@ -269,6 +269,39 @@ func Test_confirm_cmd_cancel()
   call StopVimInTerminal(buf)
 endfunc
 
+" It was discovered that ":confirm" prompts are sometimes displayed with the
+" terminal in cooked mode.  Thus, a "\<CR>" char is required to dismiss the
+" prompt.  This test verifies that a "\<CR>" character is NOT required to
+" respond to a prompt from the ":conf q" and ":conf wq" commands.
+func Test_confirm_q_wq()
+  CheckNotGui
+  CheckRunVimInTerminal
+
+  call writefile(['foo'], 'foo')
+
+  let buf = RunVimInTerminal('', {'rows': 20})
+  call term_sendkeys(buf, ":set hidden nomore\n")
+  call term_sendkeys(buf, ":call setline(1, 'abc')\n")
+  call term_sendkeys(buf, ":edit foo\n")
+  call term_sendkeys(buf, ":confirm q\n")
+  call WaitForAssert({-> assert_match('^\[Y\]es, (N)o, (C)ancel: *$',
+        \ term_getline(buf, 20))}, 1000)
+  call term_sendkeys(buf, 'C')
+  call WaitForAssert({-> assert_notmatch('^\[Y\]es, (N)o, (C)ancel: C*$',
+        \ term_getline(buf, 20))}, 1000)
+
+  call term_sendkeys(buf, ":edit foo\n")
+  call term_sendkeys(buf, ":confirm wq\n")
+  call WaitForAssert({-> assert_match('^\[Y\]es, (N)o, (C)ancel: *$',
+        \ term_getline(buf, 20))}, 1000)
+  call term_sendkeys(buf, 'C')
+  call WaitForAssert({-> assert_notmatch('^\[Y\]es, (N)o, (C)ancel: C*$',
+        \ term_getline(buf, 20))}, 1000)
+  call StopVimInTerminal(buf)
+
+  call delete('foo')
+endfunc
+
 " Test for the :print command
 func Test_print_cmd()
   call assert_fails('print', 'E749:')
diff --git a/src/message.c b/src/message.c
index 006e648fe..57eae68a8 100644
--- a/src/message.c
+++ b/src/message.c
@@ -3652,6 +3652,7 @@ do_dialog(
     char_u	*hotkeys;
     int		c;
     int		i;
+    tmode_T save_tmode;
 
 #ifndef NO_CONSOLE
     // Don't output anything in silent mode ("ex -s")
@@ -3683,6 +3684,10 @@ do_dialog(
     State = CONFIRM;
     setmouse();
 
+    // Ensure that the terminal is in raw mode when a dialog is presented.
+    save_tmode = cur_tmode;
+    settmode(TMODE_RAW);
+
     /*
      * Since we wait for a keypress, don't make the
      * user press RETURN as well afterwards.
@@ -3743,6 +3748,7 @@ do_dialog(
 	vim_free(hotkeys);
     }
 
+    settmode(save_tmode);
     State = oldState;
     setmouse();
     --no_wait_return;

Raspunde prin e-mail lui