Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VSCodeVim Undo stack should be synced with VSCode undo stack #1490

Open
casey-speer opened this issue Apr 10, 2017 · 67 comments
Open

VSCodeVim Undo stack should be synced with VSCode undo stack #1490

casey-speer opened this issue Apr 10, 2017 · 67 comments

Comments

@casey-speer
Copy link

casey-speer commented Apr 10, 2017

VSCodeVim undo is not synced with VSCode undo. I've provided a couple different issues/test cases below to illustrate what I mean:

Simple undo
VSCode and VSCodeVim seem to maintain different undo stacks, such that pressing u in VIM adds to the VSCode undo stack so that doing a VSCode undo (CMD-Z) undoes the VIM undo. u and CMD-Z should have the same function and share a common undo stack.

Search Replace
When doing a vim-based search and replace, one change with all the replacements is pushed to the VSCodeVim undo stack, whereas one change for each replacement is pushed to the VSCode undo stack. It's easy to get confused about the state of the document if you make a replacement, then press CMD-Z thinking you've reversed all the changes, make some other changes, then have to backtrack to revert the rest of the replacements.

I'm not familiar with the extension architecture for VSCode, so I'm not sure what is technically possible here.

I can break these off into separate issues if you'd prefer.

thumbs-up 👍 this issue if it personally affects you! You can do this by clicking on the emoji-face on the top right of this post. Issues with more thumbs-up will be prioritized.


Simple undo

What did you do?
Press i. Type some text: PIZZA. Press escape. Press i. Type some more text: IS GREAT. Press the u key to undo. Press CMD-Z.

What did you expect to happen?
" IS GREAT" should disappear upon pressing u. "PIZZA" should disappear upon pressing CMD-Z so we're left with an empty string.

What happened instead?
" IS GREAT" disappeared and then reappeared upon pressing CMD-Z so we're left with "PIZZA IS GREAT".

Search and replace

What did you do?
Given a 50-line document with the string "Pizza" on each line, type %s/Pizza/Hot Dogs/ from the VSCodeVim command line. Press CMD-Z.

What did you expect to happen?
"Pizza" should appear on every line.

What happened instead?
"Hot Dogs" appears on every line except the last one which shows "Pizza". Similarly, if you first undo with u then press CMD-Z, "Pizza" appears on every line except the first one which shows "Hot Dogs".

Technical details:

  • VSCode Version: 1.11.1
  • VsCodeVim Version: 0.6.14
  • OS: MacOS 10.11.6
@johnfn
Copy link
Member

johnfn commented Apr 19, 2017

The basic explanation is this.

We could very easily map ctrl-z to u and ctrl-y to redo. We don't. Why?

We have u/Ctrl-r, and (to my untrained eyes) they seem to work basically perfectly. HOWEVER, as you noticed, we are maintaining our own undo history. We have to because it diverges from VSCode.

That means there is a naggling possibility there's still a bug somewhere that would lose your history soehow. Indeed, #1503 looks like one example. If there is such a bug, that would be REALLY BAD and you would lose work you finished. So rather than risk that 1% possibility, we just leave in the ctrl-z/y behavior, so that if we do screw up, you can still use them.

Feel free to leave feedback on whether this seems like a reasonable approach or not.

@johnfn
Copy link
Member

johnfn commented Apr 19, 2017

I can see that the search & replace thing would be the cause of some confusion though. Let me know what you think.

@Maistho
Copy link

Maistho commented Apr 23, 2017

I think I would prefer it if u/ctrl+R just was mapped straight to the same commands as ctrl+Z/ctrl+Y.

What functionality is so important that VSCodeVim had to reimplement a history stack?

@johnfn
Copy link
Member

johnfn commented Apr 23, 2017

@Maistho That would be history itself. 😄 Vim's history does not correspond with VSCode's in important ways.

@Maistho
Copy link

Maistho commented Apr 23, 2017

@johnfn okay 👌

I mapped u and C-r to undo/redo instead and it seems to work as it should imo. Not sure what I'm missing x)

@johnfn
Copy link
Member

johnfn commented Apr 23, 2017

@Maistho did my explanation (#1490 (comment)) not explain it? 😉

@Maistho
Copy link

Maistho commented Apr 23, 2017

@johnfn What I mean is that I bound u and C-r to vscodes built in commands (undo/redo) instead of the vim extensions undo/redo. Which means that I just don't use the vim extensions undo/redo functionality at all. :)

@johnfn
Copy link
Member

johnfn commented Apr 23, 2017

Ohh, I misread, my mistake!

Trust you me @Maistho, if there is a single absolute truth in this treacherous world, it's that for every single Vim behavior, there is a person who will be very upset if that feature is off even by a single character. 😄 So yeah, we do have to do them the Vim way.

I'm glad that the VSCode commands work for you, though. That's awesome.

@Chillee
Copy link
Member

Chillee commented May 2, 2017

@Maistho There's a couple big limitations with Vim's Ctrl-z functionality. One big example is macros.

@bs
Copy link

bs commented May 10, 2017

Could you explain in more details the differences between Vim's und VSCode's undo stack features? I'm curious to understand what causes the conflict in this case.

@Chillee
Copy link
Member

Chillee commented May 10, 2017

@bs One example is macros. Following VSCode's undo stack, every ctrl+z press would undo one of the actions of the macro. However, in vim, you would want to undo the entire macro.

At the time undo functionality was implemented, VSCode didn't have the API features it has now. I believe VSCode added some new API features that allow us to interface with the undo stack, though.

@bs
Copy link

bs commented May 10, 2017

@Chillee Ah, fantastic. I'm not a huge user of macros, otherwise I would dive in. Looking forward to this being tackled though!

@Chillee
Copy link
Member

Chillee commented May 16, 2017

@johnfn Do you think that if we set VSCode's undo stops to correspond with how they should be in vim, we can get rid of our undo stack completely?

It does mean that we'll never implement the vim undo tree though... 😏

@johnfn
Copy link
Member

johnfn commented May 16, 2017

Yes, definitely.

That won't actually solve the problem in this issue however. Fixing this issue would essentially be a search and replace to replace "trigger a vscodevim undo step" with "trigger a vscode undo step". But the real problem here is that there are places where we should be triggering a step that we aren't.

@Chillee
Copy link
Member

Chillee commented May 16, 2017

@johnfn wait what is it that simple? I've seen a bunch of buggy behavior related to undo that would probably be fixed by having vscode manage undo stops. Is there any advantage to having us manage undo behavior?

Is there actually a vscode "trigger undo stop" command we can call? I've only seen it around the edit API's.

@johnfn
Copy link
Member

johnfn commented May 16, 2017

There are a fair amount of times where we use our undo history for something that vscode can't give us trivially. The biggest one that comes to mind is definitely stuff like jj to escape, which walks back a certain number of insertions (that may not have been stored in undo history).

But my approach is the basic strategy yeah.

@pluskid
Copy link

pluskid commented Aug 15, 2017

It is funny that I never remembered the shortcut for REDO in VIM, so whenever I try to undo and it undid a huge chunk of my code, I try to REDO, using the VSCode menu entry. And then the editor enters some weird state. Sometimes very confusing, and sometimes I end up losing a big chunk of my code. I have to say, this is very scary to use.

@brandonbloom
Copy link
Contributor

At least for me, the currently broken behavior of undo right now is far worse than undo not undoing an entire macro execution. The behavior that happens in #2007 happens to me frequently and it is tantamount to corrupting my files. I am often left in a state completely unaware of how much was undone and whether or not I'm able to use vscode vim undo/redo to adequately recover from that.

@brandonbloom
Copy link
Contributor

@Maistho How did you accomplish the remapping to bypass vscode vim's undo/redo? I tried vim.otherModesKeyBindingsNonRecursive and I can't get it to work.

@chuckdries
Copy link

chuckdries commented Sep 12, 2017

Meanwhile...

microsoft/vscode#20889

@chuckdries
Copy link

Hey @johnfn, @Zalastax and I are working on implementing undo branches in vscode's native history system. We'd like to make it possible for you to hook into us instead of needing to maintain your own history, what would an API look like that would allow you to do that without compromising on all the wonderful vim-ness that your fans demand?

Zalastax/vscode#2

P.S. should I open a new issue for this here?

@eddy-geek
Copy link

Here's a sub-bug that I'm hoping can be fixed or worked-around:
Using vscode's "Toggle Comment" (Ctrl+/) does not feed vim undo stack.

@J-Fields
Copy link
Member

J-Fields commented Dec 7, 2020

Here's a sub-bug that I'm hoping can be fixed or worked-around:
Using vscode's "Toggle Comment" (Ctrl+/) does not feed vim undo stack.

This can be fixed by using the gc operator. You could map <C-/> to it, if you like that keybinding.

@trusktr
Copy link

trusktr commented Dec 22, 2020

There's a newer VS Code extension called Neo Vim that runs VS Code as Neovim's GUI (or think of it as all key strokes control a headless Neovim, and Neovim in turn controls the VS Code text buffers).

With this you get vim's actual undo/redo tree (not just a stack). I haven't tried it yet, but I suspect that vim's (neovim's) persistent history tree will also work (VS Code will have no idea it exists, neovim will simply be updating the text buffers in VS Code, so the history state effectively lives outside of VS Code and you never touch VS Code's history yourself).

In the following video I skip to the closing JSX (HTML-like) tag with % (works out of the box), I make three edits on the next line (thus the history tree has three branches thanks to Neovim), then I undo (u) and redo (<c-r>) a few times, and then I use g+ and g- to cycle through the three edits. Note that TypeScript (on the VS Code side, which Neovim has no idea exists) is performing the syntax checking and putting the red squigglies under the invalid syntax, and momentarily shows a tooltip with type information:

history-tree


The March edition of VSCode introduced saving the undo/redo stack even after the file is closed

@HamboLagos For me it only works if the file is re-opened in the same VS Code session. When I exit VS Code, the history is gone, and does not come back when I re-launch VS Code.

@ViaxCo
Copy link

ViaxCo commented Mar 2, 2021

For anybody still facing this issue, this setting gives me the desired behaviour:

  "vim.normalModeKeyBindings": [
    {
      "before": ["u"],
      "after": [],
      "commands": [
        {
          "command": "undo"
        }
      ]
    }
  ]

@J-Fields J-Fields removed their assignment Apr 8, 2021
@haberman
Copy link

@J-Fields I noticed you un-assigned yourself from this issue. Would you be able to do a brain dump of the latest status, to help give a starting point in case someone else wants to pick this up?

In particular:

  • Did you get a chance to experiment with making VSCodeVim use the native VSCode undo stack as described in VSCodeVim Undo stack should be synced with VSCode undo stack #1490 (comment)?
  • How big of change is it? What are the tricky issues, and how far are they from being resolved?
  • Does the native VSCode stack provide enough features now that it should be theoretically possible to use it and also give native Vim behavior?

@atulpatildbz
Copy link

Followed suggession given by @ViaxCo and added the following mapping

  "vim.normalModeKeyBindingsNonRecursive": [    {
      "before": ["u"],
      "commands": ["undo"]
    },
    {
      "before": ["C-r"],
      "commands": ["redo"]
    }
  ]

Works fine. Does anyone see a risk with this workaround?

@insidewhy
Copy link
Contributor

@atulpatildbz As has been mentioned several times in the thread you are replying to, this doesn't work with macros. There's a few other commands and things this doesn't work with also, tabdo, many more.

@v-au
Copy link

v-au commented Jul 11, 2021

There's a newer VS Code extension called Neo Vim

With this you get vim's actual undo/redo tree (not just a stack). I haven't tried it yet, but I suspect that vim's (neovim's) persistent history tree will also work (VS Code will have no idea it exists, neovim will simply be updating the text buffers in VS Code, so the history state effectively lives outside of VS Code and you never touch VS Code's history yourself).

FWIW, it doesn't appear to run quite well yet, see this issue.

@praksekar
Copy link

Maybe I am missing something here, but instead of trying to have Vim use VS Code's undo stack, why not have VS Code use Vim's undo stack and undo/redo commands? i.e. Ctrl-Z is mapped to "vim-undo". It seems to me that Vim's undo implementation can perform a super set of the tasks that VS Code's does, so I don't see why this could go wrong.

@skplunkerin
Copy link

Maybe I am missing something here, but instead of trying to have Vim use VS Code's undo stack, why not have VS Code use Vim's undo stack and undo/redo commands? i.e. Ctrl-Z is mapped to "vim-undo". It seems to me that Vim's undo implementation can perform a super set of the tasks that VS Code's does, so I don't see why this could go wrong.

I believe the issue is that the extension can't just tap into vim-undo/redo, but instead is trying to emulate how vim-undo/redo works and that the emulation of this isn't identical enough to vim-undo/redo... so since it doesn't work as expected (how we all know/love how it works in vim), the suggestions have been to not use it until it's fixed, and to use VS Code's undo stack since that one works more predictably/consistently.

@wakywayne
Copy link

wakywayne commented Aug 17, 2022

I can personally say that vims undo has left me screwed twice already.

Thankfully I had git committed recently both times. If I hadn't my code would've been left looking like some kind of heiroglifics. Yes, it was that bad, letters became scattered all over the place. And redoing actually made it worse.


All this when the only changes I made were very minor. Has anyone else experienced this?

@skplunkerin
Copy link

@wakywayne yes, that's pretty much the whole point of this issue about the VSCode-Vim undo being unreliable. And I'm glad Git exists, I have also been saved from Git due to this.

You will want to map your vim undo to use VSCode's undo (and redo) until this issue is fixed.

@trusktr
Copy link

trusktr commented Sep 29, 2022

@J-Fields would you kindly mind putting vscodevim's undo/redo behind an option, disabled by default, and marked "experimental", with VS Code's undo/redo being the default?

@max-sixty
Copy link
Contributor

@J-Fields would you kindly mind putting vscodevim's undo/redo behind an option, disabled by default, and marked "experimental", with VS Code's undo/redo being the default?

Could I politely suggest that people can a) discuss ideas, and b) submit pull requests. But asking specific people to complete tasks is not in the spirit of open-source.

@wilbur4321
Copy link

@wakywayne yes, that's pretty much the whole point of this issue about the VSCode-Vim undo being unreliable. And I'm glad Git exists, I have also been saved from Git due to this.

You will want to map your vim undo to use VSCode's undo (and redo) until this issue is fixed.

To save people time, the workaround/solution here seems to work for me (very basic testing ONLY). Handily, vscode also no longer shows a file as modified after undoing my changes!

#2007 (comment)

@zvalcav
Copy link

zvalcav commented Feb 8, 2023

@atulpatildbz As has been mentioned several times in the thread you are replying to, this doesn't work with macros. There's a few other commands and things this doesn't work with also, tabdo, many more.

Maybe it doesn't allow something, maybe it breaks something. Yet @atulpatildbz gave the freedom of choice to every user of your extension. Since last update of VSCode there are some issues with u(ndo) in vim. Remaping to VSCode undo / redo commands helped me get back to work for now.

@martinemde
Copy link

martinemde commented Feb 9, 2023

Just within the last few days my undo has switched from being perfect to being completely broken. As an example, I will now make a motion like dd and a line will delete. Hitting u immediately after will say "Already at oldest change". Clearly something is broken beyond just this being vscode undo stack vs VIm. Has anyone found a solution to this?

EDIT: I'm nearly certain this sudden change is related to enabling "ruby.format": "rufo". This broke around the same time I was trying to get ruby formatting working. If I comment ruby.format it seemingly stops wrecking my vim undo stack. I'm also trying running without format on save. In the case above with dd u I did not save or format in between, but it's still a possible culprit since I got formatting working correctly right when the undo bug surfaced.

@ianchanning
Copy link

@martinemde see #8157

@ivnsch
Copy link

ivnsch commented Mar 17, 2023

Relatedly, is there a way to reduce the granularity of vim's undo? in my experience it's quite high compared to the default one, which I find much better.

@rsslldnphy
Copy link
Contributor

I'm also seeing weirdness with u causing my code to end up in completely garbled states with characters missing etc, and I think it's likely caused by a combination of vs code vim and prettier format on write. The nasty thing about it is that once it happens, neither u nor Cmd+z can get me back to a good state. I just have to try to reconstruct things myself.

<EDIT: I'm nearly certain this sudden change is related to enabling "ruby.format": "rufo"

@martinemde what i'm seeing sounds similar to what you describe, did you ever get to the bottom of this, or was it fixed in #8157?

@martinemde
Copy link

I gave up on format on save. I haven't tried again since this disruptive problem. Maybe someone else figured it out?

@rsslldnphy
Copy link
Contributor

@martinemde sad to hear that! ok in the meantime i'm going to try using the below normal mode remapping to remap u and ctrl-r to the native undo/redo commands and see if that avoids the issue.

"vim.normalModeKeyBindingsNonRecursive": [
    
    {
      "before": ["u"],
      "after": [],
      "commands": [
        {
          "command": "undo",
          "args": []
        }
      ]
    },
    {
      "before": ["<C-r>"],
      "after": [],
      "commands": [
        {
          "command": "redo",
          "args": []
        }
      ]
    }
  ]

@ivnsch
Copy link

ivnsch commented Sep 30, 2024

Any progress here?

@kimminss0
Copy link

... I think it's likely caused by a combination of vs code vim and prettier format on write.

Is the workaround of not using format-on-save still valid to this issue? I moved to Neovim from VSCode a couple of years ago because of this very problem, and now I’m considering moving back to VSCode.

@ivnsch Have you tried that workaround, and did you find it helpful?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests