kakoune icon indicating copy to clipboard operation
kakoune copied to clipboard

Undo selection change

Open occivink opened this issue 8 years ago • 27 comments

Hi,

It often happens to me that I carefully craft a selection with multiple cursors, ready to make changes elegantly, only to completely mess it up by pressing a wrong key (by merging the cursors for example). Being able to undo the last selection change (even if only until the previous buffer change) would make this much less painful.

occivink avatar Oct 27 '16 08:10 occivink

Answer

lenormf avatar Oct 27 '16 11:10 lenormf

I think it's a bit different, my issue is more of a feature request regarding selection changes within the same state of the buffer, and not really related to the current undo feature.

occivink avatar Oct 27 '16 11:10 occivink

This happens to me all the times. Do you get all your multiple selections perfectly in your workflow?

doppioandante avatar Oct 27 '16 12:10 doppioandante

@occivink The relevant part is:

I am not sure if we can do much better without saving selections in the undo data, which might be a bit coslty memory wise.

The feature you want would force the editor to save selection modifications, and saving only the last one wouldn't be very consistent, so that's that.

lenormf avatar Oct 27 '16 15:10 lenormf

The feature you want would force the editor to save selection modifications, and saving only the last one wouldn't be very consistent, so that's that.

One generally needs to undo selections only when multiple selections are used, what about saving the previous selections as soon as there's more than one selection, while we save only the last one when there is only one?

Tangentially, I think that an hypothetic "undo selection" should be associated to a different command/key than u.

doppioandante avatar Oct 27 '16 19:10 doppioandante

hook global NormalKey .* %{ %sh{
  selection_count=$(echo $kak_selections_desc | awk -F : '{ print NF }')
  if test $selection_count -gt 1; then
    echo exec '<c-s>'
  fi
}}

alexherbo2 avatar Oct 27 '16 21:10 alexherbo2

That actually works nicely, but it's a shame that you kind of lose the jump-list functionality.

occivink avatar Oct 28 '16 08:10 occivink

Maybe jump list could benefit from registers.

alexherbo2 avatar Oct 28 '16 08:10 alexherbo2

Sublime Text has this feature, and I use it. It does save every cursor and selection modification (coalescing multiple character moves into a single undo item and such), and it offers two undo commands: "undo" (on a mac, cmd+z) and "soft undo" (cmd+u). "Soft undo" undoes everything -- cursor moves or selection changes or modifications -- where "undo" continually undoes everything until it reaches the first modification. I use it for these things, in order of frequency:

  • I hit cmd-d too many times and selected one too many words (this seems less compelling in Kakoune given range-refinement)
  • I jumped somewhere else in the file, and I want to return my cursor to where it was (an after-the-fact mark, like ``)
  • I flubbed a multiselect (though after six years with Sublime, I have gotten pretty careful)

ianthehenry avatar Jan 20 '17 13:01 ianthehenry

Can we put this under a feature request badge or so? It's an oft-asked feature here and on IRC. I'd be happy to use my computer's memory to store millions of cursors from the past :)

danr avatar May 03 '17 07:05 danr

Yeah, I think I will implement that, because it seems pretty useful, and I realized we only need to store selection changes from the last buffer change (they are not relevant before that). What is still missing is a nice keybinding for it.

mawww avatar May 03 '17 17:05 mawww

Yeah, I think I will implement that, because it seems pretty useful, and I realized we only need to store selection changes from the last buffer change (they are not relevant before that). What is still missing is a nice keybinding for it.

mawww avatar May 03 '17 17:05 mawww

we only need to store selection changes from the last buffer change (they are not relevant before that)

What about the undo-tree, aren't all changes relevant to allow going back/forward in time?

lenormf avatar May 03 '17 18:05 lenormf

we only need to store selection changes from the last buffer change (they are not relevant before that)

I'm also confused about this: I would like to be able to undo several times and have my cursors restore as they were at that point (and not use today's heuristics).

danr avatar May 04 '17 06:05 danr

@danr I think you're confusing two issues, you're thinking of saving cursors position in the undo tree (#1184) , while this issue is about a potential new selection-undo-stack which would let you cycle between cursors position without modifying the state of the buffer.

occivink avatar May 04 '17 07:05 occivink

Vim had this feature (in a limited form) as gv, restoring last selection. I missed it a lot when using kak.

irisjae avatar Feb 14 '19 11:02 irisjae

It's been a while since this has been bumped, and it's absence has been my biggest (still minor) annoyance with using kak.

Suggestion for keybindings: gu (back) and gU (forward), since it's really an undoing of a movement command.

If there aren't any plans to look at this in the near future, I can take a look at it when I get a chance. I'd enjoy another excuse to dive into the source.

geppettodivacin avatar Feb 17 '20 05:02 geppettodivacin

For reference:

# Save selections to the [b]ackup register.
hook -group backup-selections global NormalIdle .* %{
  set-register b %reg{z}
  execute-keys -draft '"zZ'
}

# Add a mapping to easily reach the command.
map -docstring 'Restore selections from the [b]ackup register' global user z '"bz'

Source: Restoring selections after accidental clear

alexherbo2 avatar Nov 15 '20 05:11 alexherbo2

Another case for which I want this feature: Using f or t and then repeating <a-.>, it's easy to overshoot the character you meant to stop at and want to back up one. In vim I use ; and , to iterate both forward and backward, but in oak I think I would need a selection undo to pair with <a-.>.

kconner avatar Mar 18 '21 03:03 kconner

Note for newbies: https://github.com/mawww/kakoune/issues/898#issuecomment-727516233 restores with ,z (thanks to map ... global user). It doesn't seem to be possible to move the mapping to e.g. global view or global goto (i.e. gz or vz)

mralusw avatar Jun 13 '21 03:06 mralusw

Prefix the mapping with <esc> to go back in normal mode where "bz can be executed.

alexherbo2 avatar Jun 13 '21 07:06 alexherbo2

(I'm completely new to kakoune and to modal editing, but..)

Wasn't this the entire point of having object-verb grammar? As it is right now, having to start a sentence over in Kakoune seems no different than having to undo and then start over in vi.

from "Why Kakoune":

vi basic grammar is verb followed by object ... That means that errors are not handled well. If you express your object wrongly with a delete verb, the wrong text will get deleted, you will need to undo, and try again.

Kakoune’s grammar is object followed by verb, combined with instantaneous feedback, that means you always see the current object (In Kakoune we call that the selection) before you apply your change, which allows you to correct errors on the go.

As an additional note, wouldn't backspace be an appropriate key for this in normal mode? Thinking of the editing model as "interactive sentence-building," an undo selection would be "delete one command from the sentence (object of the sentence)"

oati avatar Dec 29 '21 21:12 oati

@erinkim4 The point of the object->verb grammar is to interactively build and get visual feedback on your "object" before you have to commit to a "verb".

E.g. in Vim, you have to simply know that 5cw is the amount of words you want to replace. Only after you typed w you might realize that you wanted just four. In Kakoune, you could instead do a conservative 3w, pause and verify, add one more w and only then commit with c. Or you can build an arbitrary sequence of n and <s-n> if you want to replace very specific occurrences of a search term while leaving others untouched.

It is true that without undo functionality the "correct errors on the go" part is not always possible, especially for the more complex commands. But some selection changes can already be reverted through an opposite action (e.g. <s-h> reverts <s-l>).

sclu1034 avatar Dec 29 '21 22:12 sclu1034

I understand that, but just having visual feedback doesn't seem to take full advantage of the potential of object-verb grammar. Having opposite actions for everything seems like an ad-hoc solution, and it won't be possible (or easy) for actions that "increase entropy" (e.g. deselect, collapse anchors). Wouldn't it be better to allow users to modify sentences before executing with a verb?

oati avatar Dec 29 '21 23:12 oati

hook global NormalKey .* %{ %sh{
  selection_count=$(echo $kak_selections_desc | awk -F : '{ print NF }')
  if test $selection_count -gt 1; then
    echo exec '<c-s>'
  fi
}}

After trying this and working on the issues it has had for me, I've completed a working implementation of undo selection change, generated using nix home-manager: https://gist.github.com/erinkim4/1b02459a988ea3fe2b0ac54a4af95f72

It breaks pretty much all autoinfo normal dialogues, but that's a price I'm willing to pay.

The quoted implementation breaks numbers and all "mode keys" (g, v, <a-i>, <a-p>, [, ], etc.), so I excluded those with regex. But this made it so that none of those functions would trigger a <c-s>, so i added a hook for <esc> in normal mode, and since there were no hooks for keys in prompt, goto, or object mode, I mapped every single one of them to trigger <c-s>.

At some point in the future I'm going to fork kakoune and integrate selections into the undo tree, since this is a pretty terrible workaround.

oati avatar Jan 23 '22 17:01 oati

Update: I realized that f and t didn't work. Since map lacks modes for f, t, <a-f>, and <a-t>, I created user modes for each of them, and mapped every single character to execute <c-s>.

Working on this "solution" seemed to expose a number of problems with hooks and maps.

  • There are no hooks for keys entered in prompt, goto, or object mode.
  • There are no hooks or maps for f and t modes.
  • There are no escape characters for commands.
  • Maybe maps could benefit from regex.

note: ModeChange hooks did not work, as they executed <c-s> before any selection change happened.

Here's the new kakrc, with 468 lines: https://gist.github.com/oati/94c234778c1e2bced4207865f21dc080

oati avatar Jan 31 '22 21:01 oati

I have an experimental implementation in my undo-selection-change branch. Happy to hear feedback on the UI. I haven't tested it much yet (it's hard to unlearn muscle memory).

krobelus avatar Aug 07 '22 07:08 krobelus

Functional implementation here, this is indeed a very useful and intuitive feature. Naturally, Gimp has had it for years. I wonder if there are other features we can steal from image editors

krobelus avatar Sep 29 '22 02:09 krobelus

So far in my short testing this is great! However I think the keybindings could be better.

I'd like to make 2 additional proposals for default bindings:

  • <c-h> backwards and <c-l> forwards

    • more idiomatic since h is char-back and l is char-forward in normal mode
  • <c-k> backwards and <c-l> forwards

    • directly under i and o, and somewhat similar to <c-i> and <c-o>
    • side by side home row keys (good if this gets used as much as @krobelus says)

jtrv avatar Sep 29 '22 03:09 jtrv

<c-l> is a secret undocumented command to force-redraw the screen (rarely necessary but sometimes useful after scrolling a terminal). This is from the ncurses influence.

krobelus avatar Sep 29 '22 03:09 krobelus