Vsvim: Hitting escape does not exit visual mode (latest VS2017 preview)

Created on 22 May 2017  路  27Comments  路  Source: VsVim/VsVim

However, clicking anywhere in the text does exit visual mode.

FYI @khyperia

Most helpful comment

Okay figured out what is going on here. This is the commit that caused the behavior around escape.

https://github.com/jaredpar/VsVim/commit/c5e5079db9dce11089ca6675e28b3404238aeddc

The commit itself is fine, but it exposed a different bug in VsVim that's been there practically since the beginning. To explain this bug though have to first explain two important concepts about modes in VsVim.

The first concept is that vim needs the concept of current and previous mode. The previous mode is essentially the mode that becomes active when the current mode is completed. The current mode can be completed by a variety of actions like Escape, finishing a command, etc ...

Users who haven't explored vim in depth may think the previous mode is a fixed set. For instance when hitting Escape in Visual mode it should always return to normal mode (I definitely thought that was the case before I started writing VsVim). In reality though it's more complex due to features like insert mode ctrl-o. This takes you from insert mode to normal mode. When this normal mode, or any subsequent mode, is completed, the new active mode should be insert. Hence if you enter visual mode from ctrl-o,v then Escape should return to insert mode, not normal mode.

VsVim deals with this by tracking the current and previous mode for every buffer. Commands like Escape essentially map directly to making the active mode the previous mode. One of the invariant of the tracking code though is that the previous mode should never be any visual mode.

The second concept is VsVim has a mode called uninitialized. The first mode a user sees is Normal mode but under the hood all VsVim buffers begin in uninitialized. The reason is the VS editor startup sequence is complex and VsVim gets attached before the editor is fully initialized. Hence VsVim begins in uninitialized mode (has no operations) and transitions to Normal mode once it sees the editor is finished starting up. Essentially after the first editor layout VsVim will snap to Normal mode.

Turns out there is a subtle bug in the current / previous mode tracking code. It only operates correctly if the first two modes are uninitialized then normal. If the sequence is instead uninitialized then visual then very quickly the code will get into a state where both current and previous are visual mode. That violates the invariant stated above and very quickly both current and previous will be visual mode. Hence every time users hit Escape after that it's just looping on visual mode. Sigh ...

The flagged commit allows for this situation to happen. Due to changes in VS2017 editor startup, VsVim had to delay the transition from uninitialized to normal mode. I implemented this by essentially doing a SynchronizationContext.Post call. This means there is a small window where VsVim is in uninitialized mode and other code can pick the first mode.

Part of the Navigate To implementation will select the text of the target symbol. Any code selection generally causes VsVim to enter Visual Mode. Hence if Navigate To also opens the file then the selection event can happen in that small window and cause the first mode to be Visual, not normal. Then the bug is exposed 馃槮

Writing that all down makes me realize just how complex some of that low level tracking code is. It's fairly old and could probably use a revisit. But anyhow, this should be simple enough to fix now that I know what is going on.

All 27 comments

@tyoverby mentioned that you can also exit visual mode by hitting v.

^ err, you can exit visual mode by hitting v and then Escape.

For me it works to just hit v.

weird, for me, hitting v again stays in visual mode (but then it is exitable via escape)

I am having the same error. Unable to exit visual mode via Esc. For the time being I am hitting v to exit visual mode.

You can also escape by typing :, then hitting backspace until you exit the bar.

Also, I managed to get into a scenario where typing :w would enter visual mode. Restarting seemed to make it go away, I'll keep trying to repro consistently.

Also, I managed to get into a scenario where typing :w would enter visual mode. Restarting seemed to make it go away, I'll keep trying to repro consistently.

Quick note that this isn't a just-you thing, it's been happening for me too (I was vaguely sure of it, but then it happened again just now). No idea what repro steps would be, I'll see if I can figure it out next time it happens.

I'm having this same issue in VS 2015, and it only started recently. It typically happens after some time of running VS, and when I use ctrl+F12 it goes to the method definition, but also puts me in Visual Mode. When I hit escape at that point, I get the error: "The given key was not present in the dictionary."

Restarting VS does fix it temporarily.

same problem here, both 2015 and 2017.

Having the same problem, in VS 2015 running on Parallels.

Notice it only happens when editing .cs file, maybe there exists an active extension for c# mode using same hotkey causing editor to switch to select mode.

The error just disappeared after removing all map starting with v from .vsvimrc & .vimrc files. I also fixed some errors reported by vsvim related to configuration files loading. You can enable errors reporting here:

image

Something really interesting is, before fixing the error, after v key has been pressed, it takes a while to vsvim to turn into -- VISUAL -- mode.

Wanted to give an update here. Seen enough reports of this, and watched it on a coworkers machine, to know it's a real bug. Unfortunately it refuses to reproduce on my machine and once I started looking at it the bug vanished on all my coworkers machines. Seeing if I can enable a logging mode that will give me a clue to what is going on here.

I found the problem to be 100% reproducible when navigating to a type, for example using "GoTo Implementation" from an interface.

When doing this a new editor window opens and the type that got navigated to is highlighted.

After that vsvim is stuck in visual mode - occasionally I get a "The given key was not present in the dictionary" error when trying to move via jklh .

For me it happens when I do ":w" (which I do often) (VS2015 Community). When I start up a new VS instance it doesn't happen for a while, but once it happens once it happens until I restart VS again.

@thumbmunkeys

I tried the "GoTo Implementation" route and could not reproduce the bug. I used both the mouse and keyboard (Ctrl+F12) to invoke the command. In both cases I do see VsVim entering Visual Mode but I can still use Escape to exit.

There is some other component I'm missing. I've tried using the vimrc file of other users and still can't produce the behavior.

For anyone able to reproduce the bug, if possible could you grab a full heap dump of Visual Studio with procdump and share it out?

>procdump -ma <devenv process id>

This is definitely a real bug but I can't find a way to reproduce it locally. Looking at a dump is the next best way to try and track this down.

Note: this file will be big. But can't be avoided. A simple dump won't help in tracking this down 馃槮

I have a dump file. Ping me for the share.

@jaredpar Just sent you an email (to your public Github email) with a link to the dump file.

Eureka! I have steps to reproduce this consistently (on a brand-new barebones solution):

  1. Open one .cs file
  2. use Edit > Navigate To (or its bound shortcut key, in my case ctrl+p to search for another file in the solution _which is not yet open in any tab_
  3. hit enter to choose the first result in the list ("Class1 - project ...")
  4. :w to write the file

You should now be in -- VISUAL -- mode, and escape will not return to normal mode, though clicking the mouse in the editor or typing v will. Note that step 1 is required. If you have all tabs closed and start with step 2, the problem will not occur.

These steps work for me in both VS 2015 and 2017 Pro.

@raztus

Thanks! I'm able to reproduce the problem using those steps.

Strangely the code that is at fault is very old, probably some of the earliest code I wrote in VsVim. I'm unsure why it suddenly starting affecting developers so frequently. Anyway though, should be able to fix it soon.

Okay figured out what is going on here. This is the commit that caused the behavior around escape.

https://github.com/jaredpar/VsVim/commit/c5e5079db9dce11089ca6675e28b3404238aeddc

The commit itself is fine, but it exposed a different bug in VsVim that's been there practically since the beginning. To explain this bug though have to first explain two important concepts about modes in VsVim.

The first concept is that vim needs the concept of current and previous mode. The previous mode is essentially the mode that becomes active when the current mode is completed. The current mode can be completed by a variety of actions like Escape, finishing a command, etc ...

Users who haven't explored vim in depth may think the previous mode is a fixed set. For instance when hitting Escape in Visual mode it should always return to normal mode (I definitely thought that was the case before I started writing VsVim). In reality though it's more complex due to features like insert mode ctrl-o. This takes you from insert mode to normal mode. When this normal mode, or any subsequent mode, is completed, the new active mode should be insert. Hence if you enter visual mode from ctrl-o,v then Escape should return to insert mode, not normal mode.

VsVim deals with this by tracking the current and previous mode for every buffer. Commands like Escape essentially map directly to making the active mode the previous mode. One of the invariant of the tracking code though is that the previous mode should never be any visual mode.

The second concept is VsVim has a mode called uninitialized. The first mode a user sees is Normal mode but under the hood all VsVim buffers begin in uninitialized. The reason is the VS editor startup sequence is complex and VsVim gets attached before the editor is fully initialized. Hence VsVim begins in uninitialized mode (has no operations) and transitions to Normal mode once it sees the editor is finished starting up. Essentially after the first editor layout VsVim will snap to Normal mode.

Turns out there is a subtle bug in the current / previous mode tracking code. It only operates correctly if the first two modes are uninitialized then normal. If the sequence is instead uninitialized then visual then very quickly the code will get into a state where both current and previous are visual mode. That violates the invariant stated above and very quickly both current and previous will be visual mode. Hence every time users hit Escape after that it's just looping on visual mode. Sigh ...

The flagged commit allows for this situation to happen. Due to changes in VS2017 editor startup, VsVim had to delay the transition from uninitialized to normal mode. I implemented this by essentially doing a SynchronizationContext.Post call. This means there is a small window where VsVim is in uninitialized mode and other code can pick the first mode.

Part of the Navigate To implementation will select the text of the target symbol. Any code selection generally causes VsVim to enter Visual Mode. Hence if Navigate To also opens the file then the selection event can happen in that small window and cause the first mode to be Visual, not normal. Then the bug is exposed 馃槮

Writing that all down makes me realize just how complex some of that low level tracking code is. It's fairly old and could probably use a revisit. But anyhow, this should be simple enough to fix now that I know what is going on.

I'm currently having (I think) this issue - where the only way to exit visual mode is to click somewhere and and then you can hit I or o or a or whatever.

Do you know where 2.4.1 is expected to drop?

Looking forward to it and great job!

Just installed 2.4.1, Escape can leave Visual Mode now 馃憤

experiencing this now. vwx[esc] leaves it consistently in an undefined state.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mqudsi picture mqudsi  路  12Comments

Kazark picture Kazark  路  12Comments

kalebpederson picture kalebpederson  路  12Comments

jfmcoronel picture jfmcoronel  路  22Comments

loosche picture loosche  路  29Comments