eraserhd / parinfer-rust

A Rust port of parinfer.
ISC License
546 stars 42 forks source link

[Kakoune] Can't completely undo certain changes #74

Closed andreyorst closed 2 years ago

andreyorst commented 4 years ago

After some changes made by parinfer smart mode it is impossible to recover original file state. I'll add minimal example later

andreyorst commented 4 years ago

A minimal example with smart mode:

(def vaiv
    {:a 1
     :b 2})

Now use <a-j> on first line to join it with second line:

(def vaiv {:a 1
           :b 2})

Try to undo:

(def vaiv {:a 1}
     :b 2)

No further undo is possible without disabling parinfer entirely.

Undo is also impossible if parinfer is running in paren mode, but code is not broken at very least. Here's the recording: https://asciinema.org/a/JJgxChcUnejJllsbTlAh03uoU

I join lines and then trying to undo.

Calum-J-I commented 4 years ago

I have experienced the same problem. I will add that the unexpected behavior doesn't occur for all edits but any edit that triggers a parinfer change will cause this. For example deleting a line in the middle of a list is no problem

["one"
 "two"
 "three"]

becoming

;;2xd
["one"
 "three"]

is not a problem but this edit cannot be undone

;;3xd
["one"
 "two"]

The only edits this doesn't seem to apply to is insertions. If you do i<esc>i<esc>i<esc> or c<esc>c<esc>c<esc> and each insertion triggers a parinfer edit you can undo each change as expected with uuu. The actual change doesn't matter. If I use c in place of d for the edits I mentioned above then they can be undone as expected.

eraserhd commented 4 years ago

@andreyorst The current work-around is to do "2u" when you get stuck, and the problem is definitely that the parinfer change is separate, and so when you type "u", you undo parinfer's "fixup commit", and when parinfer retriggers it does the same thing again.

Vim has an "undojoin" command, which Kakoune does not have, that allows the Vim plugin to merge the edits into one. There are different possible ways around this, one of which is to make parinfer somehow undo the user edit then add it back with the fixes. This is actually not too hard... hrmm...