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

Save the . #6299

Open
laktak opened this issue Jun 19, 2020 · 14 comments
Open

Save the . #6299

laktak opened this issue Jun 19, 2020 · 14 comments

Comments

@laktak
Copy link

laktak commented Jun 19, 2020

I often search through text or code and use the . command to repeat my change (for example change a name etc.).

Halfway through I notice another change I'd like to make (e.g. remove a misplaced comma, add an s to the end of a word ...) but by making the change my . command would be cleared.

So now I either have to interrupt my workflow, make the change and then start again or remember the position to go back later.

I think being able to save the action of the . to a register and later repeat it as a macro would solve the problem.

@inkarkat
Copy link

I really like this idea, and think that this would be a great addition. Here's some brainstorming on how this could be offered:

  • If the last change command and applicable scope / motion could be represented in a meaningful way, so that it could also be synthesized by plugins, such functionality could also make any plugin action repeatable, and would allow to natively support what many plugins today use the repeat.vim plugin for (which remaps the . and u keys to hook into the redo system). That would be really great.

  • If clients would only be able to treat the value of a hypothetical getlastchange() / setlastchange() as an opaque blob, it would be far less useful, allowing not much more than what you suggest, though I would love to have a mapping that makes the next normal mode command exempt from being recorded as the last change, too.

  • Somewhat in between, if last change and scope could be described, but that representation would not be enough to synthesize new artificial changes (maybe because the internal structure within Vim is complex), a change history could be offered, like q: for Ex commands (e.g. via a new q. command). This could be used to restore any previous change, covering your use case (of skipping the most recent change) and also allowing access to earlier changes, too. This solution would offer what is described in the previous paragraph more or less automatically through histget() / histadd().

@lacygoill
Copy link

Item from the todo list which may be relevant:

Redo only remembers the last change. Could use "{count}g." to redo an older
change. How does the user know which change? At least have a way to list
them: ":repeats". Add to history, like search history and command line history.

@jlittlenz
Copy link

I've wished for this for a long time, going back to my vi days.

Like there's a scratch register for deleted or changed text, could there be a scratch register that records every change? So macro recording is always on?

@vim-ml
Copy link

vim-ml commented Jun 19, 2020 via email

@brammool
Copy link
Contributor

brammool commented Jun 20, 2020 via email

@tejr
Copy link

tejr commented Jun 21, 2020

When I first thought how handy something like this would be, the way I imagined it working would be to automatically store the relevant keys for the previous change in a read-only register.

@chrisbra
Copy link
Member

I think there even was a patch for accessing the . register floating around. Here it is: https://groups.google.com/d/msg/vim_dev/TIH6wsD4Qo4/msUMWHnWt3oJ

@laktak
Copy link
Author

laktak commented Jun 21, 2020

There are some questions about how this behaves exactly. E.g. after using "3g." does that redo operation become the current one, so that "." will redo it again? That's a bit like how the command history works. Then will "3g." do the same thing, or have the entries shifted?

Yes, I would expect it to become the current one, so I can continue using it with . (especially when going through matches).

Just having g. would be great because you still remember what that does. I'm not sure if I would find a :repeats as helpful ... maybe for the case where you do multiple changes before you go to the next match.

@tejr
Copy link

tejr commented Jun 21, 2020

Thank you @chrisbra . I really like this idea and would love to see it in mainline Vim.

@Shane-XB-Qian
Copy link
Contributor

:repeats could list them with the "g.", "2g.", etc. command that would execute them.

@brammool maybe [also] working with 'g,', 'g;' would be better, enhance it: echo the last 'repeat' at that location, then 'g.' switch to it, now '.' can repeat that one ..

@Houl
Copy link
Contributor

Houl commented Jun 23, 2020

I use g. to repeat n. on the Visual area or the remaining buffer. No, it's not released anywhere, pretty sure someone has done the same (in a more polished manner) (using which key combo?). Just want to point out a conflicting use ... which IMHO is even more useful, and also is a candidate for a builtin command.

@laktak
Copy link
Author

laktak commented Jun 26, 2020

@chrisbra thanks for the link! I've updated it, added setreg() support and created a PR. Could you take a look at it? #6346

@Shane-XB-Qian
Copy link
Contributor

jump-in .. :)
um, what was that gg link saying? (no chance to open gg link -_-#)
i was thinking 'g.' working with 'g,' and 'g;', but now - your pr, if so, no 2,3,4..g. but only 2, then how or was there still 'g.' to switch ?

@sheerun
Copy link

sheerun commented Jul 1, 2020

I think it would be really really nice if vim implemented functionality of repeat.vim natively (so developers can repeat not only last command, but last group of commands), I can't use vim without repeat.vim. Macros are nice but hard to use, and you need to remember to start recording.

arp242 added a commit to arp242/vim that referenced this issue Oct 4, 2022
This exposes the last redo command (what "." runs) in the "," register;
"." already contains the last inserted text and "," is the next best
thing. The previous redo command is available in the ";" register.

Both can be read and written to, so to restore the previous one you
could do something like:

	nnoremap <silent> g. :let [@,, @;] = [@;, '']<CR>

This is something I frequently want, for example I search for
"some_text", do "cwothertext" ("change word"), "n." a few times, but in
one instance I find some other (often small) change I need to do, or
want to change "some_text" to something else just this one time. But
doing that will have me lose the "." contents.

Issue vim#6299 contains some discussion about a "redo history" and "3g."
command, a :repeats command, etc. The idea is to provide some basic
"primitives" so people can do Clever Things™ with it, such as the
mapping above. This is a much smaller change, probably enough for most
use cases, and will still be useful if that's implemented later on
(although this could possibly just be a bundled VimScript plugin, which
will be easier to maintain than writing it all in C).

For more extensive history, a RedoChanged autocmd can be added:

	var redo_hist = []
	autocmd RedoChanged * add(redo_hist, @,)  # Matches against @,?

I'll work on that after this is merged.
arp242 added a commit to arp242/vim that referenced this issue Oct 4, 2022
This exposes the last redo command (what "." runs) in the "," register;
"." already contains the last inserted text and "," is the next best
thing. The previous redo command is available in the ";" register.

Both can be read and written to, so to restore the previous one you
could do something like:

	nnoremap <silent> g. :let [@,, @;] = [@;, '']<CR>

This is something I frequently want, for example I search for
"some_text", do "cwothertext" ("change word"), "n." a few times, but in
one instance I find some other (often small) change I need to do, or
want to change "some_text" to something else just this one time. But
doing that will have me lose the "." contents.

Issue vim#6299 contains some discussion about a "redo history" and "3g."
command, a :repeats command, etc. The idea is to provide some basic
"primitives" so people can do Clever Things™ with it, such as the
mapping above. This is a much smaller change, probably enough for most
use cases, and will still be useful if that's implemented later on
(although this could possibly just be a bundled VimScript plugin, which
will be easier to maintain than writing it all in C).

For more extensive history, a RedoChanged autocmd can be added:

	var redo_hist = []
	autocmd RedoChanged * add(redo_hist, @,)  # Matches against @,?

I'll work on that after this is merged.
arp242 added a commit to arp242/vim that referenced this issue Oct 4, 2022
This exposes the last redo command (what "." runs) in the "," register;
"." already contains the last inserted text and "," is the next best
thing. The previous redo command is available in the ";" register.

Both can be read and written to, so to restore the previous one you
could do something like:

	nnoremap <silent> g. :let [@,, @;] = [@;, '']<CR>

This is something I frequently want, for example I search for
"some_text", do "cwothertext" ("change word"), "n." a few times, but in
one instance I find some other (often small) change I need to do, or
want to change "some_text" to something else just this one time. But
doing that will have me lose the "." contents.

Issue vim#6299 contains some discussion about a "redo history" and "3g."
command, a :repeats command, etc. The idea is to provide some basic
"primitives" so people can do Clever Things™ with it, such as the
mapping above. This is a much smaller change, probably enough for most
use cases, and will still be useful if that's implemented later on
(although this could possibly just be a bundled VimScript plugin, which
will be easier to maintain than writing it all in C).

For more extensive history, a RedoChanged autocmd can be added:

	var redo_hist = []
	autocmd RedoChanged * add(redo_hist, @,)  # Matches against @,?

I'll work on that after this is merged.
arp242 added a commit to arp242/vim that referenced this issue Oct 4, 2022
This exposes the last redo command (what "." runs) in the "," register;
"." already contains the last inserted text and "," is the next best
thing. The previous redo command is available in the ";" register.

Both can be read and written to, so to restore the previous one you
could do something like:

	nnoremap <silent> g. :let [@,, @;] = [@;, '']<CR>

This is something I frequently want, for example I search for
"some_text", do "cwothertext" ("change word"), "n." a few times, but in
one instance I find some other (often small) change I need to do, or
want to change "some_text" to something else just this one time. But
doing that will have me lose the "." contents.

Issue vim#6299 contains some discussion about a "redo history" and "3g."
command, a :repeats command, etc. The idea is to provide some basic
"primitives" so people can do Clever Things™ with it, such as the
mapping above. This is a much smaller change, probably enough for most
use cases, and will still be useful if that's implemented later on
(although this could possibly just be a bundled VimScript plugin, which
will be easier to maintain than writing it all in C).

For more extensive history, a RedoChanged autocmd can be added:

	var redo_hist = []
	autocmd RedoChanged * add(redo_hist, @,)  # Matches against @,?

I'll work on that after this is merged.
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