Describe the bug
In the latest internal previews of 16.2 (Int Preview 28929.309), hitting escape while in inline rename to exit insert mode also exits the inline rename session.
To Reproduce
Steps to reproduce the behavior:
esc.Expected behavior
Insert mode is exited, and normal mode is entered (as occurred previously). Inline rename is _not_ cancelled.
Environment (please complete the following information):
Note that you _could_ exit inline rename in the previous behavior, but it took an extra esc or two.
Well, we had a bug reported (issue #2427) when it behaved the other way. And I fixed that in PR #2522. I will let @jaredpar decide whether to close this issue as "won't fix" or to revert PR #2522 and re-close the other issue as "won't fix". My preference is to keep it the way that it is because that is what rename is expecting and that is what the [X] on the rename says typing escape will do.
@jaredpar, This use to work, then got broken and @333fred came to rely on the broken behavior, then got fixed. What do you think we should do?
https://xkcd.com/1172/ feels all too relevant.
that is what the [X] on the rename says typing escape will do.
Personally, I feel like VsVim users should understand that pressing escape doesn't always mean what VS's built-in dialogue says it will mean. We're not using the standard keybindings, and escape has very special meaning. For reference, I've already hit this about 5 times since I noticed the issue, and probably hit it a few times before and just chalked it up to user error until I got irritated enough.
The intent of Escape was to mimic vim's interpretation. That is to exit the current mode and return to the previous mode: typically normal mode.
Refactoring is a case I always intended to mimic this behavior. It does so many nasty actions with selection that it renders vim nearly unusable. Every time you take a step forward, refactoring changes a selection and vim jumps to some unexpected mode. Hence the reasoning for leaving disabled mode going to normal and cancelling refactoring.
There is a narrow path where you can be in refactoring mode and not trigger the bad behaviors. Basically simple movement motions and single character actions. I'm sure a few developers have figured this out though and depend on it.
Want to think about this more and see if it's worth keeping around as an option of sorts.
For reference, what I often do is change the last few letters of a variable or class when renaming. An example I just hit on Friday: renaming Snapshotter to SnapshotManager. What I wanted to do was F2 <esc> e 3h cw, which has worked for me in the past.
I also find the "fixed" behavior annoying. I got used to being able to continue using vim while renaming (being able to enter normal mode on esc). I think the argument regarding that the visual studio popup says that esc cancels is for people using vs keybindings. I installed vsvim because I always want to edit using vim bindings. Seems like some people like to sometimes take a break from vim and switch to vs editing and if the dev wants to make everyone happy, he should add a config variable to control this behavior.
I am slowly coming around to the opinion of @333fred and @tibimunteanu that, if possible, keeping VsVim fully enabled during refactoring, even perhaps in all the cases where we currently use external edit mode now, would be the ideal if we could make it work.
I know the whole reason we have external edit mode is because VsVim "goes bonkers" or otherwise behaves in some way that is detrimental to the refactoring going on. But, if we can work around that bad behavior, then instead of disabling VsVim temporarily we can leave it enabled in insert or select mode or whatever and make everyone happy.
However, the upshot of this issue is that, even if we get that working, we still have to decide how to "accept" and "cancel" the operation in ways that are intuitive and yet non-invasive to the refactoring.
Well.. up until a few days ago when the update changed it, when I wanted to refactor a symbol, I would press Esc to go to normal mode and go on using vim to edit the symbol name. And the accept came with an Enter in insert mode. I think this worked out fine because you never need a new line on Enter while renaming symbols..since symbols cannot contain new lines in their names.
@ricksladkey personally, I think the most intuitive way to cancel is to hit esc while in normal mode. enter should probably commit in insert mode (and I could be convinced that it should also commit in other modes as well). If you're not in normal mode, esc should behave as it always done in vim.
OK, I have a proposal. Feedback requested from @jaredpar, @333fred, @tibimunteanu, @msloan and others.
External edit mode is a feature that makes refactoring less surprising to casual vim users. It causes VsVim to interfere less and allows the external edit to proceed as the provider intended it to. Therefore we should keep external edit mode. However, more advanced users may want the full power of VsVim during refactoring.
In vim in insert mode there is a subtle difference between <Esc> and <C-c>: it is documented (:vimhelp i_CTRL-C) that abbreviations are not checked and the normal "leave" auto-command is not run. We can leverage this semantic difference to handle external edit mode. Normally, there is no in-progress operation and so <Esc> and <C-c> do the same thing. But if there is an in-progress operation, <C-c> will cancel it whereas <Esc> will not. In any case we end up in normal mode.
And in normal mode in vim, <C-c> means "interrupt the current search".
In short, I propose that we differentiate between <Esc> and <C-c>, just as vim itself does. Typing <Esc> in normal, insert, and external edit mode means "go to normal mode" but typing <C-c> means "cancel any in-progress operation and go to normal mode".
To make this clear to the user, in external edit mode a banner will be displayed:
External edit detected (hit <Esc> to return to previous mode, <C-c> to cancel external edit)
The only ways to complete an external edit mode would be:
<C-c> from normal, insert, or external edit mode<Enter> that causes the refactoring itself to completeOnce you have exited external edit mode, you cannot re-enter it intentionally but there is no need to do so as the user has specifically opted out of the transparency of external edit mode and can easily complete the refactoring from insert mode or cancel the refactoring from insert or normal mode.
The only users who suffer from this solution are the ones who (like @msloan) are expecting that <Esc> in external edit mode will cancel the refactoring. These users will have to train their fingers to type <C-c> instead.
Does this seem like a workable solution?
Sounds great
馃憤 from me as well.
After some testing, I found some changes that I think will be good. As you might have noticed, I don't really use rename myself in daily use, so I haven't previously developed any opinions about how it should work.
First, it turns out that we have a VsVim option "Rename and Snippet Tracking" which defaults to true and enables external edit mode. So these so-called "advanced users" should be able to simply turn off external edit mode altogether. However, it also turns out that the special handling regarding the Roslyn rename refactoring doesn't respect that setting. I've fixed that now.
So if you have :behave mswin in your VsVim rc file (as I recommend that you do!), I now also recommend that you turn off "Rename and Snippet Tracking". With these settings, the rename operation behaves perfectly intuitively without external edit mode and now even supports cancellation with <C-c>.
Second, it turns out that the Roslyn rename support only works in C# and VB files. But, empirically, F# also uses Roslyn rename and so I have enabled support for F# rename.
Most helpful comment
Sounds great