[vim/vim] cannot quit visual mode using `:normal` in command-line window (Issue #10950)

37 views
Skip to first unread message

lacygoill

unread,
Aug 20, 2022, 9:19:59 PM8/20/22
to vim/vim, Subscribed

Steps to reproduce

Run this shell command:

vim -Nu NONE -i NONE +'call feedkeys("q::normal! \<C-V>\<Esc>\<CR>\<Esc>")'

The command-line window is no longer open.

Expected behavior

The command-line window is still open.

Version of Vim

9.0 Included patches: 1-233

Environment

Operating system: Ubuntu 20.04.4 LTS
Terminal: XTerm(353)
Value of $TERM: xterm-256color
Shell: GNU bash, version 5.0.17

Additional context

I'm not sure whether this is a bug or working as intended. The command-line window remained open before the patch 8.2.2548.

The message title of the patch is:

may get stuck in the cmdline window using :normal

But there is no reference to any issue or PR. I looked at the issues and PRs posted the same week, but couldn't find something relevant.

And the patch doesn't contain any test. Only this comment:

// When :normal runs out of characters while in the command line window
// vgetorpeek() will return ESC.  Exit the cmdline window to break the
// loop.

I don't know how Vim could get stuck using :normal before.


In any case, the patch 8.2.2548 introduces a regression in the matchit plugin. MRE:

vim -Nu NONE -i NONE +'packadd matchit' +'call feedkeys("q:i()\<Esc>v0%")'

At first glance, it seems that no error has been given. But if we look at the :messages, we can find this error:

E492: Not an editor command: (:if col("''") != col("$") | exe ":normal! m'" | endif)

In practice, the error can be more visible, and is annoying because not only does it quit the command-line window while we were trying to expand the visual selection to the next paren, but it also executes a command which results from a mix between whatever was written on the cursor line and some part of a matchit mapping (% in visual mode), which is confusing.

This patch should fix the bug:

diff --git a/runtime/pack/dist/opt/matchit/autoload/matchit.vim b/runtime/pack/dist/opt/matchit/autoload/matchit.vim
index eafb7c055..ad04106f7 100644
--- a/runtime/pack/dist/opt/matchit/autoload/matchit.vim
+++ b/runtime/pack/dist/opt/matchit/autoload/matchit.vim
@@ -61,7 +61,11 @@ function matchit#Match_wrapper(word, forward, mode) range
   " If this function was called from Visual mode, make sure that the cursor
   " is at the correct end of the Visual range:
   elseif a:mode == "v"
-    execute "normal! gv\<Esc>"
+    let escape = "\<Esc>"
+    if getcmdwintype() != ''
+      let escape = visualmode()
+    endif
+    execute 'normal! gv' .. escape
     let startpos = [line("."), col(".")]
   endif
 

Although, not sure how reliable it is. If we can no longer use :normal to press <Esc> and quit visual mode. How are we meant to do it? I've tried to fix the matchit plugin in other ways (using :normal to press <C-C>, <C-\>\<C-N>, using feedkeys(), ...). None of them worked. The only way I found is to use :normal to press v or V or <C-V> depending on the type of the last visual selection.

Do we need a :stopvisual command (similar to :startinsert)?


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10950@github.com>

Bram Moolenaar

unread,
Aug 21, 2022, 5:40:53 AM8/21/22
to vim/vim, Subscribed

Closed #10950 as completed via 8d69637.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/10950/issue_event/7227470965@github.com>

Bram Moolenaar

unread,
Aug 21, 2022, 5:41:28 AM8/21/22
to vim/vim, Subscribed


> **Steps to reproduce**

>
> Run this shell command:
>
> vim -Nu NONE -i NONE +'call feedkeys("q::normal! \<C-V>\<Esc>\<CR>\<Esc>")'
>
> The command-line window is no longer open.
>
> **Expected behavior**

>
> The command-line window is still open.
>
> **Version of Vim**
>
> 9.0 Included patches: 1-233
>
> **Environment**

>
> Operating system: Ubuntu 20.04.4 LTS
> Terminal: XTerm(353)
> Value of $TERM: xterm-256color
> Shell: GNU bash, version 5.0.17
>
> **Additional context**
>
> I'm not sure whether this is a bug or working as intended. The command-line window remained open before the patch [8.2.2548](https://github.com/vim/vim/releases/tag/v8.2.2548).

>
> The message title of the patch is:
>
> may get stuck in the cmdline window using :normal
>
> But there is no reference to any issue or PR. I looked at the [issues](https://github.com/vim/vim/issues?q=is%3Aissue+created%3A2021-02-16..2021-02-24) and [PRs](https://github.com/vim/vim/pulls?q=is%3Apr+created%3A2021-02-16..2021-02-24+) posted the same week, but couldn't find something relevant.

>
> And the patch doesn't contain any test. Only this comment:
>
> // When :normal runs out of characters while in the command line window
> // vgetorpeek() will return ESC. Exit the cmdline window to break the
> // loop.
>
> I don't know how Vim could get stuck using `:normal` before.

I don't recall the repro case, but it would indeed get stuck. When
vgetorpeek() runs out of characters when ex_normal_busy is set, then it
must return something to get back to exec_normal(). E.g. to end Insert
mode. But this currently cannot be distinguished from typing that character.



> In any case, the patch 8.2.2548 introduces a regression in the matchit plugin. MRE:
>
> vim -Nu NONE -i NONE +'packadd matchit' +'call feedkeys("q:i()\<Esc>v0%")'
>
> At first glance, it seems that no error has been given. But if we look at the `:messages`, we can find this error:

>
> E492: Not an editor command: (:if col("''") != col("$") | exe ":normal! m'" | endif)
>
> In practice, the error can be more visible, and is annoying because not only does it quit the command-line window while we were trying to expand the visual selection to the next paren, but it also executes a command which results from a mix between whatever was written on the cursor line and some part of a matchit mapping (`%` in visual mode), which is confusing.

>
> This patch should fix the bug:
> ```diff
> diff --git a/runtime/pack/dist/opt/matchit/autoload/matchit.vim b/runtime/pack/dist/opt/matchit/autoload/matchit.vim
> index eafb7c055..ad04106f7 100644
> --- a/runtime/pack/dist/opt/matchit/autoload/matchit.vim
> +++ b/runtime/pack/dist/opt/matchit/autoload/matchit.vim
> @@ -61,7 +61,11 @@ function matchit#Match_wrapper(word, forward, mode) range
> " If this function was called from Visual mode, make sure that the cursor
> " is at the correct end of the Visual range:
> elseif a:mode == "v"
> - execute "normal! gv\<Esc>"
> + let escape = "\<Esc>"
> + if getcmdwintype() != ''
> + let escape = visualmode()
> + endif
> + execute 'normal! gv' .. escape
> let startpos = [line("."), col(".")]
> endif
>
> ```
> Although, not sure how reliable it is. If we can no longer use
> `:normal` to press `<Esc>` and quit visual mode. How are we meant to
> do it? I've tried to fix the matchit plugin in other ways (using
> `:normal` to press `<C-C>`, `<C-\>\<C-N>`, using `feedkeys()`, ...).

> None of them worked. The only way I found is to use `:normal` to
> press `v` or `V` or `<C-V>` depending on the type of the last visual
> selection.

This looks more like a workaround than a solution.

> Do we need a `:stopvisual` command (similar to `:startinsert`)?

That would be strange, because when entering ":stopvisual" you probably
already left Visual mode. In a mapping one can just use Esc.

I'll add a flag to make this specific case work. Without a test,
because it is not that easy. Feel free to come up with a test if you
can.

--
ARTHUR: Listen, old crone! Unless you tell us where we can buy a shrubbery,
my friend and I will ... we will say "Ni!"
CRONE: Do your worst!
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10950/1221509644@github.com>

lacygoill

unread,
Aug 21, 2022, 4:22:04 PM8/21/22
to vim/vim, Subscribed

Without a test, because it is not that easy. Feel free to come up with a test if you can.

How about this:

diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
index 8cfb248f7..86ddca4ef 100644
--- a/src/testdir/test_cmdwin.vim
+++ b/src/testdir/test_cmdwin.vim
@@ -373,5 +373,11 @@ func Test_cmdwin_virtual_edit()
   set ve= cpo-=$
 endfunc
 
+func Test_normal_escapes_visual()
+  let g:norm_esc_vis = 1
+  call feedkeys("q:ilet g:norm_esc_vis = 2\<Esc>:normal! \<C-V>\<Esc>\<CR>\<CR>", 'ntx')
+  call assert_equal(1, g:norm_esc_vis)
+  unlet! g:norm_esc_vis
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10950/1221614384@github.com>

Bram Moolenaar

unread,
Aug 22, 2022, 8:58:22 AM8/22/22
to vim/vim, Subscribed


> > Without a test, because it is not that easy. Feel free to come up with a test if you can.
>
> How about this:
> ```diff
> diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
> index 8cfb248f7..86ddca4ef 100644
> --- a/src/testdir/test_cmdwin.vim
> +++ b/src/testdir/test_cmdwin.vim
> @@ -373,5 +373,11 @@ func Test_cmdwin_virtual_edit()
> set ve= cpo-=$
> endfunc
>
> +func Test_normal_escapes_visual()
> + let g:norm_esc_vis = 1
> + call feedkeys("q:ilet g:norm_esc_vis = 2\<Esc>:normal! \<C-V>\<Esc>\<CR>\<CR>", 'ntx')
> + call assert_equal(1, g:norm_esc_vis)
> + unlet! g:norm_esc_vis
> +endfunc
>
> " vim: shiftwidth=2 sts=2 expandtab
> ```

As it is it fails. I can make it pass by changing the assert to check
for "2". But when reverting the fix it still passes...

--
If cars evolved at the same rate as computers have, they'd cost five euro,
run for a year on a couple of liters of petrol, and explode once a day.


/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10950/1222323389@github.com>

lacygoill

unread,
Aug 22, 2022, 9:09:14 PM8/22/22
to vim/vim, Subscribed

Sorry, new try:

diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
index 8cfb248f7..a7071fc71 100644
--- a/src/testdir/test_cmdwin.vim
+++ b/src/testdir/test_cmdwin.vim
@@ -373,5 +373,9 @@ func Test_cmdwin_virtual_edit()
   set ve= cpo-=$
 endfunc
 
+func Test_normal_escape()
+  call feedkeys("q:i\" foo\<Esc>:normal! \<C-V>\<Esc>\<CR>:\" bar\<CR>", 'ntx')
+  call assert_equal('" bar', @:)
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab

On my machine, this test correctly passes on 9.0.0246:

$ cd src/testdir/
$ rm test.log
$ vim -u NONE -i NONE -S runtest.vim ./test_cmdwin.vim normal_escape
$ cat test.log
cat: test.log: No such file or directory

And correctly fails on 9.0.0233:

$ cd src/testdir/
$ rm test.log
$ ../vim -u NONE -i NONE -S runtest.vim ./test_cmdwin.vim normal_escape
$ cat test.log
From ./test_cmdwin.vim:
Found errors in Test_normal_escape():
command line..script /home/lgc/VCS/vim/src/testdir/runtest.vim[468]..function RunTheTest[44]..Test_normal_escape line 2: Expected '" bar' but got '" fo:" baro'


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10950/1223393475@github.com>

Bram Moolenaar

unread,
Aug 23, 2022, 2:55:58 PM8/23/22
to vim/vim, Subscribed


> Sorry, new try:
> ```diff
Yes, this one works, thanks.

--
I wonder, do vegetarians eat fruit bats?


/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10950/1224620086@github.com>

Reply all
Reply to author
Forward
0 new messages