Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

More granular undo #1583

Closed
eugenesvk opened this issue Jan 26, 2022 · 13 comments
Closed

More granular undo #1583

eugenesvk opened this issue Jan 26, 2022 · 13 comments
Labels
A-helix-term Area: Helix term improvements C-enhancement Category: Improvements

Comments

@eugenesvk
Copy link

Currently undo seems to undo all the changes per an "Insert session"
So, this
insert_mode
type a lot of text
normal_mode
undo

deletes "type a lot of text"

This is too coarse, especially when typing a lot of text in one go.
Is there a way to increase the undo granularity to delete, say, by typed word? So it would behave more like this:
1st undo deletes "text"
2nd undo deletes "of "
3rd undo deletes "lot "
...

(can be a separate command or an additional argument like :undo 1w or something)

@eugenesvk eugenesvk added the C-enhancement Category: Improvements label Jan 26, 2022
@Jedsek
Copy link

Jedsek commented Jan 26, 2022

I agree what you say.
vim has the same behaviour(maybe a place for improvement?), but <n> wd increase the undo in both hx and vim.

@Jedsek
Copy link

Jedsek commented Jan 26, 2022

See #1142

@Omnikar
Copy link
Contributor

Omnikar commented Jan 26, 2022

This issue should probably be closed as a duplicate.

@eugenesvk
Copy link
Author

The time based undo in the other issue is a rather new approach and is a bit unpredictable and also potentially fits too much text (when you type without interruptions) into a single undo vs the usual text units-based undo proposed here, so not really a duplicate

@Omnikar
Copy link
Contributor

Omnikar commented Jan 26, 2022

Oh, true.

@kirawi kirawi added the A-helix-term Area: Helix term improvements label Jan 26, 2022
@pickfire
Copy link
Contributor

What about implementing save-based undo? Like vim :ear 1f?

@archseer
Copy link
Member

archseer commented Jan 27, 2022

Ctrl-u will be added so that you can commit undo state while in insert mode. I'm not going to add anything more granular, preciseness is a feature to me (similar to how git commit doesn't auto commit after every file change).

@eugenesvk
Copy link
Author

What about implementing save-based undo? Like vim :ear 1f?

It's a good command that's worth implementing (and I like it better than undos based on time as I can have a better mental model of saving after some logical chunk of work rather than trying to guess how much time that chunk of work took), but it operates on a different "time frame": it's suitable to undo big chunks of edits you've committed to a file, but unsuitable for smaller changes of the last few words/sentences/edits.
These "undo a few latest changes" operations should require no pre-thought/planning, so you shouldn't need to save on every word or something to make them work

@eugenesvk
Copy link
Author

similar to how git commit doesn't auto commit after every file change).

and a text editor isn't git, so not sure how that's relevant, we'd better use text editing experience from other apps for comparison.
The workflow you describe can be approximated with file saves and undos based on a number of saves, and with a "hot exit/persistent undo" feature implemented where you wouldn't need to save a file to avoid losing your changes, file saves would be an even better fit for this workflow.
But to require introducing this whole new mental model not required elsewhere just to be able to undo a few last edits is an overkill, these types of operations shouldn't require any preliminary planning

@archseer
Copy link
Member

we'd better use text editing experience from other apps for comparison.

We do. Helix has roots from Vim and Kakoune which have matching behavior. Having to press u a few dozen times to undo a single insert is an anti-feature for me. A single edit is one insert mode session -- I frequently exit insert mode at certain points to chunk my edits accordingly.

whole new mental model not required elsewhere

That's sort of the point though, hx is a modal editor that operates on (multiple) selections. That's hugely different from your browser or any other input model. It's meant to be used differently, which is why I'm against trying to imitate something like VSCode.

You can delete back by one word via Ctrl-w. Once Ctrl-u is added you should be able to remap enter as ctrl-u + insert_newline to commit groups one line at a time. Or possibly space as ctrl-u + insert_char(' ') to commit after each word. The Vim manual suggests a similar remap:

An example for using CTRL-G u:

	:inoremap <C-H> <C-G>u<C-H>

This redefines the backspace key to start a new undo sequence.  You can now
undo the effect of the backspace key, without changing what you typed before
that, with CTRL-O u.

Using CTRL-O splits undo: the text typed before and after it is undone
separately.  If you want to avoid this (e.g., in a mapping) you might be able
to use CTRL-R = |i_CTRL-R|.  E.g., to call a function:
	:imap <F2> <C-R>=MyFunc()<CR>

@eugenesvk
Copy link
Author

Having to press u a few dozen times to undo a single insert is an anti-feature for me.

But you don't need to do that! I'm not proposing you to remove all the other undo operations, so we can continue to press a single button to undo a whole chunk of text (e.g., execute an imaginary :undo 1 insert session command which is the current meaning of undo) — when it's useful!
What I'm arguing against is forcing this model onto everything even if it doesn't suit very well.

A single edit is one insert mode session -- I frequently exit insert mode at certain points to chunk my edits accordingly.

So do I, until I don't and type whole sentences/paragraphs without any edits (sometimes even leaving fixing typos for later to avoid interrupting the flow). What's the value of being able to wipe out the changes only by sentences/paragraphs of text or having to break the flow to add undo points manually?
Yeah, in this definition the whole paragraph is one single edit, but mentally it's definitely not one

That's sort of the point though, hx is a modal editor that operates on (multiple) selections

The modality is the point of this model, and it brings with it a host of benefits like the ability to bind a command to a single key without modifiers (and play vim golf outside of hx if the weather is nice ;)) etc. Having to manually manage undo points within long editing sessions doesn't follow from that.

The Vim manual suggests a similar remap:
This redefines the backspace key to start a new undo sequence.

But this is a bad suggestion precisely for the anti-feature reason you described above — that just floods your undo history on a per char basis. I don't need that kind of granularity :)
Of course, there are corrections to this like a "smart undo" script from here that lumps all the backspaced deletes together in one block, so you can redo them at once rather then by a single character

Then you could also combine it with adding undo breaks on punctuation:

inoremap <buffer> . .<c-g>u
inoremap <buffer> ! !<c-g>u
inoremap <buffer> ? ?<c-g>u
inoremap <buffer> , ,<c-g>u

And on spaces like you suggest, then I think that should fully resolve this feature request
I just thought that might be worth improving on internally, hence the request, but being able to achieve it via an addon similar to the one above and a few additional key remaps is also fine

insert_char

Is this an existing command or a planned one? Tried to use it, but it errored out on launch, would also be great for some other things I wanted to do

P.S.

Once Ctrl-u is added

Just out of curiosity, how would this command differ from a ['normal_mode','insert_mode']?

@tmarkov
Copy link

tmarkov commented Feb 12, 2023

For anyone coming here from google, a commit_undo_checkpoint command is already implemented. By default it's mapped to ctrl-s. But if you don't want to manually keep track of checkpoints, you could also map it to Enter:

[keys.insert]
ret = ["insert_newline", "commit_undo_checkpoint"]

Maybe also to up and down, or even space, depending on how granular you want your undo to be.

@pascalkuthe
Copy link
Member

I think @archseer made his stance clear here and I agree.

commit_undo_checkpoint already exists so you can map that to a keybinding (like c-u) to manually create a checkpoint. This could also be used to implement a more granular undo in a plugin (by firing on insert hooks as implemented in #8021 ). I don't see us supporting this in core

@helix-editor helix-editor locked and limited conversation to collaborators Sep 1, 2023
@pascalkuthe pascalkuthe converted this issue into discussion #8141 Sep 1, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
A-helix-term Area: Helix term improvements C-enhancement Category: Improvements
Projects
None yet
Development

No branches or pull requests

8 participants